Class: Arcp::Runtime::LeaseManager
- Inherits:
-
Object
- Object
- Arcp::Runtime::LeaseManager
- Defined in:
- lib/arcp/runtime/lease_manager.rb
Overview
Tracks per-job leases and bound budget counters. The runtime asks ‘#check!(job_id, capability:)` before every authority op.
Instance Method Summary collapse
- #check!(job_id, capability:) ⇒ Object
- #check_model!(job_id, model_id:) ⇒ Object
- #counter(job_id) ⇒ Object
- #get(job_id) ⇒ Object
-
#initialize(clock: Arcp::SystemClock.new, enforce_model_use: false) ⇒ LeaseManager
constructor
A new instance of LeaseManager.
- #register(job_id, lease) ⇒ Object
- #remaining(job_id) ⇒ Object
- #revoke(job_id) ⇒ Object
-
#try_spend!(job_id, currency, amount) ⇒ Object
Try to decrement the bound budget.
Constructor Details
#initialize(clock: Arcp::SystemClock.new, enforce_model_use: false) ⇒ LeaseManager
Returns a new instance of LeaseManager.
8 9 10 11 12 13 14 |
# File 'lib/arcp/runtime/lease_manager.rb', line 8 def initialize(clock: Arcp::SystemClock.new, enforce_model_use: false) @clock = clock @enforce_model_use = enforce_model_use @leases = {} @counters = {} @mutex = Mutex.new end |
Instance Method Details
#check!(job_id, capability:) ⇒ Object
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/arcp/runtime/lease_manager.rb', line 27 def check!(job_id, capability:) lease = get(job_id) return if lease.nil? if lease.expired?(@clock.now) raise Arcp::Errors::LeaseExpired.new( "lease #{lease.id} expired at #{lease.expires_at}", details: { 'lease_id' => lease.id } ) end return if lease.capabilities.include?(capability) raise Arcp::Errors::PermissionDenied.new( "capability #{capability.inspect} not in lease #{lease.id}", details: { 'capability' => capability, 'lease_id' => lease.id } ) end |
#check_model!(job_id, model_id:) ⇒ Object
46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/arcp/runtime/lease_manager.rb', line 46 def check_model!(job_id, model_id:) lease = get(job_id) return true if lease.nil? && !@enforce_model_use return true if lease&.model_use && Arcp::ModelPattern.match?(lease.model_use, model_id) raise Arcp::Errors::PermissionDenied.new( "model #{model_id.inspect} not permitted by lease", details: { 'model' => model_id, 'lease_id' => lease&.id } ) end |
#counter(job_id) ⇒ Object
25 |
# File 'lib/arcp/runtime/lease_manager.rb', line 25 def counter(job_id) = @mutex.synchronize { @counters[job_id] } |
#get(job_id) ⇒ Object
24 |
# File 'lib/arcp/runtime/lease_manager.rb', line 24 def get(job_id) = @mutex.synchronize { @leases[job_id] } |
#register(job_id, lease) ⇒ Object
16 17 18 19 20 21 22 |
# File 'lib/arcp/runtime/lease_manager.rb', line 16 def register(job_id, lease) @mutex.synchronize do @leases[job_id] = lease @counters[job_id] = Arcp::Lease::BudgetCounter.new(initial: lease.budget&.per_currency&.dup || {}) end lease end |
#remaining(job_id) ⇒ Object
75 76 77 78 |
# File 'lib/arcp/runtime/lease_manager.rb', line 75 def remaining(job_id) c = counter(job_id) c ? c.snapshot : {} end |
#revoke(job_id) ⇒ Object
80 81 82 83 84 85 |
# File 'lib/arcp/runtime/lease_manager.rb', line 80 def revoke(job_id) @mutex.synchronize do @leases.delete(job_id) @counters.delete(job_id) end end |
#try_spend!(job_id, currency, amount) ⇒ Object
Try to decrement the bound budget. Returns true on success, raises BudgetExhausted if no balance covers the amount. Straight-line —no scheduler-yielding calls between read and write.
61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/arcp/runtime/lease_manager.rb', line 61 def try_spend!(job_id, currency, amount) counter = self.counter(job_id) return true if counter.nil? return true if counter.get(currency).zero? && !counter.remaining.key?(currency) unless counter.try_decrement(currency, amount) raise Arcp::Errors::BudgetExhausted.new( "budget #{currency} exhausted", details: { 'currency' => currency, 'remaining' => counter.get(currency).to_s('F') } ) end true end |