Class: ToggleCraft::Client
- Inherits:
-
Object
- Object
- ToggleCraft::Client
- Defined in:
- lib/togglecraft/client.rb
Overview
Main ToggleCraft client class Provides the primary interface for feature flag evaluation with real-time updates
Instance Attribute Summary collapse
-
#config ⇒ Object
readonly
Returns the value of attribute config.
-
#ready ⇒ Object
readonly
Returns the value of attribute ready.
Instance Method Summary collapse
-
#all_flag_keys ⇒ Array<String>
Get all flag keys.
-
#connect ⇒ void
Connect to SSE server.
-
#connected? ⇒ Boolean
Check if connected to SSE server.
-
#destroy ⇒ void
Clean up resources.
-
#disconnect ⇒ void
Disconnect from SSE server.
-
#enabled?(flag_key, context = {}, default: false) ⇒ Boolean
Evaluate a boolean flag.
-
#evaluate(flag_key, context = {}, default: false) ⇒ Object
Evaluate any flag type.
-
#flag_metadata(flag_key) ⇒ Hash?
Get flag metadata.
-
#handle_connect ⇒ void
Handle SSE connection event.
-
#handle_disconnect ⇒ void
Handle SSE disconnection event.
-
#handle_error(error) ⇒ void
Handle error.
-
#handle_flags_update(payload) ⇒ void
Handle flags update from SSE.
-
#has_flag?(flag_key) ⇒ Boolean
Check if flag exists.
-
#in_percentage?(flag_key, context = {}, default: false) ⇒ Boolean
Check if in percentage rollout.
-
#initialize(sdk_key:, **options) ⇒ Client
constructor
Initialize the ToggleCraft client.
-
#off(event, callable = nil) ⇒ void
Remove event listener.
-
#on(event, &block) ⇒ void
Add event listener.
-
#once(event, &block) ⇒ void
Add one-time event listener.
-
#percentage(flag_key) ⇒ Integer?
Get current percentage for a flag.
-
#ready? ⇒ Boolean
Check if client is ready.
-
#reconnect ⇒ void
Reconnect to SSE server.
-
#variant(flag_key, context = {}, default: nil) ⇒ String?
Get variant for multivariate flag.
-
#wait_for_ready(timeout: 5) ⇒ void
Wait for client to be ready.
Constructor Details
#initialize(sdk_key:, **options) ⇒ Client
Initialize the ToggleCraft client
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/togglecraft/client.rb', line 12 def initialize(sdk_key:, **) raise ArgumentError, 'sdk_key is required' if sdk_key.nil? || sdk_key.empty? @config = { url: 'https://sse.togglecraft.io', enable_cache: true, cache_adapter: :memory, cache_ttl: 300, # 5 minutes reconnect_interval: 1, max_reconnect_interval: 30, max_reconnect_attempts: 10, slow_reconnect_interval: 60, share_connection: true, debug: false, enable_rollout_stage_polling: true, rollout_stage_check_interval: 60, fetch_jitter: 1500, # milliseconds api_domain: 'https://togglecraft.io', heartbeat_domain: 'https://togglecraft.io' # Default heartbeat domain }.merge().merge(sdk_key: sdk_key) # Initialize components @evaluator = Evaluator.new @cache = @config[:enable_cache] ? Cache.new(adapter: @config[:cache_adapter], ttl: @config[:cache_ttl]) : nil # State @ready = Concurrent::AtomicBoolean.new(false) @flags = Concurrent::Map.new @current_version = Concurrent::AtomicReference.new(nil) @project_key = Concurrent::AtomicReference.new(nil) @environment_key = Concurrent::AtomicReference.new(nil) @fetch_in_progress = Concurrent::AtomicBoolean.new(false) # Event listeners @listeners = Concurrent::Map.new @listeners[:ready] = [] @listeners[:flags_updated] = [] @listeners[:error] = [] @listeners[:disconnected] = [] @listeners[:reconnecting] = [] @listeners[:rollout_stage_changed] = [] @listeners_mutex = Mutex.new # Rollout stage polling @rollout_stage_percentages = {} @rollout_stage_timer = nil # Initialize connection initialize_connection # Enable debug on connection pool if debug is enabled ConnectionPool.set_debug(true) if @config[:debug] && @config[:share_connection] end |
Instance Attribute Details
#config ⇒ Object (readonly)
Returns the value of attribute config.
7 8 9 |
# File 'lib/togglecraft/client.rb', line 7 def config @config end |
#ready ⇒ Object (readonly)
Returns the value of attribute ready.
7 8 9 |
# File 'lib/togglecraft/client.rb', line 7 def ready @ready end |
Instance Method Details
#all_flag_keys ⇒ Array<String>
Get all flag keys
199 200 201 |
# File 'lib/togglecraft/client.rb', line 199 def all_flag_keys @evaluator.flag_keys end |
#connect ⇒ void
This method returns an undefined value.
Connect to SSE server
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/togglecraft/client.rb', line 68 def connect # Try to load from cache first if @cache cached_flags = @cache.all_flags if cached_flags.any? @flags.clear cached_flags.each { |k, v| @flags[k] = v } @evaluator.update_flags(cached_flags) log 'Loaded flags from cache' end end # Connect to SSE server if @using_shared_connection @connection.connect(self) else @connection.connect end log 'Connected to ToggleCraft' rescue StandardError => e handle_error(e) raise end |
#connected? ⇒ Boolean
Check if connected to SSE server
117 118 119 |
# File 'lib/togglecraft/client.rb', line 117 def connected? @connection&.connected? || false end |
#destroy ⇒ void
This method returns an undefined value.
Clean up resources
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 |
# File 'lib/togglecraft/client.rb', line 256 def destroy log 'Destroying client instance' stop_rollout_stage_polling # Handle cleanup based on connection type if @using_shared_connection && @connection @connection.remove_client(self) elsif @connection disconnect end @cache&.destroy # Clear all listeners @listeners_mutex.synchronize do @listeners.each_key { |key| @listeners[key] = [] } end @connection = nil @flags.clear @ready.make_false end |
#disconnect ⇒ void
This method returns an undefined value.
Disconnect from SSE server
95 96 97 98 99 100 |
# File 'lib/togglecraft/client.rb', line 95 def disconnect log 'Disconnecting from SSE' stop_rollout_stage_polling @connection.disconnect @ready.make_false end |
#enabled?(flag_key, context = {}, default: false) ⇒ Boolean
Evaluate a boolean flag
144 145 146 147 148 149 150 151 |
# File 'lib/togglecraft/client.rb', line 144 def enabled?(flag_key, context = {}, default: false) result = @evaluator.evaluate_boolean(flag_key, context, default) # Cache the result cache_evaluation(flag_key, context, result) if @cache && context result end |
#evaluate(flag_key, context = {}, default: false) ⇒ Object
Evaluate any flag type
193 194 195 |
# File 'lib/togglecraft/client.rb', line 193 def evaluate(flag_key, context = {}, default: false) @evaluator.evaluate(flag_key, context, default) end |
#flag_metadata(flag_key) ⇒ Hash?
Get flag metadata
206 207 208 |
# File 'lib/togglecraft/client.rb', line 206 def (flag_key) @evaluator.(flag_key) end |
#handle_connect ⇒ void
This method returns an undefined value.
Handle SSE connection event
282 283 284 |
# File 'lib/togglecraft/client.rb', line 282 def handle_connect log 'SSE connected' end |
#handle_disconnect ⇒ void
This method returns an undefined value.
Handle SSE disconnection event
288 289 290 291 |
# File 'lib/togglecraft/client.rb', line 288 def handle_disconnect @ready.make_false emit(:disconnected) end |
#handle_error(error) ⇒ void
This method returns an undefined value.
Handle error
296 297 298 299 |
# File 'lib/togglecraft/client.rb', line 296 def handle_error(error) log "Error: #{error.message}" emit(:error, error) end |
#handle_flags_update(payload) ⇒ void
This method returns an undefined value.
Handle flags update from SSE
304 305 306 307 308 309 310 311 312 313 314 315 |
# File 'lib/togglecraft/client.rb', line 304 def handle_flags_update(payload) log "Received message: #{payload}" # Handle version update notification if payload[:type] == 'version_update' handle_version_update(payload) return end # Handle full flags payload process_flags_payload(payload) if payload[:flags] end |
#has_flag?(flag_key) ⇒ Boolean
Check if flag exists
213 214 215 |
# File 'lib/togglecraft/client.rb', line 213 def has_flag?(flag_key) @evaluator.has_flag?(flag_key) end |
#in_percentage?(flag_key, context = {}, default: false) ⇒ Boolean
Check if in percentage rollout
172 173 174 175 176 177 178 179 |
# File 'lib/togglecraft/client.rb', line 172 def in_percentage?(flag_key, context = {}, default: false) result = @evaluator.evaluate_percentage(flag_key, context, default) # Cache the result cache_evaluation(flag_key, context, result) if @cache && context result end |
#off(event, callable = nil) ⇒ void
This method returns an undefined value.
Remove event listener
244 245 246 247 248 249 250 251 252 |
# File 'lib/togglecraft/client.rb', line 244 def off(event, callable = nil) @listeners_mutex.synchronize do if callable @listeners[event]&.delete(callable) else @listeners[event] = [] end end end |
#on(event, &block) ⇒ void
This method returns an undefined value.
Add event listener
221 222 223 224 225 226 |
# File 'lib/togglecraft/client.rb', line 221 def on(event, &block) @listeners_mutex.synchronize do @listeners[event] ||= [] @listeners[event] << block end end |
#once(event, &block) ⇒ void
This method returns an undefined value.
Add one-time event listener
232 233 234 235 236 237 238 |
# File 'lib/togglecraft/client.rb', line 232 def once(event, &block) wrapper = lambda do |*args| block.call(*args) off(event, wrapper) end on(event, &wrapper) end |
#percentage(flag_key) ⇒ Integer?
Get current percentage for a flag
184 185 186 |
# File 'lib/togglecraft/client.rb', line 184 def percentage(flag_key) @evaluator.percentage(flag_key) end |
#ready? ⇒ Boolean
Check if client is ready
111 112 113 |
# File 'lib/togglecraft/client.rb', line 111 def ready? @ready.value end |
#reconnect ⇒ void
This method returns an undefined value.
Reconnect to SSE server
104 105 106 107 |
# File 'lib/togglecraft/client.rb', line 104 def reconnect emit(:reconnecting) @connection.reconnect end |
#variant(flag_key, context = {}, default: nil) ⇒ String?
Get variant for multivariate flag
158 159 160 161 162 163 164 165 |
# File 'lib/togglecraft/client.rb', line 158 def variant(flag_key, context = {}, default: nil) result = @evaluator.evaluate_multivariate(flag_key, context, default) # Cache the result cache_evaluation(flag_key, context, result) if @cache && context result end |
#wait_for_ready(timeout: 5) ⇒ void
This method returns an undefined value.
Wait for client to be ready
125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/togglecraft/client.rb', line 125 def wait_for_ready(timeout: 5) return if ready? ready_latch = Concurrent::CountDownLatch.new(1) ready_handler = -> { ready_latch.count_down } once(:ready, &ready_handler) return if ready_latch.wait(timeout) off(:ready, ready_handler) raise Timeout::Error, 'Timeout waiting for client to be ready' end |