omnibase_infra 0.2.6__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/adapters/adapter_onex_tool_execution.py +451 -0
- omnibase_infra/capabilities/__init__.py +15 -0
- omnibase_infra/capabilities/capability_inference_rules.py +211 -0
- omnibase_infra/capabilities/contract_capability_extractor.py +221 -0
- omnibase_infra/capabilities/intent_type_extractor.py +160 -0
- omnibase_infra/cli/__init__.py +1 -0
- omnibase_infra/cli/commands.py +216 -0
- omnibase_infra/clients/__init__.py +0 -0
- omnibase_infra/configs/widget_mapping.yaml +176 -0
- omnibase_infra/constants_topic_patterns.py +26 -0
- omnibase_infra/contracts/handlers/filesystem/handler_contract.yaml +264 -0
- omnibase_infra/contracts/handlers/mcp/handler_contract.yaml +141 -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 +132 -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_consumer_group_purpose.py +92 -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 +111 -0
- omnibase_infra/enums/enum_handler_loader_error.py +178 -0
- omnibase_infra/enums/enum_handler_source_mode.py +86 -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_kafka_acks.py +99 -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 +160 -0
- omnibase_infra/errors/error_architecture_violation.py +152 -0
- omnibase_infra/errors/error_binding_resolution.py +128 -0
- omnibase_infra/errors/error_chain_propagation.py +188 -0
- omnibase_infra/errors/error_compute_registry.py +95 -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 +105 -0
- omnibase_infra/errors/error_infra.py +610 -0
- omnibase_infra/errors/error_message_type_registry.py +101 -0
- omnibase_infra/errors/error_policy_registry.py +115 -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 +84 -0
- omnibase_infra/event_bus/event_bus_inmemory.py +797 -0
- omnibase_infra/event_bus/event_bus_kafka.py +1716 -0
- omnibase_infra/event_bus/mixin_kafka_broadcast.py +180 -0
- omnibase_infra/event_bus/mixin_kafka_dlq.py +771 -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 +693 -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/testing/__init__.py +26 -0
- omnibase_infra/event_bus/testing/adapter_protocol_event_publisher_inmemory.py +418 -0
- omnibase_infra/event_bus/testing/model_publisher_metrics.py +64 -0
- omnibase_infra/event_bus/topic_constants.py +376 -0
- omnibase_infra/handlers/__init__.py +82 -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 +795 -0
- omnibase_infra/handlers/handler_db.py +1046 -0
- omnibase_infra/handlers/handler_filesystem.py +1478 -0
- omnibase_infra/handlers/handler_graph.py +2015 -0
- omnibase_infra/handlers/handler_http.py +926 -0
- omnibase_infra/handlers/handler_intent.py +387 -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 +1430 -0
- omnibase_infra/handlers/handler_qdrant.py +1076 -0
- omnibase_infra/handlers/handler_vault.py +428 -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 +47 -0
- omnibase_infra/handlers/mixins/mixin_consul_initialization.py +349 -0
- omnibase_infra/handlers/mixins/mixin_consul_kv.py +338 -0
- omnibase_infra/handlers/mixins/mixin_consul_service.py +542 -0
- omnibase_infra/handlers/mixins/mixin_consul_topic_index.py +585 -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 +922 -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 +1051 -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 +109 -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/migrations/001_create_event_ledger.sql +166 -0
- omnibase_infra/migrations/001_drop_event_ledger.sql +18 -0
- omnibase_infra/mixins/__init__.py +71 -0
- omnibase_infra/mixins/mixin_async_circuit_breaker.py +656 -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 +2670 -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 +144 -0
- omnibase_infra/models/bindings/__init__.py +59 -0
- omnibase_infra/models/bindings/constants.py +144 -0
- omnibase_infra/models/bindings/model_binding_resolution_result.py +103 -0
- omnibase_infra/models/bindings/model_operation_binding.py +44 -0
- omnibase_infra/models/bindings/model_operation_bindings_subcontract.py +152 -0
- omnibase_infra/models/bindings/model_parsed_binding.py +52 -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 +330 -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 +155 -0
- omnibase_infra/models/dispatch/model_debug_trace_snapshot.py +114 -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_materialized_dispatch.py +141 -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 +80 -0
- omnibase_infra/models/handlers/model_bootstrap_handler_descriptor.py +162 -0
- omnibase_infra/models/handlers/model_contract_discovery_result.py +82 -0
- omnibase_infra/models/handlers/model_handler_descriptor.py +200 -0
- omnibase_infra/models/handlers/model_handler_identifier.py +215 -0
- omnibase_infra/models/handlers/model_handler_source_config.py +220 -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/mcp/__init__.py +15 -0
- omnibase_infra/models/mcp/model_mcp_contract_config.py +80 -0
- omnibase_infra/models/mcp/model_mcp_server_config.py +67 -0
- omnibase_infra/models/mcp/model_mcp_tool_definition.py +73 -0
- omnibase_infra/models/mcp/model_mcp_tool_parameter.py +35 -0
- omnibase_infra/models/model_node_identity.py +126 -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 +591 -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 +68 -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_event_bus_topic_entry.py +59 -0
- omnibase_infra/models/registration/model_introspection_metrics.py +253 -0
- omnibase_infra/models/registration/model_node_capabilities.py +190 -0
- omnibase_infra/models/registration/model_node_event_bus_config.py +99 -0
- omnibase_infra/models/registration/model_node_heartbeat_event.py +126 -0
- omnibase_infra/models/registration/model_node_introspection_event.py +195 -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 +49 -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 +296 -0
- omnibase_infra/models/runtime/model_loaded_handler.py +129 -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 +57 -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 +203 -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 +106 -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/contract_registry_reducer/__init__.py +29 -0
- omnibase_infra/nodes/contract_registry_reducer/contract.yaml +255 -0
- omnibase_infra/nodes/contract_registry_reducer/models/__init__.py +38 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_contract_registry_state.py +266 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_payload_cleanup_topic_references.py +55 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_payload_deactivate_contract.py +58 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_payload_mark_stale.py +49 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_payload_update_heartbeat.py +71 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_payload_update_topic.py +66 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_payload_upsert_contract.py +92 -0
- omnibase_infra/nodes/contract_registry_reducer/node.py +121 -0
- omnibase_infra/nodes/contract_registry_reducer/reducer.py +784 -0
- omnibase_infra/nodes/contract_registry_reducer/registry/__init__.py +9 -0
- omnibase_infra/nodes/contract_registry_reducer/registry/registry_infra_contract_registry_reducer.py +101 -0
- omnibase_infra/nodes/effects/README.md +358 -0
- omnibase_infra/nodes/effects/__init__.py +26 -0
- omnibase_infra/nodes/effects/contract.yaml +167 -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/handlers/consul/contract.yaml +85 -0
- omnibase_infra/nodes/handlers/db/contract.yaml +72 -0
- omnibase_infra/nodes/handlers/graph/contract.yaml +127 -0
- omnibase_infra/nodes/handlers/http/contract.yaml +74 -0
- omnibase_infra/nodes/handlers/intent/contract.yaml +66 -0
- omnibase_infra/nodes/handlers/mcp/contract.yaml +69 -0
- omnibase_infra/nodes/handlers/vault/contract.yaml +91 -0
- omnibase_infra/nodes/node_intent_storage_effect/__init__.py +50 -0
- omnibase_infra/nodes/node_intent_storage_effect/contract.yaml +194 -0
- omnibase_infra/nodes/node_intent_storage_effect/models/__init__.py +24 -0
- omnibase_infra/nodes/node_intent_storage_effect/models/model_intent_storage_input.py +141 -0
- omnibase_infra/nodes/node_intent_storage_effect/models/model_intent_storage_output.py +130 -0
- omnibase_infra/nodes/node_intent_storage_effect/node.py +94 -0
- omnibase_infra/nodes/node_intent_storage_effect/registry/__init__.py +35 -0
- omnibase_infra/nodes/node_intent_storage_effect/registry/registry_infra_intent_storage.py +294 -0
- omnibase_infra/nodes/node_ledger_projection_compute/__init__.py +50 -0
- omnibase_infra/nodes/node_ledger_projection_compute/contract.yaml +104 -0
- omnibase_infra/nodes/node_ledger_projection_compute/node.py +284 -0
- omnibase_infra/nodes/node_ledger_projection_compute/registry/__init__.py +29 -0
- omnibase_infra/nodes/node_ledger_projection_compute/registry/registry_infra_ledger_projection.py +118 -0
- omnibase_infra/nodes/node_ledger_write_effect/__init__.py +82 -0
- omnibase_infra/nodes/node_ledger_write_effect/contract.yaml +200 -0
- omnibase_infra/nodes/node_ledger_write_effect/handlers/__init__.py +22 -0
- omnibase_infra/nodes/node_ledger_write_effect/handlers/handler_ledger_append.py +372 -0
- omnibase_infra/nodes/node_ledger_write_effect/handlers/handler_ledger_query.py +597 -0
- omnibase_infra/nodes/node_ledger_write_effect/models/__init__.py +31 -0
- omnibase_infra/nodes/node_ledger_write_effect/models/model_ledger_append_result.py +54 -0
- omnibase_infra/nodes/node_ledger_write_effect/models/model_ledger_entry.py +92 -0
- omnibase_infra/nodes/node_ledger_write_effect/models/model_ledger_query.py +53 -0
- omnibase_infra/nodes/node_ledger_write_effect/models/model_ledger_query_result.py +41 -0
- omnibase_infra/nodes/node_ledger_write_effect/node.py +89 -0
- omnibase_infra/nodes/node_ledger_write_effect/protocols/__init__.py +13 -0
- omnibase_infra/nodes/node_ledger_write_effect/protocols/protocol_ledger_persistence.py +127 -0
- omnibase_infra/nodes/node_ledger_write_effect/registry/__init__.py +9 -0
- omnibase_infra/nodes/node_ledger_write_effect/registry/registry_infra_ledger_write.py +121 -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 +482 -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 +694 -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 +528 -0
- omnibase_infra/nodes/node_registration_orchestrator/timeout_coordinator.py +393 -0
- omnibase_infra/nodes/node_registration_orchestrator/wiring.py +743 -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 +220 -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 +112 -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 +215 -0
- omnibase_infra/nodes/node_registry_effect/__init__.py +85 -0
- omnibase_infra/nodes/node_registry_effect/contract.yaml +677 -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 +417 -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 +222 -0
- omnibase_infra/nodes/reducers/__init__.py +30 -0
- omnibase_infra/nodes/reducers/models/__init__.py +37 -0
- omnibase_infra/nodes/reducers/models/model_payload_consul_register.py +87 -0
- omnibase_infra/nodes/reducers/models/model_payload_ledger_append.py +133 -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 +1138 -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 +449 -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 +104 -0
- omnibase_infra/protocols/protocol_capability_projection.py +253 -0
- omnibase_infra/protocols/protocol_capability_query.py +251 -0
- omnibase_infra/protocols/protocol_container_aware.py +200 -0
- omnibase_infra/protocols/protocol_dispatch_engine.py +152 -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 +445 -0
- omnibase_infra/runtime/binding_config_resolver.py +2771 -0
- omnibase_infra/runtime/binding_resolver.py +753 -0
- omnibase_infra/runtime/chain_aware_dispatch.py +467 -0
- omnibase_infra/runtime/constants_notification.py +75 -0
- omnibase_infra/runtime/constants_security.py +70 -0
- omnibase_infra/runtime/contract_handler_discovery.py +587 -0
- omnibase_infra/runtime/contract_loaders/__init__.py +51 -0
- omnibase_infra/runtime/contract_loaders/handler_routing_loader.py +464 -0
- omnibase_infra/runtime/contract_loaders/operation_bindings_loader.py +789 -0
- omnibase_infra/runtime/dispatch_context_enforcer.py +427 -0
- omnibase_infra/runtime/emit_daemon/__init__.py +97 -0
- omnibase_infra/runtime/emit_daemon/cli.py +844 -0
- omnibase_infra/runtime/emit_daemon/client.py +811 -0
- omnibase_infra/runtime/emit_daemon/config.py +535 -0
- omnibase_infra/runtime/emit_daemon/daemon.py +812 -0
- omnibase_infra/runtime/emit_daemon/event_registry.py +477 -0
- omnibase_infra/runtime/emit_daemon/model_daemon_request.py +139 -0
- omnibase_infra/runtime/emit_daemon/model_daemon_response.py +191 -0
- omnibase_infra/runtime/emit_daemon/queue.py +618 -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/event_bus_subcontract_wiring.py +466 -0
- omnibase_infra/runtime/handler_bootstrap_source.py +507 -0
- omnibase_infra/runtime/handler_contract_config_loader.py +603 -0
- omnibase_infra/runtime/handler_contract_source.py +750 -0
- omnibase_infra/runtime/handler_identity.py +81 -0
- omnibase_infra/runtime/handler_plugin_loader.py +2046 -0
- omnibase_infra/runtime/handler_registry.py +329 -0
- omnibase_infra/runtime/handler_source_resolver.py +367 -0
- omnibase_infra/runtime/invocation_security_enforcer.py +427 -0
- omnibase_infra/runtime/kafka_contract_source.py +984 -0
- omnibase_infra/runtime/kernel.py +40 -0
- omnibase_infra/runtime/mixin_policy_validation.py +522 -0
- omnibase_infra/runtime/mixin_semver_cache.py +402 -0
- omnibase_infra/runtime/mixins/__init__.py +24 -0
- omnibase_infra/runtime/mixins/mixin_projector_notification_publishing.py +566 -0
- omnibase_infra/runtime/mixins/mixin_projector_sql_operations.py +778 -0
- omnibase_infra/runtime/models/__init__.py +229 -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_contract_load_result.py +224 -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 +229 -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_notification_config.py +171 -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_contract_config.py +268 -0
- omnibase_infra/runtime/models/model_runtime_scheduler_config.py +625 -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_security_config.py +109 -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/models/model_transition_notification_outbox_config.py +112 -0
- omnibase_infra/runtime/models/model_transition_notification_outbox_metrics.py +140 -0
- omnibase_infra/runtime/models/model_transition_notification_publisher_metrics.py +357 -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 +1330 -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 +37 -0
- omnibase_infra/runtime/protocols/protocol_runtime_scheduler.py +468 -0
- omnibase_infra/runtime/publisher_topic_scoped.py +294 -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 +445 -0
- omnibase_infra/runtime/registry_compute.py +1143 -0
- omnibase_infra/runtime/registry_contract_source.py +693 -0
- omnibase_infra/runtime/registry_dispatcher.py +678 -0
- omnibase_infra/runtime/registry_policy.py +1185 -0
- omnibase_infra/runtime/runtime_contract_config_loader.py +406 -0
- omnibase_infra/runtime/runtime_scheduler.py +1070 -0
- omnibase_infra/runtime/secret_resolver.py +2112 -0
- omnibase_infra/runtime/security_metadata_validator.py +776 -0
- omnibase_infra/runtime/service_kernel.py +1651 -0
- omnibase_infra/runtime/service_message_dispatch_engine.py +2350 -0
- omnibase_infra/runtime/service_runtime_host_process.py +3493 -0
- omnibase_infra/runtime/transition_notification_outbox.py +1190 -0
- omnibase_infra/runtime/transition_notification_publisher.py +765 -0
- omnibase_infra/runtime/util_container_wiring.py +1124 -0
- omnibase_infra/runtime/util_validation.py +314 -0
- omnibase_infra/runtime/util_version.py +98 -0
- omnibase_infra/runtime/util_wiring.py +723 -0
- omnibase_infra/schemas/schema_registration_projection.sql +320 -0
- omnibase_infra/schemas/schema_transition_notification_outbox.sql +245 -0
- omnibase_infra/services/__init__.py +89 -0
- omnibase_infra/services/corpus_capture.py +684 -0
- omnibase_infra/services/mcp/__init__.py +31 -0
- omnibase_infra/services/mcp/mcp_server_lifecycle.py +449 -0
- omnibase_infra/services/mcp/service_mcp_tool_discovery.py +411 -0
- omnibase_infra/services/mcp/service_mcp_tool_registry.py +329 -0
- omnibase_infra/services/mcp/service_mcp_tool_sync.py +565 -0
- omnibase_infra/services/registry_api/__init__.py +40 -0
- omnibase_infra/services/registry_api/main.py +261 -0
- omnibase_infra/services/registry_api/models/__init__.py +66 -0
- omnibase_infra/services/registry_api/models/model_capability_widget_mapping.py +38 -0
- omnibase_infra/services/registry_api/models/model_pagination_info.py +48 -0
- omnibase_infra/services/registry_api/models/model_registry_discovery_response.py +73 -0
- omnibase_infra/services/registry_api/models/model_registry_health_response.py +49 -0
- omnibase_infra/services/registry_api/models/model_registry_instance_view.py +88 -0
- omnibase_infra/services/registry_api/models/model_registry_node_view.py +88 -0
- omnibase_infra/services/registry_api/models/model_registry_summary.py +60 -0
- omnibase_infra/services/registry_api/models/model_response_list_instances.py +43 -0
- omnibase_infra/services/registry_api/models/model_response_list_nodes.py +51 -0
- omnibase_infra/services/registry_api/models/model_warning.py +49 -0
- omnibase_infra/services/registry_api/models/model_widget_defaults.py +28 -0
- omnibase_infra/services/registry_api/models/model_widget_mapping.py +51 -0
- omnibase_infra/services/registry_api/routes.py +371 -0
- omnibase_infra/services/registry_api/service.py +837 -0
- omnibase_infra/services/service_capability_query.py +945 -0
- omnibase_infra/services/service_health.py +898 -0
- omnibase_infra/services/service_node_selector.py +530 -0
- omnibase_infra/services/service_timeout_emitter.py +699 -0
- omnibase_infra/services/service_timeout_scanner.py +394 -0
- omnibase_infra/services/session/__init__.py +56 -0
- omnibase_infra/services/session/config_consumer.py +137 -0
- omnibase_infra/services/session/config_store.py +139 -0
- omnibase_infra/services/session/consumer.py +1007 -0
- omnibase_infra/services/session/protocol_session_aggregator.py +117 -0
- omnibase_infra/services/session/store.py +997 -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/topics/__init__.py +45 -0
- omnibase_infra/topics/platform_topic_suffixes.py +140 -0
- omnibase_infra/topics/util_topic_composition.py +95 -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 +29 -0
- omnibase_infra/types/typed_dict/typed_dict_envelope_build_params.py +115 -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 +117 -0
- omnibase_infra/utils/correlation.py +208 -0
- omnibase_infra/utils/util_atomic_file.py +261 -0
- omnibase_infra/utils/util_consumer_group.py +232 -0
- omnibase_infra/utils/util_datetime.py +372 -0
- omnibase_infra/utils/util_db_transaction.py +239 -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_retry_optimistic.py +281 -0
- omnibase_infra/utils/util_semver.py +233 -0
- omnibase_infra/validation/__init__.py +307 -0
- omnibase_infra/validation/contracts/security.validation.yaml +114 -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 +1514 -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 +2033 -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 +513 -0
- omnibase_infra/validation/validator_topic_category.py +1152 -0
- omnibase_infra-0.2.6.dist-info/METADATA +197 -0
- omnibase_infra-0.2.6.dist-info/RECORD +833 -0
- omnibase_infra-0.2.6.dist-info/WHEEL +4 -0
- omnibase_infra-0.2.6.dist-info/entry_points.txt +5 -0
- omnibase_infra-0.2.6.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,611 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2025 OmniNode Team
|
|
3
|
+
# ruff: noqa: S608
|
|
4
|
+
# S608 disabled: All SQL f-strings use storage_table which is validated via:
|
|
5
|
+
# 1. Pydantic regex pattern (PATTERN_TABLE_NAME) in ModelDlqTrackingConfig
|
|
6
|
+
# 2. Runtime validation in _validate_storage_table() (defense-in-depth)
|
|
7
|
+
# Both use the shared PATTERN_TABLE_NAME constant from constants_dlq.py.
|
|
8
|
+
# This defense-in-depth approach ensures only valid PostgreSQL identifiers are used,
|
|
9
|
+
# preventing SQL injection even if config validation is somehow bypassed.
|
|
10
|
+
"""DLQ Replay Tracking Service.
|
|
11
|
+
|
|
12
|
+
This module provides a PostgreSQL-based service for tracking DLQ replay
|
|
13
|
+
operations, enabling persistent history of replay attempts.
|
|
14
|
+
|
|
15
|
+
The service uses asyncpg for async database operations and provides
|
|
16
|
+
methods for recording replay attempts and querying replay history.
|
|
17
|
+
|
|
18
|
+
Table Schema:
|
|
19
|
+
CREATE TABLE IF NOT EXISTS dlq_replay_history (
|
|
20
|
+
id UUID PRIMARY KEY,
|
|
21
|
+
original_message_id UUID NOT NULL,
|
|
22
|
+
replay_correlation_id UUID NOT NULL,
|
|
23
|
+
original_topic VARCHAR(255) NOT NULL,
|
|
24
|
+
target_topic VARCHAR(255) NOT NULL,
|
|
25
|
+
replay_status VARCHAR(50) NOT NULL,
|
|
26
|
+
replay_timestamp TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
|
|
27
|
+
success BOOLEAN NOT NULL,
|
|
28
|
+
error_message TEXT,
|
|
29
|
+
dlq_offset BIGINT NOT NULL,
|
|
30
|
+
dlq_partition INTEGER NOT NULL,
|
|
31
|
+
retry_count INTEGER NOT NULL DEFAULT 0
|
|
32
|
+
);
|
|
33
|
+
CREATE INDEX IF NOT EXISTS idx_dlq_replay_message_id ON dlq_replay_history(original_message_id);
|
|
34
|
+
CREATE INDEX IF NOT EXISTS idx_dlq_replay_timestamp ON dlq_replay_history(replay_timestamp);
|
|
35
|
+
|
|
36
|
+
Security Note:
|
|
37
|
+
- DSN contains credentials - never log the raw value
|
|
38
|
+
- Use parameterized queries to prevent SQL injection
|
|
39
|
+
- Connection pool handles credential management
|
|
40
|
+
- Table names are validated at both config and runtime level (defense-in-depth)
|
|
41
|
+
|
|
42
|
+
Related:
|
|
43
|
+
- scripts/dlq_replay.py - CLI tool that uses this service
|
|
44
|
+
- OMN-1032 - PostgreSQL tracking integration ticket
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
from __future__ import annotations
|
|
48
|
+
|
|
49
|
+
import logging
|
|
50
|
+
from uuid import UUID, uuid4
|
|
51
|
+
|
|
52
|
+
import asyncpg
|
|
53
|
+
|
|
54
|
+
from omnibase_infra.dlq.constants_dlq import PATTERN_TABLE_NAME, REGEX_TABLE_NAME
|
|
55
|
+
from omnibase_infra.dlq.models import (
|
|
56
|
+
EnumReplayStatus,
|
|
57
|
+
ModelDlqReplayRecord,
|
|
58
|
+
ModelDlqTrackingConfig,
|
|
59
|
+
)
|
|
60
|
+
from omnibase_infra.enums import EnumInfraTransportType
|
|
61
|
+
from omnibase_infra.errors import (
|
|
62
|
+
InfraConnectionError,
|
|
63
|
+
InfraTimeoutError,
|
|
64
|
+
ModelInfraErrorContext,
|
|
65
|
+
ModelTimeoutErrorContext,
|
|
66
|
+
ProtocolConfigurationError,
|
|
67
|
+
RuntimeHostError,
|
|
68
|
+
)
|
|
69
|
+
from omnibase_infra.mixins import MixinAsyncCircuitBreaker
|
|
70
|
+
from omnibase_infra.models.resilience import ModelCircuitBreakerConfig
|
|
71
|
+
|
|
72
|
+
logger = logging.getLogger(__name__)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class ServiceDlqTracking(MixinAsyncCircuitBreaker):
|
|
76
|
+
"""PostgreSQL-based service for tracking DLQ replay operations.
|
|
77
|
+
|
|
78
|
+
This service provides persistent storage for DLQ replay history,
|
|
79
|
+
enabling operators to track which messages have been replayed,
|
|
80
|
+
when, and with what outcome.
|
|
81
|
+
|
|
82
|
+
Features:
|
|
83
|
+
- Async PostgreSQL operations via asyncpg
|
|
84
|
+
- Connection pooling for efficient database access
|
|
85
|
+
- Replay history tracking with correlation IDs
|
|
86
|
+
- Query methods for replay history analysis
|
|
87
|
+
- Defense-in-depth table name validation for SQL injection prevention
|
|
88
|
+
- Circuit breaker pattern for fault tolerance (via MixinAsyncCircuitBreaker)
|
|
89
|
+
|
|
90
|
+
Circuit Breaker Pattern (Production-Grade):
|
|
91
|
+
- Uses MixinAsyncCircuitBreaker for consistent circuit breaker implementation
|
|
92
|
+
- Prevents cascading failures to PostgreSQL service
|
|
93
|
+
- Three states: CLOSED (normal), OPEN (blocking), HALF_OPEN (testing)
|
|
94
|
+
- Configurable failure_threshold (default: 5 consecutive failures)
|
|
95
|
+
- Configurable reset_timeout (default: 60 seconds)
|
|
96
|
+
- Raises InfraUnavailableError when circuit is OPEN
|
|
97
|
+
|
|
98
|
+
Security:
|
|
99
|
+
Table names are validated at two levels:
|
|
100
|
+
1. Pydantic config model: regex pattern on storage_table field
|
|
101
|
+
2. Runtime validation: _validate_storage_table() in __init__
|
|
102
|
+
|
|
103
|
+
This defense-in-depth approach ensures SQL injection prevention even
|
|
104
|
+
if the config validation is somehow bypassed (e.g., through direct
|
|
105
|
+
attribute assignment or deserialization from untrusted sources).
|
|
106
|
+
|
|
107
|
+
Thread Safety:
|
|
108
|
+
This service is thread-safe. The underlying asyncpg pool handles
|
|
109
|
+
connection management and concurrent access safely. Circuit breaker
|
|
110
|
+
operations are protected by async locks (via MixinAsyncCircuitBreaker).
|
|
111
|
+
|
|
112
|
+
Example:
|
|
113
|
+
>>> from uuid import uuid4
|
|
114
|
+
>>> from datetime import datetime, timezone
|
|
115
|
+
>>> config = ModelDlqTrackingConfig(
|
|
116
|
+
... dsn="postgresql://user:pass@localhost:5432/mydb",
|
|
117
|
+
... storage_table="dlq_replay_history",
|
|
118
|
+
... )
|
|
119
|
+
>>> service = ServiceDlqTracking(config)
|
|
120
|
+
>>> await service.initialize()
|
|
121
|
+
>>> try:
|
|
122
|
+
... record = ModelDlqReplayRecord(
|
|
123
|
+
... id=uuid4(),
|
|
124
|
+
... original_message_id=uuid4(),
|
|
125
|
+
... replay_correlation_id=uuid4(),
|
|
126
|
+
... original_topic="dev.orders.command.v1",
|
|
127
|
+
... target_topic="dev.orders.command.v1",
|
|
128
|
+
... replay_status=EnumReplayStatus.COMPLETED,
|
|
129
|
+
... replay_timestamp=datetime.now(timezone.utc),
|
|
130
|
+
... success=True,
|
|
131
|
+
... dlq_offset=12345,
|
|
132
|
+
... dlq_partition=0,
|
|
133
|
+
... retry_count=1,
|
|
134
|
+
... )
|
|
135
|
+
... await service.record_replay_attempt(record)
|
|
136
|
+
... finally:
|
|
137
|
+
... await service.shutdown()
|
|
138
|
+
"""
|
|
139
|
+
|
|
140
|
+
def __init__(self, config: ModelDlqTrackingConfig) -> None:
|
|
141
|
+
"""Initialize the DLQ tracking service.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
config: Configuration model containing DSN and pool settings.
|
|
145
|
+
|
|
146
|
+
Raises:
|
|
147
|
+
ProtocolConfigurationError: If storage_table contains invalid characters
|
|
148
|
+
(defense-in-depth validation for SQL injection prevention).
|
|
149
|
+
"""
|
|
150
|
+
self._config = config
|
|
151
|
+
self._pool: asyncpg.Pool | None = None
|
|
152
|
+
self._initialized: bool = False
|
|
153
|
+
|
|
154
|
+
# Initialize circuit breaker for PostgreSQL fault tolerance
|
|
155
|
+
# Uses MixinAsyncCircuitBreaker for consistent implementation across infra services
|
|
156
|
+
cb_config = ModelCircuitBreakerConfig.from_env(
|
|
157
|
+
service_name="dlq_tracking_service",
|
|
158
|
+
transport_type=EnumInfraTransportType.DATABASE,
|
|
159
|
+
)
|
|
160
|
+
self._init_circuit_breaker_from_config(cb_config)
|
|
161
|
+
|
|
162
|
+
# Defense-in-depth: Validate table name at runtime even though
|
|
163
|
+
# Pydantic config already validates it. This protects against:
|
|
164
|
+
# - Direct attribute assignment bypassing Pydantic validation
|
|
165
|
+
# - Deserialization from untrusted sources
|
|
166
|
+
# - Future code changes that might bypass config validation
|
|
167
|
+
self._validate_storage_table(config.storage_table)
|
|
168
|
+
|
|
169
|
+
@property
|
|
170
|
+
def is_initialized(self) -> bool:
|
|
171
|
+
"""Return True if the service has been initialized."""
|
|
172
|
+
return self._initialized
|
|
173
|
+
|
|
174
|
+
@property
|
|
175
|
+
def is_tracking_enabled(self) -> bool:
|
|
176
|
+
"""Return True if the service is initialized and ready to track replays.
|
|
177
|
+
|
|
178
|
+
This is an alias for is_initialized that provides clearer semantics
|
|
179
|
+
when the service is used specifically for replay tracking.
|
|
180
|
+
|
|
181
|
+
Returns:
|
|
182
|
+
True if tracking is available, False otherwise.
|
|
183
|
+
"""
|
|
184
|
+
return self._initialized and self._pool is not None
|
|
185
|
+
|
|
186
|
+
def _validate_storage_table(self, storage_table: str) -> None:
|
|
187
|
+
"""Validate storage table name for SQL injection prevention (defense-in-depth).
|
|
188
|
+
|
|
189
|
+
This method provides runtime validation of the storage table pattern,
|
|
190
|
+
complementing the Pydantic field validation in the config model.
|
|
191
|
+
Together they form a defense-in-depth approach to prevent SQL injection.
|
|
192
|
+
|
|
193
|
+
Both validations use the shared PATTERN_TABLE_NAME constant from
|
|
194
|
+
constants_dlq.py to ensure consistency. See that module for details
|
|
195
|
+
on why both validation layers are intentional and required.
|
|
196
|
+
|
|
197
|
+
Args:
|
|
198
|
+
storage_table: The storage table name to validate.
|
|
199
|
+
|
|
200
|
+
Raises:
|
|
201
|
+
ProtocolConfigurationError: If storage_table doesn't match the
|
|
202
|
+
expected pattern (PATTERN_TABLE_NAME constant).
|
|
203
|
+
"""
|
|
204
|
+
if not REGEX_TABLE_NAME.match(storage_table):
|
|
205
|
+
context = ModelInfraErrorContext.with_correlation(
|
|
206
|
+
transport_type=EnumInfraTransportType.DATABASE,
|
|
207
|
+
operation="validate_storage_table",
|
|
208
|
+
target_name="dlq_tracking_service",
|
|
209
|
+
)
|
|
210
|
+
raise ProtocolConfigurationError(
|
|
211
|
+
f"Invalid storage table: {storage_table}. "
|
|
212
|
+
f"Must match pattern {PATTERN_TABLE_NAME} "
|
|
213
|
+
"(letters, digits, underscores only, must start with letter or underscore)",
|
|
214
|
+
context=context,
|
|
215
|
+
parameter="storage_table",
|
|
216
|
+
value=storage_table,
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
async def initialize(self) -> None:
|
|
220
|
+
"""Initialize the connection pool and ensure table exists.
|
|
221
|
+
|
|
222
|
+
Creates the asyncpg connection pool and verifies (or creates)
|
|
223
|
+
the dlq_replay_history table with proper schema.
|
|
224
|
+
|
|
225
|
+
Raises:
|
|
226
|
+
InfraConnectionError: If database connection fails.
|
|
227
|
+
RuntimeHostError: If pool creation or table setup fails.
|
|
228
|
+
"""
|
|
229
|
+
if self._initialized:
|
|
230
|
+
return
|
|
231
|
+
|
|
232
|
+
correlation_id = uuid4()
|
|
233
|
+
context = ModelInfraErrorContext(
|
|
234
|
+
transport_type=EnumInfraTransportType.DATABASE,
|
|
235
|
+
operation="initialize",
|
|
236
|
+
target_name="dlq_tracking_service",
|
|
237
|
+
correlation_id=correlation_id,
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
try:
|
|
241
|
+
self._pool = await asyncpg.create_pool(
|
|
242
|
+
dsn=self._config.dsn,
|
|
243
|
+
min_size=self._config.pool_min_size,
|
|
244
|
+
max_size=self._config.pool_max_size,
|
|
245
|
+
command_timeout=self._config.command_timeout,
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
# Ensure table exists with proper schema
|
|
249
|
+
await self._ensure_table_exists()
|
|
250
|
+
|
|
251
|
+
self._initialized = True
|
|
252
|
+
logger.info(
|
|
253
|
+
"ServiceDlqTracking initialized",
|
|
254
|
+
extra={
|
|
255
|
+
"table_name": self._config.storage_table,
|
|
256
|
+
"pool_min_size": self._config.pool_min_size,
|
|
257
|
+
"pool_max_size": self._config.pool_max_size,
|
|
258
|
+
},
|
|
259
|
+
)
|
|
260
|
+
except asyncpg.InvalidPasswordError as e:
|
|
261
|
+
raise InfraConnectionError(
|
|
262
|
+
"Database authentication failed - check credentials",
|
|
263
|
+
context=context,
|
|
264
|
+
) from e
|
|
265
|
+
except asyncpg.InvalidCatalogNameError as e:
|
|
266
|
+
raise InfraConnectionError(
|
|
267
|
+
"Database not found - check database name",
|
|
268
|
+
context=context,
|
|
269
|
+
) from e
|
|
270
|
+
except OSError as e:
|
|
271
|
+
raise InfraConnectionError(
|
|
272
|
+
"Failed to connect to database - check host and port",
|
|
273
|
+
context=context,
|
|
274
|
+
) from e
|
|
275
|
+
except Exception as e:
|
|
276
|
+
raise RuntimeHostError(
|
|
277
|
+
f"Failed to initialize DLQ tracking service: {type(e).__name__}",
|
|
278
|
+
context=context,
|
|
279
|
+
) from e
|
|
280
|
+
finally:
|
|
281
|
+
# Cleanup pool if initialization failed
|
|
282
|
+
if not self._initialized and self._pool is not None:
|
|
283
|
+
logger.debug("Cleaning up connection pool after initialization failure")
|
|
284
|
+
await self._pool.close()
|
|
285
|
+
self._pool = None
|
|
286
|
+
|
|
287
|
+
async def _ensure_table_exists(self) -> None:
|
|
288
|
+
"""Create the DLQ replay history table if it doesn't exist.
|
|
289
|
+
|
|
290
|
+
Creates the table with:
|
|
291
|
+
- UUID primary key
|
|
292
|
+
- Indexes on original_message_id and replay_timestamp
|
|
293
|
+
- All required columns for replay tracking
|
|
294
|
+
"""
|
|
295
|
+
if self._pool is None:
|
|
296
|
+
raise RuntimeHostError(
|
|
297
|
+
"Pool not initialized - call initialize() first",
|
|
298
|
+
context=ModelInfraErrorContext.with_correlation(
|
|
299
|
+
transport_type=EnumInfraTransportType.DATABASE,
|
|
300
|
+
operation="_ensure_table_exists",
|
|
301
|
+
target_name="dlq_tracking_service",
|
|
302
|
+
),
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
# Note: Table name is validated in config (alphanumeric + underscore only)
|
|
306
|
+
# so safe to use in SQL. We still use parameterized queries for data values.
|
|
307
|
+
create_table_sql = f"""
|
|
308
|
+
CREATE TABLE IF NOT EXISTS {self._config.storage_table} (
|
|
309
|
+
id UUID PRIMARY KEY,
|
|
310
|
+
original_message_id UUID NOT NULL,
|
|
311
|
+
replay_correlation_id UUID NOT NULL,
|
|
312
|
+
original_topic VARCHAR(255) NOT NULL,
|
|
313
|
+
target_topic VARCHAR(255) NOT NULL,
|
|
314
|
+
replay_status VARCHAR(50) NOT NULL,
|
|
315
|
+
replay_timestamp TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
|
|
316
|
+
success BOOLEAN NOT NULL,
|
|
317
|
+
error_message TEXT,
|
|
318
|
+
dlq_offset BIGINT NOT NULL,
|
|
319
|
+
dlq_partition INTEGER NOT NULL,
|
|
320
|
+
retry_count INTEGER NOT NULL DEFAULT 0
|
|
321
|
+
)
|
|
322
|
+
"""
|
|
323
|
+
|
|
324
|
+
create_message_id_index_sql = f"""
|
|
325
|
+
CREATE INDEX IF NOT EXISTS idx_{self._config.storage_table}_message_id
|
|
326
|
+
ON {self._config.storage_table}(original_message_id)
|
|
327
|
+
"""
|
|
328
|
+
|
|
329
|
+
create_timestamp_index_sql = f"""
|
|
330
|
+
CREATE INDEX IF NOT EXISTS idx_{self._config.storage_table}_timestamp
|
|
331
|
+
ON {self._config.storage_table}(replay_timestamp)
|
|
332
|
+
"""
|
|
333
|
+
|
|
334
|
+
async with self._pool.acquire() as conn:
|
|
335
|
+
# Wrap DDL in transaction for atomicity - if index creation fails,
|
|
336
|
+
# the table creation will be rolled back to avoid partial schema state
|
|
337
|
+
async with conn.transaction():
|
|
338
|
+
await conn.execute(create_table_sql)
|
|
339
|
+
await conn.execute(create_message_id_index_sql)
|
|
340
|
+
await conn.execute(create_timestamp_index_sql)
|
|
341
|
+
|
|
342
|
+
async def shutdown(self) -> None:
|
|
343
|
+
"""Close the connection pool and release resources."""
|
|
344
|
+
if self._pool is not None:
|
|
345
|
+
await self._pool.close()
|
|
346
|
+
self._pool = None
|
|
347
|
+
self._initialized = False
|
|
348
|
+
logger.info("ServiceDlqTracking shutdown complete")
|
|
349
|
+
|
|
350
|
+
async def record_replay_attempt(self, record: ModelDlqReplayRecord) -> None:
|
|
351
|
+
"""Record a DLQ replay attempt.
|
|
352
|
+
|
|
353
|
+
Inserts a new replay record into the database. Each replay attempt
|
|
354
|
+
gets its own record, enabling full audit trail of replay operations.
|
|
355
|
+
|
|
356
|
+
Circuit breaker integration:
|
|
357
|
+
- Checks circuit state before execution (raises InfraUnavailableError if OPEN)
|
|
358
|
+
- Records success/failure for circuit state management
|
|
359
|
+
- Allows test request in HALF_OPEN state
|
|
360
|
+
|
|
361
|
+
Args:
|
|
362
|
+
record: The replay record to persist.
|
|
363
|
+
|
|
364
|
+
Raises:
|
|
365
|
+
InfraConnectionError: If database connection fails.
|
|
366
|
+
InfraTimeoutError: If operation times out.
|
|
367
|
+
InfraUnavailableError: If circuit breaker is OPEN.
|
|
368
|
+
RuntimeHostError: If service is not initialized.
|
|
369
|
+
"""
|
|
370
|
+
correlation_id = record.replay_correlation_id
|
|
371
|
+
context = ModelInfraErrorContext(
|
|
372
|
+
transport_type=EnumInfraTransportType.DATABASE,
|
|
373
|
+
operation="record_replay_attempt",
|
|
374
|
+
target_name="dlq_tracking_service",
|
|
375
|
+
correlation_id=correlation_id,
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
if not self._initialized or self._pool is None:
|
|
379
|
+
raise RuntimeHostError(
|
|
380
|
+
"Service not initialized - call initialize() first",
|
|
381
|
+
context=context,
|
|
382
|
+
)
|
|
383
|
+
|
|
384
|
+
# Circuit breaker check (caller-held lock pattern per ONEX circuit breaker pattern)
|
|
385
|
+
async with self._circuit_breaker_lock:
|
|
386
|
+
await self._check_circuit_breaker("record_replay_attempt", correlation_id)
|
|
387
|
+
|
|
388
|
+
# storage_table is validated via regex in ModelDlqTrackingConfig
|
|
389
|
+
insert_sql = f"""
|
|
390
|
+
INSERT INTO {self._config.storage_table}
|
|
391
|
+
(id, original_message_id, replay_correlation_id, original_topic,
|
|
392
|
+
target_topic, replay_status, replay_timestamp, success,
|
|
393
|
+
error_message, dlq_offset, dlq_partition, retry_count)
|
|
394
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
|
|
395
|
+
"""
|
|
396
|
+
|
|
397
|
+
try:
|
|
398
|
+
async with self._pool.acquire() as conn:
|
|
399
|
+
await conn.execute(
|
|
400
|
+
insert_sql,
|
|
401
|
+
record.id,
|
|
402
|
+
record.original_message_id,
|
|
403
|
+
record.replay_correlation_id,
|
|
404
|
+
record.original_topic,
|
|
405
|
+
record.target_topic,
|
|
406
|
+
record.replay_status.value,
|
|
407
|
+
record.replay_timestamp,
|
|
408
|
+
record.success,
|
|
409
|
+
record.error_message,
|
|
410
|
+
record.dlq_offset,
|
|
411
|
+
record.dlq_partition,
|
|
412
|
+
record.retry_count,
|
|
413
|
+
)
|
|
414
|
+
logger.debug(
|
|
415
|
+
"Recorded replay attempt",
|
|
416
|
+
extra={
|
|
417
|
+
"record_id": str(record.id),
|
|
418
|
+
"original_message_id": str(record.original_message_id),
|
|
419
|
+
"replay_status": record.replay_status.value,
|
|
420
|
+
},
|
|
421
|
+
)
|
|
422
|
+
|
|
423
|
+
# Circuit breaker success (caller-held lock pattern per ONEX circuit breaker pattern)
|
|
424
|
+
async with self._circuit_breaker_lock:
|
|
425
|
+
await self._reset_circuit_breaker()
|
|
426
|
+
|
|
427
|
+
except asyncpg.QueryCanceledError as e:
|
|
428
|
+
# Circuit breaker failure (caller-held lock pattern per ONEX circuit breaker pattern)
|
|
429
|
+
async with self._circuit_breaker_lock:
|
|
430
|
+
await self._record_circuit_failure(
|
|
431
|
+
"record_replay_attempt", correlation_id
|
|
432
|
+
)
|
|
433
|
+
timeout_ctx = ModelTimeoutErrorContext(
|
|
434
|
+
transport_type=EnumInfraTransportType.DATABASE,
|
|
435
|
+
operation="record_replay_attempt",
|
|
436
|
+
target_name="dlq_tracking_service",
|
|
437
|
+
correlation_id=correlation_id,
|
|
438
|
+
timeout_seconds=self._config.command_timeout,
|
|
439
|
+
)
|
|
440
|
+
raise InfraTimeoutError(
|
|
441
|
+
f"Record replay attempt timed out after {self._config.command_timeout}s",
|
|
442
|
+
context=timeout_ctx,
|
|
443
|
+
) from e
|
|
444
|
+
except asyncpg.PostgresConnectionError as e:
|
|
445
|
+
# Circuit breaker failure (caller-held lock pattern per ONEX circuit breaker pattern)
|
|
446
|
+
async with self._circuit_breaker_lock:
|
|
447
|
+
await self._record_circuit_failure(
|
|
448
|
+
"record_replay_attempt", correlation_id
|
|
449
|
+
)
|
|
450
|
+
raise InfraConnectionError(
|
|
451
|
+
"Database connection lost during record_replay_attempt",
|
|
452
|
+
context=context,
|
|
453
|
+
) from e
|
|
454
|
+
except asyncpg.PostgresError as e:
|
|
455
|
+
# Circuit breaker failure (caller-held lock pattern per ONEX circuit breaker pattern)
|
|
456
|
+
async with self._circuit_breaker_lock:
|
|
457
|
+
await self._record_circuit_failure(
|
|
458
|
+
"record_replay_attempt", correlation_id
|
|
459
|
+
)
|
|
460
|
+
raise RuntimeHostError(
|
|
461
|
+
f"Database error during record_replay_attempt: {type(e).__name__}",
|
|
462
|
+
context=context,
|
|
463
|
+
) from e
|
|
464
|
+
|
|
465
|
+
async def get_replay_history(self, message_id: UUID) -> list[ModelDlqReplayRecord]:
|
|
466
|
+
"""Get replay history for a specific message.
|
|
467
|
+
|
|
468
|
+
Retrieves all replay attempts for a given original message ID,
|
|
469
|
+
ordered by replay timestamp (most recent first).
|
|
470
|
+
|
|
471
|
+
Circuit breaker integration:
|
|
472
|
+
- Checks circuit state before execution (raises InfraUnavailableError if OPEN)
|
|
473
|
+
- Records success/failure for circuit state management
|
|
474
|
+
- Allows test request in HALF_OPEN state
|
|
475
|
+
|
|
476
|
+
Args:
|
|
477
|
+
message_id: The original message correlation ID to query.
|
|
478
|
+
|
|
479
|
+
Returns:
|
|
480
|
+
List of replay records for the message, ordered by timestamp desc.
|
|
481
|
+
|
|
482
|
+
Raises:
|
|
483
|
+
InfraConnectionError: If database connection fails.
|
|
484
|
+
InfraTimeoutError: If query times out.
|
|
485
|
+
InfraUnavailableError: If circuit breaker is OPEN.
|
|
486
|
+
RuntimeHostError: If service is not initialized.
|
|
487
|
+
"""
|
|
488
|
+
correlation_id = uuid4()
|
|
489
|
+
context = ModelInfraErrorContext(
|
|
490
|
+
transport_type=EnumInfraTransportType.DATABASE,
|
|
491
|
+
operation="get_replay_history",
|
|
492
|
+
target_name="dlq_tracking_service",
|
|
493
|
+
correlation_id=correlation_id,
|
|
494
|
+
)
|
|
495
|
+
|
|
496
|
+
if not self._initialized or self._pool is None:
|
|
497
|
+
raise RuntimeHostError(
|
|
498
|
+
"Service not initialized - call initialize() first",
|
|
499
|
+
context=context,
|
|
500
|
+
)
|
|
501
|
+
|
|
502
|
+
# Circuit breaker check (caller-held lock pattern per ONEX circuit breaker pattern)
|
|
503
|
+
async with self._circuit_breaker_lock:
|
|
504
|
+
await self._check_circuit_breaker("get_replay_history", correlation_id)
|
|
505
|
+
|
|
506
|
+
# storage_table is validated via regex in ModelDlqTrackingConfig
|
|
507
|
+
query_sql = f"""
|
|
508
|
+
SELECT id, original_message_id, replay_correlation_id, original_topic,
|
|
509
|
+
target_topic, replay_status, replay_timestamp, success,
|
|
510
|
+
error_message, dlq_offset, dlq_partition, retry_count
|
|
511
|
+
FROM {self._config.storage_table}
|
|
512
|
+
WHERE original_message_id = $1
|
|
513
|
+
ORDER BY replay_timestamp DESC
|
|
514
|
+
"""
|
|
515
|
+
|
|
516
|
+
try:
|
|
517
|
+
async with self._pool.acquire() as conn:
|
|
518
|
+
rows = await conn.fetch(query_sql, message_id)
|
|
519
|
+
|
|
520
|
+
records = []
|
|
521
|
+
for row in rows:
|
|
522
|
+
records.append(
|
|
523
|
+
ModelDlqReplayRecord(
|
|
524
|
+
id=row["id"],
|
|
525
|
+
original_message_id=row["original_message_id"],
|
|
526
|
+
replay_correlation_id=row["replay_correlation_id"],
|
|
527
|
+
original_topic=row["original_topic"],
|
|
528
|
+
target_topic=row["target_topic"],
|
|
529
|
+
replay_status=EnumReplayStatus(row["replay_status"]),
|
|
530
|
+
replay_timestamp=row["replay_timestamp"],
|
|
531
|
+
success=row["success"],
|
|
532
|
+
error_message=row["error_message"],
|
|
533
|
+
dlq_offset=row["dlq_offset"],
|
|
534
|
+
dlq_partition=row["dlq_partition"],
|
|
535
|
+
retry_count=row["retry_count"],
|
|
536
|
+
)
|
|
537
|
+
)
|
|
538
|
+
|
|
539
|
+
# Circuit breaker success (caller-held lock pattern per ONEX circuit breaker pattern)
|
|
540
|
+
async with self._circuit_breaker_lock:
|
|
541
|
+
await self._reset_circuit_breaker()
|
|
542
|
+
|
|
543
|
+
return records
|
|
544
|
+
|
|
545
|
+
except asyncpg.QueryCanceledError as e:
|
|
546
|
+
# Circuit breaker failure (caller-held lock pattern per ONEX circuit breaker pattern)
|
|
547
|
+
async with self._circuit_breaker_lock:
|
|
548
|
+
await self._record_circuit_failure("get_replay_history", correlation_id)
|
|
549
|
+
timeout_ctx = ModelTimeoutErrorContext(
|
|
550
|
+
transport_type=EnumInfraTransportType.DATABASE,
|
|
551
|
+
operation="get_replay_history",
|
|
552
|
+
target_name="dlq_tracking_service",
|
|
553
|
+
correlation_id=correlation_id,
|
|
554
|
+
timeout_seconds=self._config.command_timeout,
|
|
555
|
+
)
|
|
556
|
+
raise InfraTimeoutError(
|
|
557
|
+
f"Get replay history timed out after {self._config.command_timeout}s",
|
|
558
|
+
context=timeout_ctx,
|
|
559
|
+
) from e
|
|
560
|
+
except asyncpg.PostgresConnectionError as e:
|
|
561
|
+
# Circuit breaker failure (caller-held lock pattern per ONEX circuit breaker pattern)
|
|
562
|
+
async with self._circuit_breaker_lock:
|
|
563
|
+
await self._record_circuit_failure("get_replay_history", correlation_id)
|
|
564
|
+
raise InfraConnectionError(
|
|
565
|
+
"Database connection lost during get_replay_history",
|
|
566
|
+
context=context,
|
|
567
|
+
) from e
|
|
568
|
+
except asyncpg.PostgresError as e:
|
|
569
|
+
# Circuit breaker failure (caller-held lock pattern per ONEX circuit breaker pattern)
|
|
570
|
+
async with self._circuit_breaker_lock:
|
|
571
|
+
await self._record_circuit_failure("get_replay_history", correlation_id)
|
|
572
|
+
raise RuntimeHostError(
|
|
573
|
+
f"Database error during get_replay_history: {type(e).__name__}",
|
|
574
|
+
context=context,
|
|
575
|
+
) from e
|
|
576
|
+
|
|
577
|
+
async def health_check(self) -> bool:
|
|
578
|
+
"""Check if the service is healthy and can accept operations.
|
|
579
|
+
|
|
580
|
+
Performs a simple query to verify database connectivity
|
|
581
|
+
and table existence.
|
|
582
|
+
|
|
583
|
+
Returns:
|
|
584
|
+
True if the service is healthy, False otherwise.
|
|
585
|
+
"""
|
|
586
|
+
if not self._initialized or self._pool is None:
|
|
587
|
+
return False
|
|
588
|
+
|
|
589
|
+
try:
|
|
590
|
+
async with self._pool.acquire() as conn:
|
|
591
|
+
# Verify read access
|
|
592
|
+
await conn.fetchval("SELECT 1")
|
|
593
|
+
|
|
594
|
+
# Verify table exists and is accessible
|
|
595
|
+
check_table_sql = """
|
|
596
|
+
SELECT 1 FROM information_schema.tables
|
|
597
|
+
WHERE table_name = $1
|
|
598
|
+
LIMIT 1
|
|
599
|
+
"""
|
|
600
|
+
table_exists = await conn.fetchval(
|
|
601
|
+
check_table_sql, self._config.storage_table
|
|
602
|
+
)
|
|
603
|
+
|
|
604
|
+
return table_exists is not None
|
|
605
|
+
|
|
606
|
+
except Exception:
|
|
607
|
+
logger.debug("Health check failed", exc_info=True)
|
|
608
|
+
return False
|
|
609
|
+
|
|
610
|
+
|
|
611
|
+
__all__: list[str] = ["ServiceDlqTracking"]
|