0

I am working on an hourly hotel booking application. There is a peak_seasons table which stores start_date and end_date. Peak_Seasons are pre-defined dates for current year in my application. Whenever a customer makes a booking for the selected hours then I have to check if any of those hours belongs to peak season, so that I can apply a different rate for those hours.

This operation is so frequent that I want to optimise it. Need ideas. My current pseudo code is this:

def calculate_price(customer_start_time, customer_end_time)
    price = 0
    (customer_start_time.to_i...customer_end_time.to_i).step(1.hour) do |hour|
    //now check if this hour belongs to peak season over here
    if peak_seasons?(hour)
      price += price + peak_season_price
    else
      price += price + standard_price
    end
    return price
end

//peak_seasons? somewhere
def peak_seasons?(hour)
    PeakSeason.where("start_date <= ? and end_date >= ?", hour.to_date, hour.to_date).any?
end

I guess this is not efficient code when hundreads of customers are checking the price for selected hours, then it will fetch data from DB for every hour selected. How to optimize it?

neydroid
  • 1,913
  • 13
  • 14
Vijay Meena
  • 683
  • 1
  • 7
  • 12
  • are `customer_start_time, customer_end_time` DateTime? – neydroid Jul 26 '16 at 05:36
  • You could use `BETWEEN` for the query, `? BETWEEN start_date AND end_date`. Instead of querying for every hour you could query for the four possible interval intersections, which are at most 4 queries. – sschmeck Jul 26 '16 at 06:04
  • @neydroid Yes, `customer_start_time, customer_end_time` are DateTime. @sschmeck, thanks, yeah i can reduce queries by checking for intervals rather than hours. Is there some way by which we just have to fetch peak seasons once and store it in memory ? will it be better ? – Vijay Meena Jul 26 '16 at 07:23
  • Actually, customers can only select start_time and end_time within 3 months from today. But peak-seasons are pre-defined for whole year ahead of time. So why don't i take benefit of it, and fetch and store peak-seasons in some memory in rails, and only update that memory if required. Something like this possible ? – Vijay Meena Jul 26 '16 at 07:36

2 Answers2

1

You could create a super efficient solution by caching all PeakSeason data and using an Interval tree (see also this answer) for calculation. But you say "I guess this is not efficient" - honestly, I advice against this kind of optimization unless you really know there is a performance problem.

Community
  • 1
  • 1
claasz
  • 2,059
  • 1
  • 14
  • 16
0

You could try to select all PeakSeason records for a given interval at once.

def all_peak_seasons(customer_start_time, customer_end_time)
  PeakSeason.where(":start_time BETWEEN start_date AND end_date OR "\
                   ":end_time BETWEEN start_date AND end_date OR "\
                   "start_date BETWEEN :start_time AND :end_time",
                   {start_time: customer_start_time, end_time: customer_end_time}) 
end
sschmeck
  • 7,233
  • 4
  • 40
  • 67