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_grpc_channel_args ⇒ Hash{String => String, Integer}
Low-level gRPC channel arguments for the Cerbos client (default: Authorization::CerbosGrpcRetryPolicy.channel_args, which retries UNAVAILABLE calls).
-
#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.
-
#command_group_guard_evaluator_class(context_name, aggregate_name, group_name) ⇒ Class?
Retrieve a guard evaluator class for a specific command group.
-
#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_command_group_class(context_name, aggregate_name, group_name, klass) ⇒ Object
Register a command_group command class for a specific aggregate.
-
#register_command_group_guard_evaluator_class(context_name, aggregate_name, group_name, klass) ⇒ Object
Register a command_group guard evaluator class for a specific aggregate.
-
#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.
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 133 134 135 136 137 |
# File 'lib/yes/core/configuration.rb', line 108 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_grpc_channel_args = Authorization::CerbosGrpcRetryPolicy.channel_args @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).
105 106 107 |
# File 'lib/yes/core/configuration.rb', line 105 def auth_adapter @auth_adapter end |
#cerbos_commands_authorizer_include_metadata ⇒ Boolean
Returns Whether to include metadata in Cerbos command authorizer responses.
53 54 55 |
# File 'lib/yes/core/configuration.rb', line 53 def @cerbos_commands_authorizer_include_metadata end |
#cerbos_grpc_channel_args ⇒ Hash{String => String, Integer}
Returns low-level gRPC channel arguments for the Cerbos client (default: Authorization::CerbosGrpcRetryPolicy.channel_args, which retries UNAVAILABLE calls).
50 51 52 |
# File 'lib/yes/core/configuration.rb', line 50 def cerbos_grpc_channel_args @cerbos_grpc_channel_args 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.
59 60 61 |
# File 'lib/yes/core/configuration.rb', line 59 def @cerbos_read_authorizer_actions end |
#cerbos_read_authorizer_include_metadata ⇒ Boolean
Returns Whether to include metadata in Cerbos read authorizer responses.
56 57 58 |
# File 'lib/yes/core/configuration.rb', line 56 def @cerbos_read_authorizer_include_metadata end |
#cerbos_read_authorizer_principal_anonymous_id ⇒ String
Returns Anonymous principal ID for Cerbos read authorizer.
85 86 87 |
# File 'lib/yes/core/configuration.rb', line 85 def @cerbos_read_authorizer_principal_anonymous_id end |
#cerbos_read_authorizer_resource_id_prefix ⇒ String
Returns Prefix for Cerbos read authorizer resource ids.
62 63 64 |
# File 'lib/yes/core/configuration.rb', line 62 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.
79 80 81 |
# File 'lib/yes/core/configuration.rb', line 79 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) }.
70 71 72 |
# File 'lib/yes/core/configuration.rb', line 70 def error_reporter @error_reporter end |
#logger ⇒ Object
Returns Logger instance.
65 66 67 |
# File 'lib/yes/core/configuration.rb', line 65 def logger @logger end |
#otl_tracer ⇒ Object?
Returns OpenTelemetry tracer instance. When nil, all tracing is no-op.
82 83 84 |
# File 'lib/yes/core/configuration.rb', line 82 def otl_tracer @otl_tracer end |
#payload_store_client ⇒ Object?
Returns Payload store client for resolving large payload references.
73 74 75 |
# File 'lib/yes/core/configuration.rb', line 73 def payload_store_client @payload_store_client end |
#process_commands_inline ⇒ Boolean
Returns Whether to process commands inline (synchronously) or via ActiveJob.
76 77 78 |
# File 'lib/yes/core/configuration.rb', line 76 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.
88 89 90 |
# File 'lib/yes/core/configuration.rb', line 88 def raise_on_missing_handler_method @raise_on_missing_handler_method end |
#service_name ⇒ String
Returns Service name for telemetry and identification.
97 98 99 |
# File 'lib/yes/core/configuration.rb', line 97 def service_name @service_name end |
#service_version ⇒ String
Returns Service version for telemetry.
100 101 102 |
# File 'lib/yes/core/configuration.rb', line 100 def service_version @service_version end |
#subscriptions_heartbeat_interval ⇒ Integer
Returns Interval in seconds between heartbeat pings (default: 30).
94 95 96 |
# File 'lib/yes/core/configuration.rb', line 94 def subscriptions_heartbeat_interval @subscriptions_heartbeat_interval end |
#subscriptions_heartbeat_url ⇒ String?
Returns URL for subscription heartbeat pings (default: nil, disables heartbeat).
91 92 93 |
# File 'lib/yes/core/configuration.rb', line 91 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
310 311 312 313 314 315 316 |
# File 'lib/yes/core/configuration.rb', line 310 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
377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 |
# File 'lib/yes/core/configuration.rb', line 377 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)
405 406 407 408 409 410 411 |
# File 'lib/yes/core/configuration.rb', line 405 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
471 472 473 |
# File 'lib/yes/core/configuration.rb', line 471 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
421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 |
# File 'lib/yes/core/configuration.rb', line 421 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
283 284 285 |
# File 'lib/yes/core/configuration.rb', line 283 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
271 272 273 274 |
# File 'lib/yes/core/configuration.rb', line 271 def command_event_mappings(context_name, aggregate_name) key = [context_name, aggregate_name] @registered_classes[key][:command_event_mappings] || {} end |
#command_group_guard_evaluator_class(context_name, aggregate_name, group_name) ⇒ Class?
Retrieve a guard evaluator class for a specific command group.
Aggregate-DSL command groups register their guard evaluator under the
dedicated :command_group_guard_evaluator type (see
#register_command_group_guard_evaluator_class), not :guard_evaluator,
so a group cannot be resolved through #guard_evaluator_class.
352 353 354 |
# File 'lib/yes/core/configuration.rb', line 352 def command_group_guard_evaluator_class(context_name, aggregate_name, group_name) aggregate_class(context_name, aggregate_name, group_name.to_s.underscore.to_sym, :command_group_guard_evaluator) end |
#event_classes_for_command(context_name, aggregate_name, command_name) ⇒ Array<Class>
Retrieve the actual event classes associated with a specific command
294 295 296 297 298 |
# File 'lib/yes/core/configuration.rb', line 294 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
335 336 337 |
# File 'lib/yes/core/configuration.rb', line 335 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
324 325 326 |
# File 'lib/yes/core/configuration.rb', line 324 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
368 369 370 |
# File 'lib/yes/core/configuration.rb', line 368 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
236 237 238 239 |
# File 'lib/yes/core/configuration.rb', line 236 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
147 148 149 150 |
# File 'lib/yes/core/configuration.rb', line 147 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
248 249 250 |
# File 'lib/yes/core/configuration.rb', line 248 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
182 183 184 |
# File 'lib/yes/core/configuration.rb', line 182 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
259 260 261 262 263 |
# File 'lib/yes/core/configuration.rb', line 259 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_command_group_class(context_name, aggregate_name, group_name, klass) ⇒ Object
Register a command_group command class for a specific aggregate
215 216 217 |
# File 'lib/yes/core/configuration.rb', line 215 def register_command_group_class(context_name, aggregate_name, group_name, klass) register_aggregate_class(context_name, aggregate_name, group_name, :command_group, klass) end |
#register_command_group_guard_evaluator_class(context_name, aggregate_name, group_name, klass) ⇒ Object
Register a command_group guard evaluator class for a specific aggregate
226 227 228 |
# File 'lib/yes/core/configuration.rb', line 226 def register_command_group_guard_evaluator_class(context_name, aggregate_name, group_name, klass) register_aggregate_class(context_name, aggregate_name, group_name, :command_group_guard_evaluator, klass) end |
#register_event_class(context_name, aggregate_name, event_name, klass) ⇒ Object
Register an event class for a specific aggregate
193 194 195 |
# File 'lib/yes/core/configuration.rb', line 193 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
204 205 206 |
# File 'lib/yes/core/configuration.rb', line 204 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
158 159 160 161 162 |
# File 'lib/yes/core/configuration.rb', line 158 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
170 171 172 173 |
# File 'lib/yes/core/configuration.rb', line 170 def register_read_model_filter_class(context_name, aggregate_name, klass) key = [context_name, aggregate_name] @registered_classes[key][:read_model_filter] = klass end |