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,915 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2025 OmniNode Team
|
|
3
|
+
"""PostgreSQL Registration Storage Handler.
|
|
4
|
+
|
|
5
|
+
This module provides a PostgreSQL-backed implementation of the registration
|
|
6
|
+
storage handler protocol, wrapping existing PostgreSQL functionality with
|
|
7
|
+
circuit breaker resilience.
|
|
8
|
+
|
|
9
|
+
Connection Pooling:
|
|
10
|
+
- Uses asyncpg connection pool for efficient database access
|
|
11
|
+
- Configurable pool size (default: 10)
|
|
12
|
+
- Pool gracefully closed on handler shutdown
|
|
13
|
+
|
|
14
|
+
Circuit Breaker:
|
|
15
|
+
- Uses MixinAsyncCircuitBreaker for consistent resilience
|
|
16
|
+
- Three states: CLOSED (normal), OPEN (blocking), HALF_OPEN (testing)
|
|
17
|
+
- Configurable failure threshold and reset timeout
|
|
18
|
+
|
|
19
|
+
SQL Security:
|
|
20
|
+
All SQL queries in this module use parameterized queries with positional
|
|
21
|
+
placeholders ($1, $2, etc.) to prevent SQL injection attacks. The asyncpg
|
|
22
|
+
library handles proper escaping and type conversion for all parameters.
|
|
23
|
+
|
|
24
|
+
Query parameters are ALWAYS passed as separate arguments to execute/fetch
|
|
25
|
+
methods, never interpolated into SQL strings:
|
|
26
|
+
|
|
27
|
+
SAFE:
|
|
28
|
+
await conn.execute("SELECT * FROM users WHERE id = $1", user_id)
|
|
29
|
+
|
|
30
|
+
UNSAFE (never do this):
|
|
31
|
+
await conn.execute(f"SELECT * FROM users WHERE id = {user_id}") # WRONG!
|
|
32
|
+
|
|
33
|
+
Dynamic WHERE clauses (e.g., in query_registrations) are built by appending
|
|
34
|
+
conditions with parameterized placeholders, not by string interpolation of
|
|
35
|
+
user values.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
from __future__ import annotations
|
|
39
|
+
|
|
40
|
+
import asyncio
|
|
41
|
+
import json
|
|
42
|
+
import logging
|
|
43
|
+
import time
|
|
44
|
+
from datetime import UTC, datetime
|
|
45
|
+
from typing import TYPE_CHECKING
|
|
46
|
+
from uuid import UUID, uuid4
|
|
47
|
+
|
|
48
|
+
# Import asyncpg at module level to avoid redundant imports inside methods
|
|
49
|
+
import asyncpg
|
|
50
|
+
|
|
51
|
+
from omnibase_core.enums.enum_node_kind import EnumNodeKind
|
|
52
|
+
from omnibase_infra.enums import EnumInfraTransportType
|
|
53
|
+
from omnibase_infra.errors import (
|
|
54
|
+
InfraConnectionError,
|
|
55
|
+
InfraTimeoutError,
|
|
56
|
+
ModelInfraErrorContext,
|
|
57
|
+
ModelTimeoutErrorContext,
|
|
58
|
+
)
|
|
59
|
+
from omnibase_infra.handlers.registration_storage.models import (
|
|
60
|
+
ModelDeleteRegistrationRequest,
|
|
61
|
+
ModelUpdateRegistrationRequest,
|
|
62
|
+
)
|
|
63
|
+
from omnibase_infra.mixins import MixinAsyncCircuitBreaker
|
|
64
|
+
from omnibase_infra.models.resilience import ModelCircuitBreakerConfig
|
|
65
|
+
from omnibase_infra.nodes.node_registration_storage_effect.models import (
|
|
66
|
+
ModelDeleteResult,
|
|
67
|
+
ModelRegistrationRecord,
|
|
68
|
+
ModelStorageHealthCheckDetails,
|
|
69
|
+
ModelStorageHealthCheckResult,
|
|
70
|
+
ModelStorageQuery,
|
|
71
|
+
ModelStorageResult,
|
|
72
|
+
ModelUpsertResult,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
if TYPE_CHECKING:
|
|
76
|
+
from omnibase_infra.nodes.effects.protocol_postgres_adapter import (
|
|
77
|
+
ProtocolPostgresAdapter,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
logger = logging.getLogger(__name__)
|
|
81
|
+
|
|
82
|
+
# Default configuration values
|
|
83
|
+
DEFAULT_CIRCUIT_BREAKER_THRESHOLD = 5
|
|
84
|
+
DEFAULT_CIRCUIT_BREAKER_RESET_TIMEOUT = 30.0
|
|
85
|
+
DEFAULT_POOL_SIZE = 10
|
|
86
|
+
DEFAULT_TIMEOUT_SECONDS = 30.0
|
|
87
|
+
|
|
88
|
+
# SQL statements
|
|
89
|
+
SQL_CREATE_TABLE = """
|
|
90
|
+
CREATE TABLE IF NOT EXISTS node_registrations (
|
|
91
|
+
node_id UUID PRIMARY KEY,
|
|
92
|
+
node_type VARCHAR(64) NOT NULL,
|
|
93
|
+
node_version VARCHAR(32) NOT NULL,
|
|
94
|
+
capabilities JSONB NOT NULL DEFAULT '[]',
|
|
95
|
+
endpoints JSONB NOT NULL DEFAULT '{}',
|
|
96
|
+
metadata JSONB NOT NULL DEFAULT '{}',
|
|
97
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
98
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
99
|
+
);
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
SQL_UPSERT = """
|
|
103
|
+
INSERT INTO node_registrations (node_id, node_type, node_version, capabilities, endpoints, metadata, created_at, updated_at)
|
|
104
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
|
105
|
+
ON CONFLICT (node_id) DO UPDATE SET
|
|
106
|
+
node_type = EXCLUDED.node_type,
|
|
107
|
+
node_version = EXCLUDED.node_version,
|
|
108
|
+
capabilities = EXCLUDED.capabilities,
|
|
109
|
+
endpoints = EXCLUDED.endpoints,
|
|
110
|
+
metadata = EXCLUDED.metadata,
|
|
111
|
+
updated_at = EXCLUDED.updated_at
|
|
112
|
+
RETURNING (xmax = 0) AS was_insert;
|
|
113
|
+
"""
|
|
114
|
+
|
|
115
|
+
SQL_QUERY_BASE = """
|
|
116
|
+
SELECT node_id, node_type, node_version, capabilities, endpoints, metadata, created_at, updated_at
|
|
117
|
+
FROM node_registrations
|
|
118
|
+
"""
|
|
119
|
+
|
|
120
|
+
SQL_QUERY_COUNT = """
|
|
121
|
+
SELECT COUNT(*) FROM node_registrations
|
|
122
|
+
"""
|
|
123
|
+
|
|
124
|
+
SQL_UPDATE = """
|
|
125
|
+
UPDATE node_registrations SET
|
|
126
|
+
capabilities = COALESCE($2, capabilities),
|
|
127
|
+
endpoints = COALESCE($3, endpoints),
|
|
128
|
+
metadata = COALESCE($4, metadata),
|
|
129
|
+
node_version = COALESCE($5, node_version),
|
|
130
|
+
updated_at = NOW()
|
|
131
|
+
WHERE node_id = $1
|
|
132
|
+
RETURNING node_id;
|
|
133
|
+
"""
|
|
134
|
+
|
|
135
|
+
SQL_DELETE = """
|
|
136
|
+
DELETE FROM node_registrations WHERE node_id = $1 RETURNING node_id;
|
|
137
|
+
"""
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class HandlerRegistrationStoragePostgres(MixinAsyncCircuitBreaker):
|
|
141
|
+
"""PostgreSQL implementation of ProtocolRegistrationStorageHandler.
|
|
142
|
+
|
|
143
|
+
Wraps existing PostgreSQL adapter functionality with circuit breaker
|
|
144
|
+
resilience and proper error handling.
|
|
145
|
+
|
|
146
|
+
Thread Safety:
|
|
147
|
+
This handler is coroutine-safe. All database operations use
|
|
148
|
+
asyncpg's connection pool, and circuit breaker state is protected
|
|
149
|
+
by asyncio.Lock.
|
|
150
|
+
|
|
151
|
+
Attributes:
|
|
152
|
+
handler_type: Returns "postgresql" identifier.
|
|
153
|
+
|
|
154
|
+
Example:
|
|
155
|
+
>>> handler = HandlerRegistrationStoragePostgres(
|
|
156
|
+
... postgres_adapter=postgres_adapter,
|
|
157
|
+
... circuit_breaker_config={"threshold": 5, "reset_timeout": 30.0},
|
|
158
|
+
... )
|
|
159
|
+
>>> result = await handler.store_registration(record)
|
|
160
|
+
"""
|
|
161
|
+
|
|
162
|
+
def __init__(
|
|
163
|
+
self,
|
|
164
|
+
postgres_adapter: ProtocolPostgresAdapter | None = None,
|
|
165
|
+
dsn: str | None = None,
|
|
166
|
+
host: str = "localhost",
|
|
167
|
+
port: int = 5432,
|
|
168
|
+
database: str = "omninode_bridge",
|
|
169
|
+
user: str = "postgres",
|
|
170
|
+
password: str | None = None,
|
|
171
|
+
pool_size: int = DEFAULT_POOL_SIZE,
|
|
172
|
+
circuit_breaker_config: ModelCircuitBreakerConfig
|
|
173
|
+
| dict[str, object]
|
|
174
|
+
| None = None,
|
|
175
|
+
timeout_seconds: float = DEFAULT_TIMEOUT_SECONDS,
|
|
176
|
+
auto_create_schema: bool = False,
|
|
177
|
+
) -> None:
|
|
178
|
+
"""Initialize HandlerRegistrationStoragePostgres.
|
|
179
|
+
|
|
180
|
+
Args:
|
|
181
|
+
postgres_adapter: Optional existing PostgreSQL adapter (ProtocolPostgresAdapter).
|
|
182
|
+
If not provided, a new asyncpg connection pool will be created.
|
|
183
|
+
dsn: Optional PostgreSQL connection DSN (overrides host/port/etc).
|
|
184
|
+
host: PostgreSQL server hostname (default: "localhost").
|
|
185
|
+
port: PostgreSQL server port (default: 5432).
|
|
186
|
+
database: Database name (default: "omninode_bridge").
|
|
187
|
+
user: Database user (default: "postgres").
|
|
188
|
+
password: Optional database password.
|
|
189
|
+
pool_size: Connection pool size (default: 10).
|
|
190
|
+
circuit_breaker_config: Optional circuit breaker configuration.
|
|
191
|
+
Accepts ModelCircuitBreakerConfig or dict with keys:
|
|
192
|
+
- threshold: Max failures before opening (default: 5)
|
|
193
|
+
- reset_timeout_seconds: Seconds before reset (default: 60.0)
|
|
194
|
+
- service_name: Service identifier (default: "postgres.storage")
|
|
195
|
+
timeout_seconds: Operation timeout in seconds (default: 30.0).
|
|
196
|
+
auto_create_schema: If True, automatically create the node_registrations
|
|
197
|
+
table on first connection. Default is False. Production deployments
|
|
198
|
+
should use database migrations instead of auto-creation.
|
|
199
|
+
"""
|
|
200
|
+
# Normalize circuit breaker config to ModelCircuitBreakerConfig
|
|
201
|
+
if isinstance(circuit_breaker_config, ModelCircuitBreakerConfig):
|
|
202
|
+
cb_config = circuit_breaker_config
|
|
203
|
+
elif circuit_breaker_config is not None:
|
|
204
|
+
# Handle dict with legacy key names (reset_timeout -> reset_timeout_seconds)
|
|
205
|
+
config_dict = dict(circuit_breaker_config)
|
|
206
|
+
if (
|
|
207
|
+
"reset_timeout" in config_dict
|
|
208
|
+
and "reset_timeout_seconds" not in config_dict
|
|
209
|
+
):
|
|
210
|
+
config_dict["reset_timeout_seconds"] = config_dict.pop("reset_timeout")
|
|
211
|
+
# Set defaults for service_name and transport_type if not provided
|
|
212
|
+
config_dict.setdefault("service_name", "postgres.storage")
|
|
213
|
+
config_dict.setdefault("transport_type", EnumInfraTransportType.DATABASE)
|
|
214
|
+
cb_config = ModelCircuitBreakerConfig(**config_dict)
|
|
215
|
+
else:
|
|
216
|
+
cb_config = ModelCircuitBreakerConfig(
|
|
217
|
+
service_name="postgres.storage",
|
|
218
|
+
transport_type=EnumInfraTransportType.DATABASE,
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
self._init_circuit_breaker(
|
|
222
|
+
threshold=cb_config.threshold,
|
|
223
|
+
reset_timeout=cb_config.reset_timeout_seconds,
|
|
224
|
+
service_name=cb_config.service_name,
|
|
225
|
+
transport_type=cb_config.transport_type,
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
# Store configuration
|
|
229
|
+
self._dsn = dsn
|
|
230
|
+
self._host = host
|
|
231
|
+
self._port = port
|
|
232
|
+
self._database = database
|
|
233
|
+
self._user = user
|
|
234
|
+
self._password = password
|
|
235
|
+
self._pool_size = pool_size
|
|
236
|
+
self._timeout_seconds = timeout_seconds
|
|
237
|
+
self._auto_create_schema = auto_create_schema
|
|
238
|
+
|
|
239
|
+
# Connection pool (initialized on first use)
|
|
240
|
+
self._pool: asyncpg.Pool | None = None
|
|
241
|
+
self._pool_lock = asyncio.Lock()
|
|
242
|
+
self._initialized = False
|
|
243
|
+
|
|
244
|
+
# External adapter (if provided)
|
|
245
|
+
self._postgres_adapter = postgres_adapter
|
|
246
|
+
|
|
247
|
+
logger.info(
|
|
248
|
+
"HandlerRegistrationStoragePostgres created",
|
|
249
|
+
extra={
|
|
250
|
+
"host": host,
|
|
251
|
+
"port": port,
|
|
252
|
+
"database": database,
|
|
253
|
+
"pool_size": pool_size,
|
|
254
|
+
},
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
@property
|
|
258
|
+
def handler_type(self) -> str:
|
|
259
|
+
"""Return the handler type identifier.
|
|
260
|
+
|
|
261
|
+
Returns:
|
|
262
|
+
"postgresql" identifier string.
|
|
263
|
+
"""
|
|
264
|
+
return "postgresql"
|
|
265
|
+
|
|
266
|
+
async def _ensure_pool(
|
|
267
|
+
self,
|
|
268
|
+
correlation_id: UUID | None = None,
|
|
269
|
+
) -> asyncpg.Pool:
|
|
270
|
+
"""Ensure connection pool is initialized.
|
|
271
|
+
|
|
272
|
+
Args:
|
|
273
|
+
correlation_id: Optional correlation ID for tracing.
|
|
274
|
+
|
|
275
|
+
Returns:
|
|
276
|
+
The asyncpg connection pool.
|
|
277
|
+
|
|
278
|
+
Raises:
|
|
279
|
+
InfraConnectionError: If pool creation fails.
|
|
280
|
+
"""
|
|
281
|
+
if self._pool is not None:
|
|
282
|
+
return self._pool
|
|
283
|
+
|
|
284
|
+
async with self._pool_lock:
|
|
285
|
+
# Double-check after acquiring lock
|
|
286
|
+
if self._pool is not None:
|
|
287
|
+
return self._pool
|
|
288
|
+
|
|
289
|
+
try:
|
|
290
|
+
if self._dsn:
|
|
291
|
+
self._pool = await asyncpg.create_pool(
|
|
292
|
+
dsn=self._dsn,
|
|
293
|
+
min_size=1,
|
|
294
|
+
max_size=self._pool_size,
|
|
295
|
+
)
|
|
296
|
+
else:
|
|
297
|
+
self._pool = await asyncpg.create_pool(
|
|
298
|
+
host=self._host,
|
|
299
|
+
port=self._port,
|
|
300
|
+
database=self._database,
|
|
301
|
+
user=self._user,
|
|
302
|
+
password=self._password,
|
|
303
|
+
min_size=1,
|
|
304
|
+
max_size=self._pool_size,
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
# Create table only if auto_create_schema is enabled
|
|
308
|
+
# Production deployments should use database migrations
|
|
309
|
+
if self._auto_create_schema:
|
|
310
|
+
async with self._pool.acquire() as conn:
|
|
311
|
+
await conn.execute(SQL_CREATE_TABLE)
|
|
312
|
+
|
|
313
|
+
self._initialized = True
|
|
314
|
+
|
|
315
|
+
logger.info(
|
|
316
|
+
"PostgreSQL connection pool initialized",
|
|
317
|
+
extra={
|
|
318
|
+
"host": self._host,
|
|
319
|
+
"port": self._port,
|
|
320
|
+
"database": self._database,
|
|
321
|
+
"auto_create_schema": self._auto_create_schema,
|
|
322
|
+
},
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
return self._pool
|
|
326
|
+
|
|
327
|
+
except Exception as e:
|
|
328
|
+
context = ModelInfraErrorContext(
|
|
329
|
+
transport_type=EnumInfraTransportType.DATABASE,
|
|
330
|
+
operation="initialize_pool",
|
|
331
|
+
target_name="postgres.storage",
|
|
332
|
+
correlation_id=correlation_id,
|
|
333
|
+
)
|
|
334
|
+
raise InfraConnectionError(
|
|
335
|
+
f"Failed to initialize PostgreSQL pool: {type(e).__name__}",
|
|
336
|
+
context=context,
|
|
337
|
+
) from e
|
|
338
|
+
|
|
339
|
+
async def store_registration(
|
|
340
|
+
self,
|
|
341
|
+
record: ModelRegistrationRecord,
|
|
342
|
+
correlation_id: UUID | None = None,
|
|
343
|
+
) -> ModelUpsertResult:
|
|
344
|
+
"""Store a registration record in PostgreSQL.
|
|
345
|
+
|
|
346
|
+
Args:
|
|
347
|
+
record: Registration record to store.
|
|
348
|
+
correlation_id: Optional correlation ID for tracing.
|
|
349
|
+
|
|
350
|
+
Returns:
|
|
351
|
+
ModelUpsertResult with upsert outcome.
|
|
352
|
+
|
|
353
|
+
Raises:
|
|
354
|
+
InfraConnectionError: If connection to PostgreSQL fails.
|
|
355
|
+
InfraTimeoutError: If operation times out.
|
|
356
|
+
InfraUnavailableError: If circuit breaker is open.
|
|
357
|
+
"""
|
|
358
|
+
correlation_id = correlation_id or uuid4()
|
|
359
|
+
start_time = time.monotonic()
|
|
360
|
+
|
|
361
|
+
# Check circuit breaker
|
|
362
|
+
async with self._circuit_breaker_lock:
|
|
363
|
+
await self._check_circuit_breaker(
|
|
364
|
+
operation="store_registration",
|
|
365
|
+
correlation_id=correlation_id,
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
try:
|
|
369
|
+
pool = await self._ensure_pool(correlation_id=correlation_id)
|
|
370
|
+
|
|
371
|
+
now = datetime.now(UTC)
|
|
372
|
+
capabilities_json = json.dumps(record.capabilities)
|
|
373
|
+
endpoints_json = json.dumps(record.endpoints)
|
|
374
|
+
metadata_json = json.dumps(record.metadata)
|
|
375
|
+
|
|
376
|
+
async with pool.acquire() as conn:
|
|
377
|
+
result = await asyncio.wait_for(
|
|
378
|
+
conn.fetchrow(
|
|
379
|
+
SQL_UPSERT,
|
|
380
|
+
record.node_id,
|
|
381
|
+
record.node_type.value,
|
|
382
|
+
record.node_version,
|
|
383
|
+
capabilities_json,
|
|
384
|
+
endpoints_json,
|
|
385
|
+
metadata_json,
|
|
386
|
+
record.created_at or now,
|
|
387
|
+
now,
|
|
388
|
+
),
|
|
389
|
+
timeout=self._timeout_seconds,
|
|
390
|
+
)
|
|
391
|
+
|
|
392
|
+
# Reset circuit breaker on success
|
|
393
|
+
async with self._circuit_breaker_lock:
|
|
394
|
+
await self._reset_circuit_breaker()
|
|
395
|
+
|
|
396
|
+
was_insert = result["was_insert"] if result else False
|
|
397
|
+
operation = "insert" if was_insert else "update"
|
|
398
|
+
duration_ms = (time.monotonic() - start_time) * 1000
|
|
399
|
+
|
|
400
|
+
logger.info(
|
|
401
|
+
"Registration stored in PostgreSQL",
|
|
402
|
+
extra={
|
|
403
|
+
"node_id": str(record.node_id),
|
|
404
|
+
"operation": operation,
|
|
405
|
+
"duration_ms": duration_ms,
|
|
406
|
+
"correlation_id": str(correlation_id),
|
|
407
|
+
},
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
return ModelUpsertResult(
|
|
411
|
+
success=True,
|
|
412
|
+
node_id=record.node_id,
|
|
413
|
+
operation=operation,
|
|
414
|
+
duration_ms=duration_ms,
|
|
415
|
+
backend_type=self.handler_type,
|
|
416
|
+
correlation_id=correlation_id,
|
|
417
|
+
)
|
|
418
|
+
|
|
419
|
+
except TimeoutError as e:
|
|
420
|
+
async with self._circuit_breaker_lock:
|
|
421
|
+
await self._record_circuit_failure(
|
|
422
|
+
operation="store_registration",
|
|
423
|
+
correlation_id=correlation_id,
|
|
424
|
+
)
|
|
425
|
+
duration_ms = (time.monotonic() - start_time) * 1000
|
|
426
|
+
raise InfraTimeoutError(
|
|
427
|
+
f"PostgreSQL upsert timed out after {self._timeout_seconds}s",
|
|
428
|
+
context=ModelTimeoutErrorContext(
|
|
429
|
+
transport_type=EnumInfraTransportType.DATABASE,
|
|
430
|
+
operation="store_registration",
|
|
431
|
+
target_name="postgres.storage",
|
|
432
|
+
correlation_id=correlation_id,
|
|
433
|
+
timeout_seconds=self._timeout_seconds,
|
|
434
|
+
),
|
|
435
|
+
) from e
|
|
436
|
+
|
|
437
|
+
except Exception as e:
|
|
438
|
+
async with self._circuit_breaker_lock:
|
|
439
|
+
await self._record_circuit_failure(
|
|
440
|
+
operation="store_registration",
|
|
441
|
+
correlation_id=correlation_id,
|
|
442
|
+
)
|
|
443
|
+
duration_ms = (time.monotonic() - start_time) * 1000
|
|
444
|
+
context = ModelInfraErrorContext(
|
|
445
|
+
transport_type=EnumInfraTransportType.DATABASE,
|
|
446
|
+
operation="store_registration",
|
|
447
|
+
target_name="postgres.storage",
|
|
448
|
+
correlation_id=correlation_id,
|
|
449
|
+
)
|
|
450
|
+
raise InfraConnectionError(
|
|
451
|
+
f"PostgreSQL upsert failed: {type(e).__name__}",
|
|
452
|
+
context=context,
|
|
453
|
+
) from e
|
|
454
|
+
|
|
455
|
+
async def query_registrations(
|
|
456
|
+
self,
|
|
457
|
+
query: ModelStorageQuery,
|
|
458
|
+
correlation_id: UUID | None = None,
|
|
459
|
+
) -> ModelStorageResult:
|
|
460
|
+
"""Query registration records from PostgreSQL.
|
|
461
|
+
|
|
462
|
+
Args:
|
|
463
|
+
query: ModelStorageQuery containing filter and pagination parameters.
|
|
464
|
+
correlation_id: Optional correlation ID for tracing.
|
|
465
|
+
|
|
466
|
+
Returns:
|
|
467
|
+
ModelStorageResult with list of matching records.
|
|
468
|
+
|
|
469
|
+
Raises:
|
|
470
|
+
InfraConnectionError: If connection to PostgreSQL fails.
|
|
471
|
+
InfraTimeoutError: If operation times out.
|
|
472
|
+
InfraUnavailableError: If circuit breaker is open.
|
|
473
|
+
"""
|
|
474
|
+
correlation_id = correlation_id or uuid4()
|
|
475
|
+
start_time = time.monotonic()
|
|
476
|
+
|
|
477
|
+
# Check circuit breaker
|
|
478
|
+
async with self._circuit_breaker_lock:
|
|
479
|
+
await self._check_circuit_breaker(
|
|
480
|
+
operation="query_registrations",
|
|
481
|
+
correlation_id=correlation_id,
|
|
482
|
+
)
|
|
483
|
+
|
|
484
|
+
try:
|
|
485
|
+
pool = await self._ensure_pool(correlation_id=correlation_id)
|
|
486
|
+
|
|
487
|
+
# Build query with parameterized filters
|
|
488
|
+
# NOTE: All filter values use positional parameters ($1, $2, etc.)
|
|
489
|
+
# to prevent SQL injection. The param_idx tracks parameter positions.
|
|
490
|
+
# User values are NEVER interpolated into SQL strings.
|
|
491
|
+
conditions: list[str] = []
|
|
492
|
+
params: list[object] = []
|
|
493
|
+
param_idx = 1
|
|
494
|
+
|
|
495
|
+
# Filter by node_id if specified (exact match)
|
|
496
|
+
if query.node_id is not None:
|
|
497
|
+
conditions.append(f"node_id = ${param_idx}")
|
|
498
|
+
params.append(query.node_id)
|
|
499
|
+
param_idx += 1
|
|
500
|
+
|
|
501
|
+
# Filter by node_type if specified
|
|
502
|
+
if query.node_type is not None:
|
|
503
|
+
conditions.append(f"node_type = ${param_idx}")
|
|
504
|
+
params.append(query.node_type.value)
|
|
505
|
+
param_idx += 1
|
|
506
|
+
|
|
507
|
+
# Filter by capability (JSONB array contains match)
|
|
508
|
+
if query.capability_filter is not None:
|
|
509
|
+
# Use JSONB containment operator to check if capability exists in array
|
|
510
|
+
conditions.append(f"capabilities @> ${param_idx}::jsonb")
|
|
511
|
+
params.append(json.dumps([query.capability_filter]))
|
|
512
|
+
param_idx += 1
|
|
513
|
+
|
|
514
|
+
where_clause = ""
|
|
515
|
+
if conditions:
|
|
516
|
+
where_clause = " WHERE " + " AND ".join(conditions)
|
|
517
|
+
|
|
518
|
+
# Query for records with pagination
|
|
519
|
+
sql_query = f"{SQL_QUERY_BASE}{where_clause} ORDER BY updated_at DESC LIMIT ${param_idx} OFFSET ${param_idx + 1}"
|
|
520
|
+
params.extend([query.limit, query.offset])
|
|
521
|
+
|
|
522
|
+
# Query for total count
|
|
523
|
+
count_query = f"{SQL_QUERY_COUNT}{where_clause}"
|
|
524
|
+
count_params = params[:-2] # Exclude limit and offset
|
|
525
|
+
|
|
526
|
+
async with pool.acquire() as conn:
|
|
527
|
+
rows, count_result = await asyncio.gather(
|
|
528
|
+
asyncio.wait_for(
|
|
529
|
+
conn.fetch(sql_query, *params),
|
|
530
|
+
timeout=self._timeout_seconds,
|
|
531
|
+
),
|
|
532
|
+
asyncio.wait_for(
|
|
533
|
+
conn.fetchval(count_query, *count_params),
|
|
534
|
+
timeout=self._timeout_seconds,
|
|
535
|
+
),
|
|
536
|
+
)
|
|
537
|
+
|
|
538
|
+
# Reset circuit breaker on success
|
|
539
|
+
async with self._circuit_breaker_lock:
|
|
540
|
+
await self._reset_circuit_breaker()
|
|
541
|
+
|
|
542
|
+
# Convert rows to records
|
|
543
|
+
records: list[ModelRegistrationRecord] = []
|
|
544
|
+
for row in rows:
|
|
545
|
+
capabilities = (
|
|
546
|
+
json.loads(row["capabilities"]) if row["capabilities"] else []
|
|
547
|
+
)
|
|
548
|
+
endpoints = json.loads(row["endpoints"]) if row["endpoints"] else {}
|
|
549
|
+
metadata = json.loads(row["metadata"]) if row["metadata"] else {}
|
|
550
|
+
|
|
551
|
+
records.append(
|
|
552
|
+
ModelRegistrationRecord(
|
|
553
|
+
node_id=row["node_id"],
|
|
554
|
+
node_type=EnumNodeKind(row["node_type"]),
|
|
555
|
+
node_version=row["node_version"],
|
|
556
|
+
capabilities=capabilities,
|
|
557
|
+
endpoints=endpoints,
|
|
558
|
+
metadata=metadata,
|
|
559
|
+
created_at=row["created_at"],
|
|
560
|
+
updated_at=row["updated_at"],
|
|
561
|
+
correlation_id=correlation_id,
|
|
562
|
+
)
|
|
563
|
+
)
|
|
564
|
+
|
|
565
|
+
duration_ms = (time.monotonic() - start_time) * 1000
|
|
566
|
+
total_count = count_result or 0
|
|
567
|
+
|
|
568
|
+
logger.info(
|
|
569
|
+
"Registration query completed",
|
|
570
|
+
extra={
|
|
571
|
+
"record_count": len(records),
|
|
572
|
+
"total_count": total_count,
|
|
573
|
+
"duration_ms": duration_ms,
|
|
574
|
+
"correlation_id": str(correlation_id),
|
|
575
|
+
},
|
|
576
|
+
)
|
|
577
|
+
|
|
578
|
+
return ModelStorageResult(
|
|
579
|
+
success=True,
|
|
580
|
+
records=tuple(records),
|
|
581
|
+
total_count=total_count,
|
|
582
|
+
duration_ms=duration_ms,
|
|
583
|
+
backend_type=self.handler_type,
|
|
584
|
+
correlation_id=correlation_id,
|
|
585
|
+
)
|
|
586
|
+
|
|
587
|
+
except TimeoutError as e:
|
|
588
|
+
async with self._circuit_breaker_lock:
|
|
589
|
+
await self._record_circuit_failure(
|
|
590
|
+
operation="query_registrations",
|
|
591
|
+
correlation_id=correlation_id,
|
|
592
|
+
)
|
|
593
|
+
duration_ms = (time.monotonic() - start_time) * 1000
|
|
594
|
+
raise InfraTimeoutError(
|
|
595
|
+
f"PostgreSQL query timed out after {self._timeout_seconds}s",
|
|
596
|
+
context=ModelTimeoutErrorContext(
|
|
597
|
+
transport_type=EnumInfraTransportType.DATABASE,
|
|
598
|
+
operation="query_registrations",
|
|
599
|
+
target_name="postgres.storage",
|
|
600
|
+
correlation_id=correlation_id,
|
|
601
|
+
timeout_seconds=self._timeout_seconds,
|
|
602
|
+
),
|
|
603
|
+
) from e
|
|
604
|
+
|
|
605
|
+
except Exception as e:
|
|
606
|
+
async with self._circuit_breaker_lock:
|
|
607
|
+
await self._record_circuit_failure(
|
|
608
|
+
operation="query_registrations",
|
|
609
|
+
correlation_id=correlation_id,
|
|
610
|
+
)
|
|
611
|
+
duration_ms = (time.monotonic() - start_time) * 1000
|
|
612
|
+
context = ModelInfraErrorContext(
|
|
613
|
+
transport_type=EnumInfraTransportType.DATABASE,
|
|
614
|
+
operation="query_registrations",
|
|
615
|
+
target_name="postgres.storage",
|
|
616
|
+
correlation_id=correlation_id,
|
|
617
|
+
)
|
|
618
|
+
raise InfraConnectionError(
|
|
619
|
+
f"PostgreSQL query failed: {type(e).__name__}",
|
|
620
|
+
context=context,
|
|
621
|
+
) from e
|
|
622
|
+
|
|
623
|
+
async def update_registration(
|
|
624
|
+
self,
|
|
625
|
+
request: ModelUpdateRegistrationRequest,
|
|
626
|
+
) -> ModelUpsertResult:
|
|
627
|
+
"""Update an existing registration record.
|
|
628
|
+
|
|
629
|
+
Args:
|
|
630
|
+
request: ModelUpdateRegistrationRequest containing:
|
|
631
|
+
- node_id: ID of the node to update
|
|
632
|
+
- updates: ModelRegistrationUpdate with fields to update
|
|
633
|
+
(only non-None fields will be applied)
|
|
634
|
+
- correlation_id: Optional correlation ID for tracing
|
|
635
|
+
|
|
636
|
+
Returns:
|
|
637
|
+
ModelUpsertResult with update outcome.
|
|
638
|
+
|
|
639
|
+
Raises:
|
|
640
|
+
InfraConnectionError: If connection to PostgreSQL fails.
|
|
641
|
+
InfraTimeoutError: If operation times out.
|
|
642
|
+
InfraUnavailableError: If circuit breaker is open.
|
|
643
|
+
"""
|
|
644
|
+
# Extract fields from request model
|
|
645
|
+
node_id = request.node_id
|
|
646
|
+
updates = request.updates
|
|
647
|
+
correlation_id = request.correlation_id or uuid4()
|
|
648
|
+
start_time = time.monotonic()
|
|
649
|
+
|
|
650
|
+
# Check circuit breaker
|
|
651
|
+
async with self._circuit_breaker_lock:
|
|
652
|
+
await self._check_circuit_breaker(
|
|
653
|
+
operation="update_registration",
|
|
654
|
+
correlation_id=correlation_id,
|
|
655
|
+
)
|
|
656
|
+
|
|
657
|
+
try:
|
|
658
|
+
pool = await self._ensure_pool(correlation_id=correlation_id)
|
|
659
|
+
|
|
660
|
+
# Extract fields from the update model
|
|
661
|
+
# Use `is not None` checks to allow explicitly clearing fields with empty
|
|
662
|
+
# lists/dicts. Truthiness checks would treat [] and {} as "no update".
|
|
663
|
+
capabilities_json = (
|
|
664
|
+
json.dumps(updates.capabilities)
|
|
665
|
+
if updates.capabilities is not None
|
|
666
|
+
else None
|
|
667
|
+
)
|
|
668
|
+
endpoints_json = (
|
|
669
|
+
json.dumps(updates.endpoints) if updates.endpoints is not None else None
|
|
670
|
+
)
|
|
671
|
+
metadata_json = (
|
|
672
|
+
json.dumps(updates.metadata) if updates.metadata is not None else None
|
|
673
|
+
)
|
|
674
|
+
node_version = updates.node_version
|
|
675
|
+
|
|
676
|
+
async with pool.acquire() as conn:
|
|
677
|
+
result = await asyncio.wait_for(
|
|
678
|
+
conn.fetchval(
|
|
679
|
+
SQL_UPDATE,
|
|
680
|
+
node_id,
|
|
681
|
+
capabilities_json,
|
|
682
|
+
endpoints_json,
|
|
683
|
+
metadata_json,
|
|
684
|
+
node_version,
|
|
685
|
+
),
|
|
686
|
+
timeout=self._timeout_seconds,
|
|
687
|
+
)
|
|
688
|
+
|
|
689
|
+
# Reset circuit breaker on success
|
|
690
|
+
async with self._circuit_breaker_lock:
|
|
691
|
+
await self._reset_circuit_breaker()
|
|
692
|
+
|
|
693
|
+
success = result is not None
|
|
694
|
+
duration_ms = (time.monotonic() - start_time) * 1000
|
|
695
|
+
|
|
696
|
+
logger.info(
|
|
697
|
+
"Registration updated",
|
|
698
|
+
extra={
|
|
699
|
+
"node_id": str(node_id),
|
|
700
|
+
"success": success,
|
|
701
|
+
"duration_ms": duration_ms,
|
|
702
|
+
"correlation_id": str(correlation_id),
|
|
703
|
+
},
|
|
704
|
+
)
|
|
705
|
+
|
|
706
|
+
return ModelUpsertResult(
|
|
707
|
+
success=success,
|
|
708
|
+
node_id=node_id,
|
|
709
|
+
operation="update",
|
|
710
|
+
error="Record not found" if not success else None,
|
|
711
|
+
duration_ms=duration_ms,
|
|
712
|
+
backend_type=self.handler_type,
|
|
713
|
+
correlation_id=correlation_id,
|
|
714
|
+
)
|
|
715
|
+
|
|
716
|
+
except TimeoutError as e:
|
|
717
|
+
async with self._circuit_breaker_lock:
|
|
718
|
+
await self._record_circuit_failure(
|
|
719
|
+
operation="update_registration",
|
|
720
|
+
correlation_id=correlation_id,
|
|
721
|
+
)
|
|
722
|
+
duration_ms = (time.monotonic() - start_time) * 1000
|
|
723
|
+
raise InfraTimeoutError(
|
|
724
|
+
f"PostgreSQL update timed out after {self._timeout_seconds}s",
|
|
725
|
+
context=ModelTimeoutErrorContext(
|
|
726
|
+
transport_type=EnumInfraTransportType.DATABASE,
|
|
727
|
+
operation="update_registration",
|
|
728
|
+
target_name="postgres.storage",
|
|
729
|
+
correlation_id=correlation_id,
|
|
730
|
+
timeout_seconds=self._timeout_seconds,
|
|
731
|
+
),
|
|
732
|
+
) from e
|
|
733
|
+
|
|
734
|
+
except Exception as e:
|
|
735
|
+
async with self._circuit_breaker_lock:
|
|
736
|
+
await self._record_circuit_failure(
|
|
737
|
+
operation="update_registration",
|
|
738
|
+
correlation_id=correlation_id,
|
|
739
|
+
)
|
|
740
|
+
duration_ms = (time.monotonic() - start_time) * 1000
|
|
741
|
+
context = ModelInfraErrorContext(
|
|
742
|
+
transport_type=EnumInfraTransportType.DATABASE,
|
|
743
|
+
operation="update_registration",
|
|
744
|
+
target_name="postgres.storage",
|
|
745
|
+
correlation_id=correlation_id,
|
|
746
|
+
)
|
|
747
|
+
raise InfraConnectionError(
|
|
748
|
+
f"PostgreSQL update failed: {type(e).__name__}",
|
|
749
|
+
context=context,
|
|
750
|
+
) from e
|
|
751
|
+
|
|
752
|
+
async def delete_registration(
|
|
753
|
+
self,
|
|
754
|
+
request: ModelDeleteRegistrationRequest,
|
|
755
|
+
) -> ModelDeleteResult:
|
|
756
|
+
"""Delete a registration record from PostgreSQL.
|
|
757
|
+
|
|
758
|
+
Args:
|
|
759
|
+
request: ModelDeleteRegistrationRequest containing:
|
|
760
|
+
- node_id: ID of the node to delete
|
|
761
|
+
- correlation_id: Optional correlation ID for tracing
|
|
762
|
+
|
|
763
|
+
Returns:
|
|
764
|
+
ModelDeleteResult with deletion outcome.
|
|
765
|
+
|
|
766
|
+
Raises:
|
|
767
|
+
InfraConnectionError: If connection to PostgreSQL fails.
|
|
768
|
+
InfraTimeoutError: If operation times out.
|
|
769
|
+
InfraUnavailableError: If circuit breaker is open.
|
|
770
|
+
"""
|
|
771
|
+
# Extract fields from request model
|
|
772
|
+
node_id = request.node_id
|
|
773
|
+
correlation_id = request.correlation_id or uuid4()
|
|
774
|
+
start_time = time.monotonic()
|
|
775
|
+
|
|
776
|
+
# Check circuit breaker
|
|
777
|
+
async with self._circuit_breaker_lock:
|
|
778
|
+
await self._check_circuit_breaker(
|
|
779
|
+
operation="delete_registration",
|
|
780
|
+
correlation_id=correlation_id,
|
|
781
|
+
)
|
|
782
|
+
|
|
783
|
+
try:
|
|
784
|
+
pool = await self._ensure_pool(correlation_id=correlation_id)
|
|
785
|
+
|
|
786
|
+
async with pool.acquire() as conn:
|
|
787
|
+
result = await asyncio.wait_for(
|
|
788
|
+
conn.fetchval(SQL_DELETE, node_id),
|
|
789
|
+
timeout=self._timeout_seconds,
|
|
790
|
+
)
|
|
791
|
+
|
|
792
|
+
# Reset circuit breaker on success
|
|
793
|
+
async with self._circuit_breaker_lock:
|
|
794
|
+
await self._reset_circuit_breaker()
|
|
795
|
+
|
|
796
|
+
deleted = result is not None
|
|
797
|
+
duration_ms = (time.monotonic() - start_time) * 1000
|
|
798
|
+
|
|
799
|
+
logger.info(
|
|
800
|
+
"Registration deletion completed",
|
|
801
|
+
extra={
|
|
802
|
+
"node_id": str(node_id),
|
|
803
|
+
"deleted": deleted,
|
|
804
|
+
"duration_ms": duration_ms,
|
|
805
|
+
"correlation_id": str(correlation_id),
|
|
806
|
+
},
|
|
807
|
+
)
|
|
808
|
+
|
|
809
|
+
return ModelDeleteResult(
|
|
810
|
+
success=True,
|
|
811
|
+
node_id=node_id,
|
|
812
|
+
deleted=deleted,
|
|
813
|
+
duration_ms=duration_ms,
|
|
814
|
+
backend_type=self.handler_type,
|
|
815
|
+
correlation_id=correlation_id,
|
|
816
|
+
)
|
|
817
|
+
|
|
818
|
+
except TimeoutError as e:
|
|
819
|
+
async with self._circuit_breaker_lock:
|
|
820
|
+
await self._record_circuit_failure(
|
|
821
|
+
operation="delete_registration",
|
|
822
|
+
correlation_id=correlation_id,
|
|
823
|
+
)
|
|
824
|
+
raise InfraTimeoutError(
|
|
825
|
+
f"PostgreSQL delete timed out after {self._timeout_seconds}s",
|
|
826
|
+
context=ModelTimeoutErrorContext(
|
|
827
|
+
transport_type=EnumInfraTransportType.DATABASE,
|
|
828
|
+
operation="delete_registration",
|
|
829
|
+
target_name="postgres.storage",
|
|
830
|
+
correlation_id=correlation_id,
|
|
831
|
+
timeout_seconds=self._timeout_seconds,
|
|
832
|
+
),
|
|
833
|
+
) from e
|
|
834
|
+
|
|
835
|
+
except Exception as e:
|
|
836
|
+
async with self._circuit_breaker_lock:
|
|
837
|
+
await self._record_circuit_failure(
|
|
838
|
+
operation="delete_registration",
|
|
839
|
+
correlation_id=correlation_id,
|
|
840
|
+
)
|
|
841
|
+
context = ModelInfraErrorContext(
|
|
842
|
+
transport_type=EnumInfraTransportType.DATABASE,
|
|
843
|
+
operation="delete_registration",
|
|
844
|
+
target_name="postgres.storage",
|
|
845
|
+
correlation_id=correlation_id,
|
|
846
|
+
)
|
|
847
|
+
raise InfraConnectionError(
|
|
848
|
+
f"PostgreSQL delete failed: {type(e).__name__}",
|
|
849
|
+
context=context,
|
|
850
|
+
) from e
|
|
851
|
+
|
|
852
|
+
async def health_check(
|
|
853
|
+
self,
|
|
854
|
+
correlation_id: UUID | None = None,
|
|
855
|
+
) -> ModelStorageHealthCheckResult:
|
|
856
|
+
"""Perform a health check on the PostgreSQL connection.
|
|
857
|
+
|
|
858
|
+
Args:
|
|
859
|
+
correlation_id: Optional correlation ID for tracing.
|
|
860
|
+
|
|
861
|
+
Returns:
|
|
862
|
+
ModelStorageHealthCheckResult with health status information.
|
|
863
|
+
"""
|
|
864
|
+
correlation_id = correlation_id or uuid4()
|
|
865
|
+
start_time = time.monotonic()
|
|
866
|
+
|
|
867
|
+
try:
|
|
868
|
+
pool = await self._ensure_pool(correlation_id=correlation_id)
|
|
869
|
+
|
|
870
|
+
async with pool.acquire() as conn:
|
|
871
|
+
await asyncio.wait_for(
|
|
872
|
+
conn.fetchval("SELECT 1"),
|
|
873
|
+
timeout=5.0, # Short timeout for health check
|
|
874
|
+
)
|
|
875
|
+
|
|
876
|
+
duration_ms = (time.monotonic() - start_time) * 1000
|
|
877
|
+
|
|
878
|
+
return ModelStorageHealthCheckResult(
|
|
879
|
+
healthy=True,
|
|
880
|
+
backend_type=self.handler_type,
|
|
881
|
+
latency_ms=duration_ms,
|
|
882
|
+
reason="ok",
|
|
883
|
+
details=ModelStorageHealthCheckDetails(
|
|
884
|
+
pool_size=self._pool_size,
|
|
885
|
+
database_name=self._database,
|
|
886
|
+
),
|
|
887
|
+
correlation_id=correlation_id,
|
|
888
|
+
)
|
|
889
|
+
|
|
890
|
+
except Exception as e:
|
|
891
|
+
duration_ms = (time.monotonic() - start_time) * 1000
|
|
892
|
+
return ModelStorageHealthCheckResult(
|
|
893
|
+
healthy=False,
|
|
894
|
+
backend_type=self.handler_type,
|
|
895
|
+
latency_ms=duration_ms,
|
|
896
|
+
reason=f"Health check failed: {type(e).__name__}",
|
|
897
|
+
error_type=type(e).__name__,
|
|
898
|
+
details=ModelStorageHealthCheckDetails(
|
|
899
|
+
pool_size=self._pool_size,
|
|
900
|
+
database_name=self._database,
|
|
901
|
+
),
|
|
902
|
+
correlation_id=correlation_id,
|
|
903
|
+
)
|
|
904
|
+
|
|
905
|
+
async def shutdown(self) -> None:
|
|
906
|
+
"""Shutdown the handler and release resources."""
|
|
907
|
+
if self._pool is not None:
|
|
908
|
+
await self._pool.close()
|
|
909
|
+
self._pool = None
|
|
910
|
+
|
|
911
|
+
self._initialized = False
|
|
912
|
+
logger.info("HandlerRegistrationStoragePostgres shutdown complete")
|
|
913
|
+
|
|
914
|
+
|
|
915
|
+
__all__ = ["HandlerRegistrationStoragePostgres"]
|