Class: Statistics::RestaurantWorker
- Inherits:
-
ApplicationWorker
- Object
- ApplicationWorker
- Statistics::RestaurantWorker
- Defined in:
- app/workers/statistics/restaurant_worker.rb
Overview
typed: ignore frozen_string_literal: true
Instance Method Summary collapse
- #perform ⇒ Object
-
#update_reservations_count(restaurant, days_ago = 30) ⇒ Object
update total reservations based on few X days ago.
- #update_top_restaurants ⇒ Object
Instance Method Details
#perform ⇒ Object
17 18 19 20 21 22 23 24 |
# File 'app/workers/statistics/restaurant_worker.rb', line 17 def perform ::Restaurant.find_each do |restaurant| update_reservations_count restaurant, 3 rescue StandardError => e APMErrorHandler.report(e, restaurant_id: restaurant.id) end update_top_restaurants end |
#update_reservations_count(restaurant, days_ago = 30) ⇒ Object
update total reservations based on few X days ago
7 8 9 10 11 12 13 14 15 |
# File 'app/workers/statistics/restaurant_worker.rb', line 7 def update_reservations_count(restaurant, days_ago = 30) date = days_ago.days.ago.to_date # Use ClickHouse replica for reading data, but maintain exact same query structure clickhouse_restaurant = restaurant.clickhouse_replica return unless clickhouse_restaurant count = clickhouse_restaurant.reservations.where('created_at >= ?', date).exclude_temporary.count restaurant.update reservations_count: count end |
#update_top_restaurants ⇒ Object
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'app/workers/statistics/restaurant_worker.rb', line 26 def update_top_restaurants today = Date.today revenue_data = HhClickHouseRestaurant.select('restaurants.id, SUM(reservation_properties.revenue) as revenue'). joins(reservations: :property). where('restaurants.active = ? AND expiry_date >= ?', 1, today). where('reservations.created_at >= ? AND reservations.created_at <= ?', today - 3.days, today). group('restaurants.id'). order('revenue DESC') # Extract restaurant IDs and their corresponding top_order values restaurant_updates = revenue_data.each_with_index.map do |result, index| { id: result.id, top_order: index } end # True batch update using a single SQL statement with CASE # This is secure because we're using parameterized values, not string interpolation if restaurant_updates.any? restaurant_ids = restaurant_updates.pluck(:id) # Build parameterized CASE statement - secure because values are bound parameters case_conditions = restaurant_updates.map.with_index do |_update, _index| 'WHEN id = ? THEN ?' end.join(' ') # Flatten the parameters: [id1, top_order1, id2, top_order2, ...] case_params = restaurant_updates.flat_map { |update| [update[:id], update[:top_order]] } # Single secure SQL update with bound parameters Restaurant.where(id: restaurant_ids).update_all( ["top_order = CASE #{case_conditions} END"] + case_params, ) end end |