Class: Tasker::HandlerFactory
- Inherits:
-
Registry::BaseRegistry
- Object
- Registry::BaseRegistry
- Tasker::HandlerFactory
- Includes:
- Singleton
- Defined in:
- lib/tasker/handler_factory.rb
Overview
Factory for creating task handler instances
This class maintains a registry of task handlers by name and dependent system, providing namespaced handler organization while maintaining backward compatibility. It follows the Singleton pattern to ensure a single registry and uses thread-safe storage with modern registry patterns.
Constant Summary
Constants included from Concerns::StructuredLogging
Concerns::StructuredLogging::CORRELATION_ID_KEY
Instance Attribute Summary collapse
-
#handler_classes ⇒ Concurrent::Hash
readonly
Thread-safe registered handler classes by dependent system and handler name.
-
#namespaces ⇒ Set
readonly
Set of registered namespaces for efficient enumeration.
Instance Method Summary collapse
-
#all_items ⇒ Hash
Get all registered handlers (required by BaseRegistry).
-
#clear! ⇒ Boolean
Clear all registered handlers (required by BaseRegistry).
-
#clear_all! ⇒ Boolean
Clear all registered handlers (for testing).
-
#get(name, namespace_name: :default, version: '0.1.0') ⇒ Object
Get a task handler instance by name and optional dependent system.
-
#initialize ⇒ HandlerFactory
constructor
Initialize a new handler factory.
-
#list_handlers(namespace: nil) ⇒ Hash
List handlers, optionally filtered by namespace.
-
#register(name, class_or_class_name, namespace_name: :default, version: '0.1.0', **options) ⇒ Boolean
Register a task handler class with a name and optional dependent system.
-
#registered_namespaces ⇒ Array<Symbol>
Get list of all registered namespaces.
-
#stats ⇒ Hash
Get comprehensive registry statistics.
Methods inherited from Registry::BaseRegistry
#base_stats, #health_check, #healthy?, #log_registration, #log_registry_error, #log_registry_operation, #log_unregistration, #log_validation_failure, #thread_safe_operation, #validate_registration_params!
Methods included from Concerns::StructuredLogging
#correlation_id, #correlation_id=, #log_exception, #log_orchestration_event, #log_performance_event, #log_step_event, #log_structured, #log_task_event, #with_correlation_id
Constructor Details
#initialize ⇒ HandlerFactory
Initialize a new handler factory
28 29 30 31 32 33 |
# File 'lib/tasker/handler_factory.rb', line 28 def initialize super @handler_classes = Concurrent::Hash.new @namespaces = Set.new([:default]) log_registry_operation('initialized', namespaces: @namespaces.to_a) end |
Instance Attribute Details
#handler_classes ⇒ Concurrent::Hash (readonly)
Returns Thread-safe registered handler classes by dependent system and handler name.
20 21 22 |
# File 'lib/tasker/handler_factory.rb', line 20 def handler_classes @handler_classes end |
#namespaces ⇒ Set (readonly)
Returns Set of registered namespaces for efficient enumeration.
23 24 25 |
# File 'lib/tasker/handler_factory.rb', line 23 def namespaces @namespaces end |
Instance Method Details
#all_items ⇒ Hash
Get all registered handlers (required by BaseRegistry)
161 162 163 |
# File 'lib/tasker/handler_factory.rb', line 161 def all_items @handler_classes.dup end |
#clear! ⇒ Boolean
Clear all registered handlers (required by BaseRegistry)
168 169 170 |
# File 'lib/tasker/handler_factory.rb', line 168 def clear! clear_all! end |
#clear_all! ⇒ Boolean
Clear all registered handlers (for testing)
175 176 177 178 179 180 181 182 |
# File 'lib/tasker/handler_factory.rb', line 175 def clear_all! thread_safe_operation do @handler_classes.clear @namespaces = Set.new([:default]) log_registry_operation('cleared_all') true end end |
#get(name, namespace_name: :default, version: '0.1.0') ⇒ Object
Get a task handler instance by name and optional dependent system
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/tasker/handler_factory.rb', line 42 def get(name, namespace_name: :default, version: '0.1.0') namespace_name = namespace_name.to_sym name_sym = name.to_sym # Find the handler class within the mutex lock handler_class = thread_safe_operation do # Direct namespace lookup - allows same name in different systems handler_class = @handler_classes.dig(namespace_name, name_sym, version) raise_handler_not_found(name, namespace_name, version) unless handler_class log_registry_operation('handler_retrieved', entity_type: 'task_handler', entity_id: "#{namespace_name}/#{name_sym}/#{version}", handler_class: handler_class.is_a?(Class) ? handler_class.name : handler_class) handler_class end # Instantiate the handler OUTSIDE the mutex lock to avoid recursive locking # when ConfiguredTask handlers try to register themselves during instantiation instantiate_handler(handler_class) end |
#list_handlers(namespace: nil) ⇒ Hash
List handlers, optionally filtered by namespace
131 132 133 134 135 136 137 |
# File 'lib/tasker/handler_factory.rb', line 131 def list_handlers(namespace: nil) if namespace @handler_classes[namespace.to_sym] || Concurrent::Hash.new else @handler_classes.dup end end |
#register(name, class_or_class_name, namespace_name: :default, version: '0.1.0', **options) ⇒ Boolean
Register a task handler class with a name and optional dependent system
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/tasker/handler_factory.rb', line 76 def register(name, class_or_class_name, namespace_name: :default, version: '0.1.0', **) name_sym = name.to_sym namespace_name = namespace_name.to_sym replace = .fetch(:replace, false) thread_safe_operation do # Validate custom event configuration BEFORE modifying registry state # This ensures atomic registration - either fully succeeds or fully fails normalized_class = normalize_class_name(class_or_class_name) # Validate handler interface using unified validator begin Registry::InterfaceValidator.validate_handler!(normalized_class.is_a?(Class) ? normalized_class : normalized_class.constantize) rescue ArgumentError => e log_validation_failure('task_handler', "#{namespace_name}/#{name_sym}/#{version}", e.) raise end discover_and_register_custom_events(class_or_class_name) # Initialize nested hash structure @handler_classes[namespace_name] ||= Concurrent::Hash.new @handler_classes[namespace_name][name_sym] ||= Concurrent::Hash.new # Check for existing handler entity_id = "#{namespace_name}/#{name_sym}/#{version}" if @handler_classes[namespace_name][name_sym].key?(version) && !replace raise ArgumentError, "Handler '#{name_sym}' already registered in namespace '#{namespace_name}' version '#{version}'. Use replace: true to override." end # Log replacement if needed if @handler_classes[namespace_name][name_sym].key?(version) existing_class = @handler_classes[namespace_name][name_sym][version] log_unregistration('task_handler', entity_id, existing_class.is_a?(Class) ? existing_class : existing_class.constantize) end # Register handler @handler_classes[namespace_name][name_sym][version] = normalized_class @namespaces.add(namespace_name) # Log successful registration log_registration('task_handler', entity_id, normalized_class.is_a?(Class) ? normalized_class : normalized_class.constantize, { namespace_name: namespace_name, version: version, ** }) true end end |
#registered_namespaces ⇒ Array<Symbol>
Get list of all registered namespaces
142 143 144 |
# File 'lib/tasker/handler_factory.rb', line 142 def registered_namespaces @namespaces.to_a end |
#stats ⇒ Hash
Get comprehensive registry statistics
149 150 151 152 153 154 155 156 |
# File 'lib/tasker/handler_factory.rb', line 149 def stats base_stats.merge( total_namespaces: @namespaces.size, total_handlers: count_total_handlers, handlers_by_namespace: count_handlers_by_namespace, versions_by_namespace: count_versions_by_namespace ) end |