Module: Takagi::Registry::Base

Overview

Thread-safe base module for implementing registries.

Provides a consistent API and thread-safety for all registry implementations. Designed to support the plugin system by allowing safe concurrent access.

Examples:

Basic usage with class methods

class MyRegistry
  extend Takagi::Registry::Base
end

MyRegistry.register(:foo, SomeClass)
MyRegistry.get(:foo)  # => SomeClass
MyRegistry.registered?(:foo)  # => true

With validation

class MyRegistry
  extend Takagi::Registry::Base

  def self.validate_entry!(key, value, **)
    raise ArgumentError, "Invalid value" unless value.respond_to?(:call)
  end
end

With custom storage structure

class MyRegistry
  extend Takagi::Registry::Base

  def self.store_entry(key, value, **)
    registry[key] = { klass: value, options:  }
  end
end

Defined Under Namespace

Classes: AlreadyRegisteredError, NotFoundError, ValidationError

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.extended(base) ⇒ Object



46
47
48
49
# File 'lib/takagi/registry/base.rb', line 46

def self.extended(base)
  base.instance_variable_set(:@registry, {})
  base.instance_variable_set(:@mutex, Mutex.new)
end

Instance Method Details

#[](key) ⇒ Object?

Retrieve an entry from the registry (returns nil if not found)

Examples:

transport = MyRegistry[:udp]

Parameters:

  • key (Object)

    The key to look up

Returns:

  • (Object, nil)

    The registered value or nil



110
111
112
# File 'lib/takagi/registry/base.rb', line 110

def [](key)
  @mutex.synchronize { fetch_entry(key) }
end

#clear!void

This method returns an undefined value.

Clear all registrations

Primarily useful for testing. Thread-safe.

Examples:

MyRegistry.clear!


179
180
181
182
183
184
# File 'lib/takagi/registry/base.rb', line 179

def clear!
  @mutex.synchronize do
    before_clear if respond_to?(:before_clear, true)
    registry.clear
  end
end

#countInteger Also known as: size

Get count of registered entries

Examples:

MyRegistry.count  # => 3

Returns:

  • (Integer)

    Number of registered entries



192
193
194
# File 'lib/takagi/registry/base.rb', line 192

def count
  @mutex.synchronize { registry.size }
end

#each {|key, value| ... } ⇒ Enumerator

Iterate over all entries

Examples:

MyRegistry.each do |key, value|
  puts "#{key}: #{value}"
end

Yields:

  • (key, value)

    Each key-value pair

Returns:

  • (Enumerator)

    If no block given



216
217
218
219
220
221
222
# File 'lib/takagi/registry/base.rb', line 216

def each(&block)
  return enum_for(:each) unless block_given?

  # Get snapshot to avoid holding lock during iteration
  snapshot = @mutex.synchronize { registry.dup }
  snapshot.each(&block)
end

#empty?Boolean

Check if registry is empty

Examples:

MyRegistry.empty?  # => false

Returns:

  • (Boolean)

    true if no entries registered



203
204
205
# File 'lib/takagi/registry/base.rb', line 203

def empty?
  @mutex.synchronize { registry.empty? }
end

#entriesHash

Get all entries as a hash

Examples:

MyRegistry.entries  # => { udp: UdpTransport, tcp: TcpTransport }

Returns:

  • (Hash)

    Copy of the registry



142
143
144
# File 'lib/takagi/registry/base.rb', line 142

def entries
  @mutex.synchronize { registry.dup }
end

#get(key) ⇒ Object

Retrieve an entry from the registry

Examples:

transport = MyRegistry.get(:udp)

Parameters:

  • key (Object)

    The key to look up

Returns:

  • (Object)

    The registered value

Raises:



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/takagi/registry/base.rb', line 87

def get(key)
  value = self[key]
  unless value
    # Enhanced error with suggestions
    available = keys
    error = Errors::RegistryError.not_found(
      self.class.name,
      key,
      available
    )
    raise NotFoundError, error.message
  end

  value
end

#keysArray Also known as: all

Get all registered keys

Examples:

MyRegistry.keys  # => [:udp, :tcp, :dtls]

Returns:

  • (Array)

    List of all keys



131
132
133
# File 'lib/takagi/registry/base.rb', line 131

def keys
  @mutex.synchronize { registry.keys.dup }
end

#metadata_for(key) ⇒ Hash?

Get metadata for a registered entry

Examples:

MyRegistry.(:udp)  # => { rfc: 'RFC 7252' }

Parameters:

  • key (Object)

    The key to look up

Returns:

  • (Hash, nil)

    Metadata hash or nil if not found



153
154
155
# File 'lib/takagi/registry/base.rb', line 153

def (key)
  @mutex.synchronize { (key) }
end

#register(key, value, overwrite: false, **metadata) ⇒ void

This method returns an undefined value.

Register a new entry in the registry

Examples:

MyRegistry.register(:udp, UdpTransport, rfc: 'RFC 7252')

Parameters:

  • key (Object)

    Unique identifier for the entry

  • value (Object)

    The value to register

  • metadata (Hash)

    Optional metadata to store with the entry

  • overwrite (Boolean) (defaults to: false)

    Whether to allow overwriting existing entries

Raises:



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/takagi/registry/base.rb', line 63

def register(key, value, overwrite: false, **)
  validate_entry!(key, value, **) if respond_to?(:validate_entry!, true)

  @mutex.synchronize do
    if registry.key?(key) && !overwrite
      # Enhanced error with suggestions
      error = Errors::RegistryError.already_registered(self.class.name, key)
      raise AlreadyRegisteredError, error.message
    end

    store_entry(key, value, **)
  end

  after_register(key, value, **) if respond_to?(:after_register, true)
end

#registered?(key) ⇒ Boolean

Check if a key is registered

Examples:

MyRegistry.registered?(:udp)  # => true

Parameters:

  • key (Object)

    The key to check

Returns:

  • (Boolean)

    true if registered



121
122
123
# File 'lib/takagi/registry/base.rb', line 121

def registered?(key)
  @mutex.synchronize { registry.key?(key) }
end

#unregister(key) ⇒ Object?

Unregister an entry

Examples:

MyRegistry.unregister(:udp)

Parameters:

  • key (Object)

    The key to remove

Returns:

  • (Object, nil)

    The removed value or nil if not found



164
165
166
167
168
169
# File 'lib/takagi/registry/base.rb', line 164

def unregister(key)
  @mutex.synchronize do
    before_unregister(key) if respond_to?(:before_unregister, true)
    registry.delete(key)
  end
end