Class: FirebaseCleanupService
- Inherits:
-
Object
- Object
- FirebaseCleanupService
- Includes:
- ElasticAPM::SpanHelpers
- Defined in:
- app/services/firebase_cleanup_service.rb
Overview
Service to cleanup Firebase Realtime Database reservation entries by deleting specific reservation IDs or IDs up to a threshold.
Phase 1: Safety-first approach - supports deletion by specific IDs or threshold to prevent accidental mass deletion of data.
This service uses FirebaseCleanupWorker which processes deletions in batches by accepting explicit reservation IDs and deleting them from Firebase.
Key features:
-
Supports specific reservation IDs or threshold-based cleanup
-
Batch deletion using Firebase update with nil values (1000 IDs per batch)
-
Validates and normalizes input (compact, unique, remove zeros/nils)
-
Comprehensive logging and error handling
-
APM instrumentation for monitoring
Usage:
service = FirebaseCleanupService.new
# Cleanup specific reservation IDs
service.cleanup_by_ids([12345, 67890, 11111])
service.cleanup_by_ids(12345) # Single ID
# Cleanup all reservation IDs <= threshold (up to max id)
service.cleanup_by_ids(1000) # Deletes all reservation_id <= 1000
Constant Summary collapse
- BATCH_SIZE =
1000- MAX_RANGE_SIZE =
1_000_000
Instance Method Summary collapse
-
#cleanup_by_ids(reservation_ids, threshold_mode: nil) ⇒ Hash
Delete specific reservation IDs from Firebase, all IDs <= threshold, or a range of IDs This method accepts: - A single ID (Integer): Treated as threshold, deletes all IDs <= this value - An array of two integers: Treated as a range, deletes all IDs between from_id and to_id (inclusive) Example: [100, 200] will delete IDs: 100, 101, 102, …, 199, 200 - An array of IDs: Deletes only the specified IDs.
-
#cleanup_by_range(from_id, to_id) ⇒ Hash
Delete all reservation IDs between from_id and to_id (inclusive) from Firebase Fetches IDs from database where id >= from_id and id <= to_id and processes in batches.
Instance Method Details
#cleanup_by_ids(reservation_ids, threshold_mode: nil) ⇒ Hash
Delete specific reservation IDs from Firebase, all IDs <= threshold, or a range of IDs This method accepts:
-
A single ID (Integer): Treated as threshold, deletes all IDs <= this value
-
An array of two integers: Treated as a range, deletes all IDs between from_id and to_id (inclusive) Example: [100, 200] will delete IDs: 100, 101, 102, …, 199, 200
-
An array of IDs: Deletes only the specified IDs
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 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 |
# File 'app/services/firebase_cleanup_service.rb', line 46 def cleanup_by_ids(reservation_ids, threshold_mode: nil) # Auto-detect threshold mode: single integer input is threshold mode is_threshold_mode = threshold_mode.nil? ? !reservation_ids.is_a?(Array) : threshold_mode if is_threshold_mode # Threshold mode: delete all reservation IDs <= threshold threshold = reservation_ids.to_i if threshold <= 0 return error_response( 'Threshold must be a positive integer', threshold: threshold, ) end cleanup_by_threshold(threshold) elsif reservation_ids.is_a?(Array) && reservation_ids.size == 2 && reservation_ids.all? { |id| id.is_a?(Integer) } # Range mode: delete all reservation IDs between from_id and to_id (inclusive) # Validate before sorting if reservation_ids.any? { |id| id <= 0 } return error_response( 'Invalid range for reservation IDs. Both IDs must be positive integers.', from_id: reservation_ids[0], to_id: reservation_ids[1], ) end from_id, to_id = reservation_ids.sort range_size = to_id - from_id + 1 if range_size > MAX_RANGE_SIZE return error_response( "Range too large (#{range_size} IDs). Maximum allowed range: #{MAX_RANGE_SIZE}", from_id: from_id, to_id: to_id, range_size: range_size, ) end cleanup_by_range(from_id, to_id) else # Specific IDs mode: delete only provided IDs cleanup_specific_ids(reservation_ids) end end |
#cleanup_by_range(from_id, to_id) ⇒ Hash
Delete all reservation IDs between from_id and to_id (inclusive) from Firebase Fetches IDs from database where id >= from_id and id <= to_id and processes in batches
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'app/services/firebase_cleanup_service.rb', line 98 def cleanup_by_range(from_id, to_id) BUSINESS_LOGGER.set_business_context( service: 'FirebaseCleanupService', method: 'cleanup_by_range', from_id: from_id, to_id: to_id, ) BUSINESS_LOGGER.info( 'Starting Firebase cleanup by range', { from_id: from_id, to_id: to_id, mode: 'range', }, ) # Fetch all reservation IDs in the range from database ids_array = Reservation.where('id >= ? AND id <= ?', from_id, to_id).order(:id).pluck(:id) if ids_array.empty? BUSINESS_LOGGER.info( 'No reservations found in database for range cleanup', { from_id: from_id, to_id: to_id, mode: 'range', }, ) return { success: true, job_ids: [], total_ids: 0, batches_enqueued: 0, from_id: from_id, to_id: to_id, mode: 'range', message: 'No reservations found to delete in range', } end BUSINESS_LOGGER.info( 'Fetched reservation IDs from database for range cleanup', { from_id: from_id, to_id: to_id, total_ids: ids_array.count, mode: 'range', }, ) # Split IDs into batches and enqueue workers job_ids = [] ids_array.each_slice(BATCH_SIZE) do |batch| job_id = FirebaseCleanupWorker.perform_async(batch) job_ids << job_id BUSINESS_LOGGER.info( 'Enqueued Firebase cleanup batch for range mode', { job_id: job_id, batch_size: batch.size, from_id: from_id, to_id: to_id, mode: 'range', }, ) end result = build_success_result( job_ids: job_ids, total_ids: ids_array.size, mode: 'range', message: "Enqueued #{job_ids.size} worker(s) to delete #{ids_array.size} reservation(s) from ID #{from_id} to #{to_id} from Firebase", from_id: from_id, to_id: to_id, ) BUSINESS_LOGGER.info('Firebase cleanup by range - workers enqueued', result) result end |