Class: Smplkit::Flags::FlagsClient
- Inherits:
-
Object
- Object
- Smplkit::Flags::FlagsClient
- Defined in:
- lib/smplkit/flags/client.rb
Overview
Synchronous flags runtime namespace.
Obtained via Smplkit::Client#flags. Exposes typed handles (boolean_flag/string_flag/number_flag/json_flag) and runtime control (refresh, stats, on_change). CRUD has moved to mgmt.flags.*. Per-request context is set via client.set_context().
Instance Method Summary collapse
- #_close ⇒ Object
- #_evaluate_handle(flag_id, default, context) ⇒ Object
- #boolean_flag(id, default:) ⇒ Object
-
#initialize(parent, manage:, metrics:, flags_base_url:, app_base_url:) ⇒ FlagsClient
constructor
A new instance of FlagsClient.
- #json_flag(id, default:) ⇒ Object
- #number_flag(id, default:) ⇒ Object
-
#on_change(flag_id = nil, &block) ⇒ Object
Register a change listener.
- #refresh ⇒ Object
-
#start ⇒ Object
Eagerly initialize the flags subclient.
- #stats ⇒ Object
- #string_flag(id, default:) ⇒ Object
Constructor Details
#initialize(parent, manage:, metrics:, flags_base_url:, app_base_url:) ⇒ FlagsClient
Returns a new instance of FlagsClient.
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/smplkit/flags/client.rb', line 82 def initialize(parent, manage:, metrics:, flags_base_url:, app_base_url:) @parent = parent @manage = manage @metrics = metrics @service = parent._service @environment = parent._environment @flags_base_url = flags_base_url @app_base_url = app_base_url @flag_store = {} @connected = false @cache = ResolutionCache.new @handles = {} @global_listeners = [] @key_listeners = Hash.new { |h, k| h[k] = [] } @ws_manager = nil @lock = Mutex.new end |
Instance Method Details
#_close ⇒ Object
164 165 166 |
# File 'lib/smplkit/flags/client.rb', line 164 def _close # No durable resources here — kept for symmetry with Python SDK. end |
#_evaluate_handle(flag_id, default, context) ⇒ Object
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 |
# File 'lib/smplkit/flags/client.rb', line 168 def _evaluate_handle(flag_id, default, context) start unless @connected eval_dict = if context @manage.contexts.register(context) if @manage.respond_to?(:contexts) contexts_to_eval_dict(context) else current = Smplkit.request_context current.empty? ? {} : contexts_to_eval_dict(current) end eval_dict["service"] = { "key" => @service } if @service && !eval_dict.key?("service") ctx_hash = hash_context(eval_dict) cache_key = "#{flag_id}:#{ctx_hash}" hit, cached_value = @cache.get(cache_key) if hit @metrics&.record("flags.cache_hits", unit: "hits") @metrics&.record("flags.evaluations", unit: "evaluations", dimensions: { "flag" => flag_id }) return cached_value end flag_def = @flag_store[flag_id] if flag_def.nil? @cache.put(cache_key, default) return default end value = evaluate_flag(flag_def, @environment, eval_dict) value = default if value.nil? @cache.put(cache_key, value) @metrics&.record("flags.cache_misses", unit: "misses") @metrics&.record("flags.evaluations", unit: "evaluations", dimensions: { "flag" => flag_id }) value end |
#boolean_flag(id, default:) ⇒ Object
101 102 103 |
# File 'lib/smplkit/flags/client.rb', line 101 def boolean_flag(id, default:) register_handle(BooleanFlag, id, "BOOLEAN", default) end |
#json_flag(id, default:) ⇒ Object
113 114 115 |
# File 'lib/smplkit/flags/client.rb', line 113 def json_flag(id, default:) register_handle(JsonFlag, id, "JSON", default) end |
#number_flag(id, default:) ⇒ Object
109 110 111 |
# File 'lib/smplkit/flags/client.rb', line 109 def number_flag(id, default:) register_handle(NumberFlag, id, "NUMERIC", default) end |
#on_change(flag_id = nil, &block) ⇒ Object
Register a change listener.
client.flags.on_change { |event| ... } # global
client.flags.on_change("checkout-v2") { |e| ... } # flag-scoped
153 154 155 156 157 158 159 160 161 162 |
# File 'lib/smplkit/flags/client.rb', line 153 def on_change(flag_id = nil, &block) raise ArgumentError, "on_change requires a block" unless block if flag_id.nil? @global_listeners << block else @key_listeners[flag_id] << block end block end |
#refresh ⇒ Object
139 140 141 142 143 |
# File 'lib/smplkit/flags/client.rb', line 139 def refresh fetch_all_flags @cache.clear fire_change_listeners_all("manual") end |
#start ⇒ Object
Eagerly initialize the flags subclient.
Drains any pending flag-declaration buffer, fetches all flag definitions, opens the shared WebSocket and subscribes to flag_changed / flag_deleted / flags_changed events.
Idempotent — safe to call multiple times. Called automatically on first flag.get evaluation if not invoked manually.
125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/smplkit/flags/client.rb', line 125 def start return if @connected @environment = @parent._environment flush_flags_safely refresh @connected = true @ws_manager = @parent._ensure_ws @ws_manager.on("flag_changed") { |data| handle_flag_changed(data) } @ws_manager.on("flag_deleted") { |data| handle_flag_deleted(data) } @ws_manager.on("flags_changed") { |data| handle_flags_changed(data) } end |
#stats ⇒ Object
145 146 147 |
# File 'lib/smplkit/flags/client.rb', line 145 def stats FlagStats.new(cache_hits: @cache.cache_hits, cache_misses: @cache.cache_misses) end |
#string_flag(id, default:) ⇒ Object
105 106 107 |
# File 'lib/smplkit/flags/client.rb', line 105 def string_flag(id, default:) register_handle(StringFlag, id, "STRING", default) end |