Class: Collavre::CreativePresenceStore
- Inherits:
-
Object
- Object
- Collavre::CreativePresenceStore
- Defined in:
- app/models/collavre/creative_presence_store.rb
Constant Summary collapse
- KEY_PREFIX =
"creative_presence:"- LOCK_TTL =
seconds
2- PRESENCE_TTL =
minutes
10
Class Method Summary collapse
- .add(root_id, user_id) ⇒ Object
- .key(root_id) ⇒ Object
- .list(root_id) ⇒ Object
- .lock_key(root_id) ⇒ Object
- .remove(root_id, user_id) ⇒ Object
-
.with_lock(root_id, &block) ⇒ Object
Simple spin-lock using cache.
Class Method Details
.add(root_id, user_id) ⇒ Object
7 8 9 10 11 12 13 14 15 16 |
# File 'app/models/collavre/creative_presence_store.rb', line 7 def self.add(root_id, user_id) with_lock(root_id) do ids = list(root_id) unless ids.include?(user_id) ids << user_id end Rails.cache.write(key(root_id), ids, expires_in: PRESENCE_TTL.minutes) ids end end |
.key(root_id) ⇒ Object
32 33 34 |
# File 'app/models/collavre/creative_presence_store.rb', line 32 def self.key(root_id) "#{KEY_PREFIX}#{root_id}" end |
.list(root_id) ⇒ Object
28 29 30 |
# File 'app/models/collavre/creative_presence_store.rb', line 28 def self.list(root_id) Rails.cache.read(key(root_id)) || [] end |
.lock_key(root_id) ⇒ Object
36 37 38 |
# File 'app/models/collavre/creative_presence_store.rb', line 36 def self.lock_key(root_id) "#{KEY_PREFIX}lock:#{root_id}" end |
.remove(root_id, user_id) ⇒ Object
18 19 20 21 22 23 24 25 26 |
# File 'app/models/collavre/creative_presence_store.rb', line 18 def self.remove(root_id, user_id) with_lock(root_id) do ids = list(root_id) if ids.delete(user_id) Rails.cache.write(key(root_id), ids, expires_in: PRESENCE_TTL.minutes) end ids end end |
.with_lock(root_id, &block) ⇒ Object
Simple spin-lock using cache. Prevents race conditions in multi-process environments.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'app/models/collavre/creative_presence_store.rb', line 41 def self.with_lock(root_id, &block) lk = lock_key(root_id) # Try to acquire lock (expires after LOCK_TTL to avoid deadlocks) 10.times do if Rails.cache.write(lk, true, unless_exist: true, expires_in: LOCK_TTL.seconds) begin return block.call ensure Rails.cache.delete(lk) end end sleep(0.05) end # Fallback: proceed without lock (better than blocking forever) block.call end |