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,945 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2025 OmniNode Team
|
|
3
|
+
"""Capability Query Service.
|
|
4
|
+
|
|
5
|
+
Provides high-level service for querying the registry by capability rather
|
|
6
|
+
than by name. This enables capability-based auto-configuration where nodes
|
|
7
|
+
declare what they need, not who provides it.
|
|
8
|
+
|
|
9
|
+
Core Principle: "I'm interested in what you do, not what you are."
|
|
10
|
+
|
|
11
|
+
Coroutine Safety:
|
|
12
|
+
This service uses MixinAsyncCircuitBreaker for coroutine-safe circuit
|
|
13
|
+
breaker protection. The circuit breaker provides defense-in-depth on top
|
|
14
|
+
of the underlying ProjectionReaderRegistration's circuit breaker.
|
|
15
|
+
|
|
16
|
+
Circuit Breaker:
|
|
17
|
+
This service implements its own circuit breaker as a defense-in-depth layer.
|
|
18
|
+
While ProjectionReaderRegistration also has circuit breakers, having them
|
|
19
|
+
at the service layer provides:
|
|
20
|
+
- Service-level failure isolation
|
|
21
|
+
- Independent failure thresholds tuned for query patterns
|
|
22
|
+
- Protection against issues beyond database connectivity
|
|
23
|
+
|
|
24
|
+
Related Tickets:
|
|
25
|
+
- OMN-1135: ServiceCapabilityQuery for capability-based discovery
|
|
26
|
+
- OMN-1134: Registry Projection Extensions for Capabilities
|
|
27
|
+
|
|
28
|
+
Example:
|
|
29
|
+
>>> from omnibase_infra.services import ServiceCapabilityQuery
|
|
30
|
+
>>> from omnibase_infra.projectors import ProjectionReaderRegistration
|
|
31
|
+
>>>
|
|
32
|
+
>>> reader = ProjectionReaderRegistration(pool)
|
|
33
|
+
>>> query = ServiceCapabilityQuery(reader)
|
|
34
|
+
>>>
|
|
35
|
+
>>> # Find all postgres storage providers
|
|
36
|
+
>>> nodes = await query.find_nodes_by_capability("postgres.storage")
|
|
37
|
+
>>>
|
|
38
|
+
>>> # Resolve a dependency spec
|
|
39
|
+
>>> spec = ModelDependencySpec(name="db", type="node", capability="postgres.storage")
|
|
40
|
+
>>> node = await query.resolve_dependency(spec)
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
from __future__ import annotations
|
|
44
|
+
|
|
45
|
+
import logging
|
|
46
|
+
from typing import TYPE_CHECKING
|
|
47
|
+
from uuid import UUID, uuid4
|
|
48
|
+
|
|
49
|
+
from omnibase_core.container import ModelONEXContainer
|
|
50
|
+
from omnibase_infra.enums import (
|
|
51
|
+
EnumInfraTransportType,
|
|
52
|
+
EnumRegistrationState,
|
|
53
|
+
EnumSelectionStrategy,
|
|
54
|
+
)
|
|
55
|
+
from omnibase_infra.errors import ProtocolConfigurationError, RuntimeHostError
|
|
56
|
+
from omnibase_infra.mixins import MixinAsyncCircuitBreaker
|
|
57
|
+
from omnibase_infra.models.discovery.model_dependency_spec import ModelDependencySpec
|
|
58
|
+
from omnibase_infra.models.errors.model_infra_error_context import (
|
|
59
|
+
ModelInfraErrorContext,
|
|
60
|
+
)
|
|
61
|
+
from omnibase_infra.models.projection import ModelRegistrationProjection
|
|
62
|
+
from omnibase_infra.services.service_node_selector import ServiceNodeSelector
|
|
63
|
+
|
|
64
|
+
if TYPE_CHECKING:
|
|
65
|
+
from omnibase_infra.projectors.projection_reader_registration import (
|
|
66
|
+
ProjectionReaderRegistration,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
logger = logging.getLogger(__name__)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class ServiceCapabilityQuery(MixinAsyncCircuitBreaker):
|
|
73
|
+
"""Queries registry for nodes by capability, not by name.
|
|
74
|
+
|
|
75
|
+
Core Principle: "I'm interested in what you do, not what you are."
|
|
76
|
+
|
|
77
|
+
This service wraps ProjectionReaderRegistration to provide high-level
|
|
78
|
+
capability-based discovery. Instead of hardcoding module paths, consumers
|
|
79
|
+
can declare what capabilities they need and the system discovers which
|
|
80
|
+
nodes provide them.
|
|
81
|
+
|
|
82
|
+
Query Methods:
|
|
83
|
+
- find_nodes_by_capability: Find by capability tag
|
|
84
|
+
- find_nodes_by_intent_type: Find by single intent type handled
|
|
85
|
+
- find_nodes_by_intent_types: Find by multiple intent types (bulk query)
|
|
86
|
+
- find_nodes_by_protocol: Find by protocol implemented
|
|
87
|
+
|
|
88
|
+
Dependency Resolution:
|
|
89
|
+
The resolve_dependency method takes a ModelDependencySpec and:
|
|
90
|
+
1. Determines the discovery strategy (capability/intent/protocol)
|
|
91
|
+
2. Queries the registry for matching nodes
|
|
92
|
+
3. Applies the selection strategy to choose one node
|
|
93
|
+
|
|
94
|
+
Circuit Breaker:
|
|
95
|
+
This service implements MixinAsyncCircuitBreaker for defense-in-depth
|
|
96
|
+
protection. While ProjectionReaderRegistration has its own circuit
|
|
97
|
+
breakers, the service-level circuit breaker provides:
|
|
98
|
+
- Independent failure isolation at the service layer
|
|
99
|
+
- Service-specific failure thresholds (5 failures, 60s reset)
|
|
100
|
+
- Protection against issues beyond database connectivity
|
|
101
|
+
|
|
102
|
+
Design Notes:
|
|
103
|
+
- All queries delegate to ProjectionReaderRegistration
|
|
104
|
+
- Service-level circuit breaker provides defense-in-depth
|
|
105
|
+
- Node selection is handled by ServiceNodeSelector
|
|
106
|
+
- Round-robin state is maintained per-service instance
|
|
107
|
+
|
|
108
|
+
Example:
|
|
109
|
+
>>> reader = ProjectionReaderRegistration(pool)
|
|
110
|
+
>>> query = ServiceCapabilityQuery(reader)
|
|
111
|
+
>>>
|
|
112
|
+
>>> # Find active Kafka consumers
|
|
113
|
+
>>> nodes = await query.find_nodes_by_capability(
|
|
114
|
+
... "kafka.consumer",
|
|
115
|
+
... state=EnumRegistrationState.ACTIVE,
|
|
116
|
+
... )
|
|
117
|
+
>>>
|
|
118
|
+
>>> # Find nodes that handle postgres.upsert intent
|
|
119
|
+
>>> handlers = await query.find_nodes_by_intent_type(
|
|
120
|
+
... "postgres.upsert",
|
|
121
|
+
... contract_type="effect",
|
|
122
|
+
... )
|
|
123
|
+
|
|
124
|
+
Raises:
|
|
125
|
+
InfraConnectionError: If database connection fails
|
|
126
|
+
InfraTimeoutError: If query times out
|
|
127
|
+
InfraUnavailableError: If circuit breaker is open
|
|
128
|
+
RuntimeHostError: For other database errors
|
|
129
|
+
|
|
130
|
+
Note:
|
|
131
|
+
Dependency Injection Pattern: This service is a leaf infrastructure
|
|
132
|
+
service that receives its dependencies directly via constructor
|
|
133
|
+
parameters rather than resolving them from a container. Unlike
|
|
134
|
+
orchestrators that use ``container.resolve()`` to obtain services
|
|
135
|
+
dynamically, leaf services like this one are instantiated with
|
|
136
|
+
concrete dependencies (projection_reader, node_selector) and are
|
|
137
|
+
themselves resolved by higher-level components.
|
|
138
|
+
"""
|
|
139
|
+
|
|
140
|
+
def __init__(
|
|
141
|
+
self,
|
|
142
|
+
projection_reader: ProjectionReaderRegistration,
|
|
143
|
+
container: ModelONEXContainer | None = None,
|
|
144
|
+
node_selector: ServiceNodeSelector | None = None,
|
|
145
|
+
) -> None:
|
|
146
|
+
"""Initialize the capability query service.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
projection_reader: The projection reader for database queries.
|
|
150
|
+
Must be initialized with an asyncpg connection pool.
|
|
151
|
+
container: Optional ONEX container for dependency injection.
|
|
152
|
+
Passed to default ServiceNodeSelector if node_selector is None.
|
|
153
|
+
node_selector: Optional node selector for selection strategies.
|
|
154
|
+
If None, creates a new ServiceNodeSelector instance.
|
|
155
|
+
|
|
156
|
+
Example:
|
|
157
|
+
>>> pool = await asyncpg.create_pool(dsn)
|
|
158
|
+
>>> reader = ProjectionReaderRegistration(pool)
|
|
159
|
+
>>> query = ServiceCapabilityQuery(reader)
|
|
160
|
+
"""
|
|
161
|
+
# Initialize circuit breaker for defense-in-depth protection
|
|
162
|
+
self._init_circuit_breaker(
|
|
163
|
+
threshold=5,
|
|
164
|
+
reset_timeout=60.0,
|
|
165
|
+
service_name="capability-query",
|
|
166
|
+
transport_type=EnumInfraTransportType.DATABASE,
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
self._projection_reader = projection_reader
|
|
170
|
+
self._container = container
|
|
171
|
+
self._node_selector = node_selector or ServiceNodeSelector(container=container)
|
|
172
|
+
|
|
173
|
+
async def find_nodes_by_capability(
|
|
174
|
+
self,
|
|
175
|
+
capability: str,
|
|
176
|
+
contract_type: str | None = None,
|
|
177
|
+
state: EnumRegistrationState | None = None,
|
|
178
|
+
correlation_id: UUID | None = None,
|
|
179
|
+
) -> list[ModelRegistrationProjection]:
|
|
180
|
+
"""Find nodes that provide a specific capability.
|
|
181
|
+
|
|
182
|
+
Queries the registry for nodes with the specified capability tag.
|
|
183
|
+
Results can be filtered by contract type and registration state.
|
|
184
|
+
|
|
185
|
+
Coroutine Safety:
|
|
186
|
+
This method is coroutine-safe when called concurrently from multiple
|
|
187
|
+
coroutines within the same event loop. The circuit breaker state is
|
|
188
|
+
protected by an asyncio.Lock.
|
|
189
|
+
|
|
190
|
+
Args:
|
|
191
|
+
capability: Capability tag to search for (e.g., "postgres.storage",
|
|
192
|
+
"kafka.consumer", "consul.registration").
|
|
193
|
+
contract_type: Optional filter by contract type ("effect", "compute",
|
|
194
|
+
"reducer", "orchestrator").
|
|
195
|
+
state: Registration state filter. When None (default), filters to
|
|
196
|
+
EnumRegistrationState.ACTIVE to return only actively registered
|
|
197
|
+
nodes. Pass an explicit EnumRegistrationState value to query
|
|
198
|
+
nodes in other states (e.g., PENDING_REGISTRATION, LIVENESS_EXPIRED).
|
|
199
|
+
correlation_id: Optional correlation ID for distributed tracing.
|
|
200
|
+
When provided, included in all log messages for request tracking.
|
|
201
|
+
|
|
202
|
+
Returns:
|
|
203
|
+
List of matching registration projections. Empty list if no matches.
|
|
204
|
+
|
|
205
|
+
Raises:
|
|
206
|
+
InfraConnectionError: If database connection fails
|
|
207
|
+
InfraTimeoutError: If query times out
|
|
208
|
+
InfraUnavailableError: If circuit breaker is open
|
|
209
|
+
RuntimeHostError: For other database errors
|
|
210
|
+
|
|
211
|
+
Example:
|
|
212
|
+
>>> nodes = await query.find_nodes_by_capability(
|
|
213
|
+
... "postgres.storage",
|
|
214
|
+
... contract_type="effect",
|
|
215
|
+
... state=EnumRegistrationState.ACTIVE,
|
|
216
|
+
... )
|
|
217
|
+
>>> for node in nodes:
|
|
218
|
+
... print(f"Found: {node.entity_id} - {node.node_type}")
|
|
219
|
+
"""
|
|
220
|
+
correlation_id = self._ensure_correlation_id(correlation_id)
|
|
221
|
+
state = state or EnumRegistrationState.ACTIVE
|
|
222
|
+
|
|
223
|
+
# Check circuit breaker before operation
|
|
224
|
+
async with self._circuit_breaker_lock:
|
|
225
|
+
await self._check_circuit_breaker(
|
|
226
|
+
operation="find_nodes_by_capability",
|
|
227
|
+
correlation_id=correlation_id,
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
logger.debug(
|
|
231
|
+
"Finding nodes by capability",
|
|
232
|
+
extra={
|
|
233
|
+
"capability": capability,
|
|
234
|
+
"contract_type": contract_type,
|
|
235
|
+
"state": str(state),
|
|
236
|
+
"correlation_id": str(correlation_id),
|
|
237
|
+
},
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
try:
|
|
241
|
+
# Query by capability tag
|
|
242
|
+
results = await self._projection_reader.get_by_capability_tag(
|
|
243
|
+
tag=capability,
|
|
244
|
+
state=state,
|
|
245
|
+
correlation_id=correlation_id,
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
results = self._filter_by_contract_type(results, contract_type)
|
|
249
|
+
|
|
250
|
+
# Record success
|
|
251
|
+
async with self._circuit_breaker_lock:
|
|
252
|
+
await self._reset_circuit_breaker()
|
|
253
|
+
|
|
254
|
+
logger.debug(
|
|
255
|
+
"Capability query completed",
|
|
256
|
+
extra={
|
|
257
|
+
"capability": capability,
|
|
258
|
+
"result_count": len(results),
|
|
259
|
+
"correlation_id": str(correlation_id),
|
|
260
|
+
},
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
return results
|
|
264
|
+
|
|
265
|
+
except RuntimeHostError:
|
|
266
|
+
# Record failure and re-raise infrastructure errors as-is
|
|
267
|
+
async with self._circuit_breaker_lock:
|
|
268
|
+
await self._record_circuit_failure(
|
|
269
|
+
operation="find_nodes_by_capability",
|
|
270
|
+
correlation_id=correlation_id,
|
|
271
|
+
)
|
|
272
|
+
raise
|
|
273
|
+
except Exception as e:
|
|
274
|
+
# Record failure
|
|
275
|
+
async with self._circuit_breaker_lock:
|
|
276
|
+
await self._record_circuit_failure(
|
|
277
|
+
operation="find_nodes_by_capability",
|
|
278
|
+
correlation_id=correlation_id,
|
|
279
|
+
)
|
|
280
|
+
# Wrap unexpected exceptions with RuntimeHostError
|
|
281
|
+
context = ModelInfraErrorContext(
|
|
282
|
+
transport_type=EnumInfraTransportType.DATABASE,
|
|
283
|
+
operation="find_nodes_by_capability",
|
|
284
|
+
correlation_id=correlation_id,
|
|
285
|
+
)
|
|
286
|
+
raise RuntimeHostError(
|
|
287
|
+
f"Capability query failed: {type(e).__name__}",
|
|
288
|
+
context=context,
|
|
289
|
+
capability=capability,
|
|
290
|
+
) from e
|
|
291
|
+
|
|
292
|
+
async def find_nodes_by_intent_type(
|
|
293
|
+
self,
|
|
294
|
+
intent_type: str,
|
|
295
|
+
contract_type: str = "effect",
|
|
296
|
+
state: EnumRegistrationState | None = None,
|
|
297
|
+
correlation_id: UUID | None = None,
|
|
298
|
+
) -> list[ModelRegistrationProjection]:
|
|
299
|
+
"""Find effect nodes that handle a specific intent type.
|
|
300
|
+
|
|
301
|
+
Queries the registry for nodes that can handle the specified intent type.
|
|
302
|
+
Typically used to find effect nodes that execute specific intents.
|
|
303
|
+
|
|
304
|
+
Coroutine Safety:
|
|
305
|
+
This method is coroutine-safe when called concurrently from multiple
|
|
306
|
+
coroutines within the same event loop. The circuit breaker state is
|
|
307
|
+
protected by an asyncio.Lock.
|
|
308
|
+
|
|
309
|
+
Args:
|
|
310
|
+
intent_type: Intent type to search for (e.g., "postgres.upsert",
|
|
311
|
+
"consul.register", "kafka.publish").
|
|
312
|
+
contract_type: Filter by contract type (default: "effect").
|
|
313
|
+
Intents are typically handled by effect nodes.
|
|
314
|
+
state: Registration state filter. When None (default), filters to
|
|
315
|
+
EnumRegistrationState.ACTIVE to return only actively registered
|
|
316
|
+
nodes. Pass an explicit EnumRegistrationState value to query
|
|
317
|
+
nodes in other states (e.g., PENDING_REGISTRATION, LIVENESS_EXPIRED).
|
|
318
|
+
correlation_id: Optional correlation ID for distributed tracing.
|
|
319
|
+
When provided, included in all log messages for request tracking.
|
|
320
|
+
|
|
321
|
+
Returns:
|
|
322
|
+
List of matching registration projections. Empty list if no matches.
|
|
323
|
+
|
|
324
|
+
Raises:
|
|
325
|
+
InfraConnectionError: If database connection fails
|
|
326
|
+
InfraTimeoutError: If query times out
|
|
327
|
+
InfraUnavailableError: If circuit breaker is open
|
|
328
|
+
RuntimeHostError: For other database errors
|
|
329
|
+
|
|
330
|
+
Example:
|
|
331
|
+
>>> handlers = await query.find_nodes_by_intent_type(
|
|
332
|
+
... "postgres.query",
|
|
333
|
+
... contract_type="effect",
|
|
334
|
+
... state=EnumRegistrationState.ACTIVE,
|
|
335
|
+
... )
|
|
336
|
+
>>> for handler in handlers:
|
|
337
|
+
... print(f"Can handle postgres.query: {handler.entity_id}")
|
|
338
|
+
"""
|
|
339
|
+
correlation_id = self._ensure_correlation_id(correlation_id)
|
|
340
|
+
state = state or EnumRegistrationState.ACTIVE
|
|
341
|
+
|
|
342
|
+
# Check circuit breaker before operation
|
|
343
|
+
async with self._circuit_breaker_lock:
|
|
344
|
+
await self._check_circuit_breaker(
|
|
345
|
+
operation="find_nodes_by_intent_type",
|
|
346
|
+
correlation_id=correlation_id,
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
logger.debug(
|
|
350
|
+
"Finding nodes by intent type",
|
|
351
|
+
extra={
|
|
352
|
+
"intent_type": intent_type,
|
|
353
|
+
"contract_type": contract_type,
|
|
354
|
+
"state": str(state),
|
|
355
|
+
"correlation_id": str(correlation_id),
|
|
356
|
+
},
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
try:
|
|
360
|
+
# Query by intent type
|
|
361
|
+
results = await self._projection_reader.get_by_intent_type(
|
|
362
|
+
intent_type=intent_type,
|
|
363
|
+
state=state,
|
|
364
|
+
correlation_id=correlation_id,
|
|
365
|
+
)
|
|
366
|
+
|
|
367
|
+
results = self._filter_by_contract_type(results, contract_type)
|
|
368
|
+
|
|
369
|
+
# Record success
|
|
370
|
+
async with self._circuit_breaker_lock:
|
|
371
|
+
await self._reset_circuit_breaker()
|
|
372
|
+
|
|
373
|
+
logger.debug(
|
|
374
|
+
"Intent type query completed",
|
|
375
|
+
extra={
|
|
376
|
+
"intent_type": intent_type,
|
|
377
|
+
"result_count": len(results),
|
|
378
|
+
"correlation_id": str(correlation_id),
|
|
379
|
+
},
|
|
380
|
+
)
|
|
381
|
+
|
|
382
|
+
return results
|
|
383
|
+
|
|
384
|
+
except RuntimeHostError:
|
|
385
|
+
# Record failure and re-raise infrastructure errors as-is
|
|
386
|
+
async with self._circuit_breaker_lock:
|
|
387
|
+
await self._record_circuit_failure(
|
|
388
|
+
operation="find_nodes_by_intent_type",
|
|
389
|
+
correlation_id=correlation_id,
|
|
390
|
+
)
|
|
391
|
+
raise
|
|
392
|
+
except Exception as e:
|
|
393
|
+
# Record failure
|
|
394
|
+
async with self._circuit_breaker_lock:
|
|
395
|
+
await self._record_circuit_failure(
|
|
396
|
+
operation="find_nodes_by_intent_type",
|
|
397
|
+
correlation_id=correlation_id,
|
|
398
|
+
)
|
|
399
|
+
# Wrap unexpected exceptions with RuntimeHostError
|
|
400
|
+
context = ModelInfraErrorContext(
|
|
401
|
+
transport_type=EnumInfraTransportType.DATABASE,
|
|
402
|
+
operation="find_nodes_by_intent_type",
|
|
403
|
+
correlation_id=correlation_id,
|
|
404
|
+
)
|
|
405
|
+
raise RuntimeHostError(
|
|
406
|
+
f"Intent type query failed: {type(e).__name__}",
|
|
407
|
+
context=context,
|
|
408
|
+
intent_type=intent_type,
|
|
409
|
+
) from e
|
|
410
|
+
|
|
411
|
+
async def find_nodes_by_intent_types(
|
|
412
|
+
self,
|
|
413
|
+
intent_types: list[str],
|
|
414
|
+
contract_type: str = "effect",
|
|
415
|
+
state: EnumRegistrationState | None = None,
|
|
416
|
+
correlation_id: UUID | None = None,
|
|
417
|
+
) -> list[ModelRegistrationProjection]:
|
|
418
|
+
"""Find effect nodes that handle ANY of the specified intent types.
|
|
419
|
+
|
|
420
|
+
Bulk query method that retrieves nodes matching any intent type in a single
|
|
421
|
+
database call. This is more efficient than calling find_nodes_by_intent_type
|
|
422
|
+
repeatedly for each intent type.
|
|
423
|
+
|
|
424
|
+
Coroutine Safety:
|
|
425
|
+
This method is coroutine-safe when called concurrently from multiple
|
|
426
|
+
coroutines within the same event loop. The circuit breaker state is
|
|
427
|
+
protected by an asyncio.Lock.
|
|
428
|
+
|
|
429
|
+
Performance Note:
|
|
430
|
+
This method reduces N database queries to 1 query when resolving
|
|
431
|
+
dependencies with multiple intent types. For N intent types:
|
|
432
|
+
- Previous: N sequential database calls
|
|
433
|
+
- Now: 1 bulk query using SQL array overlap
|
|
434
|
+
|
|
435
|
+
Args:
|
|
436
|
+
intent_types: List of intent types to search for (e.g.,
|
|
437
|
+
["postgres.upsert", "postgres.query", "postgres.delete"]).
|
|
438
|
+
contract_type: Filter by contract type (default: "effect").
|
|
439
|
+
Intents are typically handled by effect nodes.
|
|
440
|
+
state: Registration state filter. When None (default), filters to
|
|
441
|
+
EnumRegistrationState.ACTIVE to return only actively registered
|
|
442
|
+
nodes. Pass an explicit EnumRegistrationState value to query
|
|
443
|
+
nodes in other states (e.g., PENDING_REGISTRATION, LIVENESS_EXPIRED).
|
|
444
|
+
correlation_id: Optional correlation ID for distributed tracing.
|
|
445
|
+
When provided, included in all log messages for request tracking.
|
|
446
|
+
|
|
447
|
+
Returns:
|
|
448
|
+
List of matching registration projections. Empty list if no matches
|
|
449
|
+
or if intent_types list is empty.
|
|
450
|
+
|
|
451
|
+
Raises:
|
|
452
|
+
InfraConnectionError: If database connection fails
|
|
453
|
+
InfraTimeoutError: If query times out
|
|
454
|
+
InfraUnavailableError: If circuit breaker is open
|
|
455
|
+
RuntimeHostError: For other database errors
|
|
456
|
+
|
|
457
|
+
Example:
|
|
458
|
+
>>> handlers = await query.find_nodes_by_intent_types(
|
|
459
|
+
... ["postgres.query", "postgres.upsert", "postgres.delete"],
|
|
460
|
+
... contract_type="effect",
|
|
461
|
+
... state=EnumRegistrationState.ACTIVE,
|
|
462
|
+
... )
|
|
463
|
+
>>> for handler in handlers:
|
|
464
|
+
... print(f"Can handle postgres intents: {handler.entity_id}")
|
|
465
|
+
"""
|
|
466
|
+
correlation_id = self._ensure_correlation_id(correlation_id)
|
|
467
|
+
if not intent_types:
|
|
468
|
+
return []
|
|
469
|
+
|
|
470
|
+
state = state or EnumRegistrationState.ACTIVE
|
|
471
|
+
|
|
472
|
+
# Check circuit breaker before operation
|
|
473
|
+
async with self._circuit_breaker_lock:
|
|
474
|
+
await self._check_circuit_breaker(
|
|
475
|
+
operation="find_nodes_by_intent_types",
|
|
476
|
+
correlation_id=correlation_id,
|
|
477
|
+
)
|
|
478
|
+
|
|
479
|
+
logger.debug(
|
|
480
|
+
"Finding nodes by intent types (bulk)",
|
|
481
|
+
extra={
|
|
482
|
+
"intent_types": intent_types,
|
|
483
|
+
"intent_count": len(intent_types),
|
|
484
|
+
"contract_type": contract_type,
|
|
485
|
+
"state": str(state),
|
|
486
|
+
"correlation_id": str(correlation_id),
|
|
487
|
+
},
|
|
488
|
+
)
|
|
489
|
+
|
|
490
|
+
try:
|
|
491
|
+
# Query by intent types (bulk)
|
|
492
|
+
results = await self._projection_reader.get_by_intent_types(
|
|
493
|
+
intent_types=intent_types,
|
|
494
|
+
state=state,
|
|
495
|
+
correlation_id=correlation_id,
|
|
496
|
+
)
|
|
497
|
+
|
|
498
|
+
results = self._filter_by_contract_type(results, contract_type)
|
|
499
|
+
|
|
500
|
+
# Record success
|
|
501
|
+
async with self._circuit_breaker_lock:
|
|
502
|
+
await self._reset_circuit_breaker()
|
|
503
|
+
|
|
504
|
+
logger.debug(
|
|
505
|
+
"Intent types query completed (bulk)",
|
|
506
|
+
extra={
|
|
507
|
+
"intent_types": intent_types,
|
|
508
|
+
"result_count": len(results),
|
|
509
|
+
"correlation_id": str(correlation_id),
|
|
510
|
+
},
|
|
511
|
+
)
|
|
512
|
+
|
|
513
|
+
return results
|
|
514
|
+
|
|
515
|
+
except RuntimeHostError:
|
|
516
|
+
# Record failure and re-raise infrastructure errors as-is
|
|
517
|
+
async with self._circuit_breaker_lock:
|
|
518
|
+
await self._record_circuit_failure(
|
|
519
|
+
operation="find_nodes_by_intent_types",
|
|
520
|
+
correlation_id=correlation_id,
|
|
521
|
+
)
|
|
522
|
+
raise
|
|
523
|
+
except Exception as e:
|
|
524
|
+
# Record failure
|
|
525
|
+
async with self._circuit_breaker_lock:
|
|
526
|
+
await self._record_circuit_failure(
|
|
527
|
+
operation="find_nodes_by_intent_types",
|
|
528
|
+
correlation_id=correlation_id,
|
|
529
|
+
)
|
|
530
|
+
# Wrap unexpected exceptions with RuntimeHostError
|
|
531
|
+
context = ModelInfraErrorContext(
|
|
532
|
+
transport_type=EnumInfraTransportType.DATABASE,
|
|
533
|
+
operation="find_nodes_by_intent_types",
|
|
534
|
+
correlation_id=correlation_id,
|
|
535
|
+
)
|
|
536
|
+
raise RuntimeHostError(
|
|
537
|
+
f"Intent types query failed: {type(e).__name__}",
|
|
538
|
+
context=context,
|
|
539
|
+
intent_types=intent_types,
|
|
540
|
+
) from e
|
|
541
|
+
|
|
542
|
+
async def find_nodes_by_protocol(
|
|
543
|
+
self,
|
|
544
|
+
protocol: str,
|
|
545
|
+
contract_type: str | None = None,
|
|
546
|
+
state: EnumRegistrationState | None = None,
|
|
547
|
+
correlation_id: UUID | None = None,
|
|
548
|
+
) -> list[ModelRegistrationProjection]:
|
|
549
|
+
"""Find nodes implementing a specific protocol.
|
|
550
|
+
|
|
551
|
+
Queries the registry for nodes that implement the specified protocol.
|
|
552
|
+
Useful for finding nodes that satisfy interface requirements.
|
|
553
|
+
|
|
554
|
+
Coroutine Safety:
|
|
555
|
+
This method is coroutine-safe when called concurrently from multiple
|
|
556
|
+
coroutines within the same event loop. The circuit breaker state is
|
|
557
|
+
protected by an asyncio.Lock.
|
|
558
|
+
|
|
559
|
+
Args:
|
|
560
|
+
protocol: Protocol name to search for (e.g., "ProtocolEventPublisher",
|
|
561
|
+
"ProtocolReducer", "ProtocolDatabaseAdapter").
|
|
562
|
+
contract_type: Optional filter by contract type ("effect", "compute",
|
|
563
|
+
"reducer", "orchestrator").
|
|
564
|
+
state: Registration state filter. When None (default), filters to
|
|
565
|
+
EnumRegistrationState.ACTIVE to return only actively registered
|
|
566
|
+
nodes. Pass an explicit EnumRegistrationState value to query
|
|
567
|
+
nodes in other states (e.g., PENDING_REGISTRATION, LIVENESS_EXPIRED).
|
|
568
|
+
correlation_id: Optional correlation ID for distributed tracing.
|
|
569
|
+
When provided, included in all log messages for request tracking.
|
|
570
|
+
|
|
571
|
+
Returns:
|
|
572
|
+
List of matching registration projections. Empty list if no matches.
|
|
573
|
+
|
|
574
|
+
Raises:
|
|
575
|
+
InfraConnectionError: If database connection fails
|
|
576
|
+
InfraTimeoutError: If query times out
|
|
577
|
+
InfraUnavailableError: If circuit breaker is open
|
|
578
|
+
RuntimeHostError: For other database errors
|
|
579
|
+
|
|
580
|
+
Example:
|
|
581
|
+
>>> adapters = await query.find_nodes_by_protocol(
|
|
582
|
+
... "ProtocolEventPublisher",
|
|
583
|
+
... state=EnumRegistrationState.ACTIVE,
|
|
584
|
+
... )
|
|
585
|
+
>>> print(f"Found {len(adapters)} event publishers")
|
|
586
|
+
"""
|
|
587
|
+
correlation_id = self._ensure_correlation_id(correlation_id)
|
|
588
|
+
state = state or EnumRegistrationState.ACTIVE
|
|
589
|
+
|
|
590
|
+
# Check circuit breaker before operation
|
|
591
|
+
async with self._circuit_breaker_lock:
|
|
592
|
+
await self._check_circuit_breaker(
|
|
593
|
+
operation="find_nodes_by_protocol",
|
|
594
|
+
correlation_id=correlation_id,
|
|
595
|
+
)
|
|
596
|
+
|
|
597
|
+
logger.debug(
|
|
598
|
+
"Finding nodes by protocol",
|
|
599
|
+
extra={
|
|
600
|
+
"protocol": protocol,
|
|
601
|
+
"contract_type": contract_type,
|
|
602
|
+
"state": str(state),
|
|
603
|
+
"correlation_id": str(correlation_id),
|
|
604
|
+
},
|
|
605
|
+
)
|
|
606
|
+
|
|
607
|
+
try:
|
|
608
|
+
# Query by protocol
|
|
609
|
+
results = await self._projection_reader.get_by_protocol(
|
|
610
|
+
protocol_name=protocol,
|
|
611
|
+
state=state,
|
|
612
|
+
correlation_id=correlation_id,
|
|
613
|
+
)
|
|
614
|
+
|
|
615
|
+
results = self._filter_by_contract_type(results, contract_type)
|
|
616
|
+
|
|
617
|
+
# Record success
|
|
618
|
+
async with self._circuit_breaker_lock:
|
|
619
|
+
await self._reset_circuit_breaker()
|
|
620
|
+
|
|
621
|
+
logger.debug(
|
|
622
|
+
"Protocol query completed",
|
|
623
|
+
extra={
|
|
624
|
+
"protocol": protocol,
|
|
625
|
+
"result_count": len(results),
|
|
626
|
+
"correlation_id": str(correlation_id),
|
|
627
|
+
},
|
|
628
|
+
)
|
|
629
|
+
|
|
630
|
+
return results
|
|
631
|
+
|
|
632
|
+
except RuntimeHostError:
|
|
633
|
+
# Record failure and re-raise infrastructure errors as-is
|
|
634
|
+
async with self._circuit_breaker_lock:
|
|
635
|
+
await self._record_circuit_failure(
|
|
636
|
+
operation="find_nodes_by_protocol",
|
|
637
|
+
correlation_id=correlation_id,
|
|
638
|
+
)
|
|
639
|
+
raise
|
|
640
|
+
except Exception as e:
|
|
641
|
+
# Record failure
|
|
642
|
+
async with self._circuit_breaker_lock:
|
|
643
|
+
await self._record_circuit_failure(
|
|
644
|
+
operation="find_nodes_by_protocol",
|
|
645
|
+
correlation_id=correlation_id,
|
|
646
|
+
)
|
|
647
|
+
# Wrap unexpected exceptions with RuntimeHostError
|
|
648
|
+
context = ModelInfraErrorContext(
|
|
649
|
+
transport_type=EnumInfraTransportType.DATABASE,
|
|
650
|
+
operation="find_nodes_by_protocol",
|
|
651
|
+
correlation_id=correlation_id,
|
|
652
|
+
)
|
|
653
|
+
raise RuntimeHostError(
|
|
654
|
+
f"Protocol query failed: {type(e).__name__}",
|
|
655
|
+
context=context,
|
|
656
|
+
protocol=protocol,
|
|
657
|
+
) from e
|
|
658
|
+
|
|
659
|
+
async def resolve_dependency(
|
|
660
|
+
self,
|
|
661
|
+
dependency_spec: ModelDependencySpec,
|
|
662
|
+
correlation_id: UUID | None = None,
|
|
663
|
+
) -> ModelRegistrationProjection | None:
|
|
664
|
+
"""Resolve a dependency specification to a concrete node.
|
|
665
|
+
|
|
666
|
+
Uses the dependency specification to query the registry and select
|
|
667
|
+
a node that matches the specified capability criteria.
|
|
668
|
+
|
|
669
|
+
Resolution Strategy:
|
|
670
|
+
1. If capability specified -> find by capability
|
|
671
|
+
2. If intent_types specified -> find by intent types (bulk query)
|
|
672
|
+
3. If protocol specified -> find by protocol
|
|
673
|
+
4. Apply selection strategy from spec to choose among matches
|
|
674
|
+
|
|
675
|
+
Coroutine Safety:
|
|
676
|
+
This method is coroutine-safe when called concurrently from multiple
|
|
677
|
+
coroutines within the same event loop. Uses circuit-breaker-protected
|
|
678
|
+
query methods internally.
|
|
679
|
+
|
|
680
|
+
Args:
|
|
681
|
+
dependency_spec: Dependency specification from contract.
|
|
682
|
+
Contains capability filters and selection strategy.
|
|
683
|
+
correlation_id: Optional correlation ID for distributed tracing.
|
|
684
|
+
When provided, included in all log messages for request tracking.
|
|
685
|
+
|
|
686
|
+
Returns:
|
|
687
|
+
Resolved node registration, or None if not found.
|
|
688
|
+
|
|
689
|
+
Note:
|
|
690
|
+
Performance: When resolving by intent types, this method uses a bulk
|
|
691
|
+
query that retrieves all matching nodes in a single database call using
|
|
692
|
+
SQL array overlap. This reduces N queries to 1 query regardless of the
|
|
693
|
+
number of intent types in the dependency spec.
|
|
694
|
+
|
|
695
|
+
Example:
|
|
696
|
+
>>> spec = ModelDependencySpec(
|
|
697
|
+
... name="storage",
|
|
698
|
+
... type="node",
|
|
699
|
+
... capability="postgres.storage",
|
|
700
|
+
... contract_type="effect",
|
|
701
|
+
... selection_strategy="round_robin",
|
|
702
|
+
... )
|
|
703
|
+
>>> node = await query.resolve_dependency(spec)
|
|
704
|
+
>>> if node:
|
|
705
|
+
... print(f"Resolved to: {node.entity_id}")
|
|
706
|
+
... else:
|
|
707
|
+
... print("No node found for capability")
|
|
708
|
+
"""
|
|
709
|
+
correlation_id = self._ensure_correlation_id(correlation_id)
|
|
710
|
+
logger.debug(
|
|
711
|
+
"Resolving dependency",
|
|
712
|
+
extra={
|
|
713
|
+
"dependency_name": dependency_spec.name,
|
|
714
|
+
"dependency_type": dependency_spec.type,
|
|
715
|
+
"capability": dependency_spec.capability,
|
|
716
|
+
"intent_types": dependency_spec.intent_types,
|
|
717
|
+
"protocol": dependency_spec.protocol,
|
|
718
|
+
"selection_strategy": dependency_spec.selection_strategy,
|
|
719
|
+
"correlation_id": str(correlation_id),
|
|
720
|
+
},
|
|
721
|
+
)
|
|
722
|
+
|
|
723
|
+
# Determine state filter
|
|
724
|
+
state = self._parse_state(dependency_spec.state, correlation_id)
|
|
725
|
+
|
|
726
|
+
# Find candidates based on discovery strategy
|
|
727
|
+
candidates: list[ModelRegistrationProjection] = []
|
|
728
|
+
|
|
729
|
+
if dependency_spec.has_capability_filter():
|
|
730
|
+
# Assert for type narrowing - has_capability_filter guarantees not None
|
|
731
|
+
assert dependency_spec.capability is not None
|
|
732
|
+
candidates = await self.find_nodes_by_capability(
|
|
733
|
+
capability=dependency_spec.capability,
|
|
734
|
+
contract_type=dependency_spec.contract_type,
|
|
735
|
+
state=state,
|
|
736
|
+
correlation_id=correlation_id,
|
|
737
|
+
)
|
|
738
|
+
|
|
739
|
+
elif dependency_spec.has_intent_filter():
|
|
740
|
+
# Use bulk query for multiple intent types (single database call)
|
|
741
|
+
intent_types = dependency_spec.intent_types
|
|
742
|
+
if intent_types:
|
|
743
|
+
candidates = await self.find_nodes_by_intent_types(
|
|
744
|
+
intent_types=intent_types,
|
|
745
|
+
contract_type=dependency_spec.contract_type or "effect",
|
|
746
|
+
state=state,
|
|
747
|
+
correlation_id=correlation_id,
|
|
748
|
+
)
|
|
749
|
+
|
|
750
|
+
elif dependency_spec.has_protocol_filter():
|
|
751
|
+
# Assert for type narrowing - has_protocol_filter guarantees not None
|
|
752
|
+
assert dependency_spec.protocol is not None
|
|
753
|
+
candidates = await self.find_nodes_by_protocol(
|
|
754
|
+
protocol=dependency_spec.protocol,
|
|
755
|
+
contract_type=dependency_spec.contract_type,
|
|
756
|
+
state=state,
|
|
757
|
+
correlation_id=correlation_id,
|
|
758
|
+
)
|
|
759
|
+
|
|
760
|
+
# No matches found
|
|
761
|
+
if not candidates:
|
|
762
|
+
logger.debug(
|
|
763
|
+
"No candidates found for dependency",
|
|
764
|
+
extra={
|
|
765
|
+
"dependency_name": dependency_spec.name,
|
|
766
|
+
"correlation_id": str(correlation_id),
|
|
767
|
+
},
|
|
768
|
+
)
|
|
769
|
+
return None
|
|
770
|
+
|
|
771
|
+
# Apply selection strategy
|
|
772
|
+
strategy = self._parse_selection_strategy(
|
|
773
|
+
dependency_spec.selection_strategy, correlation_id
|
|
774
|
+
)
|
|
775
|
+
selected = await self._node_selector.select(
|
|
776
|
+
candidates=candidates,
|
|
777
|
+
strategy=strategy,
|
|
778
|
+
selection_key=dependency_spec.name,
|
|
779
|
+
correlation_id=correlation_id,
|
|
780
|
+
)
|
|
781
|
+
|
|
782
|
+
if selected:
|
|
783
|
+
logger.debug(
|
|
784
|
+
"Dependency resolved",
|
|
785
|
+
extra={
|
|
786
|
+
"dependency_name": dependency_spec.name,
|
|
787
|
+
"selected_entity_id": str(selected.entity_id),
|
|
788
|
+
"total_candidates": len(candidates),
|
|
789
|
+
"strategy": dependency_spec.selection_strategy,
|
|
790
|
+
"correlation_id": str(correlation_id),
|
|
791
|
+
},
|
|
792
|
+
)
|
|
793
|
+
else:
|
|
794
|
+
logger.debug(
|
|
795
|
+
"No node selected for dependency",
|
|
796
|
+
extra={
|
|
797
|
+
"dependency_name": dependency_spec.name,
|
|
798
|
+
"correlation_id": str(correlation_id),
|
|
799
|
+
},
|
|
800
|
+
)
|
|
801
|
+
|
|
802
|
+
return selected
|
|
803
|
+
|
|
804
|
+
def _ensure_correlation_id(self, correlation_id: UUID | None) -> UUID:
|
|
805
|
+
"""Ensure correlation ID is present, generating one if missing.
|
|
806
|
+
|
|
807
|
+
Args:
|
|
808
|
+
correlation_id: Optional correlation ID from caller. Accepts UUID
|
|
809
|
+
or None.
|
|
810
|
+
|
|
811
|
+
Returns:
|
|
812
|
+
The provided correlation ID, or a newly generated UUID4.
|
|
813
|
+
"""
|
|
814
|
+
return correlation_id or uuid4()
|
|
815
|
+
|
|
816
|
+
def _parse_state(
|
|
817
|
+
self,
|
|
818
|
+
state_value: EnumRegistrationState | str | None,
|
|
819
|
+
correlation_id: UUID | None = None,
|
|
820
|
+
) -> EnumRegistrationState:
|
|
821
|
+
"""Parse state value to EnumRegistrationState.
|
|
822
|
+
|
|
823
|
+
Accepts either an EnumRegistrationState enum value (returned as-is),
|
|
824
|
+
a string representation (parsed to enum), or None (defaults to ACTIVE).
|
|
825
|
+
|
|
826
|
+
Args:
|
|
827
|
+
state_value: State as EnumRegistrationState, string (e.g., "ACTIVE", "active"),
|
|
828
|
+
or None. When None, defaults to EnumRegistrationState.ACTIVE.
|
|
829
|
+
correlation_id: Optional correlation ID for tracing.
|
|
830
|
+
|
|
831
|
+
Returns:
|
|
832
|
+
EnumRegistrationState value.
|
|
833
|
+
|
|
834
|
+
Raises:
|
|
835
|
+
ProtocolConfigurationError: If state string is not a valid state or
|
|
836
|
+
if an unexpected error occurs during parsing.
|
|
837
|
+
"""
|
|
838
|
+
# Handle None - default to ACTIVE
|
|
839
|
+
if state_value is None:
|
|
840
|
+
return EnumRegistrationState.ACTIVE
|
|
841
|
+
|
|
842
|
+
# If already an enum, return directly
|
|
843
|
+
if isinstance(state_value, EnumRegistrationState):
|
|
844
|
+
return state_value
|
|
845
|
+
|
|
846
|
+
# Parse string to enum
|
|
847
|
+
try:
|
|
848
|
+
return EnumRegistrationState(state_value.lower())
|
|
849
|
+
except ValueError as e:
|
|
850
|
+
valid_states = [s.value for s in EnumRegistrationState]
|
|
851
|
+
raise ProtocolConfigurationError(
|
|
852
|
+
f"Invalid registration state '{state_value}'. "
|
|
853
|
+
f"Valid states are: {valid_states}",
|
|
854
|
+
details={
|
|
855
|
+
"state": state_value,
|
|
856
|
+
"valid_states": valid_states,
|
|
857
|
+
"correlation_id": correlation_id,
|
|
858
|
+
},
|
|
859
|
+
) from e
|
|
860
|
+
except Exception as e:
|
|
861
|
+
# Catch any other unexpected errors (e.g., AttributeError if state_value
|
|
862
|
+
# is an unexpected type that passed type checking)
|
|
863
|
+
raise ProtocolConfigurationError(
|
|
864
|
+
f"Failed to parse registration state: {type(e).__name__}",
|
|
865
|
+
details={
|
|
866
|
+
"state": str(state_value),
|
|
867
|
+
"error": str(e),
|
|
868
|
+
"correlation_id": correlation_id,
|
|
869
|
+
},
|
|
870
|
+
) from e
|
|
871
|
+
|
|
872
|
+
def _parse_selection_strategy(
|
|
873
|
+
self,
|
|
874
|
+
strategy: str | EnumSelectionStrategy,
|
|
875
|
+
correlation_id: UUID | None = None,
|
|
876
|
+
) -> EnumSelectionStrategy:
|
|
877
|
+
"""Parse selection strategy to enum.
|
|
878
|
+
|
|
879
|
+
Accepts either an EnumSelectionStrategy enum value (returned as-is)
|
|
880
|
+
or a string representation (parsed to enum).
|
|
881
|
+
|
|
882
|
+
Args:
|
|
883
|
+
strategy: Strategy as EnumSelectionStrategy or string
|
|
884
|
+
(e.g., "first", "round_robin").
|
|
885
|
+
correlation_id: Optional correlation ID for tracing.
|
|
886
|
+
|
|
887
|
+
Returns:
|
|
888
|
+
EnumSelectionStrategy value.
|
|
889
|
+
|
|
890
|
+
Raises:
|
|
891
|
+
ProtocolConfigurationError: If strategy string is not a valid strategy
|
|
892
|
+
or if an unexpected error occurs during parsing.
|
|
893
|
+
"""
|
|
894
|
+
# If already an enum, return directly
|
|
895
|
+
if isinstance(strategy, EnumSelectionStrategy):
|
|
896
|
+
return strategy
|
|
897
|
+
|
|
898
|
+
# Parse string to enum
|
|
899
|
+
try:
|
|
900
|
+
return EnumSelectionStrategy(strategy.lower())
|
|
901
|
+
except ValueError as e:
|
|
902
|
+
valid_strategies = [s.value for s in EnumSelectionStrategy]
|
|
903
|
+
raise ProtocolConfigurationError(
|
|
904
|
+
f"Invalid selection strategy '{strategy}'. "
|
|
905
|
+
f"Valid strategies are: {valid_strategies}",
|
|
906
|
+
details={
|
|
907
|
+
"strategy": strategy,
|
|
908
|
+
"valid_strategies": valid_strategies,
|
|
909
|
+
"correlation_id": correlation_id,
|
|
910
|
+
},
|
|
911
|
+
) from e
|
|
912
|
+
except Exception as e:
|
|
913
|
+
# Catch any other unexpected errors (e.g., AttributeError if strategy
|
|
914
|
+
# is an unexpected type that passed type checking)
|
|
915
|
+
raise ProtocolConfigurationError(
|
|
916
|
+
f"Failed to parse selection strategy: {type(e).__name__}",
|
|
917
|
+
details={
|
|
918
|
+
"strategy": str(strategy),
|
|
919
|
+
"error": str(e),
|
|
920
|
+
"correlation_id": correlation_id,
|
|
921
|
+
},
|
|
922
|
+
) from e
|
|
923
|
+
|
|
924
|
+
def _filter_by_contract_type(
|
|
925
|
+
self,
|
|
926
|
+
results: list[ModelRegistrationProjection],
|
|
927
|
+
contract_type: str | None,
|
|
928
|
+
) -> list[ModelRegistrationProjection]:
|
|
929
|
+
"""Filter results by contract type if specified.
|
|
930
|
+
|
|
931
|
+
Args:
|
|
932
|
+
results: List of registration projections to filter.
|
|
933
|
+
contract_type: Optional contract type to filter by. If None, returns
|
|
934
|
+
results unchanged.
|
|
935
|
+
|
|
936
|
+
Returns:
|
|
937
|
+
Filtered list of projections matching the contract type, or original
|
|
938
|
+
list if contract_type is None.
|
|
939
|
+
"""
|
|
940
|
+
if contract_type is None:
|
|
941
|
+
return results
|
|
942
|
+
return [r for r in results if r.contract_type == contract_type]
|
|
943
|
+
|
|
944
|
+
|
|
945
|
+
__all__: list[str] = ["ServiceCapabilityQuery"]
|