Class: Smith::PersistenceAdapters::ActiveRecordStore
- Inherits:
-
Object
- Object
- Smith::PersistenceAdapters::ActiveRecordStore
- Defined in:
- lib/smith/persistence_adapters/active_record_store.rb
Instance Method Summary collapse
- #delete(key) ⇒ Object
- #fetch(key) ⇒ Object
-
#initialize(model:, key_column: :key, payload_column: :payload, version_column: :lock_version) ⇒ ActiveRecordStore
constructor
AR transient errors resolved via class-name guard so Smith doesn't require activerecord at load time.
-
#store(key, payload, ttl: nil) ⇒ Object
rubocop:disable Lint/UnusedMethodArgument.
-
#store_versioned(key, payload, expected_version:, ttl: nil) ⇒ Object
Optimistic locking via Rails' built-in optimistic locking on the
lock_versioncolumn. - #transaction_open? ⇒ Boolean
Constructor Details
#initialize(model:, key_column: :key, payload_column: :payload, version_column: :lock_version) ⇒ ActiveRecordStore
AR transient errors resolved via class-name guard so Smith doesn't require activerecord at load time. Hosts that use this adapter already have activerecord in their dep tree.
9 10 11 12 13 14 |
# File 'lib/smith/persistence_adapters/active_record_store.rb', line 9 def initialize(model:, key_column: :key, payload_column: :payload, version_column: :lock_version) @model_source = model.is_a?(String) ? model.dup.freeze : model @key_column = normalize_column(key_column) @payload_column = normalize_column(payload_column) @version_column = normalize_column(version_column) end |
Instance Method Details
#delete(key) ⇒ Object
33 34 35 36 37 |
# File 'lib/smith/persistence_adapters/active_record_store.rb', line 33 def delete(key) Retry.with_retries(operation: :delete, transient: ActiveRecordConnectionErrors.classes) do model_class.where(@key_column => key).delete_all end end |
#fetch(key) ⇒ Object
27 28 29 30 31 |
# File 'lib/smith/persistence_adapters/active_record_store.rb', line 27 def fetch(key) Retry.with_retries(operation: :fetch, transient: ActiveRecordConnectionErrors.classes) do model_class.find_by(@key_column => key)&.public_send(@payload_column) end end |
#store(key, payload, ttl: nil) ⇒ Object
rubocop:disable Lint/UnusedMethodArgument
16 17 18 19 20 21 22 23 24 25 |
# File 'lib/smith/persistence_adapters/active_record_store.rb', line 16 def store(key, payload, ttl: nil) # rubocop:disable Lint/UnusedMethodArgument # TTL is deferred for ActiveRecordStore — would require an # `expires_at` column + a periodic sweeper job. Ignored here; # documented as a known limitation. Retry.with_retries(operation: :store, transient: ActiveRecordConnectionErrors.classes) do record = model_class.find_or_initialize_by(@key_column => key) record.public_send(:"#{@payload_column}=", payload) record.save! end end |
#store_versioned(key, payload, expected_version:, ttl: nil) ⇒ Object
Optimistic locking via Rails' built-in optimistic locking on the
lock_version column. Requires the AR model to have a
lock_version (or configured) integer column with default 0.
If absent, raises ArgumentError directing the host to migrate.
47 48 49 50 51 52 53 54 |
# File 'lib/smith/persistence_adapters/active_record_store.rb', line 47 def store_versioned(key, payload, expected_version:, ttl: nil) # rubocop:disable Lint/UnusedMethodArgument ensure_version_column! ensure_locking_configuration! write_versioned(key, payload, expected_version) rescue *ActiveRecordConnectionErrors.classes => e raise Smith::PersistenceIOError.new(operation: :store_versioned, cause: e) end |
#transaction_open? ⇒ Boolean
39 40 41 |
# File 'lib/smith/persistence_adapters/active_record_store.rb', line 39 def transaction_open? model_class.connection.transaction_open? end |