Class: Flare::UploadUrlPool
- Inherits:
-
Object
- Object
- Flare::UploadUrlPool
- Defined in:
- lib/flare/upload_url_pool.rb
Overview
Thread-safe pool of presigned R2 PUT URLs the RuleManager fills from the /api/rules response. TraceExporter checks one out before each upload; if the pool is empty (no active rules, no fresh URLs) it returns nil and the exporter gives up on that batch – caller decides what to do.
Each entry is a Hash: { upload_id:, key:, put_url:, expires_at: }. expires_at is a Time; entries past their expiry are skipped on checkout.
Fork-safe: after_fork clears the pool so child processes don’t reuse parent URLs (each child polls its own copy from /api/rules anyway).
Instance Attribute Summary collapse
-
#checkouts ⇒ Object
readonly
Returns the value of attribute checkouts.
-
#empty_count ⇒ Object
readonly
Returns the value of attribute empty_count.
-
#expired_count ⇒ Object
readonly
Returns the value of attribute expired_count.
Instance Method Summary collapse
-
#after_fork ⇒ Object
Call from Flare.after_fork.
- #checkout ⇒ Object
- #clear ⇒ Object
- #empty? ⇒ Boolean
-
#initialize ⇒ UploadUrlPool
constructor
A new instance of UploadUrlPool.
- #replace(entries) ⇒ Object
- #size ⇒ Object
-
#sweep ⇒ Object
Drop URLs that have already passed their expires_at.
Constructor Details
#initialize ⇒ UploadUrlPool
Returns a new instance of UploadUrlPool.
20 21 22 23 24 25 |
# File 'lib/flare/upload_url_pool.rb', line 20 def initialize @entries_ref = Concurrent::AtomicReference.new([].freeze) @checkouts = Concurrent::AtomicFixnum.new(0) @empty_count = Concurrent::AtomicFixnum.new(0) @expired_count = Concurrent::AtomicFixnum.new(0) end |
Instance Attribute Details
#checkouts ⇒ Object (readonly)
Returns the value of attribute checkouts.
18 19 20 |
# File 'lib/flare/upload_url_pool.rb', line 18 def checkouts @checkouts end |
#empty_count ⇒ Object (readonly)
Returns the value of attribute empty_count.
18 19 20 |
# File 'lib/flare/upload_url_pool.rb', line 18 def empty_count @empty_count end |
#expired_count ⇒ Object (readonly)
Returns the value of attribute expired_count.
18 19 20 |
# File 'lib/flare/upload_url_pool.rb', line 18 def expired_count @expired_count end |
Instance Method Details
#after_fork ⇒ Object
Call from Flare.after_fork. Parent’s URLs aren’t usable from the child’s point of view (each child should get its own from a fresh /api/rules poll), so just drop them.
82 83 84 |
# File 'lib/flare/upload_url_pool.rb', line 82 def after_fork clear end |
#checkout ⇒ Object
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/flare/upload_url_pool.rb', line 32 def checkout now = Time.now loop do current = @entries_ref.get if current.empty? @empty_count.increment return nil end candidate, *rest = current next_state = rest.freeze next unless @entries_ref.compare_and_set(current, next_state) if expired?(candidate, now) @expired_count.increment next # try the next one end @checkouts.increment return candidate end end |
#clear ⇒ Object
63 64 65 |
# File 'lib/flare/upload_url_pool.rb', line 63 def clear @entries_ref.set([].freeze) end |
#empty? ⇒ Boolean
59 60 61 |
# File 'lib/flare/upload_url_pool.rb', line 59 def empty? size.zero? end |
#replace(entries) ⇒ Object
27 28 29 30 |
# File 'lib/flare/upload_url_pool.rb', line 27 def replace(entries) normalized = (entries || []).filter_map { |raw| normalize(raw) } @entries_ref.set(normalized.freeze) end |
#size ⇒ Object
55 56 57 |
# File 'lib/flare/upload_url_pool.rb', line 55 def size @entries_ref.get.length end |
#sweep ⇒ Object
Drop URLs that have already passed their expires_at. Cheap; safe to call from RuleManager’s scheduler in between polls.
69 70 71 72 73 74 75 76 77 |
# File 'lib/flare/upload_url_pool.rb', line 69 def sweep now = Time.now current = @entries_ref.get live = current.reject { |e| expired?(e, now) } return 0 if live.length == current.length @entries_ref.set(live.freeze) current.length - live.length end |