Class: CMDx::Telemetry

Inherits:
Object
  • Object
show all
Defined in:
lib/cmdx/telemetry.rb

Overview

Pub/sub for runtime lifecycle events (see EVENTS). Subscribers are callables receiving an Event data object. Runtime emits events only when subscribers are registered so telemetry has zero cost when unused.

Defined Under Namespace

Classes: Event

Constant Summary collapse

EVENTS =

Lifecycle event names Runtime emits.

%i[
  task_started
  task_deprecated
  task_retried
  task_rolled_back
  task_executed
].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeTelemetry

Returns a new instance of Telemetry.



37
38
39
# File 'lib/cmdx/telemetry.rb', line 37

def initialize
  @registry = {}
end

Instance Attribute Details

#registryObject (readonly)

Returns the value of attribute registry.



35
36
37
# File 'lib/cmdx/telemetry.rb', line 35

def registry
  @registry
end

Instance Method Details

#countInteger

Returns total subscribers across all events.

Returns:

  • (Integer)

    total subscribers across all events



105
106
107
# File 'lib/cmdx/telemetry.rb', line 105

def count
  registry.each_value.sum(&:size)
end

#emit(event, payload) ⇒ void

This method returns an undefined value.

Dispatches payload to every subscriber of event. No-op when there are no subscribers.

Parameters:

  • event (Symbol)
  • payload (Event)


115
116
117
118
119
# File 'lib/cmdx/telemetry.rb', line 115

def emit(event, payload)
  return unless (subscribers = registry[event])

  subscribers.each { |s| s.call(payload) }
end

#empty?Boolean

Returns:

  • (Boolean)


95
96
97
# File 'lib/cmdx/telemetry.rb', line 95

def empty?
  registry.empty?
end

#initialize_copy(source) ⇒ void

This method returns an undefined value.

Parameters:

  • source (Telemetry)

    registry to duplicate



43
44
45
# File 'lib/cmdx/telemetry.rb', line 43

def initialize_copy(source)
  @registry = source.registry.transform_values(&:dup)
end

#sizeInteger

Returns number of subscribed events.

Returns:

  • (Integer)

    number of subscribed events



100
101
102
# File 'lib/cmdx/telemetry.rb', line 100

def size
  registry.size
end

#subscribe(event, callable = nil, &block) {|evt| ... } ⇒ Telemetry

Registers a subscriber for event.

Parameters:

  • event (Symbol)

    one of EVENTS

  • callable (#call, nil) (defaults to: nil)

    subscriber callable; pass either this or a block

  • block (#call, nil)

    subscriber when callable is omitted

Yield Parameters:

Returns:

Raises:

  • (ArgumentError)

    when both callable and a block are provided, when the subscriber isn't callable, or when event is unknown



56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/cmdx/telemetry.rb', line 56

def subscribe(event, callable = nil, &block)
  subscriber = callable || block

  if callable && block
    raise ArgumentError, "provide either a callable or a block, not both"
  elsif !subscriber.respond_to?(:call)
    raise ArgumentError, "subscriber must respond to #call"
  elsif !EVENTS.include?(event)
    raise ArgumentError, "unknown event #{event.inspect}, must be one of #{EVENTS.join(', ')}"
  end

  (registry[event] ||= []) << subscriber
  self
end

#subscribed?(event) ⇒ Boolean

Returns true when at least one subscriber exists for event.

Parameters:

  • event (Symbol)

Returns:

  • (Boolean)

    true when at least one subscriber exists for event



90
91
92
# File 'lib/cmdx/telemetry.rb', line 90

def subscribed?(event)
  registry.key?(event)
end

#unsubscribe(event, callable) ⇒ Telemetry

Removes a previously registered subscriber. Drops the event entry entirely when no subscribers remain.

Parameters:

  • event (Symbol)

    one of EVENTS

  • callable (#call)

    the subscriber to remove

Returns:

Raises:

  • (ArgumentError)

    when event is unknown



78
79
80
81
82
83
84
85
86
# File 'lib/cmdx/telemetry.rb', line 78

def unsubscribe(event, callable)
  raise ArgumentError, "unknown event #{event.inspect}, must be one of #{EVENTS.join(', ')}" unless EVENTS.include?(event)

  return self unless subscribed?(event)

  registry[event].delete(callable)
  registry.delete(event) if registry[event].empty?
  self
end