Class: Smplkit::Config::ConfigClient

Inherits:
Object
  • Object
show all
Defined in:
lib/smplkit/config/client.rb

Overview

Synchronous config runtime namespace.

Obtained via Smplkit::Client#config. Exposes typed accessors (get_string, get_number, get_boolean, get_json) and runtime control (refresh, on_change).

Instance Method Summary collapse

Constructor Details

#initialize(parent, manage:, metrics:) ⇒ ConfigClient

Returns a new instance of ConfigClient.



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/smplkit/config/client.rb', line 141

def initialize(parent, manage:, metrics:)
  @parent = parent
  @manage = manage
  @metrics = metrics
  @environment = parent._environment
  @service = parent._service

  @snapshots = {}
  @raw_chains = {}
  @proxies = {}
  @global_listeners = []
  @key_listeners = Hash.new { |h, k| h[k] = [] }
  @item_listeners = Hash.new { |h, k| h[k] = Hash.new { |hh, kk| hh[kk] = [] } }
  @connected = false
  @lock = Mutex.new
end

Instance Method Details

#_closeObject



264
265
266
# File 'lib/smplkit/config/client.rb', line 264

def _close
  # No durable resources; symmetry stub.
end

#_invalidate(config_key) ⇒ Object

Discard cached state for config_key; the next resolve will refetch.



269
270
271
272
273
274
# File 'lib/smplkit/config/client.rb', line 269

def _invalidate(config_key)
  @lock.synchronize do
    @snapshots.delete(config_key)
    @raw_chains.delete(config_key)
  end
end

#_observe_config_declaration(config_id, parent:, name:, description:) ⇒ Object

Internal: queue a config declaration with the management buffer.



277
278
279
280
281
282
283
284
285
286
# File 'lib/smplkit/config/client.rb', line 277

def _observe_config_declaration(config_id, parent:, name:, description:)
  @manage.config.register_config(
    config_id,
    service: @service,
    environment: @environment,
    parent: parent,
    name: name,
    description: description
  )
end

#_observe_item_declaration(config_id, item_key, item_type, default, description) ⇒ Object

Internal: queue a config item declaration with the management buffer.



289
290
291
# File 'lib/smplkit/config/client.rb', line 289

def _observe_item_declaration(config_id, item_key, item_type, default, description)
  @manage.config.register_config_item(config_id, item_key, item_type, default, description)
end

#_resolve_now(config_key) ⇒ Object



260
261
262
# File 'lib/smplkit/config/client.rb', line 260

def _resolve_now(config_key)
  resolve(config_key) || {}
end

#get(config_key, model_class = nil) ⇒ Object



175
176
177
178
179
180
181
182
183
# File 'lib/smplkit/config/client.rb', line 175

def get(config_key, model_class = nil)
  start unless @connected

  snapshot = resolve(config_key)
  raise Smplkit::NotFoundError, "Config #{config_key.inspect} not found" if snapshot.nil?
  return snapshot if model_class.nil?

  model_class.new(snapshot)
end

#get_boolean(item_key, default: nil, config: nil) ⇒ Object



220
221
222
# File 'lib/smplkit/config/client.rb', line 220

def get_boolean(item_key, default: nil, config: nil)
  typed_get(item_key, default, config) { |v| !!v }
end

#get_json(item_key, default: nil, config: nil) ⇒ Object



224
225
226
# File 'lib/smplkit/config/client.rb', line 224

def get_json(item_key, default: nil, config: nil)
  typed_get(item_key, default, config) { |v| v }
end

#get_number(item_key, default: nil, config: nil) ⇒ Object



212
213
214
215
216
217
218
# File 'lib/smplkit/config/client.rb', line 212

def get_number(item_key, default: nil, config: nil)
  typed_get(item_key, default, config) do |v|
    v.is_a?(Numeric) ? v : Float(v)
  rescue StandardError
    default
  end
end

#get_or_create(config_id, parent: nil, name: nil, description: nil) ⇒ Object

Declare a configuration from code; return a live, dict-like view.

Idempotent — repeat calls with the same id return the same LiveConfigProxy instance. The first call queues a discovery payload (the config and any items declared via typed getters on the returned handle) for upload to POST /api/v1/configs/bulk on next flush. Unlike #get, this method does not raise NotFoundError when the id is absent — discovery handles that case.



193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/smplkit/config/client.rb', line 193

def get_or_create(config_id, parent: nil, name: nil, description: nil)
  parent_id =
    case parent
    when nil then nil
    when String then parent
    when LiveConfigProxy then parent.config_id
    else
      raise ArgumentError,
            "parent must be a String id or LiveConfigProxy; got #{parent.class.name}"
    end
  _observe_config_declaration(config_id, parent: parent_id, name: name, description: description)
  start unless @connected
  cached_proxy(config_id)
end

#get_string(item_key, default: nil, config: nil) ⇒ Object



208
209
210
# File 'lib/smplkit/config/client.rb', line 208

def get_string(item_key, default: nil, config: nil)
  typed_get(item_key, default, config) { |v| v.is_a?(String) ? v : v.to_s }
end

#live(config_key) ⇒ Object



228
229
230
231
232
# File 'lib/smplkit/config/client.rb', line 228

def live(config_key)
  start unless @connected

  cached_proxy(config_key)
end

#on_change(config_key = nil, &block) ⇒ Object

Raises:

  • (ArgumentError)


234
235
236
237
238
239
240
241
242
243
# File 'lib/smplkit/config/client.rb', line 234

def on_change(config_key = nil, &block)
  raise ArgumentError, "on_change requires a block" unless block

  if config_key.nil?
    @global_listeners << block
  else
    @key_listeners[config_key] << block
  end
  block
end

#on_change_item(config_key, item_key, &block) ⇒ Object

Raises:

  • (ArgumentError)


245
246
247
248
249
250
# File 'lib/smplkit/config/client.rb', line 245

def on_change_item(config_key, item_key, &block)
  raise ArgumentError, "on_change_item requires a block" unless block

  @item_listeners[config_key][item_key.to_s] << block
  block
end

#refreshObject



252
253
254
255
256
257
258
# File 'lib/smplkit/config/client.rb', line 252

def refresh
  @lock.synchronize do
    @snapshots.clear
    @raw_chains.clear
  end
  fire_change_listeners_all("manual")
end

#startObject



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/smplkit/config/client.rb', line 158

def start
  return if @connected

  @environment = @parent._environment

  # Per ADR-037 §2.14: flush any buffered discovery declarations
  # BEFORE the lazy init touches the runtime so newly-declared
  # configs are visible to the very first +get+. The flush itself
  # swallows server/network failures.
  @manage&.config&.flush

  @ws_manager = @parent._ensure_ws
  @ws_manager.on("config_changed") { |data| handle_config_changed(data) }
  @ws_manager.on("config_deleted") { |data| handle_config_deleted(data) }
  @connected = true
end