Class: ConvertSdk::Stores::RedisStore
- Inherits:
-
Object
- Object
- ConvertSdk::Stores::RedisStore
- Defined in:
- lib/convert_sdk/stores/redis_store.rb
Overview
A first-party, in-tree store adapter backed by Redis — the cross-process answer to MemoryStore's per-process limitation.
== Why Redis (FR49)
MemoryStore keeps state in a single process. Puma clusters, Sidekiq worker fleets, and Lambda invocations each run in separate processes, so sticky bucketing (Story 2.11) and goal deduplication (Story 4.3) that round-trip through a +MemoryStore+ are inconsistent across the fleet. +RedisStore+ shares that state through a Redis instance, giving every process the same view.
== Zero gemspec footprint
The +redis+ gem is the user's dependency, never the SDK's: it is NOT a gemspec runtime dependency and is +require+-d lazily inside #initialize — and only when a client is built from connection options. Requiring this file (which +lib/convert_sdk.rb+ does unconditionally) therefore never pulls in +redis+, so +require "convert_sdk"+ stays green for users who do not install it. If a caller asks +RedisStore+ to build its own client without +redis+ installed, instantiation raises an actionable error naming the gem to add — a wiring-time programmer error, sanctioned in the same class as +ConvertSdk.create+'s argument validation, NOT a business path.
== Construction
# Preferred: inject an existing client (connection reuse / pooling).
# No require "redis", no Redis.new — works even where the adapter
# file is loaded without the gem present.
store = ConvertSdk::Stores::RedisStore.new(redis: Redis.new(url: ...))
# Or pass connection options; the adapter lazily requires redis and
# constructs the client itself.
store = ConvertSdk::Stores::RedisStore.new(url: "redis://localhost:6379/0")
An optional +key_prefix+ namespaces every key (default +"convert:"+) so the SDK's keys do not collide with other tenants of the same Redis database.
== Thin adapter — resilience lives upstream
This adapter is serialization + connection only. It does NOT rescue Redis client exceptions: DataStoreManager (Story 2.1) already wraps every +get+/+set+ in a rescue-log passthrough, degrading a raising store to +nil+/no-op instead of crashing the host. Duplicating that rescue here would swallow errors the manager is responsible for logging.
== Cross-process consistency caveat
Visitor-data merges are a read-modify-write. In-process that sequence is atomic under DataStoreManager's mutex, but across processes sharing one Redis there is no such lock: concurrent writers race and the last write wins. This matches the JS SDK contract. The SDK does NOT use Lua scripts or +WATCH+/+MULTI+ to close that race — that is deliberately out of scope.
Sidekiq / Lambda deployment guidance: see the Epic 5 documentation.
Constant Summary collapse
- DEFAULT_KEY_PREFIX =
Default namespace prepended to every key written to Redis.
"convert:"
Instance Method Summary collapse
-
#get(key) ⇒ Object?
Read and deserialize the value stored under +key+.
-
#initialize(redis: nil, key_prefix: DEFAULT_KEY_PREFIX, **options) ⇒ RedisStore
constructor
A new instance of RedisStore.
-
#set(key, value) ⇒ Object
Serialize +value+ to JSON and store it under +key+, overwriting any existing value.
Constructor Details
#initialize(redis: nil, key_prefix: DEFAULT_KEY_PREFIX, **options) ⇒ RedisStore
Returns a new instance of RedisStore.
76 77 78 79 |
# File 'lib/convert_sdk/stores/redis_store.rb', line 76 def initialize(redis: nil, key_prefix: DEFAULT_KEY_PREFIX, **) @key_prefix = key_prefix @client = redis || build_client() end |
Instance Method Details
#get(key) ⇒ Object?
Read and deserialize the value stored under +key+.
86 87 88 89 |
# File 'lib/convert_sdk/stores/redis_store.rb', line 86 def get(key) raw = @client.get(namespaced(key)) raw.nil? ? nil : JSON.parse(raw) end |
#set(key, value) ⇒ Object
Serialize +value+ to JSON and store it under +key+, overwriting any existing value.
97 98 99 |
# File 'lib/convert_sdk/stores/redis_store.rb', line 97 def set(key, value) @client.set(namespaced(key), JSON.generate(value)) end |