Class: BreakerMachines::DSL::CircuitBuilder

Inherits:
Object
  • Object
show all
Defined in:
lib/breaker_machines/dsl.rb

Overview

DSL builder for configuring circuit breakers with a fluent interface

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeCircuitBuilder

Returns a new instance of CircuitBuilder.



265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
# File 'lib/breaker_machines/dsl.rb', line 265

def initialize
  @config = {
    failure_threshold: 5,
    failure_window: 60.seconds,
    success_threshold: 1,
    timeout: nil,
    reset_timeout: 60.seconds,
    half_open_calls: 1,
    exceptions: [StandardError],
    storage: nil,
    metrics: nil,
    fallback: nil,
    on_open: nil,
    on_close: nil,
    on_half_open: nil,
    on_reject: nil,
    notifications: [],
    fiber_safe: BreakerMachines.config.fiber_safe
  }
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



263
264
265
# File 'lib/breaker_machines/dsl.rb', line 263

def config
  @config
end

Instance Method Details

#backends(*backend_list) ⇒ Object

Configure multiple backends



393
394
395
# File 'lib/breaker_machines/dsl.rb', line 393

def backends(*backend_list)
  @config[:backends] = backend_list.flatten
end

#fallback(value = nil, &block) ⇒ Object

Raises:

  • (ArgumentError)


352
353
354
355
356
357
358
359
360
361
362
363
364
# File 'lib/breaker_machines/dsl.rb', line 352

def fallback(value = nil, &block)
  raise ArgumentError, 'Fallback requires either a value or a block' if value.nil? && !block_given?

  fallback_value = block || value

  if @config[:fallback].is_a?(Array)
    @config[:fallback] << fallback_value
  elsif @config[:fallback]
    @config[:fallback] = [@config[:fallback], fallback_value]
  else
    @config[:fallback] = fallback_value
  end
end

#fiber_safe(enabled: true) ⇒ Object



416
417
418
# File 'lib/breaker_machines/dsl.rb', line 416

def fiber_safe(enabled: true)
  @config[:fiber_safe] = enabled
end

#half_open_requests(count) ⇒ Object



326
327
328
329
# File 'lib/breaker_machines/dsl.rb', line 326

def half_open_requests(count)
  validate_positive_integer!(:half_open_requests, count)
  @config[:half_open_calls] = count
end

#handle(*exceptions) ⇒ Object



412
413
414
# File 'lib/breaker_machines/dsl.rb', line 412

def handle(*exceptions)
  @config[:exceptions] = exceptions
end

#hedgedObject

Configure hedged requests



383
384
385
386
387
388
389
390
# File 'lib/breaker_machines/dsl.rb', line 383

def hedged(&)
  if block_given?
    hedged_builder = HedgedBuilder.new(@config)
    hedged_builder.instance_eval(&)
  else
    @config[:hedged_requests] = true
  end
end

#max_concurrent(limit) ⇒ Object



420
421
422
423
# File 'lib/breaker_machines/dsl.rb', line 420

def max_concurrent(limit)
  validate_positive_integer!(:max_concurrent, limit)
  @config[:max_concurrent] = limit
end

#metrics(recorder = nil, &block) ⇒ Object



348
349
350
# File 'lib/breaker_machines/dsl.rb', line 348

def metrics(recorder = nil, &block)
  @config[:metrics] = recorder || block
end

#notify(service, url = nil, events: %i[open close],, **options) ⇒ Object



402
403
404
405
406
407
408
409
410
# File 'lib/breaker_machines/dsl.rb', line 402

def notify(service, url = nil, events: %i[open close], **options)
  notification = {
    via: service,
    url: url,
    events: Array(events),
    options: options
  }
  @config[:notifications] << notification
end

#on_close(&block) ⇒ Object



370
371
372
# File 'lib/breaker_machines/dsl.rb', line 370

def on_close(&block)
  @config[:on_close] = block
end

#on_half_open(&block) ⇒ Object



374
375
376
# File 'lib/breaker_machines/dsl.rb', line 374

def on_half_open(&block)
  @config[:on_half_open] = block
end

#on_open(&block) ⇒ Object



366
367
368
# File 'lib/breaker_machines/dsl.rb', line 366

def on_open(&block)
  @config[:on_open] = block
end

#on_reject(&block) ⇒ Object



378
379
380
# File 'lib/breaker_machines/dsl.rb', line 378

def on_reject(&block)
  @config[:on_reject] = block
end

#parallel_calls(count, timeout: nil) ⇒ Object

Advanced features



426
427
428
429
# File 'lib/breaker_machines/dsl.rb', line 426

def parallel_calls(count, timeout: nil)
  @config[:parallel_calls] = count
  @config[:parallel_timeout] = timeout
end

#parallel_fallback(fallback_list) ⇒ Object

Configure parallel fallback execution



398
399
400
# File 'lib/breaker_machines/dsl.rb', line 398

def parallel_fallback(fallback_list)
  @config[:fallback] = ParallelFallbackWrapper.new(fallback_list)
end

#reset_after(duration, jitter: nil) ⇒ Object



311
312
313
314
315
316
317
318
319
# File 'lib/breaker_machines/dsl.rb', line 311

def reset_after(duration, jitter: nil)
  validate_positive_integer!(:duration, duration.to_i)
  @config[:reset_timeout] = duration.to_i

  return unless jitter

  validate_jitter!(jitter)
  @config[:reset_timeout_jitter] = jitter
end

#storage(backend) ⇒ Object



331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
# File 'lib/breaker_machines/dsl.rb', line 331

def storage(backend, **)
  @config[:storage] = case backend
                      when :memory
                        Storage::Memory.new(**)
                      when :bucket_memory
                        Storage::BucketMemory.new(**)
                      when :cache
                        Storage::Cache.new(**)
                      when :redis
                        Storage::Redis.new(**)
                      when Class
                        backend.new(**)
                      else
                        backend
                      end
end

#threshold(failures: nil, failure_rate: nil, minimum_calls: nil, within: 60.seconds, successes: nil) ⇒ Object



286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
# File 'lib/breaker_machines/dsl.rb', line 286

def threshold(failures: nil, failure_rate: nil, minimum_calls: nil, within: 60.seconds, successes: nil)
  if failure_rate
    # Rate-based threshold
    validate_failure_rate!(failure_rate)
    validate_positive_integer!(:minimum_calls, minimum_calls) if minimum_calls

    @config[:failure_rate] = failure_rate
    @config[:minimum_calls] = minimum_calls || 5
    @config[:use_rate_threshold] = true
  elsif failures
    # Absolute count threshold (existing behavior)
    validate_positive_integer!(:failures, failures)
    @config[:failure_threshold] = failures
    @config[:use_rate_threshold] = false
  end

  validate_positive_integer!(:within, within.to_i)
  @config[:failure_window] = within.to_i

  return unless successes

  validate_positive_integer!(:successes, successes)
  @config[:success_threshold] = successes
end

#timeout(duration) ⇒ Object



321
322
323
324
# File 'lib/breaker_machines/dsl.rb', line 321

def timeout(duration)
  validate_non_negative_integer!(:timeout, duration.to_i)
  @config[:timeout] = duration.to_i
end