Class: Clickwrap::StatementIdentityLock
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- Clickwrap::StatementIdentityLock
- Defined in:
- lib/clickwrap/models/statement_identity_lock.rb
Overview
A small coordination row for one exact statement identity or actor-wide state scope. Evidence stays in Event; this table exists because a row lock cannot be taken before the first projection/event creates its row.
Persisting one lock per identity avoids adapter-specific advisory locks. On PostgreSQL and MySQL each acquisition is a real row lock; SQLite emits no locking clause (Arel's SQLite visitor is a no-op for FOR UPDATE), so what serializes writers there is the database-wide write lock — a different mechanism whose contention surfaces as SQLITE_BUSY rather than a blocked row. The concurrency test lane runs on PostgreSQL and MySQL for exactly this reason. Callers acquire several identities in digest order so policies with more than one one-time statement cannot deadlock by choosing a different order.
Class Method Summary collapse
- .acquire!(identity_digest) ⇒ Object
- .acquire_for_actor!(actor_reference) ⇒ Object
- .actor_state_scope_for(actor_reference) ⇒ Object
Class Method Details
.acquire!(identity_digest) ⇒ Object
22 23 24 25 26 27 28 |
# File 'lib/clickwrap/models/statement_identity_lock.rb', line 22 def self.acquire!(identity_digest) lock_row = create_or_find_by!(identity_digest:) do |row| row.created_at = Clickwrap.now end lock_row.lock! lock_row end |
.acquire_for_actor!(actor_reference) ⇒ Object
34 35 36 |
# File 'lib/clickwrap/models/statement_identity_lock.rb', line 34 def self.acquire_for_actor!(actor_reference) acquire!(actor_state_scope_for(actor_reference)) end |
.actor_state_scope_for(actor_reference) ⇒ Object
30 31 32 |
# File 'lib/clickwrap/models/statement_identity_lock.rb', line 30 def self.actor_state_scope_for(actor_reference) Digest.digest_canonical({ "actor_state_reference" => actor_reference.to_s }) end |