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.



23
24
25
# File 'lib/cmdx/telemetry.rb', line 23

def initialize
  @registry = {}
end

Instance Attribute Details

#registryObject (readonly)

Returns the value of attribute registry.



21
22
23
# File 'lib/cmdx/telemetry.rb', line 21

def registry
  @registry
end

Instance Method Details

#countInteger

Returns total subscribers across all events.

Returns:

  • (Integer)

    total subscribers across all events



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

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)


101
102
103
104
105
# File 'lib/cmdx/telemetry.rb', line 101

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

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

#empty?Boolean

Returns:

  • (Boolean)


81
82
83
# File 'lib/cmdx/telemetry.rb', line 81

def empty?
  registry.empty?
end

#initialize_copy(source) ⇒ void

This method returns an undefined value.

Parameters:

  • source (Telemetry)

    registry to duplicate



29
30
31
# File 'lib/cmdx/telemetry.rb', line 29

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

#sizeInteger

Returns number of subscribed events.

Returns:

  • (Integer)

    number of subscribed events



86
87
88
# File 'lib/cmdx/telemetry.rb', line 86

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



42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/cmdx/telemetry.rb', line 42

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`



76
77
78
# File 'lib/cmdx/telemetry.rb', line 76

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



64
65
66
67
68
69
70
71
72
# File 'lib/cmdx/telemetry.rb', line 64

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