omnibase_infra 0.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- omnibase_infra/__init__.py +101 -0
- omnibase_infra/cli/__init__.py +1 -0
- omnibase_infra/cli/commands.py +216 -0
- omnibase_infra/clients/__init__.py +0 -0
- omnibase_infra/contracts/handlers/filesystem/handler_contract.yaml +261 -0
- omnibase_infra/contracts/handlers/mcp/handler_contract.yaml +138 -0
- omnibase_infra/decorators/__init__.py +29 -0
- omnibase_infra/decorators/allow_any.py +109 -0
- omnibase_infra/dlq/__init__.py +90 -0
- omnibase_infra/dlq/constants_dlq.py +57 -0
- omnibase_infra/dlq/models/__init__.py +26 -0
- omnibase_infra/dlq/models/enum_replay_status.py +37 -0
- omnibase_infra/dlq/models/model_dlq_replay_record.py +135 -0
- omnibase_infra/dlq/models/model_dlq_tracking_config.py +184 -0
- omnibase_infra/dlq/service_dlq_tracking.py +611 -0
- omnibase_infra/enums/__init__.py +123 -0
- omnibase_infra/enums/enum_any_type_violation.py +104 -0
- omnibase_infra/enums/enum_backend_type.py +27 -0
- omnibase_infra/enums/enum_capture_outcome.py +42 -0
- omnibase_infra/enums/enum_capture_state.py +88 -0
- omnibase_infra/enums/enum_chain_violation_type.py +119 -0
- omnibase_infra/enums/enum_circuit_state.py +51 -0
- omnibase_infra/enums/enum_confirmation_event_type.py +27 -0
- omnibase_infra/enums/enum_contract_type.py +84 -0
- omnibase_infra/enums/enum_dedupe_strategy.py +46 -0
- omnibase_infra/enums/enum_dispatch_status.py +191 -0
- omnibase_infra/enums/enum_environment.py +46 -0
- omnibase_infra/enums/enum_execution_shape_violation.py +103 -0
- omnibase_infra/enums/enum_handler_error_type.py +101 -0
- omnibase_infra/enums/enum_handler_loader_error.py +178 -0
- omnibase_infra/enums/enum_handler_source_type.py +87 -0
- omnibase_infra/enums/enum_handler_type.py +77 -0
- omnibase_infra/enums/enum_handler_type_category.py +61 -0
- omnibase_infra/enums/enum_infra_transport_type.py +73 -0
- omnibase_infra/enums/enum_introspection_reason.py +154 -0
- omnibase_infra/enums/enum_message_category.py +213 -0
- omnibase_infra/enums/enum_node_archetype.py +74 -0
- omnibase_infra/enums/enum_node_output_type.py +185 -0
- omnibase_infra/enums/enum_non_retryable_error_category.py +224 -0
- omnibase_infra/enums/enum_policy_type.py +32 -0
- omnibase_infra/enums/enum_registration_state.py +261 -0
- omnibase_infra/enums/enum_registration_status.py +33 -0
- omnibase_infra/enums/enum_registry_response_status.py +28 -0
- omnibase_infra/enums/enum_response_status.py +26 -0
- omnibase_infra/enums/enum_retry_error_category.py +98 -0
- omnibase_infra/enums/enum_security_rule_id.py +103 -0
- omnibase_infra/enums/enum_selection_strategy.py +91 -0
- omnibase_infra/enums/enum_topic_standard.py +42 -0
- omnibase_infra/enums/enum_validation_severity.py +78 -0
- omnibase_infra/errors/__init__.py +156 -0
- omnibase_infra/errors/error_architecture_violation.py +152 -0
- omnibase_infra/errors/error_chain_propagation.py +188 -0
- omnibase_infra/errors/error_compute_registry.py +92 -0
- omnibase_infra/errors/error_consul.py +132 -0
- omnibase_infra/errors/error_container_wiring.py +243 -0
- omnibase_infra/errors/error_event_bus_registry.py +102 -0
- omnibase_infra/errors/error_infra.py +608 -0
- omnibase_infra/errors/error_message_type_registry.py +101 -0
- omnibase_infra/errors/error_policy_registry.py +112 -0
- omnibase_infra/errors/error_vault.py +123 -0
- omnibase_infra/event_bus/__init__.py +72 -0
- omnibase_infra/event_bus/configs/kafka_event_bus_config.yaml +86 -0
- omnibase_infra/event_bus/event_bus_inmemory.py +743 -0
- omnibase_infra/event_bus/event_bus_kafka.py +1658 -0
- omnibase_infra/event_bus/mixin_kafka_broadcast.py +184 -0
- omnibase_infra/event_bus/mixin_kafka_dlq.py +765 -0
- omnibase_infra/event_bus/models/__init__.py +29 -0
- omnibase_infra/event_bus/models/config/__init__.py +20 -0
- omnibase_infra/event_bus/models/config/model_kafka_event_bus_config.py +725 -0
- omnibase_infra/event_bus/models/model_dlq_event.py +206 -0
- omnibase_infra/event_bus/models/model_dlq_metrics.py +304 -0
- omnibase_infra/event_bus/models/model_event_headers.py +115 -0
- omnibase_infra/event_bus/models/model_event_message.py +60 -0
- omnibase_infra/event_bus/topic_constants.py +376 -0
- omnibase_infra/handlers/__init__.py +75 -0
- omnibase_infra/handlers/filesystem/__init__.py +48 -0
- omnibase_infra/handlers/filesystem/enum_file_system_operation.py +35 -0
- omnibase_infra/handlers/filesystem/model_file_system_request.py +298 -0
- omnibase_infra/handlers/filesystem/model_file_system_result.py +166 -0
- omnibase_infra/handlers/handler_consul.py +787 -0
- omnibase_infra/handlers/handler_db.py +1039 -0
- omnibase_infra/handlers/handler_filesystem.py +1478 -0
- omnibase_infra/handlers/handler_graph.py +1154 -0
- omnibase_infra/handlers/handler_http.py +920 -0
- omnibase_infra/handlers/handler_manifest_persistence.contract.yaml +184 -0
- omnibase_infra/handlers/handler_manifest_persistence.py +1539 -0
- omnibase_infra/handlers/handler_mcp.py +748 -0
- omnibase_infra/handlers/handler_qdrant.py +1076 -0
- omnibase_infra/handlers/handler_vault.py +422 -0
- omnibase_infra/handlers/mcp/__init__.py +19 -0
- omnibase_infra/handlers/mcp/adapter_onex_to_mcp.py +446 -0
- omnibase_infra/handlers/mcp/protocols.py +178 -0
- omnibase_infra/handlers/mcp/transport_streamable_http.py +352 -0
- omnibase_infra/handlers/mixins/__init__.py +42 -0
- omnibase_infra/handlers/mixins/mixin_consul_initialization.py +349 -0
- omnibase_infra/handlers/mixins/mixin_consul_kv.py +337 -0
- omnibase_infra/handlers/mixins/mixin_consul_service.py +277 -0
- omnibase_infra/handlers/mixins/mixin_vault_initialization.py +338 -0
- omnibase_infra/handlers/mixins/mixin_vault_retry.py +412 -0
- omnibase_infra/handlers/mixins/mixin_vault_secrets.py +450 -0
- omnibase_infra/handlers/mixins/mixin_vault_token.py +365 -0
- omnibase_infra/handlers/models/__init__.py +286 -0
- omnibase_infra/handlers/models/consul/__init__.py +81 -0
- omnibase_infra/handlers/models/consul/enum_consul_operation_type.py +57 -0
- omnibase_infra/handlers/models/consul/model_consul_deregister_payload.py +51 -0
- omnibase_infra/handlers/models/consul/model_consul_handler_config.py +153 -0
- omnibase_infra/handlers/models/consul/model_consul_handler_payload.py +89 -0
- omnibase_infra/handlers/models/consul/model_consul_kv_get_found_payload.py +55 -0
- omnibase_infra/handlers/models/consul/model_consul_kv_get_not_found_payload.py +49 -0
- omnibase_infra/handlers/models/consul/model_consul_kv_get_recurse_payload.py +50 -0
- omnibase_infra/handlers/models/consul/model_consul_kv_item.py +33 -0
- omnibase_infra/handlers/models/consul/model_consul_kv_put_payload.py +41 -0
- omnibase_infra/handlers/models/consul/model_consul_register_payload.py +53 -0
- omnibase_infra/handlers/models/consul/model_consul_retry_config.py +66 -0
- omnibase_infra/handlers/models/consul/model_payload_consul.py +66 -0
- omnibase_infra/handlers/models/consul/registry_payload_consul.py +214 -0
- omnibase_infra/handlers/models/graph/__init__.py +35 -0
- omnibase_infra/handlers/models/graph/enum_graph_operation_type.py +20 -0
- omnibase_infra/handlers/models/graph/model_graph_execute_payload.py +38 -0
- omnibase_infra/handlers/models/graph/model_graph_handler_config.py +54 -0
- omnibase_infra/handlers/models/graph/model_graph_handler_payload.py +44 -0
- omnibase_infra/handlers/models/graph/model_graph_query_payload.py +40 -0
- omnibase_infra/handlers/models/graph/model_graph_record.py +22 -0
- omnibase_infra/handlers/models/http/__init__.py +50 -0
- omnibase_infra/handlers/models/http/enum_http_operation_type.py +29 -0
- omnibase_infra/handlers/models/http/model_http_body_content.py +45 -0
- omnibase_infra/handlers/models/http/model_http_get_payload.py +88 -0
- omnibase_infra/handlers/models/http/model_http_handler_payload.py +90 -0
- omnibase_infra/handlers/models/http/model_http_post_payload.py +88 -0
- omnibase_infra/handlers/models/http/model_payload_http.py +66 -0
- omnibase_infra/handlers/models/http/registry_payload_http.py +212 -0
- omnibase_infra/handlers/models/mcp/__init__.py +23 -0
- omnibase_infra/handlers/models/mcp/enum_mcp_operation_type.py +24 -0
- omnibase_infra/handlers/models/mcp/model_mcp_handler_config.py +40 -0
- omnibase_infra/handlers/models/mcp/model_mcp_tool_call.py +32 -0
- omnibase_infra/handlers/models/mcp/model_mcp_tool_result.py +45 -0
- omnibase_infra/handlers/models/model_consul_handler_response.py +96 -0
- omnibase_infra/handlers/models/model_db_describe_response.py +83 -0
- omnibase_infra/handlers/models/model_db_query_payload.py +95 -0
- omnibase_infra/handlers/models/model_db_query_response.py +60 -0
- omnibase_infra/handlers/models/model_filesystem_config.py +98 -0
- omnibase_infra/handlers/models/model_filesystem_delete_payload.py +54 -0
- omnibase_infra/handlers/models/model_filesystem_delete_result.py +77 -0
- omnibase_infra/handlers/models/model_filesystem_directory_entry.py +75 -0
- omnibase_infra/handlers/models/model_filesystem_ensure_directory_payload.py +54 -0
- omnibase_infra/handlers/models/model_filesystem_ensure_directory_result.py +60 -0
- omnibase_infra/handlers/models/model_filesystem_list_directory_payload.py +60 -0
- omnibase_infra/handlers/models/model_filesystem_list_directory_result.py +68 -0
- omnibase_infra/handlers/models/model_filesystem_read_payload.py +62 -0
- omnibase_infra/handlers/models/model_filesystem_read_result.py +61 -0
- omnibase_infra/handlers/models/model_filesystem_write_payload.py +70 -0
- omnibase_infra/handlers/models/model_filesystem_write_result.py +55 -0
- omnibase_infra/handlers/models/model_graph_handler_response.py +98 -0
- omnibase_infra/handlers/models/model_handler_response.py +103 -0
- omnibase_infra/handlers/models/model_http_handler_response.py +101 -0
- omnibase_infra/handlers/models/model_manifest_metadata.py +75 -0
- omnibase_infra/handlers/models/model_manifest_persistence_config.py +62 -0
- omnibase_infra/handlers/models/model_manifest_query_payload.py +90 -0
- omnibase_infra/handlers/models/model_manifest_query_result.py +97 -0
- omnibase_infra/handlers/models/model_manifest_retrieve_payload.py +44 -0
- omnibase_infra/handlers/models/model_manifest_retrieve_result.py +98 -0
- omnibase_infra/handlers/models/model_manifest_store_payload.py +47 -0
- omnibase_infra/handlers/models/model_manifest_store_result.py +67 -0
- omnibase_infra/handlers/models/model_operation_context.py +187 -0
- omnibase_infra/handlers/models/model_qdrant_handler_response.py +98 -0
- omnibase_infra/handlers/models/model_retry_state.py +162 -0
- omnibase_infra/handlers/models/model_vault_handler_response.py +98 -0
- omnibase_infra/handlers/models/qdrant/__init__.py +44 -0
- omnibase_infra/handlers/models/qdrant/enum_qdrant_operation_type.py +26 -0
- omnibase_infra/handlers/models/qdrant/model_qdrant_collection_payload.py +42 -0
- omnibase_infra/handlers/models/qdrant/model_qdrant_delete_payload.py +36 -0
- omnibase_infra/handlers/models/qdrant/model_qdrant_handler_config.py +42 -0
- omnibase_infra/handlers/models/qdrant/model_qdrant_handler_payload.py +54 -0
- omnibase_infra/handlers/models/qdrant/model_qdrant_search_payload.py +42 -0
- omnibase_infra/handlers/models/qdrant/model_qdrant_search_result.py +30 -0
- omnibase_infra/handlers/models/qdrant/model_qdrant_upsert_payload.py +36 -0
- omnibase_infra/handlers/models/vault/__init__.py +69 -0
- omnibase_infra/handlers/models/vault/enum_vault_operation_type.py +35 -0
- omnibase_infra/handlers/models/vault/model_payload_vault.py +66 -0
- omnibase_infra/handlers/models/vault/model_vault_delete_payload.py +57 -0
- omnibase_infra/handlers/models/vault/model_vault_handler_config.py +148 -0
- omnibase_infra/handlers/models/vault/model_vault_handler_payload.py +101 -0
- omnibase_infra/handlers/models/vault/model_vault_list_payload.py +58 -0
- omnibase_infra/handlers/models/vault/model_vault_renew_token_payload.py +67 -0
- omnibase_infra/handlers/models/vault/model_vault_retry_config.py +66 -0
- omnibase_infra/handlers/models/vault/model_vault_secret_payload.py +106 -0
- omnibase_infra/handlers/models/vault/model_vault_write_payload.py +66 -0
- omnibase_infra/handlers/models/vault/registry_payload_vault.py +213 -0
- omnibase_infra/handlers/registration_storage/__init__.py +43 -0
- omnibase_infra/handlers/registration_storage/handler_registration_storage_mock.py +392 -0
- omnibase_infra/handlers/registration_storage/handler_registration_storage_postgres.py +915 -0
- omnibase_infra/handlers/registration_storage/models/__init__.py +23 -0
- omnibase_infra/handlers/registration_storage/models/model_delete_registration_request.py +58 -0
- omnibase_infra/handlers/registration_storage/models/model_update_registration_request.py +73 -0
- omnibase_infra/handlers/registration_storage/protocol_registration_persistence.py +191 -0
- omnibase_infra/handlers/service_discovery/__init__.py +43 -0
- omnibase_infra/handlers/service_discovery/handler_service_discovery_consul.py +747 -0
- omnibase_infra/handlers/service_discovery/handler_service_discovery_mock.py +258 -0
- omnibase_infra/handlers/service_discovery/models/__init__.py +22 -0
- omnibase_infra/handlers/service_discovery/models/model_discovery_result.py +64 -0
- omnibase_infra/handlers/service_discovery/models/model_registration_result.py +138 -0
- omnibase_infra/handlers/service_discovery/models/model_service_info.py +99 -0
- omnibase_infra/handlers/service_discovery/protocol_discovery_operations.py +170 -0
- omnibase_infra/idempotency/__init__.py +94 -0
- omnibase_infra/idempotency/models/__init__.py +43 -0
- omnibase_infra/idempotency/models/model_idempotency_check_result.py +85 -0
- omnibase_infra/idempotency/models/model_idempotency_guard_config.py +130 -0
- omnibase_infra/idempotency/models/model_idempotency_record.py +86 -0
- omnibase_infra/idempotency/models/model_idempotency_store_health_check_result.py +81 -0
- omnibase_infra/idempotency/models/model_idempotency_store_metrics.py +140 -0
- omnibase_infra/idempotency/models/model_postgres_idempotency_store_config.py +299 -0
- omnibase_infra/idempotency/protocol_idempotency_store.py +184 -0
- omnibase_infra/idempotency/store_inmemory.py +265 -0
- omnibase_infra/idempotency/store_postgres.py +923 -0
- omnibase_infra/infrastructure/__init__.py +0 -0
- omnibase_infra/mixins/__init__.py +71 -0
- omnibase_infra/mixins/mixin_async_circuit_breaker.py +655 -0
- omnibase_infra/mixins/mixin_dict_like_accessors.py +146 -0
- omnibase_infra/mixins/mixin_envelope_extraction.py +119 -0
- omnibase_infra/mixins/mixin_node_introspection.py +2465 -0
- omnibase_infra/mixins/mixin_retry_execution.py +386 -0
- omnibase_infra/mixins/protocol_circuit_breaker_aware.py +133 -0
- omnibase_infra/models/__init__.py +136 -0
- omnibase_infra/models/corpus/__init__.py +17 -0
- omnibase_infra/models/corpus/model_capture_config.py +133 -0
- omnibase_infra/models/corpus/model_capture_result.py +86 -0
- omnibase_infra/models/discovery/__init__.py +42 -0
- omnibase_infra/models/discovery/model_dependency_spec.py +319 -0
- omnibase_infra/models/discovery/model_discovered_capabilities.py +50 -0
- omnibase_infra/models/discovery/model_introspection_config.py +311 -0
- omnibase_infra/models/discovery/model_introspection_performance_metrics.py +169 -0
- omnibase_infra/models/discovery/model_introspection_task_config.py +116 -0
- omnibase_infra/models/dispatch/__init__.py +147 -0
- omnibase_infra/models/dispatch/model_dispatch_context.py +439 -0
- omnibase_infra/models/dispatch/model_dispatch_error.py +336 -0
- omnibase_infra/models/dispatch/model_dispatch_log_context.py +400 -0
- omnibase_infra/models/dispatch/model_dispatch_metadata.py +228 -0
- omnibase_infra/models/dispatch/model_dispatch_metrics.py +496 -0
- omnibase_infra/models/dispatch/model_dispatch_outcome.py +317 -0
- omnibase_infra/models/dispatch/model_dispatch_outputs.py +231 -0
- omnibase_infra/models/dispatch/model_dispatch_result.py +436 -0
- omnibase_infra/models/dispatch/model_dispatch_route.py +279 -0
- omnibase_infra/models/dispatch/model_dispatcher_metrics.py +275 -0
- omnibase_infra/models/dispatch/model_dispatcher_registration.py +352 -0
- omnibase_infra/models/dispatch/model_parsed_topic.py +135 -0
- omnibase_infra/models/dispatch/model_topic_parser.py +725 -0
- omnibase_infra/models/dispatch/model_tracing_context.py +285 -0
- omnibase_infra/models/errors/__init__.py +45 -0
- omnibase_infra/models/errors/model_handler_validation_error.py +594 -0
- omnibase_infra/models/errors/model_infra_error_context.py +99 -0
- omnibase_infra/models/errors/model_message_type_registry_error_context.py +71 -0
- omnibase_infra/models/errors/model_timeout_error_context.py +110 -0
- omnibase_infra/models/handlers/__init__.py +37 -0
- omnibase_infra/models/handlers/model_contract_discovery_result.py +80 -0
- omnibase_infra/models/handlers/model_handler_descriptor.py +185 -0
- omnibase_infra/models/handlers/model_handler_identifier.py +215 -0
- omnibase_infra/models/health/__init__.py +9 -0
- omnibase_infra/models/health/model_health_check_result.py +40 -0
- omnibase_infra/models/lifecycle/__init__.py +39 -0
- omnibase_infra/models/logging/__init__.py +51 -0
- omnibase_infra/models/logging/model_log_context.py +756 -0
- omnibase_infra/models/model_retry_error_classification.py +78 -0
- omnibase_infra/models/projection/__init__.py +43 -0
- omnibase_infra/models/projection/model_capability_fields.py +112 -0
- omnibase_infra/models/projection/model_registration_projection.py +434 -0
- omnibase_infra/models/projection/model_registration_snapshot.py +322 -0
- omnibase_infra/models/projection/model_sequence_info.py +182 -0
- omnibase_infra/models/projection/model_snapshot_topic_config.py +590 -0
- omnibase_infra/models/projectors/__init__.py +41 -0
- omnibase_infra/models/projectors/model_projector_column.py +289 -0
- omnibase_infra/models/projectors/model_projector_discovery_result.py +65 -0
- omnibase_infra/models/projectors/model_projector_index.py +270 -0
- omnibase_infra/models/projectors/model_projector_schema.py +415 -0
- omnibase_infra/models/projectors/model_projector_validation_error.py +63 -0
- omnibase_infra/models/projectors/util_sql_identifiers.py +115 -0
- omnibase_infra/models/registration/__init__.py +59 -0
- omnibase_infra/models/registration/commands/__init__.py +15 -0
- omnibase_infra/models/registration/commands/model_node_registration_acked.py +108 -0
- omnibase_infra/models/registration/events/__init__.py +56 -0
- omnibase_infra/models/registration/events/model_node_became_active.py +103 -0
- omnibase_infra/models/registration/events/model_node_liveness_expired.py +103 -0
- omnibase_infra/models/registration/events/model_node_registration_accepted.py +98 -0
- omnibase_infra/models/registration/events/model_node_registration_ack_received.py +98 -0
- omnibase_infra/models/registration/events/model_node_registration_ack_timed_out.py +112 -0
- omnibase_infra/models/registration/events/model_node_registration_initiated.py +107 -0
- omnibase_infra/models/registration/events/model_node_registration_rejected.py +104 -0
- omnibase_infra/models/registration/model_introspection_metrics.py +253 -0
- omnibase_infra/models/registration/model_node_capabilities.py +179 -0
- omnibase_infra/models/registration/model_node_heartbeat_event.py +126 -0
- omnibase_infra/models/registration/model_node_introspection_event.py +175 -0
- omnibase_infra/models/registration/model_node_metadata.py +79 -0
- omnibase_infra/models/registration/model_node_registration.py +162 -0
- omnibase_infra/models/registration/model_node_registration_record.py +162 -0
- omnibase_infra/models/registry/__init__.py +29 -0
- omnibase_infra/models/registry/model_domain_constraint.py +202 -0
- omnibase_infra/models/registry/model_message_type_entry.py +271 -0
- omnibase_infra/models/resilience/__init__.py +9 -0
- omnibase_infra/models/resilience/model_circuit_breaker_config.py +227 -0
- omnibase_infra/models/routing/__init__.py +25 -0
- omnibase_infra/models/routing/model_routing_entry.py +52 -0
- omnibase_infra/models/routing/model_routing_subcontract.py +70 -0
- omnibase_infra/models/runtime/__init__.py +40 -0
- omnibase_infra/models/runtime/model_contract_security_config.py +41 -0
- omnibase_infra/models/runtime/model_discovery_error.py +81 -0
- omnibase_infra/models/runtime/model_discovery_result.py +162 -0
- omnibase_infra/models/runtime/model_discovery_warning.py +74 -0
- omnibase_infra/models/runtime/model_failed_plugin_load.py +63 -0
- omnibase_infra/models/runtime/model_handler_contract.py +280 -0
- omnibase_infra/models/runtime/model_loaded_handler.py +120 -0
- omnibase_infra/models/runtime/model_plugin_load_context.py +93 -0
- omnibase_infra/models/runtime/model_plugin_load_summary.py +124 -0
- omnibase_infra/models/security/__init__.py +50 -0
- omnibase_infra/models/security/classification_levels.py +99 -0
- omnibase_infra/models/security/model_environment_policy.py +145 -0
- omnibase_infra/models/security/model_handler_security_policy.py +107 -0
- omnibase_infra/models/security/model_security_error.py +81 -0
- omnibase_infra/models/security/model_security_validation_result.py +328 -0
- omnibase_infra/models/security/model_security_warning.py +67 -0
- omnibase_infra/models/snapshot/__init__.py +27 -0
- omnibase_infra/models/snapshot/model_field_change.py +65 -0
- omnibase_infra/models/snapshot/model_snapshot.py +270 -0
- omnibase_infra/models/snapshot/model_snapshot_diff.py +203 -0
- omnibase_infra/models/snapshot/model_subject_ref.py +81 -0
- omnibase_infra/models/types/__init__.py +71 -0
- omnibase_infra/models/validation/__init__.py +89 -0
- omnibase_infra/models/validation/model_any_type_validation_result.py +118 -0
- omnibase_infra/models/validation/model_any_type_violation.py +141 -0
- omnibase_infra/models/validation/model_category_match_result.py +345 -0
- omnibase_infra/models/validation/model_chain_violation.py +166 -0
- omnibase_infra/models/validation/model_coverage_metrics.py +316 -0
- omnibase_infra/models/validation/model_execution_shape_rule.py +159 -0
- omnibase_infra/models/validation/model_execution_shape_validation.py +208 -0
- omnibase_infra/models/validation/model_execution_shape_validation_result.py +294 -0
- omnibase_infra/models/validation/model_execution_shape_violation.py +122 -0
- omnibase_infra/models/validation/model_localhandler_validation_result.py +139 -0
- omnibase_infra/models/validation/model_localhandler_violation.py +100 -0
- omnibase_infra/models/validation/model_output_validation_params.py +74 -0
- omnibase_infra/models/validation/model_validate_and_raise_params.py +84 -0
- omnibase_infra/models/validation/model_validation_error_params.py +84 -0
- omnibase_infra/models/validation/model_validation_outcome.py +287 -0
- omnibase_infra/nodes/__init__.py +48 -0
- omnibase_infra/nodes/architecture_validator/__init__.py +79 -0
- omnibase_infra/nodes/architecture_validator/contract.yaml +252 -0
- omnibase_infra/nodes/architecture_validator/contract_architecture_validator.yaml +208 -0
- omnibase_infra/nodes/architecture_validator/mixins/__init__.py +16 -0
- omnibase_infra/nodes/architecture_validator/mixins/mixin_file_path_rule.py +92 -0
- omnibase_infra/nodes/architecture_validator/models/__init__.py +36 -0
- omnibase_infra/nodes/architecture_validator/models/model_architecture_validation_request.py +56 -0
- omnibase_infra/nodes/architecture_validator/models/model_architecture_validation_result.py +311 -0
- omnibase_infra/nodes/architecture_validator/models/model_architecture_violation.py +163 -0
- omnibase_infra/nodes/architecture_validator/models/model_rule_check_result.py +265 -0
- omnibase_infra/nodes/architecture_validator/models/model_validation_request.py +105 -0
- omnibase_infra/nodes/architecture_validator/models/model_validation_result.py +314 -0
- omnibase_infra/nodes/architecture_validator/node.py +262 -0
- omnibase_infra/nodes/architecture_validator/node_architecture_validator.py +383 -0
- omnibase_infra/nodes/architecture_validator/protocols/__init__.py +9 -0
- omnibase_infra/nodes/architecture_validator/protocols/protocol_architecture_rule.py +225 -0
- omnibase_infra/nodes/architecture_validator/registry/__init__.py +28 -0
- omnibase_infra/nodes/architecture_validator/registry/registry_infra_architecture_validator.py +99 -0
- omnibase_infra/nodes/architecture_validator/validators/__init__.py +104 -0
- omnibase_infra/nodes/architecture_validator/validators/validator_no_direct_dispatch.py +422 -0
- omnibase_infra/nodes/architecture_validator/validators/validator_no_handler_publishing.py +481 -0
- omnibase_infra/nodes/architecture_validator/validators/validator_no_orchestrator_fsm.py +491 -0
- omnibase_infra/nodes/effects/README.md +358 -0
- omnibase_infra/nodes/effects/__init__.py +26 -0
- omnibase_infra/nodes/effects/contract.yaml +172 -0
- omnibase_infra/nodes/effects/models/__init__.py +32 -0
- omnibase_infra/nodes/effects/models/model_backend_result.py +190 -0
- omnibase_infra/nodes/effects/models/model_effect_idempotency_config.py +92 -0
- omnibase_infra/nodes/effects/models/model_registry_request.py +132 -0
- omnibase_infra/nodes/effects/models/model_registry_response.py +263 -0
- omnibase_infra/nodes/effects/protocol_consul_client.py +89 -0
- omnibase_infra/nodes/effects/protocol_effect_idempotency_store.py +143 -0
- omnibase_infra/nodes/effects/protocol_postgres_adapter.py +96 -0
- omnibase_infra/nodes/effects/registry_effect.py +525 -0
- omnibase_infra/nodes/effects/store_effect_idempotency_inmemory.py +425 -0
- omnibase_infra/nodes/node_registration_orchestrator/README.md +542 -0
- omnibase_infra/nodes/node_registration_orchestrator/__init__.py +120 -0
- omnibase_infra/nodes/node_registration_orchestrator/contract.yaml +475 -0
- omnibase_infra/nodes/node_registration_orchestrator/dispatchers/__init__.py +53 -0
- omnibase_infra/nodes/node_registration_orchestrator/dispatchers/dispatcher_node_introspected.py +376 -0
- omnibase_infra/nodes/node_registration_orchestrator/dispatchers/dispatcher_node_registration_acked.py +376 -0
- omnibase_infra/nodes/node_registration_orchestrator/dispatchers/dispatcher_runtime_tick.py +373 -0
- omnibase_infra/nodes/node_registration_orchestrator/handlers/__init__.py +62 -0
- omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_heartbeat.py +376 -0
- omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_introspected.py +609 -0
- omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_registration_acked.py +458 -0
- omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_runtime_tick.py +364 -0
- omnibase_infra/nodes/node_registration_orchestrator/introspection_event_router.py +544 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/__init__.py +75 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_consul_intent_payload.py +194 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_consul_registration_intent.py +67 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_intent_execution_result.py +50 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_node_liveness_expired.py +107 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_orchestrator_config.py +67 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_orchestrator_input.py +41 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_orchestrator_output.py +166 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_postgres_intent_payload.py +235 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_postgres_upsert_intent.py +68 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_reducer_execution_result.py +384 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_reducer_state.py +60 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_registration_intent.py +177 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_registry_intent.py +247 -0
- omnibase_infra/nodes/node_registration_orchestrator/node.py +195 -0
- omnibase_infra/nodes/node_registration_orchestrator/plugin.py +909 -0
- omnibase_infra/nodes/node_registration_orchestrator/protocols.py +439 -0
- omnibase_infra/nodes/node_registration_orchestrator/registry/__init__.py +41 -0
- omnibase_infra/nodes/node_registration_orchestrator/registry/registry_infra_node_registration_orchestrator.py +525 -0
- omnibase_infra/nodes/node_registration_orchestrator/timeout_coordinator.py +392 -0
- omnibase_infra/nodes/node_registration_orchestrator/wiring.py +742 -0
- omnibase_infra/nodes/node_registration_reducer/__init__.py +15 -0
- omnibase_infra/nodes/node_registration_reducer/contract.yaml +301 -0
- omnibase_infra/nodes/node_registration_reducer/models/__init__.py +38 -0
- omnibase_infra/nodes/node_registration_reducer/models/model_validation_result.py +113 -0
- omnibase_infra/nodes/node_registration_reducer/node.py +139 -0
- omnibase_infra/nodes/node_registration_reducer/registry/__init__.py +9 -0
- omnibase_infra/nodes/node_registration_reducer/registry/registry_infra_node_registration_reducer.py +79 -0
- omnibase_infra/nodes/node_registration_storage_effect/__init__.py +41 -0
- omnibase_infra/nodes/node_registration_storage_effect/contract.yaml +225 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/__init__.py +44 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_delete_result.py +132 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_registration_record.py +199 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_registration_update.py +155 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_storage_health_check_details.py +123 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_storage_health_check_result.py +117 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_storage_query.py +100 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_storage_result.py +136 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_upsert_result.py +127 -0
- omnibase_infra/nodes/node_registration_storage_effect/node.py +109 -0
- omnibase_infra/nodes/node_registration_storage_effect/protocols/__init__.py +22 -0
- omnibase_infra/nodes/node_registration_storage_effect/protocols/protocol_registration_persistence.py +333 -0
- omnibase_infra/nodes/node_registration_storage_effect/registry/__init__.py +23 -0
- omnibase_infra/nodes/node_registration_storage_effect/registry/registry_infra_registration_storage.py +194 -0
- omnibase_infra/nodes/node_registry_effect/__init__.py +85 -0
- omnibase_infra/nodes/node_registry_effect/contract.yaml +682 -0
- omnibase_infra/nodes/node_registry_effect/handlers/__init__.py +70 -0
- omnibase_infra/nodes/node_registry_effect/handlers/handler_consul_deregister.py +211 -0
- omnibase_infra/nodes/node_registry_effect/handlers/handler_consul_register.py +212 -0
- omnibase_infra/nodes/node_registry_effect/handlers/handler_partial_retry.py +416 -0
- omnibase_infra/nodes/node_registry_effect/handlers/handler_postgres_deactivate.py +215 -0
- omnibase_infra/nodes/node_registry_effect/handlers/handler_postgres_upsert.py +208 -0
- omnibase_infra/nodes/node_registry_effect/models/__init__.py +43 -0
- omnibase_infra/nodes/node_registry_effect/models/model_partial_retry_request.py +92 -0
- omnibase_infra/nodes/node_registry_effect/node.py +165 -0
- omnibase_infra/nodes/node_registry_effect/registry/__init__.py +27 -0
- omnibase_infra/nodes/node_registry_effect/registry/registry_infra_registry_effect.py +196 -0
- omnibase_infra/nodes/node_service_discovery_effect/__init__.py +111 -0
- omnibase_infra/nodes/node_service_discovery_effect/contract.yaml +246 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/__init__.py +67 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/enum_health_status.py +72 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/enum_service_discovery_operation.py +58 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_discovery_query.py +99 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_discovery_result.py +98 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_health_check_config.py +121 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_query_metadata.py +63 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_registration_result.py +130 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_service_discovery_health_check_details.py +111 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_service_discovery_health_check_result.py +119 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_service_info.py +106 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_service_registration.py +121 -0
- omnibase_infra/nodes/node_service_discovery_effect/node.py +111 -0
- omnibase_infra/nodes/node_service_discovery_effect/protocols/__init__.py +14 -0
- omnibase_infra/nodes/node_service_discovery_effect/protocols/protocol_discovery_operations.py +279 -0
- omnibase_infra/nodes/node_service_discovery_effect/registry/__init__.py +13 -0
- omnibase_infra/nodes/node_service_discovery_effect/registry/registry_infra_service_discovery.py +214 -0
- omnibase_infra/nodes/reducers/__init__.py +30 -0
- omnibase_infra/nodes/reducers/models/__init__.py +32 -0
- omnibase_infra/nodes/reducers/models/model_payload_consul_register.py +76 -0
- omnibase_infra/nodes/reducers/models/model_payload_postgres_upsert_registration.py +60 -0
- omnibase_infra/nodes/reducers/models/model_registration_confirmation.py +166 -0
- omnibase_infra/nodes/reducers/models/model_registration_state.py +433 -0
- omnibase_infra/nodes/reducers/registration_reducer.py +1137 -0
- omnibase_infra/observability/__init__.py +143 -0
- omnibase_infra/observability/constants_metrics.py +91 -0
- omnibase_infra/observability/factory_observability_sink.py +525 -0
- omnibase_infra/observability/handlers/__init__.py +118 -0
- omnibase_infra/observability/handlers/handler_logging_structured.py +967 -0
- omnibase_infra/observability/handlers/handler_metrics_prometheus.py +1120 -0
- omnibase_infra/observability/handlers/model_logging_handler_config.py +71 -0
- omnibase_infra/observability/handlers/model_logging_handler_response.py +77 -0
- omnibase_infra/observability/handlers/model_metrics_handler_config.py +172 -0
- omnibase_infra/observability/handlers/model_metrics_handler_payload.py +135 -0
- omnibase_infra/observability/handlers/model_metrics_handler_response.py +101 -0
- omnibase_infra/observability/hooks/__init__.py +74 -0
- omnibase_infra/observability/hooks/hook_observability.py +1223 -0
- omnibase_infra/observability/models/__init__.py +30 -0
- omnibase_infra/observability/models/enum_required_log_context_key.py +77 -0
- omnibase_infra/observability/models/model_buffered_log_entry.py +117 -0
- omnibase_infra/observability/models/model_logging_sink_config.py +73 -0
- omnibase_infra/observability/models/model_metrics_sink_config.py +156 -0
- omnibase_infra/observability/sinks/__init__.py +69 -0
- omnibase_infra/observability/sinks/sink_logging_structured.py +809 -0
- omnibase_infra/observability/sinks/sink_metrics_prometheus.py +710 -0
- omnibase_infra/plugins/__init__.py +27 -0
- omnibase_infra/plugins/examples/__init__.py +28 -0
- omnibase_infra/plugins/examples/plugin_json_normalizer.py +271 -0
- omnibase_infra/plugins/examples/plugin_json_normalizer_error_handling.py +210 -0
- omnibase_infra/plugins/models/__init__.py +21 -0
- omnibase_infra/plugins/models/model_plugin_context.py +76 -0
- omnibase_infra/plugins/models/model_plugin_input_data.py +58 -0
- omnibase_infra/plugins/models/model_plugin_output_data.py +62 -0
- omnibase_infra/plugins/plugin_compute_base.py +435 -0
- omnibase_infra/projectors/__init__.py +30 -0
- omnibase_infra/projectors/contracts/__init__.py +63 -0
- omnibase_infra/projectors/contracts/registration_projector.yaml +370 -0
- omnibase_infra/projectors/projection_reader_registration.py +1559 -0
- omnibase_infra/projectors/snapshot_publisher_registration.py +1329 -0
- omnibase_infra/protocols/__init__.py +99 -0
- omnibase_infra/protocols/protocol_capability_projection.py +253 -0
- omnibase_infra/protocols/protocol_capability_query.py +251 -0
- omnibase_infra/protocols/protocol_event_bus_like.py +127 -0
- omnibase_infra/protocols/protocol_event_projector.py +96 -0
- omnibase_infra/protocols/protocol_idempotency_store.py +142 -0
- omnibase_infra/protocols/protocol_message_dispatcher.py +247 -0
- omnibase_infra/protocols/protocol_message_type_registry.py +306 -0
- omnibase_infra/protocols/protocol_plugin_compute.py +368 -0
- omnibase_infra/protocols/protocol_projector_schema_validator.py +82 -0
- omnibase_infra/protocols/protocol_registry_metrics.py +215 -0
- omnibase_infra/protocols/protocol_snapshot_publisher.py +396 -0
- omnibase_infra/protocols/protocol_snapshot_store.py +567 -0
- omnibase_infra/runtime/__init__.py +296 -0
- omnibase_infra/runtime/binding_config_resolver.py +2706 -0
- omnibase_infra/runtime/chain_aware_dispatch.py +467 -0
- omnibase_infra/runtime/contract_handler_discovery.py +582 -0
- omnibase_infra/runtime/contract_loaders/__init__.py +42 -0
- omnibase_infra/runtime/contract_loaders/handler_routing_loader.py +464 -0
- omnibase_infra/runtime/dispatch_context_enforcer.py +427 -0
- omnibase_infra/runtime/enums/__init__.py +18 -0
- omnibase_infra/runtime/enums/enum_config_ref_scheme.py +33 -0
- omnibase_infra/runtime/enums/enum_scheduler_status.py +170 -0
- omnibase_infra/runtime/envelope_validator.py +179 -0
- omnibase_infra/runtime/handler_contract_source.py +669 -0
- omnibase_infra/runtime/handler_plugin_loader.py +2029 -0
- omnibase_infra/runtime/handler_registry.py +321 -0
- omnibase_infra/runtime/invocation_security_enforcer.py +427 -0
- omnibase_infra/runtime/kernel.py +40 -0
- omnibase_infra/runtime/mixin_policy_validation.py +522 -0
- omnibase_infra/runtime/mixin_semver_cache.py +378 -0
- omnibase_infra/runtime/mixins/__init__.py +17 -0
- omnibase_infra/runtime/mixins/mixin_projector_sql_operations.py +757 -0
- omnibase_infra/runtime/models/__init__.py +192 -0
- omnibase_infra/runtime/models/model_batch_lifecycle_result.py +217 -0
- omnibase_infra/runtime/models/model_binding_config.py +168 -0
- omnibase_infra/runtime/models/model_binding_config_cache_stats.py +135 -0
- omnibase_infra/runtime/models/model_binding_config_resolver_config.py +329 -0
- omnibase_infra/runtime/models/model_cached_secret.py +138 -0
- omnibase_infra/runtime/models/model_compute_key.py +138 -0
- omnibase_infra/runtime/models/model_compute_registration.py +97 -0
- omnibase_infra/runtime/models/model_config_cache_entry.py +61 -0
- omnibase_infra/runtime/models/model_config_ref.py +331 -0
- omnibase_infra/runtime/models/model_config_ref_parse_result.py +125 -0
- omnibase_infra/runtime/models/model_domain_plugin_config.py +92 -0
- omnibase_infra/runtime/models/model_domain_plugin_result.py +270 -0
- omnibase_infra/runtime/models/model_duplicate_response.py +54 -0
- omnibase_infra/runtime/models/model_enabled_protocols_config.py +61 -0
- omnibase_infra/runtime/models/model_event_bus_config.py +54 -0
- omnibase_infra/runtime/models/model_failed_component.py +55 -0
- omnibase_infra/runtime/models/model_health_check_response.py +168 -0
- omnibase_infra/runtime/models/model_health_check_result.py +228 -0
- omnibase_infra/runtime/models/model_lifecycle_result.py +245 -0
- omnibase_infra/runtime/models/model_logging_config.py +42 -0
- omnibase_infra/runtime/models/model_optional_correlation_id.py +167 -0
- omnibase_infra/runtime/models/model_optional_string.py +94 -0
- omnibase_infra/runtime/models/model_optional_uuid.py +110 -0
- omnibase_infra/runtime/models/model_policy_context.py +100 -0
- omnibase_infra/runtime/models/model_policy_key.py +138 -0
- omnibase_infra/runtime/models/model_policy_registration.py +139 -0
- omnibase_infra/runtime/models/model_policy_result.py +103 -0
- omnibase_infra/runtime/models/model_policy_type_filter.py +157 -0
- omnibase_infra/runtime/models/model_projector_plugin_loader_config.py +47 -0
- omnibase_infra/runtime/models/model_protocol_registration_config.py +65 -0
- omnibase_infra/runtime/models/model_retry_policy.py +105 -0
- omnibase_infra/runtime/models/model_runtime_config.py +150 -0
- omnibase_infra/runtime/models/model_runtime_scheduler_config.py +624 -0
- omnibase_infra/runtime/models/model_runtime_scheduler_metrics.py +233 -0
- omnibase_infra/runtime/models/model_runtime_tick.py +193 -0
- omnibase_infra/runtime/models/model_secret_cache_stats.py +82 -0
- omnibase_infra/runtime/models/model_secret_mapping.py +63 -0
- omnibase_infra/runtime/models/model_secret_resolver_config.py +107 -0
- omnibase_infra/runtime/models/model_secret_resolver_metrics.py +111 -0
- omnibase_infra/runtime/models/model_secret_source_info.py +72 -0
- omnibase_infra/runtime/models/model_secret_source_spec.py +66 -0
- omnibase_infra/runtime/models/model_shutdown_batch_result.py +75 -0
- omnibase_infra/runtime/models/model_shutdown_config.py +94 -0
- omnibase_infra/runtime/projector_plugin_loader.py +1462 -0
- omnibase_infra/runtime/projector_schema_manager.py +565 -0
- omnibase_infra/runtime/projector_shell.py +1102 -0
- omnibase_infra/runtime/protocol_contract_descriptor.py +92 -0
- omnibase_infra/runtime/protocol_contract_source.py +92 -0
- omnibase_infra/runtime/protocol_domain_plugin.py +474 -0
- omnibase_infra/runtime/protocol_handler_discovery.py +221 -0
- omnibase_infra/runtime/protocol_handler_plugin_loader.py +327 -0
- omnibase_infra/runtime/protocol_lifecycle_executor.py +435 -0
- omnibase_infra/runtime/protocol_policy.py +366 -0
- omnibase_infra/runtime/protocols/__init__.py +27 -0
- omnibase_infra/runtime/protocols/protocol_runtime_scheduler.py +468 -0
- omnibase_infra/runtime/registry/__init__.py +93 -0
- omnibase_infra/runtime/registry/mixin_message_type_query.py +326 -0
- omnibase_infra/runtime/registry/mixin_message_type_registration.py +354 -0
- omnibase_infra/runtime/registry/registry_event_bus_binding.py +268 -0
- omnibase_infra/runtime/registry/registry_message_type.py +542 -0
- omnibase_infra/runtime/registry/registry_protocol_binding.py +444 -0
- omnibase_infra/runtime/registry_compute.py +1143 -0
- omnibase_infra/runtime/registry_dispatcher.py +678 -0
- omnibase_infra/runtime/registry_policy.py +1502 -0
- omnibase_infra/runtime/runtime_scheduler.py +1070 -0
- omnibase_infra/runtime/secret_resolver.py +2110 -0
- omnibase_infra/runtime/security_metadata_validator.py +776 -0
- omnibase_infra/runtime/service_kernel.py +1573 -0
- omnibase_infra/runtime/service_message_dispatch_engine.py +1805 -0
- omnibase_infra/runtime/service_runtime_host_process.py +2260 -0
- omnibase_infra/runtime/util_container_wiring.py +1123 -0
- omnibase_infra/runtime/util_validation.py +314 -0
- omnibase_infra/runtime/util_version.py +98 -0
- omnibase_infra/runtime/util_wiring.py +566 -0
- omnibase_infra/schemas/schema_registration_projection.sql +320 -0
- omnibase_infra/services/__init__.py +68 -0
- omnibase_infra/services/corpus_capture.py +678 -0
- omnibase_infra/services/service_capability_query.py +945 -0
- omnibase_infra/services/service_health.py +897 -0
- omnibase_infra/services/service_node_selector.py +530 -0
- omnibase_infra/services/service_timeout_emitter.py +682 -0
- omnibase_infra/services/service_timeout_scanner.py +390 -0
- omnibase_infra/services/snapshot/__init__.py +31 -0
- omnibase_infra/services/snapshot/service_snapshot.py +647 -0
- omnibase_infra/services/snapshot/store_inmemory.py +637 -0
- omnibase_infra/services/snapshot/store_postgres.py +1279 -0
- omnibase_infra/shared/__init__.py +8 -0
- omnibase_infra/testing/__init__.py +10 -0
- omnibase_infra/testing/utils.py +23 -0
- omnibase_infra/types/__init__.py +48 -0
- omnibase_infra/types/type_cache_info.py +49 -0
- omnibase_infra/types/type_dsn.py +173 -0
- omnibase_infra/types/type_infra_aliases.py +60 -0
- omnibase_infra/types/typed_dict/__init__.py +21 -0
- omnibase_infra/types/typed_dict/typed_dict_introspection_cache.py +128 -0
- omnibase_infra/types/typed_dict/typed_dict_performance_metrics_cache.py +140 -0
- omnibase_infra/types/typed_dict_capabilities.py +64 -0
- omnibase_infra/utils/__init__.py +89 -0
- omnibase_infra/utils/correlation.py +208 -0
- omnibase_infra/utils/util_datetime.py +372 -0
- omnibase_infra/utils/util_dsn_validation.py +333 -0
- omnibase_infra/utils/util_env_parsing.py +264 -0
- omnibase_infra/utils/util_error_sanitization.py +457 -0
- omnibase_infra/utils/util_pydantic_validators.py +477 -0
- omnibase_infra/utils/util_semver.py +233 -0
- omnibase_infra/validation/__init__.py +307 -0
- omnibase_infra/validation/enums/__init__.py +11 -0
- omnibase_infra/validation/enums/enum_contract_violation_severity.py +13 -0
- omnibase_infra/validation/infra_validators.py +1486 -0
- omnibase_infra/validation/linter_contract.py +907 -0
- omnibase_infra/validation/mixin_any_type_classification.py +120 -0
- omnibase_infra/validation/mixin_any_type_exemption.py +580 -0
- omnibase_infra/validation/mixin_any_type_reporting.py +106 -0
- omnibase_infra/validation/mixin_execution_shape_violation_checks.py +596 -0
- omnibase_infra/validation/mixin_node_archetype_detection.py +254 -0
- omnibase_infra/validation/models/__init__.py +15 -0
- omnibase_infra/validation/models/model_contract_lint_result.py +101 -0
- omnibase_infra/validation/models/model_contract_violation.py +41 -0
- omnibase_infra/validation/service_validation_aggregator.py +395 -0
- omnibase_infra/validation/validation_exemptions.yaml +1710 -0
- omnibase_infra/validation/validator_any_type.py +715 -0
- omnibase_infra/validation/validator_chain_propagation.py +839 -0
- omnibase_infra/validation/validator_execution_shape.py +465 -0
- omnibase_infra/validation/validator_localhandler.py +261 -0
- omnibase_infra/validation/validator_registration_security.py +410 -0
- omnibase_infra/validation/validator_routing_coverage.py +1020 -0
- omnibase_infra/validation/validator_runtime_shape.py +915 -0
- omnibase_infra/validation/validator_security.py +410 -0
- omnibase_infra/validation/validator_topic_category.py +1152 -0
- omnibase_infra-0.2.1.dist-info/METADATA +197 -0
- omnibase_infra-0.2.1.dist-info/RECORD +675 -0
- omnibase_infra-0.2.1.dist-info/WHEEL +4 -0
- omnibase_infra-0.2.1.dist-info/entry_points.txt +4 -0
- omnibase_infra-0.2.1.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,743 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2025 OmniNode Team
|
|
3
|
+
"""In-Memory Event Bus implementation for local development and testing.
|
|
4
|
+
|
|
5
|
+
Implements ProtocolEventBus interface using deque-based event history with
|
|
6
|
+
direct subscriber callback invocation. This implementation is designed for
|
|
7
|
+
local development and testing scenarios where a full message broker (Kafka)
|
|
8
|
+
is not needed.
|
|
9
|
+
|
|
10
|
+
Features:
|
|
11
|
+
- Topic-based message routing with FIFO ordering
|
|
12
|
+
- Async publish/subscribe with callback handlers
|
|
13
|
+
- Event history tracking for debugging and testing
|
|
14
|
+
- Async-safe operations using asyncio.Lock
|
|
15
|
+
- No external dependencies required
|
|
16
|
+
- Support for environment/group-based routing
|
|
17
|
+
|
|
18
|
+
Usage:
|
|
19
|
+
```python
|
|
20
|
+
from omnibase_infra.event_bus.event_bus_inmemory import EventBusInmemory
|
|
21
|
+
|
|
22
|
+
bus = EventBusInmemory(environment="dev", group="test")
|
|
23
|
+
await bus.start()
|
|
24
|
+
|
|
25
|
+
# Subscribe to a topic
|
|
26
|
+
async def handler(msg):
|
|
27
|
+
print(f"Received: {msg.value}")
|
|
28
|
+
unsubscribe = await bus.subscribe("events", "group1", handler)
|
|
29
|
+
|
|
30
|
+
# Publish a message
|
|
31
|
+
await bus.publish("events", b"key", b"value")
|
|
32
|
+
|
|
33
|
+
# Cleanup
|
|
34
|
+
await unsubscribe()
|
|
35
|
+
await bus.close()
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Protocol Compatibility:
|
|
39
|
+
This class implements ProtocolEventBus from omnibase_core using duck typing
|
|
40
|
+
(no explicit inheritance required per ONEX patterns).
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
from __future__ import annotations
|
|
44
|
+
|
|
45
|
+
import asyncio
|
|
46
|
+
import json
|
|
47
|
+
import logging
|
|
48
|
+
from collections import defaultdict, deque
|
|
49
|
+
from collections.abc import Awaitable, Callable
|
|
50
|
+
from datetime import UTC, datetime
|
|
51
|
+
from uuid import uuid4
|
|
52
|
+
|
|
53
|
+
from omnibase_infra.enums import EnumInfraTransportType
|
|
54
|
+
from omnibase_infra.errors import (
|
|
55
|
+
InfraUnavailableError,
|
|
56
|
+
ModelInfraErrorContext,
|
|
57
|
+
ProtocolConfigurationError,
|
|
58
|
+
)
|
|
59
|
+
from omnibase_infra.event_bus.models import ModelEventHeaders, ModelEventMessage
|
|
60
|
+
|
|
61
|
+
logger = logging.getLogger(__name__)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class EventBusInmemory:
|
|
65
|
+
"""In-memory event bus for local development and testing.
|
|
66
|
+
|
|
67
|
+
Implements ProtocolEventBus interface using deque-based event history
|
|
68
|
+
with direct subscriber callback invocation. Async-safe operations are
|
|
69
|
+
ensured via asyncio.Lock. This implementation provides a lightweight
|
|
70
|
+
event bus for testing and local development without external dependencies.
|
|
71
|
+
|
|
72
|
+
Transport Type:
|
|
73
|
+
Uses EnumInfraTransportType.INMEMORY for error context and logging,
|
|
74
|
+
correctly identifying this as an in-memory transport (not KAFKA).
|
|
75
|
+
|
|
76
|
+
Default Configuration:
|
|
77
|
+
- environment: "local" - Appropriate for local development scenarios.
|
|
78
|
+
Tests typically override with "test" for clarity in logs.
|
|
79
|
+
- group: "default" - Generic consumer group identifier.
|
|
80
|
+
Tests typically override with test-specific group names.
|
|
81
|
+
- max_history: 1000 - Sufficient for most testing/debugging scenarios.
|
|
82
|
+
- circuit_breaker_threshold: 5 - Consecutive failures before circuit opens.
|
|
83
|
+
|
|
84
|
+
Features:
|
|
85
|
+
- Topic-based message routing with FIFO ordering
|
|
86
|
+
- Multiple subscribers per topic with group-based filtering
|
|
87
|
+
- Event history tracking with configurable retention
|
|
88
|
+
- Async-safe operations using asyncio.Lock
|
|
89
|
+
- Environment and group-based message routing
|
|
90
|
+
- Circuit breaker pattern for subscriber failure isolation
|
|
91
|
+
- Debugging utilities for inspecting event flow
|
|
92
|
+
|
|
93
|
+
Attributes:
|
|
94
|
+
environment: Environment identifier (e.g., "local", "dev", "test")
|
|
95
|
+
group: Consumer group identifier
|
|
96
|
+
adapter: Returns self (no separate adapter for in-memory)
|
|
97
|
+
|
|
98
|
+
Example:
|
|
99
|
+
```python
|
|
100
|
+
bus = EventBusInmemory(environment="dev", group="test")
|
|
101
|
+
await bus.start()
|
|
102
|
+
|
|
103
|
+
# Subscribe
|
|
104
|
+
async def handler(msg):
|
|
105
|
+
print(f"Received: {msg.value}")
|
|
106
|
+
unsubscribe = await bus.subscribe("events", "group1", handler)
|
|
107
|
+
|
|
108
|
+
# Publish
|
|
109
|
+
await bus.publish("events", b"key", b"value")
|
|
110
|
+
|
|
111
|
+
# Cleanup
|
|
112
|
+
await unsubscribe()
|
|
113
|
+
await bus.close()
|
|
114
|
+
```
|
|
115
|
+
"""
|
|
116
|
+
|
|
117
|
+
def __init__(
|
|
118
|
+
self,
|
|
119
|
+
environment: str = "local",
|
|
120
|
+
group: str = "default",
|
|
121
|
+
max_history: int = 1000,
|
|
122
|
+
circuit_breaker_threshold: int = 5,
|
|
123
|
+
) -> None:
|
|
124
|
+
"""Initialize the in-memory event bus.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
environment: Environment identifier for message routing
|
|
128
|
+
group: Consumer group identifier for message routing
|
|
129
|
+
max_history: Maximum number of events to retain in history
|
|
130
|
+
circuit_breaker_threshold: Number of consecutive failures before circuit opens
|
|
131
|
+
|
|
132
|
+
Raises:
|
|
133
|
+
ProtocolConfigurationError: If circuit_breaker_threshold is not a positive integer
|
|
134
|
+
"""
|
|
135
|
+
if circuit_breaker_threshold < 1:
|
|
136
|
+
context = ModelInfraErrorContext(
|
|
137
|
+
transport_type=EnumInfraTransportType.INMEMORY,
|
|
138
|
+
operation="init",
|
|
139
|
+
target_name="inmemory_event_bus",
|
|
140
|
+
correlation_id=uuid4(),
|
|
141
|
+
)
|
|
142
|
+
raise ProtocolConfigurationError(
|
|
143
|
+
f"circuit_breaker_threshold must be a positive integer, got {circuit_breaker_threshold}",
|
|
144
|
+
context=context,
|
|
145
|
+
parameter="circuit_breaker_threshold",
|
|
146
|
+
value=circuit_breaker_threshold,
|
|
147
|
+
)
|
|
148
|
+
self._environment = environment
|
|
149
|
+
self._group = group
|
|
150
|
+
self._max_history = max_history
|
|
151
|
+
|
|
152
|
+
# Topic -> list of (group_id, callback) tuples
|
|
153
|
+
self._subscribers: dict[
|
|
154
|
+
str, list[tuple[str, Callable[[ModelEventMessage], Awaitable[None]]]]
|
|
155
|
+
] = defaultdict(list)
|
|
156
|
+
|
|
157
|
+
# Event history for debugging (circular buffer with O(1) operations)
|
|
158
|
+
self._event_history: deque[ModelEventMessage] = deque(maxlen=max_history)
|
|
159
|
+
|
|
160
|
+
# Topic -> offset counter for message ordering
|
|
161
|
+
self._topic_offsets: dict[str, int] = defaultdict(int)
|
|
162
|
+
|
|
163
|
+
# Lock for coroutine safety
|
|
164
|
+
self._lock = asyncio.Lock()
|
|
165
|
+
|
|
166
|
+
# Started flag
|
|
167
|
+
self._started = False
|
|
168
|
+
|
|
169
|
+
# Shutdown flag for consuming loop
|
|
170
|
+
self._shutdown = False
|
|
171
|
+
|
|
172
|
+
# Subscriber failure tracking for circuit breaker pattern
|
|
173
|
+
# Maps (topic, group_id) to consecutive failure count
|
|
174
|
+
self._subscriber_failures: dict[tuple[str, str], int] = {}
|
|
175
|
+
self._max_consecutive_failures: int = circuit_breaker_threshold
|
|
176
|
+
|
|
177
|
+
@property
|
|
178
|
+
def adapter(self) -> EventBusInmemory:
|
|
179
|
+
"""No adapter for in-memory - returns self.
|
|
180
|
+
|
|
181
|
+
Returns:
|
|
182
|
+
Self reference (in-memory bus is its own adapter)
|
|
183
|
+
"""
|
|
184
|
+
return self
|
|
185
|
+
|
|
186
|
+
@property
|
|
187
|
+
def environment(self) -> str:
|
|
188
|
+
"""Get the environment identifier.
|
|
189
|
+
|
|
190
|
+
Returns:
|
|
191
|
+
Environment string (e.g., "local", "dev", "test")
|
|
192
|
+
"""
|
|
193
|
+
return self._environment
|
|
194
|
+
|
|
195
|
+
@property
|
|
196
|
+
def group(self) -> str:
|
|
197
|
+
"""Get the consumer group identifier.
|
|
198
|
+
|
|
199
|
+
Returns:
|
|
200
|
+
Consumer group string
|
|
201
|
+
"""
|
|
202
|
+
return self._group
|
|
203
|
+
|
|
204
|
+
async def start(self) -> None:
|
|
205
|
+
"""Start the event bus.
|
|
206
|
+
|
|
207
|
+
Initializes internal state and marks the bus as ready for operations.
|
|
208
|
+
This is a no-op for in-memory implementation but required for protocol.
|
|
209
|
+
"""
|
|
210
|
+
async with self._lock:
|
|
211
|
+
self._started = True
|
|
212
|
+
self._shutdown = False
|
|
213
|
+
logger.info(
|
|
214
|
+
"EventBusInmemory started",
|
|
215
|
+
extra={"environment": self._environment, "group": self._group},
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
async def initialize(self, config: dict[str, object]) -> None:
|
|
219
|
+
"""Initialize the event bus with configuration.
|
|
220
|
+
|
|
221
|
+
Protocol method for compatibility with ProtocolEventBus.
|
|
222
|
+
Extracts configuration and delegates to start().
|
|
223
|
+
|
|
224
|
+
Args:
|
|
225
|
+
config: Configuration dictionary with optional keys:
|
|
226
|
+
- environment: Override environment setting
|
|
227
|
+
- group: Override group setting
|
|
228
|
+
- max_history: Override max_history setting
|
|
229
|
+
"""
|
|
230
|
+
# Protect configuration updates with lock to prevent race conditions
|
|
231
|
+
async with self._lock:
|
|
232
|
+
if "environment" in config:
|
|
233
|
+
self._environment = str(config["environment"])
|
|
234
|
+
if "group" in config:
|
|
235
|
+
self._group = str(config["group"])
|
|
236
|
+
if "max_history" in config:
|
|
237
|
+
self._max_history = int(str(config["max_history"]))
|
|
238
|
+
# Recreate deque with new maxlen, preserving existing history
|
|
239
|
+
self._event_history = deque(
|
|
240
|
+
self._event_history, maxlen=self._max_history
|
|
241
|
+
)
|
|
242
|
+
# start() acquires its own lock, so call it outside the lock to avoid deadlock
|
|
243
|
+
await self.start()
|
|
244
|
+
|
|
245
|
+
async def shutdown(self) -> None:
|
|
246
|
+
"""Gracefully shutdown the event bus.
|
|
247
|
+
|
|
248
|
+
Protocol method that stops consuming and clears resources.
|
|
249
|
+
"""
|
|
250
|
+
await self.close()
|
|
251
|
+
|
|
252
|
+
async def publish(
|
|
253
|
+
self,
|
|
254
|
+
topic: str,
|
|
255
|
+
key: bytes | None,
|
|
256
|
+
value: bytes,
|
|
257
|
+
headers: ModelEventHeaders | None = None,
|
|
258
|
+
) -> None:
|
|
259
|
+
"""Publish message to topic.
|
|
260
|
+
|
|
261
|
+
Delivers the message to all subscribers registered for the topic.
|
|
262
|
+
Messages are delivered asynchronously but in FIFO order per subscriber.
|
|
263
|
+
|
|
264
|
+
Args:
|
|
265
|
+
topic: Target topic name
|
|
266
|
+
key: Optional message key (for future partitioning support)
|
|
267
|
+
value: Message payload as bytes
|
|
268
|
+
headers: Optional event headers with metadata
|
|
269
|
+
|
|
270
|
+
Raises:
|
|
271
|
+
InfraUnavailableError: If the bus has not been started
|
|
272
|
+
"""
|
|
273
|
+
if not self._started:
|
|
274
|
+
context = ModelInfraErrorContext(
|
|
275
|
+
transport_type=EnumInfraTransportType.INMEMORY,
|
|
276
|
+
operation="publish",
|
|
277
|
+
target_name=f"event_bus.{self._environment}",
|
|
278
|
+
correlation_id=(
|
|
279
|
+
headers.correlation_id if headers is not None else uuid4()
|
|
280
|
+
),
|
|
281
|
+
)
|
|
282
|
+
raise InfraUnavailableError(
|
|
283
|
+
"Event bus not started. Call start() first.",
|
|
284
|
+
context=context,
|
|
285
|
+
topic=topic,
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
# Create headers if not provided
|
|
289
|
+
if headers is None:
|
|
290
|
+
headers = ModelEventHeaders(
|
|
291
|
+
source=f"{self._environment}.{self._group}",
|
|
292
|
+
event_type=topic,
|
|
293
|
+
timestamp=datetime.now(UTC),
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
async with self._lock:
|
|
297
|
+
# Get next offset for topic
|
|
298
|
+
offset = self._topic_offsets[topic]
|
|
299
|
+
self._topic_offsets[topic] = offset + 1
|
|
300
|
+
|
|
301
|
+
message = ModelEventMessage(
|
|
302
|
+
topic=topic,
|
|
303
|
+
key=key,
|
|
304
|
+
value=value,
|
|
305
|
+
headers=headers,
|
|
306
|
+
offset=str(offset), # Convert int to string for Pydantic model
|
|
307
|
+
partition=0,
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
# Add to history (deque handles maxlen automatically with O(1) performance)
|
|
311
|
+
self._event_history.append(message)
|
|
312
|
+
|
|
313
|
+
# Get subscribers snapshot
|
|
314
|
+
subscribers = list(self._subscribers.get(topic, []))
|
|
315
|
+
|
|
316
|
+
# Call subscribers outside lock to avoid deadlocks
|
|
317
|
+
for group_id, callback in subscribers:
|
|
318
|
+
failure_key = (topic, group_id)
|
|
319
|
+
|
|
320
|
+
# Check if circuit is open (too many consecutive failures) - read under lock
|
|
321
|
+
async with self._lock:
|
|
322
|
+
failure_count = self._subscriber_failures.get(failure_key, 0)
|
|
323
|
+
|
|
324
|
+
if failure_count >= self._max_consecutive_failures:
|
|
325
|
+
logger.warning(
|
|
326
|
+
"Subscriber circuit breaker open - skipping callback",
|
|
327
|
+
extra={
|
|
328
|
+
"topic": topic,
|
|
329
|
+
"group_id": group_id,
|
|
330
|
+
"consecutive_failures": failure_count,
|
|
331
|
+
"correlation_id": str(headers.correlation_id),
|
|
332
|
+
},
|
|
333
|
+
)
|
|
334
|
+
continue
|
|
335
|
+
|
|
336
|
+
try:
|
|
337
|
+
await callback(message)
|
|
338
|
+
# Reset failure count on success - under lock
|
|
339
|
+
async with self._lock:
|
|
340
|
+
if failure_key in self._subscriber_failures:
|
|
341
|
+
del self._subscriber_failures[failure_key]
|
|
342
|
+
except Exception as e:
|
|
343
|
+
# Increment failure count - under lock
|
|
344
|
+
async with self._lock:
|
|
345
|
+
self._subscriber_failures[failure_key] = (
|
|
346
|
+
self._subscriber_failures.get(failure_key, 0) + 1
|
|
347
|
+
)
|
|
348
|
+
current_failure_count = self._subscriber_failures[failure_key]
|
|
349
|
+
# Log but don't fail other subscribers
|
|
350
|
+
logger.exception(
|
|
351
|
+
"Subscriber callback failed",
|
|
352
|
+
extra={
|
|
353
|
+
"topic": topic,
|
|
354
|
+
"group_id": group_id,
|
|
355
|
+
"error": str(e),
|
|
356
|
+
"consecutive_failures": current_failure_count,
|
|
357
|
+
"correlation_id": str(headers.correlation_id),
|
|
358
|
+
},
|
|
359
|
+
)
|
|
360
|
+
|
|
361
|
+
async def publish_envelope(
|
|
362
|
+
self,
|
|
363
|
+
envelope: object,
|
|
364
|
+
topic: str,
|
|
365
|
+
) -> None:
|
|
366
|
+
"""Publish an event envelope to a topic.
|
|
367
|
+
|
|
368
|
+
Protocol method for ProtocolEventBus compatibility.
|
|
369
|
+
Serializes the envelope to JSON bytes and publishes.
|
|
370
|
+
|
|
371
|
+
Envelope Structure:
|
|
372
|
+
The envelope is expected to be a Pydantic model (typically
|
|
373
|
+
ModelEventEnvelope from omnibase_core) with the following structure:
|
|
374
|
+
|
|
375
|
+
- correlation_id: UUID for tracing the event across services
|
|
376
|
+
- event_type: String identifying the event type
|
|
377
|
+
- payload: The event data (dict or Pydantic model)
|
|
378
|
+
- metadata: Optional metadata dict
|
|
379
|
+
- timestamp: When the event was created
|
|
380
|
+
|
|
381
|
+
Serialization:
|
|
382
|
+
- Pydantic models: Uses model_dump(mode="json")
|
|
383
|
+
- Legacy Pydantic v1: Uses dict()
|
|
384
|
+
- Dict objects: Passed through directly
|
|
385
|
+
- Other types: Serialized via json.dumps (may raise TypeError)
|
|
386
|
+
|
|
387
|
+
Args:
|
|
388
|
+
envelope: Envelope object to publish. Typically ModelEventEnvelope
|
|
389
|
+
from omnibase_core, but any object with model_dump(), dict(),
|
|
390
|
+
or dict-like structure is supported.
|
|
391
|
+
topic: Target topic name for publishing.
|
|
392
|
+
|
|
393
|
+
Raises:
|
|
394
|
+
InfraUnavailableError: If the bus has not been started.
|
|
395
|
+
ProtocolConfigurationError: If envelope cannot be JSON-serialized (explicit
|
|
396
|
+
handling provides clearer error messages than raw TypeError).
|
|
397
|
+
"""
|
|
398
|
+
# Serialize envelope to JSON bytes
|
|
399
|
+
# Note: envelope is expected to have a model_dump() method (Pydantic)
|
|
400
|
+
envelope_dict: object
|
|
401
|
+
if hasattr(envelope, "model_dump"):
|
|
402
|
+
# Use getattr for type-safe method access after hasattr check
|
|
403
|
+
model_dump_method = envelope.model_dump
|
|
404
|
+
envelope_dict = model_dump_method(mode="json")
|
|
405
|
+
elif hasattr(envelope, "dict"):
|
|
406
|
+
# Use getattr for type-safe method access after hasattr check
|
|
407
|
+
dict_method = envelope.dict
|
|
408
|
+
envelope_dict = dict_method()
|
|
409
|
+
elif isinstance(envelope, dict):
|
|
410
|
+
envelope_dict = envelope
|
|
411
|
+
else:
|
|
412
|
+
# Fallback for non-Pydantic, non-dict types (e.g., primitive JSON-serializable
|
|
413
|
+
# types like str, int, list). Explicit handling below catches TypeError.
|
|
414
|
+
envelope_dict = envelope
|
|
415
|
+
|
|
416
|
+
# Explicit error handling for non-serializable envelopes
|
|
417
|
+
# This provides clearer error messages than letting json.dumps raise raw TypeError
|
|
418
|
+
try:
|
|
419
|
+
value = json.dumps(envelope_dict).encode("utf-8")
|
|
420
|
+
except TypeError as e:
|
|
421
|
+
context = ModelInfraErrorContext(
|
|
422
|
+
transport_type=EnumInfraTransportType.INMEMORY,
|
|
423
|
+
operation="publish_envelope",
|
|
424
|
+
target_name=f"event_bus.{self._environment}",
|
|
425
|
+
correlation_id=uuid4(),
|
|
426
|
+
)
|
|
427
|
+
raise ProtocolConfigurationError(
|
|
428
|
+
f"Envelope is not JSON-serializable: {e}. "
|
|
429
|
+
f"Ensure envelope is a Pydantic model (with model_dump), dict, or "
|
|
430
|
+
f"JSON-compatible primitive. Got type: {type(envelope).__name__}",
|
|
431
|
+
context=context,
|
|
432
|
+
parameter="envelope",
|
|
433
|
+
value=str(type(envelope)),
|
|
434
|
+
) from e
|
|
435
|
+
|
|
436
|
+
headers = ModelEventHeaders(
|
|
437
|
+
source=f"{self._environment}.{self._group}",
|
|
438
|
+
event_type=topic,
|
|
439
|
+
content_type="application/json",
|
|
440
|
+
timestamp=datetime.now(UTC),
|
|
441
|
+
)
|
|
442
|
+
|
|
443
|
+
await self.publish(topic, None, value, headers)
|
|
444
|
+
|
|
445
|
+
async def subscribe(
|
|
446
|
+
self,
|
|
447
|
+
topic: str,
|
|
448
|
+
group_id: str,
|
|
449
|
+
on_message: Callable[[ModelEventMessage], Awaitable[None]],
|
|
450
|
+
) -> Callable[[], Awaitable[None]]:
|
|
451
|
+
"""Subscribe to topic with callback handler.
|
|
452
|
+
|
|
453
|
+
Registers a callback to be invoked for each message published to the topic.
|
|
454
|
+
Returns an unsubscribe function to remove the subscription.
|
|
455
|
+
|
|
456
|
+
Args:
|
|
457
|
+
topic: Topic to subscribe to
|
|
458
|
+
group_id: Consumer group identifier for this subscription
|
|
459
|
+
on_message: Async callback invoked for each message
|
|
460
|
+
|
|
461
|
+
Returns:
|
|
462
|
+
Async unsubscribe function to remove this subscription
|
|
463
|
+
|
|
464
|
+
Example:
|
|
465
|
+
```python
|
|
466
|
+
async def handler(msg):
|
|
467
|
+
print(f"Received: {msg.value}")
|
|
468
|
+
|
|
469
|
+
unsubscribe = await bus.subscribe("events", "group1", handler)
|
|
470
|
+
# ... later ...
|
|
471
|
+
await unsubscribe()
|
|
472
|
+
```
|
|
473
|
+
"""
|
|
474
|
+
async with self._lock:
|
|
475
|
+
self._subscribers[topic].append((group_id, on_message))
|
|
476
|
+
logger.debug(
|
|
477
|
+
"Subscriber added",
|
|
478
|
+
extra={"topic": topic, "group_id": group_id},
|
|
479
|
+
)
|
|
480
|
+
|
|
481
|
+
async def unsubscribe() -> None:
|
|
482
|
+
"""Remove this subscription from the topic."""
|
|
483
|
+
async with self._lock:
|
|
484
|
+
try:
|
|
485
|
+
self._subscribers[topic].remove((group_id, on_message))
|
|
486
|
+
logger.debug(
|
|
487
|
+
"Subscriber removed",
|
|
488
|
+
extra={"topic": topic, "group_id": group_id},
|
|
489
|
+
)
|
|
490
|
+
except ValueError:
|
|
491
|
+
# Already unsubscribed
|
|
492
|
+
pass
|
|
493
|
+
|
|
494
|
+
return unsubscribe
|
|
495
|
+
|
|
496
|
+
async def start_consuming(self) -> None:
|
|
497
|
+
"""Start the consumer loop.
|
|
498
|
+
|
|
499
|
+
Protocol method for ProtocolEventBus compatibility.
|
|
500
|
+
For in-memory implementation, this is a no-op as messages are
|
|
501
|
+
delivered synchronously in publish().
|
|
502
|
+
|
|
503
|
+
This method blocks until shutdown() is called (for protocol compatibility).
|
|
504
|
+
"""
|
|
505
|
+
if not self._started:
|
|
506
|
+
await self.start()
|
|
507
|
+
|
|
508
|
+
# For in-memory, we don't need a consuming loop since publish
|
|
509
|
+
# delivers messages synchronously. But we provide an async wait
|
|
510
|
+
# for protocol compatibility.
|
|
511
|
+
while not self._shutdown:
|
|
512
|
+
await asyncio.sleep(0.1)
|
|
513
|
+
|
|
514
|
+
async def broadcast_to_environment(
|
|
515
|
+
self,
|
|
516
|
+
command: str,
|
|
517
|
+
payload: dict[str, object],
|
|
518
|
+
target_environment: str | None = None,
|
|
519
|
+
) -> None:
|
|
520
|
+
"""Broadcast command to environment.
|
|
521
|
+
|
|
522
|
+
Sends a command message to all subscribers in the target environment.
|
|
523
|
+
|
|
524
|
+
Args:
|
|
525
|
+
command: Command identifier
|
|
526
|
+
payload: Command payload data
|
|
527
|
+
target_environment: Target environment (defaults to current)
|
|
528
|
+
"""
|
|
529
|
+
env = target_environment or self._environment
|
|
530
|
+
topic = f"{env}.broadcast"
|
|
531
|
+
value_dict = {"command": command, "payload": payload}
|
|
532
|
+
value = json.dumps(value_dict).encode("utf-8")
|
|
533
|
+
|
|
534
|
+
headers = ModelEventHeaders(
|
|
535
|
+
source=f"{self._environment}.{self._group}",
|
|
536
|
+
event_type="broadcast",
|
|
537
|
+
content_type="application/json",
|
|
538
|
+
timestamp=datetime.now(UTC),
|
|
539
|
+
)
|
|
540
|
+
|
|
541
|
+
await self.publish(topic, None, value, headers)
|
|
542
|
+
|
|
543
|
+
async def send_to_group(
|
|
544
|
+
self,
|
|
545
|
+
command: str,
|
|
546
|
+
payload: dict[str, object],
|
|
547
|
+
target_group: str,
|
|
548
|
+
) -> None:
|
|
549
|
+
"""Send command to specific group.
|
|
550
|
+
|
|
551
|
+
Sends a command message to all subscribers in a specific group.
|
|
552
|
+
|
|
553
|
+
Args:
|
|
554
|
+
command: Command identifier
|
|
555
|
+
payload: Command payload data
|
|
556
|
+
target_group: Target group identifier
|
|
557
|
+
"""
|
|
558
|
+
topic = f"{self._environment}.{target_group}"
|
|
559
|
+
value_dict = {"command": command, "payload": payload}
|
|
560
|
+
value = json.dumps(value_dict).encode("utf-8")
|
|
561
|
+
|
|
562
|
+
headers = ModelEventHeaders(
|
|
563
|
+
source=f"{self._environment}.{self._group}",
|
|
564
|
+
event_type="group_command",
|
|
565
|
+
content_type="application/json",
|
|
566
|
+
timestamp=datetime.now(UTC),
|
|
567
|
+
)
|
|
568
|
+
|
|
569
|
+
await self.publish(topic, None, value, headers)
|
|
570
|
+
|
|
571
|
+
async def close(self) -> None:
|
|
572
|
+
"""Close the event bus and release resources.
|
|
573
|
+
|
|
574
|
+
Clears all subscribers, failure tracking, and marks the bus as stopped.
|
|
575
|
+
"""
|
|
576
|
+
async with self._lock:
|
|
577
|
+
self._subscribers.clear()
|
|
578
|
+
self._subscriber_failures.clear()
|
|
579
|
+
self._started = False
|
|
580
|
+
self._shutdown = True
|
|
581
|
+
logger.info(
|
|
582
|
+
"EventBusInmemory closed",
|
|
583
|
+
extra={"environment": self._environment, "group": self._group},
|
|
584
|
+
)
|
|
585
|
+
|
|
586
|
+
async def health_check(self) -> dict[str, object]:
|
|
587
|
+
"""Check event bus health.
|
|
588
|
+
|
|
589
|
+
Protocol method for ProtocolEventBus compatibility.
|
|
590
|
+
|
|
591
|
+
Returns:
|
|
592
|
+
Dictionary with health status information:
|
|
593
|
+
- healthy: Whether the bus is operational
|
|
594
|
+
- started: Whether start() has been called
|
|
595
|
+
- environment: Current environment
|
|
596
|
+
- group: Current consumer group
|
|
597
|
+
- subscriber_count: Total number of active subscriptions
|
|
598
|
+
- topic_count: Number of topics with subscribers
|
|
599
|
+
- history_size: Current event history size
|
|
600
|
+
"""
|
|
601
|
+
async with self._lock:
|
|
602
|
+
subscriber_count = sum(len(subs) for subs in self._subscribers.values())
|
|
603
|
+
topic_count = len(self._subscribers)
|
|
604
|
+
history_size = len(self._event_history)
|
|
605
|
+
|
|
606
|
+
return {
|
|
607
|
+
"healthy": self._started,
|
|
608
|
+
"started": self._started,
|
|
609
|
+
"environment": self._environment,
|
|
610
|
+
"group": self._group,
|
|
611
|
+
"subscriber_count": subscriber_count,
|
|
612
|
+
"topic_count": topic_count,
|
|
613
|
+
"history_size": history_size,
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
# =========================================================================
|
|
617
|
+
# Debugging/Observability Methods
|
|
618
|
+
# =========================================================================
|
|
619
|
+
|
|
620
|
+
async def get_event_history(
|
|
621
|
+
self,
|
|
622
|
+
limit: int = 100,
|
|
623
|
+
topic: str | None = None,
|
|
624
|
+
) -> list[ModelEventMessage]:
|
|
625
|
+
"""Get recent events for debugging.
|
|
626
|
+
|
|
627
|
+
Args:
|
|
628
|
+
limit: Maximum number of events to return
|
|
629
|
+
topic: Optional topic filter
|
|
630
|
+
|
|
631
|
+
Returns:
|
|
632
|
+
List of recent events (most recent last)
|
|
633
|
+
"""
|
|
634
|
+
async with self._lock:
|
|
635
|
+
# Convert deque to list for filtering operations
|
|
636
|
+
history_list = list(self._event_history)
|
|
637
|
+
|
|
638
|
+
# Apply topic filter FIRST (if specified)
|
|
639
|
+
if topic:
|
|
640
|
+
history_list = [msg for msg in history_list if msg.topic == topic]
|
|
641
|
+
|
|
642
|
+
# Then apply limit (take the most recent N messages)
|
|
643
|
+
history = (
|
|
644
|
+
history_list[-limit:] if limit < len(history_list) else history_list
|
|
645
|
+
)
|
|
646
|
+
return list(history)
|
|
647
|
+
|
|
648
|
+
async def clear_event_history(self) -> None:
|
|
649
|
+
"""Clear event history.
|
|
650
|
+
|
|
651
|
+
Useful for test isolation between test cases.
|
|
652
|
+
"""
|
|
653
|
+
async with self._lock:
|
|
654
|
+
self._event_history.clear()
|
|
655
|
+
logger.debug("Event history cleared")
|
|
656
|
+
|
|
657
|
+
async def get_subscriber_count(self, topic: str | None = None) -> int:
|
|
658
|
+
"""Get subscriber count, optionally filtered by topic.
|
|
659
|
+
|
|
660
|
+
Args:
|
|
661
|
+
topic: Optional topic to filter by
|
|
662
|
+
|
|
663
|
+
Returns:
|
|
664
|
+
Number of active subscriptions
|
|
665
|
+
"""
|
|
666
|
+
async with self._lock:
|
|
667
|
+
if topic:
|
|
668
|
+
return len(self._subscribers.get(topic, []))
|
|
669
|
+
return sum(len(subs) for subs in self._subscribers.values())
|
|
670
|
+
|
|
671
|
+
async def get_topics(self) -> list[str]:
|
|
672
|
+
"""Get list of topics with active subscribers.
|
|
673
|
+
|
|
674
|
+
Returns:
|
|
675
|
+
List of topic names with at least one subscriber
|
|
676
|
+
"""
|
|
677
|
+
async with self._lock:
|
|
678
|
+
return [topic for topic, subs in self._subscribers.items() if subs]
|
|
679
|
+
|
|
680
|
+
async def get_topic_offset(self, topic: str) -> int:
|
|
681
|
+
"""Get current offset for a topic.
|
|
682
|
+
|
|
683
|
+
Args:
|
|
684
|
+
topic: Topic name
|
|
685
|
+
|
|
686
|
+
Returns:
|
|
687
|
+
Current offset (number of messages published to topic)
|
|
688
|
+
"""
|
|
689
|
+
async with self._lock:
|
|
690
|
+
return self._topic_offsets.get(topic, 0)
|
|
691
|
+
|
|
692
|
+
# =========================================================================
|
|
693
|
+
# Circuit Breaker Methods
|
|
694
|
+
# =========================================================================
|
|
695
|
+
|
|
696
|
+
async def reset_subscriber_circuit(self, topic: str, group_id: str) -> bool:
|
|
697
|
+
"""Reset the circuit breaker for a specific subscriber.
|
|
698
|
+
|
|
699
|
+
Clears the failure count for the specified topic/group_id combination,
|
|
700
|
+
allowing the subscriber to receive messages again.
|
|
701
|
+
|
|
702
|
+
Args:
|
|
703
|
+
topic: Topic name
|
|
704
|
+
group_id: Consumer group identifier
|
|
705
|
+
|
|
706
|
+
Returns:
|
|
707
|
+
True if the circuit was reset, False if there was no circuit to reset
|
|
708
|
+
"""
|
|
709
|
+
failure_key = (topic, group_id)
|
|
710
|
+
async with self._lock:
|
|
711
|
+
if failure_key in self._subscriber_failures:
|
|
712
|
+
del self._subscriber_failures[failure_key]
|
|
713
|
+
logger.info(
|
|
714
|
+
"Subscriber circuit breaker reset",
|
|
715
|
+
extra={"topic": topic, "group_id": group_id},
|
|
716
|
+
)
|
|
717
|
+
return True
|
|
718
|
+
return False
|
|
719
|
+
|
|
720
|
+
async def get_circuit_breaker_status(self) -> dict[str, object]:
|
|
721
|
+
"""Get circuit breaker status for all subscribers.
|
|
722
|
+
|
|
723
|
+
Returns:
|
|
724
|
+
Dictionary with circuit breaker status information:
|
|
725
|
+
- open_circuits: List of dicts with topic/group_id for open circuits
|
|
726
|
+
- failure_counts: Dict mapping "topic:group_id" to failure count
|
|
727
|
+
"""
|
|
728
|
+
async with self._lock:
|
|
729
|
+
open_circuits = [
|
|
730
|
+
{"topic": topic, "group_id": group_id}
|
|
731
|
+
for (topic, group_id), count in self._subscriber_failures.items()
|
|
732
|
+
if count >= self._max_consecutive_failures
|
|
733
|
+
]
|
|
734
|
+
return {
|
|
735
|
+
"open_circuits": open_circuits,
|
|
736
|
+
"failure_counts": {
|
|
737
|
+
f"{topic}:{group_id}": count
|
|
738
|
+
for (topic, group_id), count in self._subscriber_failures.items()
|
|
739
|
+
},
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
|
|
743
|
+
__all__: list[str] = ["EventBusInmemory"]
|