Class: MongoDbSyncRestaurantDataWorker
- Inherits:
-
ApplicationWorker
- Object
- ApplicationWorker
- MongoDbSyncRestaurantDataWorker
- Defined in:
- app/workers/mongo_db_sync_restaurant_data_worker.rb
Overview
typed: true frozen_string_literal: true
Class Method Summary collapse
-
.circuit_open? ⇒ Boolean
Checks if the circuit breaker is open (too many errors have occurred) Returns true if more than 5 MongoDB errors have occurred in the last 5 minutes When true, MongoDB operations should be temporarily paused.
-
.record_error ⇒ Object
Records a MongoDB error for the circuit breaker Increments the error counter in Redis and sets a 5-minute expiration This ensures the circuit will automatically reset after 5 minutes.
-
.reset_circuit ⇒ Object
Manually resets the circuit breaker by clearing the error count Called after successful operations to quickly restore normal operation.
Instance Method Summary collapse
Methods inherited from ApplicationWorker
Class Method Details
.circuit_open? ⇒ Boolean
Checks if the circuit breaker is open (too many errors have occurred) Returns true if more than 5 MongoDB errors have occurred in the last 5 minutes When true, MongoDB operations should be temporarily paused
28 29 30 31 32 33 34 35 36 37 |
# File 'app/workers/mongo_db_sync_restaurant_data_worker.rb', line 28 def self.circuit_open? $redis_lru.with do |redis| error_count = redis.get('mongodb_error_count').to_i error_count > 5 # Circuit opens if more than 5 errors in the time window end rescue StandardError => e # If Redis fails, assume circuit is closed to allow operation APMErrorHandler.report('Failed to check MongoDB circuit breaker', error: e) false end |
.record_error ⇒ Object
Records a MongoDB error for the circuit breaker Increments the error counter in Redis and sets a 5-minute expiration This ensures the circuit will automatically reset after 5 minutes
42 43 44 45 46 47 48 49 50 |
# File 'app/workers/mongo_db_sync_restaurant_data_worker.rb', line 42 def self.record_error $redis_lru.with do |redis| redis.incr('mongodb_error_count') redis.expire('mongodb_error_count', 300) # 5-minute window end rescue StandardError => e # Silently continue if Redis fails APMErrorHandler.report('Failed to record MongoDB error for circuit breaker', error: e) end |
.reset_circuit ⇒ Object
Manually resets the circuit breaker by clearing the error count Called after successful operations to quickly restore normal operation
54 55 56 57 58 59 |
# File 'app/workers/mongo_db_sync_restaurant_data_worker.rb', line 54 def self.reset_circuit $redis_lru.with { |redis| redis.del('mongodb_error_count') } rescue StandardError => e # Silently continue if Redis fails APMErrorHandler.report('Failed to reset MongoDB circuit breaker', error: e) end |
Instance Method Details
#perform(date_time = nil, restaurant_id = nil, first_sync = false, type = nil) ⇒ Object
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'app/workers/mongo_db_sync_restaurant_data_worker.rb', line 61 def perform(date_time = nil, restaurant_id = nil, first_sync = false, type = nil) # Check circuit breaker first if self.class.circuit_open? APMErrorHandler.report('MongoDB circuit breaker open, rescheduling job', restaurant_id: restaurant_id, date_time: date_time) # If circuit is open, reschedule the job for later return self.class.perform_in(5.minutes, date_time, restaurant_id, first_sync, type) end type = type || 'by_hour' restaurant = Restaurant.find_by(id: restaurant_id, active: true) return if restaurant.blank? if first_sync first_sync_by_month(restaurant) first_sync_by_date(restaurant) first_sync_by_hour(restaurant) else date_time = date_time.blank? ? Time.current : Time.zone.parse(date_time.to_s) send("sync_#{type}", date_time.in_time_zone(restaurant.time_zone), restaurant) end # If we get here, the job completed successfully, so reset the circuit self.class.reset_circuit rescue Mongo::Error::NoServerAvailable, Mongo::Error::ConnectionCheckOutTimeout, Mongo::Error::OperationFailure => e # Record error for circuit breaker self.class.record_error # Log the specific error with context APMErrorHandler.report("MongoDB error in #{self.class}", error: e, restaurant_id: restaurant_id, date_time: date_time, first_sync: first_sync, type: type) # Retry with exponential backoff retry_in = rand(1..60).minutes self.class.perform_in(retry_in, date_time, restaurant_id, first_sync, type) ensure client.close_connection if client.present? end |