Class: Yes::Core::Configuration
- Inherits:
-
Object
- Object
- Yes::Core::Configuration
- Defined in:
- lib/yes/core/configuration.rb
Instance Attribute Summary collapse
-
#aggregate_shortcuts ⇒ Boolean
Enable aggregate shortcuts in Rails console (default: false).
-
#auth_adapter ⇒ #call?
Authentication adapter for API controllers.
-
#cerbos_commands_authorizer_include_metadata ⇒ Boolean
Whether to include metadata in Cerbos command authorizer responses.
-
#cerbos_principal_data_builder ⇒ #call
A callable that receives auth_data and returns a principal data hash for Cerbos (commands).
-
#cerbos_read_authorizer_actions ⇒ Array<String>
Default actions for Cerbos read authorizer.
-
#cerbos_read_authorizer_include_metadata ⇒ Boolean
Whether to include metadata in Cerbos read authorizer responses.
-
#cerbos_read_authorizer_principal_anonymous_id ⇒ String
Anonymous principal ID for Cerbos read authorizer.
-
#cerbos_read_authorizer_resource_id_prefix ⇒ String
Prefix for Cerbos read authorizer resource ids.
- #cerbos_read_principal_data_builder ⇒ Object
-
#cerbos_tls ⇒ Boolean
Whether to use TLS for Cerbos connections (default: true).
-
#cerbos_url ⇒ String
URL of the Cerbos server.
-
#command_notifier_classes ⇒ Array<Class>
Command notifier classes to instantiate for batch notifications.
-
#error_reporter ⇒ #call?
A callable error reporter responding to #call(error, context:).
-
#logger ⇒ Object
Logger instance.
-
#otl_tracer ⇒ Object?
OpenTelemetry tracer instance.
-
#payload_store_client ⇒ Object?
Payload store client for resolving large payload references.
-
#process_commands_inline ⇒ Boolean
Whether to process commands inline (synchronously) or via ActiveJob.
-
#raise_on_missing_handler_method ⇒ Boolean
Whether to raise on missing handler methods in aggregate state.
-
#service_name ⇒ String
Service name for telemetry and identification.
-
#service_version ⇒ String
Service version for telemetry.
-
#subscriptions_heartbeat_interval ⇒ Integer
Interval in seconds between heartbeat pings (default: 30).
-
#subscriptions_heartbeat_url ⇒ String?
URL for subscription heartbeat pings (default: nil, disables heartbeat).
-
#super_admin_check ⇒ #call
A callable that receives auth_data and returns boolean indicating super admin status.
Instance Method Summary collapse
-
#aggregate_class(context_name, aggregate_name, action_name, type) ⇒ Class?
Retrieve a registered class for a given aggregate, action, and type.
-
#all_read_model_class_names ⇒ Array<String>
Get all read model class names from registered aggregates.
-
#all_read_model_classes ⇒ Array<Class>
Get all read model classes (constantized).
-
#all_read_model_table_names ⇒ Array<String>
Get all read model table names.
-
#all_read_models_with_aggregate_classes ⇒ Array<Hash>
Get all read model classes with their associated aggregate classes.
-
#command_event_mapping(context_name, aggregate_name, command_name) ⇒ Array<Symbol, String>
Retrieve the event names associated with a specific command.
-
#command_event_mappings(context_name, aggregate_name) ⇒ Hash
Retrieve all command-to-event mappings for a specific aggregate.
-
#event_classes_for_command(context_name, aggregate_name, command_name) ⇒ Array<Class>
Retrieve the actual event classes associated with a specific command.
-
#guard_evaluator_class(context_name, aggregate_name, command_name) ⇒ Class?
Retrieve a guard evaluator class for a specific command.
-
#initialize ⇒ Configuration
constructor
Initializes a new configuration instance with nested hashes for class storage.
-
#list_aggregate_classes(context_name, aggregate_name) ⇒ Hash
List all registered classes for a specific aggregate in a context.
-
#list_all_registered_classes ⇒ Hash
List all registered classes across all aggregates and contexts.
-
#register_aggregate_authorizer_class(context_name, aggregate_name, klass) ⇒ Object
Register an aggregate authorizer class for a specific aggregate.
-
#register_aggregate_class(context_name, aggregate_name, action_name, type, klass) ⇒ Object
Register a class for a specific aggregate and type.
-
#register_command_authorizer_class(context_name, aggregate_name, command_name, klass) ⇒ Object
Register a command authorizer class for a specific aggregate.
-
#register_command_class(context_name, aggregate_name, command_name, klass) ⇒ Object
Register a command class for a specific aggregate.
-
#register_command_events(context_name, aggregate_name, command_name, event_names) ⇒ Object
Register the event(s) associated with a specific command.
-
#register_event_class(context_name, aggregate_name, event_name, klass) ⇒ Object
Register an event class for a specific aggregate.
-
#register_guard_evaluator_class(context_name, aggregate_name, command_name, klass) ⇒ Object
Register a guard evaluator class for a specific aggregate.
-
#register_read_model_class(context_name, aggregate_name, klass, draft: false) ⇒ Object
Register a read model class for a specific aggregate.
-
#register_read_model_filter_class(context_name, aggregate_name, klass) ⇒ Object
Register a read model filter class for a specific aggregate.
Constructor Details
#initialize ⇒ Configuration
Initializes a new configuration instance with nested hashes for class storage.
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/yes/core/configuration.rb', line 104 def initialize @registered_classes = Hash.new do |h, k| h[k] = Hash.new { |h2, k2| h2[k2] = {} } end @aggregate_shortcuts = false @super_admin_check = ->(_auth_data) { false } @cerbos_principal_data_builder = lambda { |auth_data| { id: auth_data[:identity_id], roles: [], attributes: {} } } @cerbos_url = ENV.fetch('CERBOS_URL', 'cerbos-cluster-ip-service:3593') @cerbos_tls = true @cerbos_commands_authorizer_include_metadata = false @cerbos_read_authorizer_include_metadata = false @cerbos_read_authorizer_actions = %w[read] @cerbos_read_authorizer_resource_id_prefix = 'read-' @cerbos_read_authorizer_principal_anonymous_id = 'anonymous' @logger = nil @error_reporter = nil @payload_store_client = nil @process_commands_inline = true @command_notifier_classes = [] @otl_tracer = nil @raise_on_missing_handler_method = defined?(Rails) ? Rails.env.local? : false @subscriptions_heartbeat_url = nil @subscriptions_heartbeat_interval = 30 @service_name = ENV.fetch('SERVICE_NAME', nil) @service_version = ENV.fetch('APP_VERSION', '') @auth_adapter = nil end |
Instance Attribute Details
#aggregate_shortcuts ⇒ Boolean
Returns Enable aggregate shortcuts in Rails console (default: false).
26 27 28 |
# File 'lib/yes/core/configuration.rb', line 26 def aggregate_shortcuts @aggregate_shortcuts end |
#auth_adapter ⇒ #call?
Returns Authentication adapter for API controllers. Must respond to #authenticate(request) (returns auth data hash, raises on failure), #verify_token(token) and #error_classes (returns array of error classes).
101 102 103 |
# File 'lib/yes/core/configuration.rb', line 101 def auth_adapter @auth_adapter end |
#cerbos_commands_authorizer_include_metadata ⇒ Boolean
Returns Whether to include metadata in Cerbos command authorizer responses.
49 50 51 |
# File 'lib/yes/core/configuration.rb', line 49 def @cerbos_commands_authorizer_include_metadata end |
#cerbos_principal_data_builder ⇒ #call
Returns A callable that receives auth_data and returns a principal data hash for Cerbos (commands).
32 33 34 |
# File 'lib/yes/core/configuration.rb', line 32 def cerbos_principal_data_builder @cerbos_principal_data_builder end |
#cerbos_read_authorizer_actions ⇒ Array<String>
Returns Default actions for Cerbos read authorizer.
55 56 57 |
# File 'lib/yes/core/configuration.rb', line 55 def @cerbos_read_authorizer_actions end |
#cerbos_read_authorizer_include_metadata ⇒ Boolean
Returns Whether to include metadata in Cerbos read authorizer responses.
52 53 54 |
# File 'lib/yes/core/configuration.rb', line 52 def @cerbos_read_authorizer_include_metadata end |
#cerbos_read_authorizer_principal_anonymous_id ⇒ String
Returns Anonymous principal ID for Cerbos read authorizer.
81 82 83 |
# File 'lib/yes/core/configuration.rb', line 81 def @cerbos_read_authorizer_principal_anonymous_id end |
#cerbos_read_authorizer_resource_id_prefix ⇒ String
Returns Prefix for Cerbos read authorizer resource ids.
58 59 60 |
# File 'lib/yes/core/configuration.rb', line 58 def @cerbos_read_authorizer_resource_id_prefix end |
#cerbos_read_principal_data_builder ⇒ Object
38 39 40 |
# File 'lib/yes/core/configuration.rb', line 38 def cerbos_read_principal_data_builder @cerbos_read_principal_data_builder || @cerbos_principal_data_builder end |
#cerbos_tls ⇒ Boolean
Returns Whether to use TLS for Cerbos connections (default: true).
46 47 48 |
# File 'lib/yes/core/configuration.rb', line 46 def cerbos_tls @cerbos_tls end |
#cerbos_url ⇒ String
Returns URL of the Cerbos server.
43 44 45 |
# File 'lib/yes/core/configuration.rb', line 43 def cerbos_url @cerbos_url end |
#command_notifier_classes ⇒ Array<Class>
Returns Command notifier classes to instantiate for batch notifications.
75 76 77 |
# File 'lib/yes/core/configuration.rb', line 75 def command_notifier_classes @command_notifier_classes end |
#error_reporter ⇒ #call?
Returns A callable error reporter responding to #call(error, context:). When nil, errors are only logged. Example: ->(error, context:) { Sentry.capture_exception(error, extra: context) }.
66 67 68 |
# File 'lib/yes/core/configuration.rb', line 66 def error_reporter @error_reporter end |
#logger ⇒ Object
Returns Logger instance.
61 62 63 |
# File 'lib/yes/core/configuration.rb', line 61 def logger @logger end |
#otl_tracer ⇒ Object?
Returns OpenTelemetry tracer instance. When nil, all tracing is no-op.
78 79 80 |
# File 'lib/yes/core/configuration.rb', line 78 def otl_tracer @otl_tracer end |
#payload_store_client ⇒ Object?
Returns Payload store client for resolving large payload references.
69 70 71 |
# File 'lib/yes/core/configuration.rb', line 69 def payload_store_client @payload_store_client end |
#process_commands_inline ⇒ Boolean
Returns Whether to process commands inline (synchronously) or via ActiveJob.
72 73 74 |
# File 'lib/yes/core/configuration.rb', line 72 def process_commands_inline @process_commands_inline end |
#raise_on_missing_handler_method ⇒ Boolean
Returns Whether to raise on missing handler methods in aggregate state.
84 85 86 |
# File 'lib/yes/core/configuration.rb', line 84 def raise_on_missing_handler_method @raise_on_missing_handler_method end |
#service_name ⇒ String
Returns Service name for telemetry and identification.
93 94 95 |
# File 'lib/yes/core/configuration.rb', line 93 def service_name @service_name end |
#service_version ⇒ String
Returns Service version for telemetry.
96 97 98 |
# File 'lib/yes/core/configuration.rb', line 96 def service_version @service_version end |
#subscriptions_heartbeat_interval ⇒ Integer
Returns Interval in seconds between heartbeat pings (default: 30).
90 91 92 |
# File 'lib/yes/core/configuration.rb', line 90 def subscriptions_heartbeat_interval @subscriptions_heartbeat_interval end |
#subscriptions_heartbeat_url ⇒ String?
Returns URL for subscription heartbeat pings (default: nil, disables heartbeat).
87 88 89 |
# File 'lib/yes/core/configuration.rb', line 87 def subscriptions_heartbeat_url @subscriptions_heartbeat_url end |
#super_admin_check ⇒ #call
Returns A callable that receives auth_data and returns boolean indicating super admin status.
29 30 31 |
# File 'lib/yes/core/configuration.rb', line 29 def super_admin_check @super_admin_check end |
Instance Method Details
#aggregate_class(context_name, aggregate_name, action_name, type) ⇒ Class?
Retrieve a registered class for a given aggregate, action, and type
283 284 285 286 287 288 289 |
# File 'lib/yes/core/configuration.rb', line 283 def aggregate_class(context_name, aggregate_name, action_name, type) if action_name.nil? @registered_classes.dig([context_name, aggregate_name], type) else @registered_classes.dig([context_name, aggregate_name], type, action_name) end end |
#all_read_model_class_names ⇒ Array<String>
Get all read model class names from registered aggregates
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 |
# File 'lib/yes/core/configuration.rb', line 333 def all_read_model_class_names list_all_registered_classes.keys.flat_map do |context_aggregate| context_name, aggregate_name = context_aggregate aggregate_class_name = "#{context_name.to_s.camelize}::#{aggregate_name.to_s.camelize}::Aggregate" begin aggregate_class = aggregate_class_name.constantize models = [] # Add main read model if it exists models << aggregate_class.read_model_name.camelize.to_s if aggregate_class.respond_to?(:read_model_name) && aggregate_class.read_model_name # Add changes read model if aggregate is draftable models << aggregate_class.changes_read_model_name.camelize.to_s if aggregate_class.respond_to?(:changes_read_model_name) && aggregate_class.changes_read_model_name models rescue NameError # Skip if aggregate class doesn't exist [] end end.compact.uniq end |
#all_read_model_classes ⇒ Array<Class>
Get all read model classes (constantized)
361 362 363 364 365 366 367 |
# File 'lib/yes/core/configuration.rb', line 361 def all_read_model_classes all_read_model_class_names.filter_map do |class_name| class_name.constantize rescue NameError nil end end |
#all_read_model_table_names ⇒ Array<String>
Get all read model table names
427 428 429 |
# File 'lib/yes/core/configuration.rb', line 427 def all_read_model_table_names all_read_model_classes.map(&:table_name).uniq end |
#all_read_models_with_aggregate_classes ⇒ Array<Hash>
Get all read model classes with their associated aggregate classes
377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 |
# File 'lib/yes/core/configuration.rb', line 377 def all_read_models_with_aggregate_classes list_all_registered_classes.keys.flat_map do |context_aggregate| context_name, aggregate_name = context_aggregate aggregate_class_name = "#{context_name.to_s.camelize}::#{aggregate_name.to_s.camelize}::Aggregate" begin aggregate_class = aggregate_class_name.constantize models = [] # Main read model (not draft) if aggregate_class.respond_to?(:read_model_name) && aggregate_class.read_model_name begin read_model_class = aggregate_class.read_model_name.camelize.constantize models << { read_model_class: read_model_class, aggregate_class: aggregate_class, is_draft: false } rescue NameError # Skip if read model class doesn't exist end end # Changes read model (draft) if aggregate_class.respond_to?(:changes_read_model_name) && aggregate_class.changes_read_model_name begin changes_model_class = aggregate_class.changes_read_model_name.camelize.constantize models << { read_model_class: changes_model_class, aggregate_class: aggregate_class, is_draft: true } rescue NameError # Skip if changes read model class doesn't exist end end models rescue NameError # Skip if aggregate class doesn't exist [] end end.compact end |
#command_event_mapping(context_name, aggregate_name, command_name) ⇒ Array<Symbol, String>
Retrieve the event names associated with a specific command
256 257 258 |
# File 'lib/yes/core/configuration.rb', line 256 def command_event_mapping(context_name, aggregate_name, command_name) command_event_mappings(context_name, aggregate_name)[command_name] || [] end |
#command_event_mappings(context_name, aggregate_name) ⇒ Hash
Retrieve all command-to-event mappings for a specific aggregate
244 245 246 247 |
# File 'lib/yes/core/configuration.rb', line 244 def command_event_mappings(context_name, aggregate_name) key = [context_name, aggregate_name] @registered_classes[key][:command_event_mappings] || {} end |
#event_classes_for_command(context_name, aggregate_name, command_name) ⇒ Array<Class>
Retrieve the actual event classes associated with a specific command
267 268 269 270 271 |
# File 'lib/yes/core/configuration.rb', line 267 def event_classes_for_command(context_name, aggregate_name, command_name) command_event_mapping(context_name, aggregate_name, command_name).map do |event_name| aggregate_class(context_name, aggregate_name, event_name, :event) end end |
#guard_evaluator_class(context_name, aggregate_name, command_name) ⇒ Class?
Retrieve a guard evaluator class for a specific command
308 309 310 |
# File 'lib/yes/core/configuration.rb', line 308 def guard_evaluator_class(context_name, aggregate_name, command_name) aggregate_class(context_name, aggregate_name, command_name.to_s.underscore.to_sym, :guard_evaluator) end |
#list_aggregate_classes(context_name, aggregate_name) ⇒ Hash
List all registered classes for a specific aggregate in a context
297 298 299 |
# File 'lib/yes/core/configuration.rb', line 297 def list_aggregate_classes(context_name, aggregate_name) @registered_classes[[context_name, aggregate_name]] end |
#list_all_registered_classes ⇒ Hash
List all registered classes across all aggregates and contexts
324 325 326 |
# File 'lib/yes/core/configuration.rb', line 324 def list_all_registered_classes @registered_classes end |
#register_aggregate_authorizer_class(context_name, aggregate_name, klass) ⇒ Object
Register an aggregate authorizer class for a specific aggregate
209 210 211 212 |
# File 'lib/yes/core/configuration.rb', line 209 def (context_name, aggregate_name, klass) key = [context_name, aggregate_name] @registered_classes[key][:aggregate_authorizer] = klass end |
#register_aggregate_class(context_name, aggregate_name, action_name, type, klass) ⇒ Object
Register a class for a specific aggregate and type
142 143 144 145 |
# File 'lib/yes/core/configuration.rb', line 142 def register_aggregate_class(context_name, aggregate_name, action_name, type, klass) key = [context_name, aggregate_name] @registered_classes[key][type][action_name] = klass end |
#register_command_authorizer_class(context_name, aggregate_name, command_name, klass) ⇒ Object
Register a command authorizer class for a specific aggregate
221 222 223 |
# File 'lib/yes/core/configuration.rb', line 221 def (context_name, aggregate_name, command_name, klass) register_aggregate_class(context_name, aggregate_name, command_name, :authorizer, klass) end |
#register_command_class(context_name, aggregate_name, command_name, klass) ⇒ Object
Register a command class for a specific aggregate
177 178 179 |
# File 'lib/yes/core/configuration.rb', line 177 def register_command_class(context_name, aggregate_name, command_name, klass) register_aggregate_class(context_name, aggregate_name, command_name, :command, klass) end |
#register_command_events(context_name, aggregate_name, command_name, event_names) ⇒ Object
Register the event(s) associated with a specific command
232 233 234 235 236 |
# File 'lib/yes/core/configuration.rb', line 232 def register_command_events(context_name, aggregate_name, command_name, event_names) key = [context_name, aggregate_name] mappings = @registered_classes[key][:command_event_mappings] ||= {} mappings[command_name] = event_names end |
#register_event_class(context_name, aggregate_name, event_name, klass) ⇒ Object
Register an event class for a specific aggregate
188 189 190 |
# File 'lib/yes/core/configuration.rb', line 188 def register_event_class(context_name, aggregate_name, event_name, klass) register_aggregate_class(context_name, aggregate_name, event_name, :event, klass) end |
#register_guard_evaluator_class(context_name, aggregate_name, command_name, klass) ⇒ Object
Register a guard evaluator class for a specific aggregate
199 200 201 |
# File 'lib/yes/core/configuration.rb', line 199 def register_guard_evaluator_class(context_name, aggregate_name, command_name, klass) register_aggregate_class(context_name, aggregate_name, command_name, :guard_evaluator, klass) end |
#register_read_model_class(context_name, aggregate_name, klass, draft: false) ⇒ Object
Register a read model class for a specific aggregate
153 154 155 156 157 |
# File 'lib/yes/core/configuration.rb', line 153 def register_read_model_class(context_name, aggregate_name, klass, draft: false) key = [context_name, aggregate_name] read_model_key = draft ? :draft_read_model : :read_model @registered_classes[key][read_model_key] = klass end |
#register_read_model_filter_class(context_name, aggregate_name, klass) ⇒ Object
Register a read model filter class for a specific aggregate
165 166 167 168 |
# File 'lib/yes/core/configuration.rb', line 165 def register_read_model_filter_class(context_name, aggregate_name, klass) key = [context_name, aggregate_name] @registered_classes[key][:read_model_filter] = klass end |