Class: Jumbotron::Synchronization::Lease
- Inherits:
-
Object
- Object
- Jumbotron::Synchronization::Lease
- Defined in:
- app/synchronization/jumbotron/synchronization/lease.rb
Overview
Narrow single-writer lease. Contract is backend-neutral; atomic acquire/release require a capable cache/store (MemoryStore or RedisCacheStore). NullStore is rejected.
Defined Under Namespace
Classes: Result
Constant Summary collapse
- DEFAULT_TTL_SECONDS =
120- KEY_PREFIX =
"jumbotron:synchronization:lease"- COMPARE_AND_DELETE_LUA =
<<~LUA if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("del", KEYS[1]) else return 0 end LUA
Class Method Summary collapse
- .normalized_acquisition_parts(acquisition) ⇒ Object
- .scope(adapter_id:, endpoint:, acquisition:) ⇒ Object
Instance Method Summary collapse
- #acquire(scope) ⇒ Object
-
#initialize(store: Rails.cache, ttl: DEFAULT_TTL_SECONDS) ⇒ Lease
constructor
A new instance of Lease.
- #release(scope, token:) ⇒ Object
Constructor Details
#initialize(store: Rails.cache, ttl: DEFAULT_TTL_SECONDS) ⇒ Lease
Returns a new instance of Lease.
44 45 46 47 48 |
# File 'app/synchronization/jumbotron/synchronization/lease.rb', line 44 def initialize(store: Rails.cache, ttl: DEFAULT_TTL_SECONDS) @store = store @ttl = Integer(ttl) assert_capable_store! end |
Class Method Details
.normalized_acquisition_parts(acquisition) ⇒ Object
38 39 40 41 42 |
# File 'app/synchronization/jumbotron/synchronization/lease.rb', line 38 def self.normalized_acquisition_parts(acquisition) hash = acquisition.respond_to?(:to_h) ? acquisition.to_h : {} hash = hash.transform_keys(&:to_s) hash.keys.sort.map { |key| hash[key].to_s } end |
.scope(adapter_id:, endpoint:, acquisition:) ⇒ Object
29 30 31 32 33 34 35 36 |
# File 'app/synchronization/jumbotron/synchronization/lease.rb', line 29 def self.scope(adapter_id:, endpoint:, acquisition:) parts = [ adapter_id.to_s, endpoint.to_s, *normalized_acquisition_parts(acquisition) ] parts.join(":") end |
Instance Method Details
#acquire(scope) ⇒ Object
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'app/synchronization/jumbotron/synchronization/lease.rb', line 50 def acquire(scope) assert_capable_store! token = SecureRandom.uuid key = cache_key(scope) written = store.write( key, token, unless_exist: true, expires_in: ttl, raw: true ) if written Result.new(acquired: true, token: token, scope: scope) else Result.new(acquired: false, token: nil, scope: scope) end end |
#release(scope, token:) ⇒ Object
68 69 70 71 72 73 |
# File 'app/synchronization/jumbotron/synchronization/lease.rb', line 68 def release(scope, token:) assert_capable_store! return false if token.nil? compare_and_delete(cache_key(scope), token.to_s) end |