Class: FeatureHub::Sdk::MemcacheSessionStore
- Inherits:
-
RawUpdateFeatureListener
- Object
- RawUpdateFeatureListener
- FeatureHub::Sdk::MemcacheSessionStore
- Includes:
- SessionStoreHelpers
- Defined in:
- lib/feature_hub/sdk/memcache_session_store.rb
Overview
Persists feature values from a FeatureHubRepository in Memcache so they survive process restarts and are shared across multiple processes.
Uses SHA256-based change detection and compare-and-set for multi-process safety.
WARNING: Do not use with server-evaluated features. Each server-evaluated context sends different resolved values; storing them in a shared Memcache key will cause processes to overwrite each other’s feature states.
On initialization the store reads any previously saved features from Memcache and replays them into the repository. A periodic timer re-reads the SHA key so that updates published by other processes are picked up automatically.
Constant Summary collapse
- SOURCE =
"memcache-store"
Instance Method Summary collapse
- #close ⇒ Object
- #delete_feature(feature, source) ⇒ Object
-
#initialize(connection_or_client, config, opts = nil) ⇒ MemcacheSessionStore
constructor
A new instance of MemcacheSessionStore.
- #process_update(feature, source) ⇒ Object
- #process_updates(features, source) ⇒ Object
Methods inherited from RawUpdateFeatureListener
Constructor Details
#initialize(connection_or_client, config, opts = nil) ⇒ MemcacheSessionStore
Returns a new instance of MemcacheSessionStore.
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/feature_hub/sdk/memcache_session_store.rb', line 43 def initialize(connection_or_client, config, opts = nil) super() = opts.is_a?(MemcacheSessionStoreOptions) ? opts : MemcacheSessionStoreOptions.new(opts) @repository = config.repository @environment_id = config.environment_id @prefix = .prefix @backoff_timeout = .backoff_timeout @retry_update_count = .retry_update_count @refresh_timeout = .refresh_timeout @internal_sha = nil @mutex = Mutex.new @task = nil @logger = .logger return unless dalli_available? @dalli = if connection_or_client.is_a?(String) Dalli::Client.new(connection_or_client, serializer: JSON) else connection_or_client end @logger&.debug("[featurehubsdk] started memcache store") Concurrent::Future.execute { load_from_memcache } start_timer end |
Instance Method Details
#close ⇒ Object
107 108 109 110 111 112 |
# File 'lib/feature_hub/sdk/memcache_session_store.rb', line 107 def close return if @task.nil? @task.shutdown @task = nil end |
#delete_feature(feature, source) ⇒ Object
98 99 100 101 102 103 104 105 |
# File 'lib/feature_hub/sdk/memcache_session_store.rb', line 98 def delete_feature(feature, source) return if source == SOURCE || !dalli_available? || !feature["id"] perform_store_with_retry do |memcache_features| updated = memcache_features.reject { |f| f["id"] == feature["id"] } updated.length < memcache_features.length ? updated : nil end end |
#process_update(feature, source) ⇒ Object
87 88 89 90 91 92 93 94 95 96 |
# File 'lib/feature_hub/sdk/memcache_session_store.rb', line 87 def process_update(feature, source) return if source == SOURCE || !dalli_available? perform_store_with_retry do |memcache_features| existing = memcache_features.find { |f| f["id"] == feature["id"] } next nil if existing && version_of(existing) >= version_of(feature) merge_features(memcache_features, [feature]) end end |
#process_updates(features, source) ⇒ Object
72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/feature_hub/sdk/memcache_session_store.rb', line 72 def process_updates(features, source) return if source == SOURCE || !dalli_available? incoming_sha = calculate_sha(features) return if incoming_sha == @dalli.get(sha_key) perform_store_with_retry do |memcache_features| has_newer = features.any? do |f| existing = memcache_features.find { |mf| mf["id"] == f["id"] } existing.nil? || version_of(f) > version_of(existing) end has_newer ? merge_features(memcache_features, features) : nil end end |