Class: Flightdeck::BulkAction
- Inherits:
-
Object
- Object
- Flightdeck::BulkAction
- Defined in:
- app/models/flightdeck/bulk_action.rb
Overview
Applies a Solid Queue operation across a filtered relation in bounded, individually-committed batches.
Three things keep this safe to run against a live queue:
* a hard record limit (`Flightdeck.config.bulk_action_limit`),
* a wall-clock deadline measured on the monotonic clock, and
* a commit per batch, so stopping early still leaves completed work done.
Stopping early is a normal outcome, not an error: the caller reports "Retried 1,000 of ~14,200" and the same request can simply be submitted again to continue.
Defined Under Namespace
Classes: Result
Constant Summary collapse
- BATCH_SIZE =
100- DEADLINE =
10.seconds
Instance Attribute Summary collapse
-
#count_cap ⇒ Object
readonly
Returns the value of attribute count_cap.
-
#deadline ⇒ Object
readonly
Returns the value of attribute deadline.
-
#limit ⇒ Object
readonly
Returns the value of attribute limit.
-
#relation ⇒ Object
readonly
Returns the value of attribute relation.
Instance Method Summary collapse
- #call(&operation) ⇒ Object
-
#initialize(relation:, limit: nil, deadline: DEADLINE, count_cap: nil) ⇒ BulkAction
constructor
A new instance of BulkAction.
Constructor Details
#initialize(relation:, limit: nil, deadline: DEADLINE, count_cap: nil) ⇒ BulkAction
Returns a new instance of BulkAction.
28 29 30 31 32 33 |
# File 'app/models/flightdeck/bulk_action.rb', line 28 def initialize(relation:, limit: nil, deadline: DEADLINE, count_cap: nil) @relation = relation @limit = (limit || Flightdeck.config.bulk_action_limit).to_i @deadline = deadline @count_cap = (count_cap || Flightdeck.config.count_cap).to_i end |
Instance Attribute Details
#count_cap ⇒ Object (readonly)
Returns the value of attribute count_cap.
26 27 28 |
# File 'app/models/flightdeck/bulk_action.rb', line 26 def count_cap @count_cap end |
#deadline ⇒ Object (readonly)
Returns the value of attribute deadline.
26 27 28 |
# File 'app/models/flightdeck/bulk_action.rb', line 26 def deadline @deadline end |
#limit ⇒ Object (readonly)
Returns the value of attribute limit.
26 27 28 |
# File 'app/models/flightdeck/bulk_action.rb', line 26 def limit @limit end |
#relation ⇒ Object (readonly)
Returns the value of attribute relation.
26 27 28 |
# File 'app/models/flightdeck/bulk_action.rb', line 26 def relation @relation end |
Instance Method Details
#call(&operation) ⇒ Object
35 36 37 38 39 40 41 42 43 44 45 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 |
# File 'app/models/flightdeck/bulk_action.rb', line 35 def call(&operation) total = relation.limit(count_cap).count started_at = monotonic_now processed = 0 failed = 0 stopped = nil relation.in_batches(of: BATCH_SIZE, order: :desc) do |batch| SolidQueue::Record.transaction do batch.each do |record| if processed + failed >= limit stopped = :limit break end begin operation.call(record) processed += 1 rescue ActiveRecord::RecordNotFound, ActiveRecord::Deadlocked # The queue moved under us — a worker finished or retried this job # first. Skip it; the caller's counts stay honest. failed += 1 end end end break if stopped if monotonic_now - started_at >= deadline stopped = :deadline break end end Result.new( processed: processed, failed: failed, total: total, total_capped: total >= count_cap, stopped: stopped ) end |