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,1076 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2025 OmniNode Team
|
|
3
|
+
"""Qdrant Vector Store Handler - implements ProtocolVectorStoreHandler.
|
|
4
|
+
|
|
5
|
+
This handler provides vector store operations for the Qdrant vector database
|
|
6
|
+
using the qdrant-client library with circuit breaker pattern for fault tolerance.
|
|
7
|
+
|
|
8
|
+
Supported Operations:
|
|
9
|
+
- store_embedding: Store a single embedding vector
|
|
10
|
+
- store_embeddings_batch: Batch store multiple embeddings
|
|
11
|
+
- query_similar: Similarity search with metadata filtering
|
|
12
|
+
- delete_embedding: Delete single embedding by ID
|
|
13
|
+
- delete_embeddings_batch: Batch delete embeddings
|
|
14
|
+
- create_index: Create a new collection/index
|
|
15
|
+
- delete_index: Delete a collection/index
|
|
16
|
+
- health_check: Check Qdrant connectivity and status
|
|
17
|
+
- describe: Return handler capabilities and metadata
|
|
18
|
+
|
|
19
|
+
Protocol Implementation:
|
|
20
|
+
This handler implements ProtocolVectorStoreHandler from omnibase_spi.protocols.storage.
|
|
21
|
+
All methods use typed models from omnibase_core.models.vector for type safety.
|
|
22
|
+
|
|
23
|
+
Circuit Breaker Pattern:
|
|
24
|
+
Uses MixinAsyncCircuitBreaker for fault tolerance with configurable
|
|
25
|
+
failure threshold and reset timeout.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
from __future__ import annotations
|
|
29
|
+
|
|
30
|
+
import logging
|
|
31
|
+
import time
|
|
32
|
+
from collections.abc import Mapping
|
|
33
|
+
from datetime import UTC, datetime
|
|
34
|
+
from uuid import UUID, uuid4
|
|
35
|
+
|
|
36
|
+
from qdrant_client import QdrantClient
|
|
37
|
+
from qdrant_client.http import models as qdrant_models
|
|
38
|
+
|
|
39
|
+
from omnibase_core.container import ModelONEXContainer
|
|
40
|
+
from omnibase_core.models.common.model_schema_value import ModelSchemaValue
|
|
41
|
+
from omnibase_core.models.vector import (
|
|
42
|
+
EnumVectorDistanceMetric,
|
|
43
|
+
EnumVectorFilterOperator,
|
|
44
|
+
ModelEmbedding,
|
|
45
|
+
ModelVectorBatchStoreResult,
|
|
46
|
+
ModelVectorConnectionConfig,
|
|
47
|
+
ModelVectorDeleteResult,
|
|
48
|
+
ModelVectorHandlerMetadata,
|
|
49
|
+
ModelVectorHealthStatus,
|
|
50
|
+
ModelVectorIndexConfig,
|
|
51
|
+
ModelVectorIndexResult,
|
|
52
|
+
ModelVectorMetadataFilter,
|
|
53
|
+
ModelVectorSearchResult,
|
|
54
|
+
ModelVectorSearchResults,
|
|
55
|
+
ModelVectorStoreResult,
|
|
56
|
+
)
|
|
57
|
+
from omnibase_core.types import JsonType
|
|
58
|
+
from omnibase_infra.enums import EnumInfraTransportType
|
|
59
|
+
from omnibase_infra.errors import (
|
|
60
|
+
InfraAuthenticationError,
|
|
61
|
+
InfraConnectionError,
|
|
62
|
+
InfraUnavailableError,
|
|
63
|
+
ModelInfraErrorContext,
|
|
64
|
+
RuntimeHostError,
|
|
65
|
+
)
|
|
66
|
+
from omnibase_infra.mixins import MixinAsyncCircuitBreaker
|
|
67
|
+
from omnibase_spi.protocols.storage import ProtocolVectorStoreHandler
|
|
68
|
+
|
|
69
|
+
logger = logging.getLogger(__name__)
|
|
70
|
+
|
|
71
|
+
# Default configuration
|
|
72
|
+
_DEFAULT_TIMEOUT_SECONDS: float = 30.0
|
|
73
|
+
_DEFAULT_BATCH_SIZE: int = 100
|
|
74
|
+
_HANDLER_VERSION: str = "1.0.0"
|
|
75
|
+
_HEALTH_CACHE_TTL_SECONDS: float = 5.0
|
|
76
|
+
|
|
77
|
+
# Metric mapping from string to Qdrant distance enum
|
|
78
|
+
_METRIC_MAP: dict[str, qdrant_models.Distance] = {
|
|
79
|
+
"cosine": qdrant_models.Distance.COSINE,
|
|
80
|
+
"euclidean": qdrant_models.Distance.EUCLID,
|
|
81
|
+
"dot_product": qdrant_models.Distance.DOT,
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
# Reverse mapping from EnumVectorDistanceMetric to Qdrant
|
|
85
|
+
_ENUM_TO_QDRANT_METRIC: dict[EnumVectorDistanceMetric, qdrant_models.Distance] = {
|
|
86
|
+
EnumVectorDistanceMetric.COSINE: qdrant_models.Distance.COSINE,
|
|
87
|
+
EnumVectorDistanceMetric.EUCLIDEAN: qdrant_models.Distance.EUCLID,
|
|
88
|
+
EnumVectorDistanceMetric.DOT_PRODUCT: qdrant_models.Distance.DOT,
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
# Filter operator mapping
|
|
92
|
+
_FILTER_OP_MAP: dict[EnumVectorFilterOperator, str] = {
|
|
93
|
+
EnumVectorFilterOperator.EQ: "match",
|
|
94
|
+
EnumVectorFilterOperator.NE: "match_except",
|
|
95
|
+
EnumVectorFilterOperator.GT: "range",
|
|
96
|
+
EnumVectorFilterOperator.GTE: "range",
|
|
97
|
+
EnumVectorFilterOperator.LT: "range",
|
|
98
|
+
EnumVectorFilterOperator.LTE: "range",
|
|
99
|
+
EnumVectorFilterOperator.IN: "match_any",
|
|
100
|
+
EnumVectorFilterOperator.NOT_IN: "match_except_any",
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class HandlerQdrant(MixinAsyncCircuitBreaker, ProtocolVectorStoreHandler):
|
|
105
|
+
"""Qdrant vector store handler implementing ProtocolVectorStoreHandler.
|
|
106
|
+
|
|
107
|
+
This handler provides vector storage, similarity search, and index management
|
|
108
|
+
operations for the Qdrant vector database.
|
|
109
|
+
|
|
110
|
+
Security Policy:
|
|
111
|
+
API keys are treated as secrets and never logged or exposed in errors.
|
|
112
|
+
|
|
113
|
+
Circuit Breaker Pattern:
|
|
114
|
+
Uses MixinAsyncCircuitBreaker for fault tolerance.
|
|
115
|
+
Configurable failure_threshold and reset_timeout.
|
|
116
|
+
|
|
117
|
+
Thread Safety:
|
|
118
|
+
This handler is NOT thread-safe. Use separate instances for concurrent
|
|
119
|
+
access from different threads. It is coroutine-safe for async operations.
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
def __init__(self, container: ModelONEXContainer) -> None:
|
|
123
|
+
"""Initialize HandlerQdrant with ONEX container for dependency injection.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
container: ONEX container providing dependency injection for
|
|
127
|
+
services, configuration, and runtime context.
|
|
128
|
+
|
|
129
|
+
Note:
|
|
130
|
+
The container is stored for interface compliance with the standard ONEX
|
|
131
|
+
handler pattern (def __init__(self, container: ModelONEXContainer)) and
|
|
132
|
+
to enable future DI-based service resolution (e.g., dispatcher routing,
|
|
133
|
+
metrics integration). Currently, the handler operates independently but
|
|
134
|
+
the container parameter ensures API consistency across all handlers.
|
|
135
|
+
"""
|
|
136
|
+
self._container = container
|
|
137
|
+
self._client: QdrantClient | None = None
|
|
138
|
+
self._config: ModelVectorConnectionConfig | None = None
|
|
139
|
+
self._default_index: str | None = None
|
|
140
|
+
self._timeout: float = _DEFAULT_TIMEOUT_SECONDS
|
|
141
|
+
self._initialized: bool = False
|
|
142
|
+
# Health check caching
|
|
143
|
+
self._cached_health: ModelVectorHealthStatus | None = None
|
|
144
|
+
self._health_cache_time: float = 0.0
|
|
145
|
+
|
|
146
|
+
@property
|
|
147
|
+
def handler_type(self) -> str:
|
|
148
|
+
"""Return the type of handler as a string identifier.
|
|
149
|
+
|
|
150
|
+
Returns:
|
|
151
|
+
String identifier "vector_store" for this handler type.
|
|
152
|
+
"""
|
|
153
|
+
return "vector_store"
|
|
154
|
+
|
|
155
|
+
@property
|
|
156
|
+
def supported_metrics(self) -> list[str]:
|
|
157
|
+
"""Return the list of distance metrics supported by this handler.
|
|
158
|
+
|
|
159
|
+
Returns:
|
|
160
|
+
List of supported metric names: cosine, euclidean, dot_product.
|
|
161
|
+
"""
|
|
162
|
+
return ["cosine", "euclidean", "dot_product"]
|
|
163
|
+
|
|
164
|
+
async def initialize(
|
|
165
|
+
self,
|
|
166
|
+
connection_config: ModelVectorConnectionConfig,
|
|
167
|
+
) -> None:
|
|
168
|
+
"""Initialize the Qdrant client with connection configuration.
|
|
169
|
+
|
|
170
|
+
Establishes connection to the Qdrant server, validates credentials,
|
|
171
|
+
and prepares the handler for operations.
|
|
172
|
+
|
|
173
|
+
Args:
|
|
174
|
+
connection_config: Configuration model containing connection parameters.
|
|
175
|
+
|
|
176
|
+
Raises:
|
|
177
|
+
RuntimeHostError: If configuration is invalid.
|
|
178
|
+
InfraConnectionError: If connection to Qdrant server fails.
|
|
179
|
+
InfraAuthenticationError: If API key authentication fails.
|
|
180
|
+
"""
|
|
181
|
+
init_correlation_id = uuid4()
|
|
182
|
+
logger.info(
|
|
183
|
+
"Initializing %s",
|
|
184
|
+
self.__class__.__name__,
|
|
185
|
+
extra={
|
|
186
|
+
"handler": self.__class__.__name__,
|
|
187
|
+
"correlation_id": str(init_correlation_id),
|
|
188
|
+
},
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
self._config = connection_config
|
|
192
|
+
self._timeout = connection_config.timeout
|
|
193
|
+
|
|
194
|
+
# Extract API key safely using SecretStr
|
|
195
|
+
api_key: str | None = None
|
|
196
|
+
if connection_config.api_key is not None:
|
|
197
|
+
api_key = connection_config.api_key.get_secret_value()
|
|
198
|
+
|
|
199
|
+
# Create client
|
|
200
|
+
try:
|
|
201
|
+
self._client = QdrantClient(
|
|
202
|
+
url=connection_config.url,
|
|
203
|
+
api_key=api_key,
|
|
204
|
+
timeout=int(self._timeout),
|
|
205
|
+
)
|
|
206
|
+
# Test connection by listing collections
|
|
207
|
+
self._client.get_collections()
|
|
208
|
+
self._initialized = True
|
|
209
|
+
logger.info(
|
|
210
|
+
"%s initialized successfully",
|
|
211
|
+
self.__class__.__name__,
|
|
212
|
+
extra={
|
|
213
|
+
"handler": self.__class__.__name__,
|
|
214
|
+
"correlation_id": str(init_correlation_id),
|
|
215
|
+
},
|
|
216
|
+
)
|
|
217
|
+
except Exception as e:
|
|
218
|
+
ctx = ModelInfraErrorContext.with_correlation(
|
|
219
|
+
correlation_id=init_correlation_id,
|
|
220
|
+
transport_type=EnumInfraTransportType.QDRANT,
|
|
221
|
+
operation="initialize",
|
|
222
|
+
target_name="qdrant_handler",
|
|
223
|
+
)
|
|
224
|
+
error_msg = str(e).lower()
|
|
225
|
+
if "unauthorized" in error_msg or "forbidden" in error_msg:
|
|
226
|
+
raise InfraAuthenticationError(
|
|
227
|
+
"Qdrant authentication failed - check API key", context=ctx
|
|
228
|
+
) from e
|
|
229
|
+
raise InfraConnectionError(
|
|
230
|
+
"Failed to connect to Qdrant server", context=ctx
|
|
231
|
+
) from e
|
|
232
|
+
|
|
233
|
+
# Initialize circuit breaker
|
|
234
|
+
self._init_circuit_breaker(
|
|
235
|
+
threshold=5,
|
|
236
|
+
reset_timeout=60.0,
|
|
237
|
+
service_name="qdrant",
|
|
238
|
+
transport_type=EnumInfraTransportType.QDRANT,
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
async def shutdown(self, timeout_seconds: float = 30.0) -> None:
|
|
242
|
+
"""Release resources and close connections to Qdrant.
|
|
243
|
+
|
|
244
|
+
Args:
|
|
245
|
+
timeout_seconds: Maximum time to wait for shutdown to complete.
|
|
246
|
+
"""
|
|
247
|
+
if self._client is not None:
|
|
248
|
+
self._client.close()
|
|
249
|
+
self._client = None
|
|
250
|
+
self._initialized = False
|
|
251
|
+
# Clear health cache
|
|
252
|
+
self._cached_health = None
|
|
253
|
+
self._health_cache_time = 0.0
|
|
254
|
+
logger.info("HandlerQdrant shutdown complete")
|
|
255
|
+
|
|
256
|
+
def _ensure_initialized(
|
|
257
|
+
self, operation: str, correlation_id: UUID | None = None
|
|
258
|
+
) -> None:
|
|
259
|
+
"""Ensure the handler is initialized before operations.
|
|
260
|
+
|
|
261
|
+
Args:
|
|
262
|
+
operation: Name of the operation being attempted.
|
|
263
|
+
correlation_id: Optional correlation ID for error context.
|
|
264
|
+
|
|
265
|
+
Raises:
|
|
266
|
+
RuntimeHostError: If handler is not initialized.
|
|
267
|
+
"""
|
|
268
|
+
if not self._initialized or self._client is None:
|
|
269
|
+
ctx = ModelInfraErrorContext.with_correlation(
|
|
270
|
+
correlation_id=correlation_id,
|
|
271
|
+
transport_type=EnumInfraTransportType.QDRANT,
|
|
272
|
+
operation=operation,
|
|
273
|
+
target_name="qdrant_handler",
|
|
274
|
+
)
|
|
275
|
+
raise RuntimeHostError(
|
|
276
|
+
"HandlerQdrant not initialized. Call initialize() first.",
|
|
277
|
+
context=ctx,
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
def _resolve_index_name(self, index_name: str | None) -> str:
|
|
281
|
+
"""Resolve index name, using default if not provided.
|
|
282
|
+
|
|
283
|
+
Args:
|
|
284
|
+
index_name: Provided index name or None.
|
|
285
|
+
|
|
286
|
+
Returns:
|
|
287
|
+
Resolved index name.
|
|
288
|
+
|
|
289
|
+
Raises:
|
|
290
|
+
RuntimeHostError: If no index name available.
|
|
291
|
+
"""
|
|
292
|
+
if index_name:
|
|
293
|
+
return index_name
|
|
294
|
+
if self._default_index:
|
|
295
|
+
return self._default_index
|
|
296
|
+
raise RuntimeHostError("No index_name provided and no default index configured")
|
|
297
|
+
|
|
298
|
+
def _convert_metadata_to_qdrant(
|
|
299
|
+
self, metadata: Mapping[str, JsonType] | None
|
|
300
|
+
) -> dict[str, object]:
|
|
301
|
+
"""Convert metadata mapping to Qdrant payload format.
|
|
302
|
+
|
|
303
|
+
Args:
|
|
304
|
+
metadata: Optional metadata mapping with JsonValue types.
|
|
305
|
+
|
|
306
|
+
Returns:
|
|
307
|
+
Dictionary suitable for Qdrant payload.
|
|
308
|
+
"""
|
|
309
|
+
if metadata is None:
|
|
310
|
+
return {}
|
|
311
|
+
return dict(metadata.items())
|
|
312
|
+
|
|
313
|
+
def _convert_model_metadata_to_qdrant(
|
|
314
|
+
self, metadata: dict[str, ModelSchemaValue]
|
|
315
|
+
) -> dict[str, object]:
|
|
316
|
+
"""Convert ModelSchemaValue metadata to Qdrant payload format.
|
|
317
|
+
|
|
318
|
+
Args:
|
|
319
|
+
metadata: Metadata with ModelSchemaValue types.
|
|
320
|
+
|
|
321
|
+
Returns:
|
|
322
|
+
Dictionary suitable for Qdrant payload.
|
|
323
|
+
"""
|
|
324
|
+
return {k: v.to_value() for k, v in metadata.items()}
|
|
325
|
+
|
|
326
|
+
def _convert_qdrant_payload_to_metadata(
|
|
327
|
+
self, payload: dict[str, object] | None
|
|
328
|
+
) -> dict[str, ModelSchemaValue]:
|
|
329
|
+
"""Convert Qdrant payload to ModelSchemaValue metadata.
|
|
330
|
+
|
|
331
|
+
Args:
|
|
332
|
+
payload: Qdrant point payload.
|
|
333
|
+
|
|
334
|
+
Returns:
|
|
335
|
+
Metadata dictionary with ModelSchemaValue types.
|
|
336
|
+
"""
|
|
337
|
+
if payload is None:
|
|
338
|
+
return {}
|
|
339
|
+
return {k: ModelSchemaValue.from_value(v) for k, v in payload.items()}
|
|
340
|
+
|
|
341
|
+
def _build_qdrant_filter(
|
|
342
|
+
self, filter_metadata: ModelVectorMetadataFilter
|
|
343
|
+
) -> qdrant_models.Filter:
|
|
344
|
+
"""Build Qdrant filter from ModelVectorMetadataFilter.
|
|
345
|
+
|
|
346
|
+
Args:
|
|
347
|
+
filter_metadata: Filter specification.
|
|
348
|
+
|
|
349
|
+
Returns:
|
|
350
|
+
Qdrant Filter object.
|
|
351
|
+
"""
|
|
352
|
+
field = filter_metadata.field
|
|
353
|
+
operator = filter_metadata.operator
|
|
354
|
+
value = filter_metadata.value.to_value()
|
|
355
|
+
|
|
356
|
+
conditions: list[qdrant_models.FieldCondition] = []
|
|
357
|
+
|
|
358
|
+
if operator == EnumVectorFilterOperator.EQ:
|
|
359
|
+
conditions.append(
|
|
360
|
+
qdrant_models.FieldCondition(
|
|
361
|
+
key=field,
|
|
362
|
+
match=qdrant_models.MatchValue(value=value),
|
|
363
|
+
)
|
|
364
|
+
)
|
|
365
|
+
elif operator == EnumVectorFilterOperator.NE:
|
|
366
|
+
# Use must_not for not-equal
|
|
367
|
+
return qdrant_models.Filter(
|
|
368
|
+
must_not=[
|
|
369
|
+
qdrant_models.FieldCondition(
|
|
370
|
+
key=field,
|
|
371
|
+
match=qdrant_models.MatchValue(value=value),
|
|
372
|
+
)
|
|
373
|
+
]
|
|
374
|
+
)
|
|
375
|
+
elif operator in (
|
|
376
|
+
EnumVectorFilterOperator.GT,
|
|
377
|
+
EnumVectorFilterOperator.GTE,
|
|
378
|
+
EnumVectorFilterOperator.LT,
|
|
379
|
+
EnumVectorFilterOperator.LTE,
|
|
380
|
+
):
|
|
381
|
+
range_params: dict[str, float | int | None] = {
|
|
382
|
+
"gt": None,
|
|
383
|
+
"gte": None,
|
|
384
|
+
"lt": None,
|
|
385
|
+
"lte": None,
|
|
386
|
+
}
|
|
387
|
+
if operator == EnumVectorFilterOperator.GT:
|
|
388
|
+
range_params["gt"] = value # type: ignore[assignment]
|
|
389
|
+
elif operator == EnumVectorFilterOperator.GTE:
|
|
390
|
+
range_params["gte"] = value # type: ignore[assignment]
|
|
391
|
+
elif operator == EnumVectorFilterOperator.LT:
|
|
392
|
+
range_params["lt"] = value # type: ignore[assignment]
|
|
393
|
+
elif operator == EnumVectorFilterOperator.LTE:
|
|
394
|
+
range_params["lte"] = value # type: ignore[assignment]
|
|
395
|
+
conditions.append(
|
|
396
|
+
qdrant_models.FieldCondition(
|
|
397
|
+
key=field,
|
|
398
|
+
range=qdrant_models.Range(**range_params), # type: ignore[arg-type]
|
|
399
|
+
)
|
|
400
|
+
)
|
|
401
|
+
elif operator == EnumVectorFilterOperator.IN:
|
|
402
|
+
if isinstance(value, list):
|
|
403
|
+
conditions.append(
|
|
404
|
+
qdrant_models.FieldCondition(
|
|
405
|
+
key=field,
|
|
406
|
+
match=qdrant_models.MatchAny(any=value),
|
|
407
|
+
)
|
|
408
|
+
)
|
|
409
|
+
elif operator == EnumVectorFilterOperator.NOT_IN:
|
|
410
|
+
if isinstance(value, list):
|
|
411
|
+
return qdrant_models.Filter(
|
|
412
|
+
must_not=[
|
|
413
|
+
qdrant_models.FieldCondition(
|
|
414
|
+
key=field,
|
|
415
|
+
match=qdrant_models.MatchAny(any=value),
|
|
416
|
+
)
|
|
417
|
+
]
|
|
418
|
+
)
|
|
419
|
+
elif operator == EnumVectorFilterOperator.CONTAINS:
|
|
420
|
+
conditions.append(
|
|
421
|
+
qdrant_models.FieldCondition(
|
|
422
|
+
key=field,
|
|
423
|
+
match=qdrant_models.MatchText(text=str(value)),
|
|
424
|
+
)
|
|
425
|
+
)
|
|
426
|
+
elif operator == EnumVectorFilterOperator.EXISTS:
|
|
427
|
+
conditions.append(
|
|
428
|
+
qdrant_models.FieldCondition(
|
|
429
|
+
key=field,
|
|
430
|
+
is_null=qdrant_models.IsNullCondition(is_null=False),
|
|
431
|
+
)
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
return qdrant_models.Filter(must=conditions)
|
|
435
|
+
|
|
436
|
+
async def store_embedding(
|
|
437
|
+
self,
|
|
438
|
+
embedding_id: str,
|
|
439
|
+
vector: list[float],
|
|
440
|
+
metadata: Mapping[str, JsonType] | None = None,
|
|
441
|
+
index_name: str | None = None,
|
|
442
|
+
) -> ModelVectorStoreResult:
|
|
443
|
+
"""Store a single embedding vector with optional metadata.
|
|
444
|
+
|
|
445
|
+
Args:
|
|
446
|
+
embedding_id: Unique identifier for the embedding.
|
|
447
|
+
vector: The embedding vector as a list of floats.
|
|
448
|
+
metadata: Optional metadata mapping to store with the embedding.
|
|
449
|
+
index_name: Name of the index/collection to store in.
|
|
450
|
+
|
|
451
|
+
Returns:
|
|
452
|
+
ModelVectorStoreResult containing operation result.
|
|
453
|
+
|
|
454
|
+
Raises:
|
|
455
|
+
RuntimeHostError: If handler not initialized.
|
|
456
|
+
InfraConnectionError: If storage operation fails.
|
|
457
|
+
"""
|
|
458
|
+
correlation_id = uuid4()
|
|
459
|
+
self._ensure_initialized("store_embedding", correlation_id)
|
|
460
|
+
|
|
461
|
+
resolved_index = self._resolve_index_name(index_name)
|
|
462
|
+
|
|
463
|
+
# Check circuit breaker
|
|
464
|
+
async with self._circuit_breaker_lock:
|
|
465
|
+
await self._check_circuit_breaker("store_embedding", correlation_id)
|
|
466
|
+
|
|
467
|
+
try:
|
|
468
|
+
if self._client is None:
|
|
469
|
+
raise RuntimeHostError("Client is None after initialization check")
|
|
470
|
+
|
|
471
|
+
payload = self._convert_metadata_to_qdrant(metadata)
|
|
472
|
+
self._client.upsert(
|
|
473
|
+
collection_name=resolved_index,
|
|
474
|
+
points=[
|
|
475
|
+
qdrant_models.PointStruct(
|
|
476
|
+
id=embedding_id,
|
|
477
|
+
vector=vector,
|
|
478
|
+
payload=payload,
|
|
479
|
+
)
|
|
480
|
+
],
|
|
481
|
+
)
|
|
482
|
+
|
|
483
|
+
# Reset circuit breaker on success
|
|
484
|
+
async with self._circuit_breaker_lock:
|
|
485
|
+
await self._reset_circuit_breaker()
|
|
486
|
+
|
|
487
|
+
return ModelVectorStoreResult(
|
|
488
|
+
success=True,
|
|
489
|
+
embedding_id=embedding_id,
|
|
490
|
+
index_name=resolved_index,
|
|
491
|
+
timestamp=datetime.now(UTC),
|
|
492
|
+
)
|
|
493
|
+
except (InfraUnavailableError, RuntimeHostError):
|
|
494
|
+
raise
|
|
495
|
+
except Exception as e:
|
|
496
|
+
ctx = ModelInfraErrorContext.with_correlation(
|
|
497
|
+
correlation_id=correlation_id,
|
|
498
|
+
transport_type=EnumInfraTransportType.QDRANT,
|
|
499
|
+
operation="store_embedding",
|
|
500
|
+
target_name=resolved_index,
|
|
501
|
+
)
|
|
502
|
+
async with self._circuit_breaker_lock:
|
|
503
|
+
await self._record_circuit_failure("store_embedding", correlation_id)
|
|
504
|
+
raise InfraConnectionError(
|
|
505
|
+
f"Failed to store embedding: {type(e).__name__}", context=ctx
|
|
506
|
+
) from e
|
|
507
|
+
|
|
508
|
+
async def store_embeddings_batch(
|
|
509
|
+
self,
|
|
510
|
+
embeddings: list[ModelEmbedding],
|
|
511
|
+
index_name: str | None = None,
|
|
512
|
+
batch_size: int = 100,
|
|
513
|
+
) -> ModelVectorBatchStoreResult:
|
|
514
|
+
"""Store multiple embeddings efficiently in a batch operation.
|
|
515
|
+
|
|
516
|
+
Args:
|
|
517
|
+
embeddings: List of ModelEmbedding instances.
|
|
518
|
+
index_name: Name of the index/collection to store in.
|
|
519
|
+
batch_size: Number of embeddings to process per batch.
|
|
520
|
+
|
|
521
|
+
Returns:
|
|
522
|
+
ModelVectorBatchStoreResult containing batch operation result.
|
|
523
|
+
|
|
524
|
+
Raises:
|
|
525
|
+
RuntimeHostError: If handler not initialized.
|
|
526
|
+
InfraConnectionError: If batch operation fails.
|
|
527
|
+
"""
|
|
528
|
+
correlation_id = uuid4()
|
|
529
|
+
self._ensure_initialized("store_embeddings_batch", correlation_id)
|
|
530
|
+
|
|
531
|
+
resolved_index = self._resolve_index_name(index_name)
|
|
532
|
+
start_time = time.time()
|
|
533
|
+
|
|
534
|
+
# Check circuit breaker
|
|
535
|
+
async with self._circuit_breaker_lock:
|
|
536
|
+
await self._check_circuit_breaker("store_embeddings_batch", correlation_id)
|
|
537
|
+
|
|
538
|
+
total_stored = 0
|
|
539
|
+
failed_ids: list[str] = []
|
|
540
|
+
|
|
541
|
+
try:
|
|
542
|
+
if self._client is None:
|
|
543
|
+
raise RuntimeHostError("Client is None after initialization check")
|
|
544
|
+
|
|
545
|
+
# Process in batches
|
|
546
|
+
for i in range(0, len(embeddings), batch_size):
|
|
547
|
+
batch = embeddings[i : i + batch_size]
|
|
548
|
+
points = [
|
|
549
|
+
qdrant_models.PointStruct(
|
|
550
|
+
id=emb.id,
|
|
551
|
+
vector=emb.vector,
|
|
552
|
+
payload=self._convert_model_metadata_to_qdrant(emb.metadata),
|
|
553
|
+
)
|
|
554
|
+
for emb in batch
|
|
555
|
+
]
|
|
556
|
+
|
|
557
|
+
try:
|
|
558
|
+
self._client.upsert(
|
|
559
|
+
collection_name=resolved_index,
|
|
560
|
+
points=points,
|
|
561
|
+
)
|
|
562
|
+
total_stored += len(batch)
|
|
563
|
+
except Exception:
|
|
564
|
+
# Track failed IDs in this batch
|
|
565
|
+
failed_ids.extend([emb.id for emb in batch])
|
|
566
|
+
|
|
567
|
+
# Reset circuit breaker on success
|
|
568
|
+
async with self._circuit_breaker_lock:
|
|
569
|
+
await self._reset_circuit_breaker()
|
|
570
|
+
|
|
571
|
+
execution_time_ms = int((time.time() - start_time) * 1000)
|
|
572
|
+
|
|
573
|
+
return ModelVectorBatchStoreResult(
|
|
574
|
+
success=len(failed_ids) == 0,
|
|
575
|
+
total_stored=total_stored,
|
|
576
|
+
failed_ids=failed_ids,
|
|
577
|
+
execution_time_ms=execution_time_ms,
|
|
578
|
+
)
|
|
579
|
+
except (InfraUnavailableError, RuntimeHostError):
|
|
580
|
+
raise
|
|
581
|
+
except Exception as e:
|
|
582
|
+
ctx = ModelInfraErrorContext.with_correlation(
|
|
583
|
+
correlation_id=correlation_id,
|
|
584
|
+
transport_type=EnumInfraTransportType.QDRANT,
|
|
585
|
+
operation="store_embeddings_batch",
|
|
586
|
+
target_name=resolved_index,
|
|
587
|
+
)
|
|
588
|
+
async with self._circuit_breaker_lock:
|
|
589
|
+
await self._record_circuit_failure(
|
|
590
|
+
"store_embeddings_batch", correlation_id
|
|
591
|
+
)
|
|
592
|
+
raise InfraConnectionError(
|
|
593
|
+
f"Batch store failed: {type(e).__name__}", context=ctx
|
|
594
|
+
) from e
|
|
595
|
+
|
|
596
|
+
async def query_similar(
|
|
597
|
+
self,
|
|
598
|
+
query_vector: list[float],
|
|
599
|
+
top_k: int = 10,
|
|
600
|
+
index_name: str | None = None,
|
|
601
|
+
filter_metadata: ModelVectorMetadataFilter | None = None,
|
|
602
|
+
include_metadata: bool = True,
|
|
603
|
+
include_vectors: bool = False,
|
|
604
|
+
score_threshold: float | None = None,
|
|
605
|
+
) -> ModelVectorSearchResults:
|
|
606
|
+
"""Find similar vectors using similarity/distance search.
|
|
607
|
+
|
|
608
|
+
Args:
|
|
609
|
+
query_vector: The query embedding vector to search against.
|
|
610
|
+
top_k: Maximum number of results to return.
|
|
611
|
+
index_name: Name of the index/collection to search.
|
|
612
|
+
filter_metadata: Optional metadata filter to restrict search.
|
|
613
|
+
include_metadata: Whether to include metadata in results.
|
|
614
|
+
include_vectors: Whether to include vectors in results.
|
|
615
|
+
score_threshold: Minimum similarity score threshold.
|
|
616
|
+
|
|
617
|
+
Returns:
|
|
618
|
+
ModelVectorSearchResults containing search results.
|
|
619
|
+
|
|
620
|
+
Raises:
|
|
621
|
+
RuntimeHostError: If handler not initialized.
|
|
622
|
+
InfraConnectionError: If search operation fails.
|
|
623
|
+
"""
|
|
624
|
+
correlation_id = uuid4()
|
|
625
|
+
self._ensure_initialized("query_similar", correlation_id)
|
|
626
|
+
|
|
627
|
+
resolved_index = self._resolve_index_name(index_name)
|
|
628
|
+
start_time = time.time()
|
|
629
|
+
|
|
630
|
+
# Check circuit breaker
|
|
631
|
+
async with self._circuit_breaker_lock:
|
|
632
|
+
await self._check_circuit_breaker("query_similar", correlation_id)
|
|
633
|
+
|
|
634
|
+
try:
|
|
635
|
+
if self._client is None:
|
|
636
|
+
raise RuntimeHostError("Client is None after initialization check")
|
|
637
|
+
|
|
638
|
+
# Build filter if provided
|
|
639
|
+
qdrant_filter: qdrant_models.Filter | None = None
|
|
640
|
+
if filter_metadata is not None:
|
|
641
|
+
qdrant_filter = self._build_qdrant_filter(filter_metadata)
|
|
642
|
+
|
|
643
|
+
# Execute search using query_points API
|
|
644
|
+
query_result = self._client.query_points(
|
|
645
|
+
collection_name=resolved_index,
|
|
646
|
+
query=query_vector,
|
|
647
|
+
limit=top_k,
|
|
648
|
+
query_filter=qdrant_filter,
|
|
649
|
+
with_payload=include_metadata,
|
|
650
|
+
with_vectors=include_vectors,
|
|
651
|
+
score_threshold=score_threshold,
|
|
652
|
+
)
|
|
653
|
+
|
|
654
|
+
# Convert results
|
|
655
|
+
results: list[ModelVectorSearchResult] = []
|
|
656
|
+
for point in query_result.points:
|
|
657
|
+
metadata = (
|
|
658
|
+
self._convert_qdrant_payload_to_metadata(point.payload)
|
|
659
|
+
if point.payload and include_metadata
|
|
660
|
+
else {}
|
|
661
|
+
)
|
|
662
|
+
vector_data: list[float] | None = None
|
|
663
|
+
if include_vectors and point.vector is not None:
|
|
664
|
+
# Handle both list and dict vector formats
|
|
665
|
+
raw_vector = point.vector
|
|
666
|
+
if isinstance(raw_vector, list):
|
|
667
|
+
vector_data = [float(v) for v in raw_vector] # type: ignore[arg-type]
|
|
668
|
+
elif isinstance(raw_vector, dict):
|
|
669
|
+
# For named vectors, get the default one
|
|
670
|
+
first_vector = next(iter(raw_vector.values()), None)
|
|
671
|
+
if first_vector is not None and isinstance(first_vector, list):
|
|
672
|
+
vector_data = [float(v) for v in first_vector] # type: ignore[arg-type]
|
|
673
|
+
|
|
674
|
+
results.append(
|
|
675
|
+
ModelVectorSearchResult(
|
|
676
|
+
id=str(point.id),
|
|
677
|
+
score=float(point.score) if point.score is not None else 0.0,
|
|
678
|
+
metadata=metadata,
|
|
679
|
+
vector=vector_data,
|
|
680
|
+
)
|
|
681
|
+
)
|
|
682
|
+
|
|
683
|
+
# Reset circuit breaker on success
|
|
684
|
+
async with self._circuit_breaker_lock:
|
|
685
|
+
await self._reset_circuit_breaker()
|
|
686
|
+
|
|
687
|
+
query_time_ms = int((time.time() - start_time) * 1000)
|
|
688
|
+
|
|
689
|
+
return ModelVectorSearchResults(
|
|
690
|
+
results=results,
|
|
691
|
+
total_results=len(results),
|
|
692
|
+
query_time_ms=query_time_ms,
|
|
693
|
+
)
|
|
694
|
+
except (InfraUnavailableError, RuntimeHostError):
|
|
695
|
+
raise
|
|
696
|
+
except Exception as e:
|
|
697
|
+
ctx = ModelInfraErrorContext.with_correlation(
|
|
698
|
+
correlation_id=correlation_id,
|
|
699
|
+
transport_type=EnumInfraTransportType.QDRANT,
|
|
700
|
+
operation="query_similar",
|
|
701
|
+
target_name=resolved_index,
|
|
702
|
+
)
|
|
703
|
+
async with self._circuit_breaker_lock:
|
|
704
|
+
await self._record_circuit_failure("query_similar", correlation_id)
|
|
705
|
+
raise InfraConnectionError(
|
|
706
|
+
f"Search failed: {type(e).__name__}", context=ctx
|
|
707
|
+
) from e
|
|
708
|
+
|
|
709
|
+
async def delete_embedding(
|
|
710
|
+
self,
|
|
711
|
+
embedding_id: str,
|
|
712
|
+
index_name: str | None = None,
|
|
713
|
+
) -> ModelVectorDeleteResult:
|
|
714
|
+
"""Remove a single embedding by ID.
|
|
715
|
+
|
|
716
|
+
Args:
|
|
717
|
+
embedding_id: Unique identifier of the embedding to delete.
|
|
718
|
+
index_name: Name of the index/collection containing the embedding.
|
|
719
|
+
|
|
720
|
+
Returns:
|
|
721
|
+
ModelVectorDeleteResult containing deletion result.
|
|
722
|
+
|
|
723
|
+
Raises:
|
|
724
|
+
RuntimeHostError: If handler not initialized.
|
|
725
|
+
InfraConnectionError: If deletion operation fails.
|
|
726
|
+
"""
|
|
727
|
+
correlation_id = uuid4()
|
|
728
|
+
self._ensure_initialized("delete_embedding", correlation_id)
|
|
729
|
+
|
|
730
|
+
resolved_index = self._resolve_index_name(index_name)
|
|
731
|
+
|
|
732
|
+
# Check circuit breaker
|
|
733
|
+
async with self._circuit_breaker_lock:
|
|
734
|
+
await self._check_circuit_breaker("delete_embedding", correlation_id)
|
|
735
|
+
|
|
736
|
+
try:
|
|
737
|
+
if self._client is None:
|
|
738
|
+
raise RuntimeHostError("Client is None after initialization check")
|
|
739
|
+
|
|
740
|
+
self._client.delete(
|
|
741
|
+
collection_name=resolved_index,
|
|
742
|
+
points_selector=qdrant_models.PointIdsList(points=[embedding_id]),
|
|
743
|
+
)
|
|
744
|
+
|
|
745
|
+
# Reset circuit breaker on success
|
|
746
|
+
async with self._circuit_breaker_lock:
|
|
747
|
+
await self._reset_circuit_breaker()
|
|
748
|
+
|
|
749
|
+
return ModelVectorDeleteResult(
|
|
750
|
+
success=True,
|
|
751
|
+
embedding_id=embedding_id,
|
|
752
|
+
deleted=True,
|
|
753
|
+
)
|
|
754
|
+
except (InfraUnavailableError, RuntimeHostError):
|
|
755
|
+
raise
|
|
756
|
+
except Exception as e:
|
|
757
|
+
ctx = ModelInfraErrorContext.with_correlation(
|
|
758
|
+
correlation_id=correlation_id,
|
|
759
|
+
transport_type=EnumInfraTransportType.QDRANT,
|
|
760
|
+
operation="delete_embedding",
|
|
761
|
+
target_name=resolved_index,
|
|
762
|
+
)
|
|
763
|
+
async with self._circuit_breaker_lock:
|
|
764
|
+
await self._record_circuit_failure("delete_embedding", correlation_id)
|
|
765
|
+
raise InfraConnectionError(
|
|
766
|
+
f"Delete failed: {type(e).__name__}", context=ctx
|
|
767
|
+
) from e
|
|
768
|
+
|
|
769
|
+
async def delete_embeddings_batch(
|
|
770
|
+
self,
|
|
771
|
+
embedding_ids: list[str],
|
|
772
|
+
index_name: str | None = None,
|
|
773
|
+
) -> ModelVectorDeleteResult:
|
|
774
|
+
"""Remove multiple embeddings by their IDs.
|
|
775
|
+
|
|
776
|
+
Args:
|
|
777
|
+
embedding_ids: List of embedding IDs to delete.
|
|
778
|
+
index_name: Name of the index/collection containing the embeddings.
|
|
779
|
+
|
|
780
|
+
Returns:
|
|
781
|
+
ModelVectorDeleteResult containing batch deletion result.
|
|
782
|
+
|
|
783
|
+
Raises:
|
|
784
|
+
RuntimeHostError: If handler not initialized.
|
|
785
|
+
InfraConnectionError: If batch deletion fails.
|
|
786
|
+
"""
|
|
787
|
+
correlation_id = uuid4()
|
|
788
|
+
self._ensure_initialized("delete_embeddings_batch", correlation_id)
|
|
789
|
+
|
|
790
|
+
resolved_index = self._resolve_index_name(index_name)
|
|
791
|
+
|
|
792
|
+
# Check circuit breaker
|
|
793
|
+
async with self._circuit_breaker_lock:
|
|
794
|
+
await self._check_circuit_breaker("delete_embeddings_batch", correlation_id)
|
|
795
|
+
|
|
796
|
+
try:
|
|
797
|
+
if self._client is None:
|
|
798
|
+
raise RuntimeHostError("Client is None after initialization check")
|
|
799
|
+
|
|
800
|
+
self._client.delete(
|
|
801
|
+
collection_name=resolved_index,
|
|
802
|
+
points_selector=qdrant_models.PointIdsList(points=embedding_ids),
|
|
803
|
+
)
|
|
804
|
+
|
|
805
|
+
# Reset circuit breaker on success
|
|
806
|
+
async with self._circuit_breaker_lock:
|
|
807
|
+
await self._reset_circuit_breaker()
|
|
808
|
+
|
|
809
|
+
# Return first ID for the single embedding_id field
|
|
810
|
+
# The protocol uses embedding_id singular even for batch
|
|
811
|
+
return ModelVectorDeleteResult(
|
|
812
|
+
success=True,
|
|
813
|
+
embedding_id=embedding_ids[0] if embedding_ids else "",
|
|
814
|
+
deleted=True,
|
|
815
|
+
)
|
|
816
|
+
except (InfraUnavailableError, RuntimeHostError):
|
|
817
|
+
raise
|
|
818
|
+
except Exception as e:
|
|
819
|
+
ctx = ModelInfraErrorContext.with_correlation(
|
|
820
|
+
correlation_id=correlation_id,
|
|
821
|
+
transport_type=EnumInfraTransportType.QDRANT,
|
|
822
|
+
operation="delete_embeddings_batch",
|
|
823
|
+
target_name=resolved_index,
|
|
824
|
+
)
|
|
825
|
+
async with self._circuit_breaker_lock:
|
|
826
|
+
await self._record_circuit_failure(
|
|
827
|
+
"delete_embeddings_batch", correlation_id
|
|
828
|
+
)
|
|
829
|
+
raise InfraConnectionError(
|
|
830
|
+
f"Batch delete failed: {type(e).__name__}", context=ctx
|
|
831
|
+
) from e
|
|
832
|
+
|
|
833
|
+
async def create_index(
|
|
834
|
+
self,
|
|
835
|
+
index_name: str,
|
|
836
|
+
dimension: int,
|
|
837
|
+
metric: str = "cosine",
|
|
838
|
+
index_config: ModelVectorIndexConfig | None = None,
|
|
839
|
+
) -> ModelVectorIndexResult:
|
|
840
|
+
"""Create a new vector index/collection.
|
|
841
|
+
|
|
842
|
+
Args:
|
|
843
|
+
index_name: Unique name for the new index.
|
|
844
|
+
dimension: Vector dimension.
|
|
845
|
+
metric: Distance metric to use (cosine, euclidean, dot_product).
|
|
846
|
+
index_config: Optional configuration with HNSW and quantization settings.
|
|
847
|
+
|
|
848
|
+
Returns:
|
|
849
|
+
ModelVectorIndexResult containing creation result.
|
|
850
|
+
|
|
851
|
+
Raises:
|
|
852
|
+
RuntimeHostError: If handler not initialized.
|
|
853
|
+
InfraConnectionError: If index creation fails.
|
|
854
|
+
ValueError: If metric is not supported.
|
|
855
|
+
"""
|
|
856
|
+
correlation_id = uuid4()
|
|
857
|
+
self._ensure_initialized("create_index", correlation_id)
|
|
858
|
+
|
|
859
|
+
# Validate metric
|
|
860
|
+
metric_lower = metric.lower()
|
|
861
|
+
if metric_lower not in self.supported_metrics:
|
|
862
|
+
raise ValueError(
|
|
863
|
+
f"Unsupported metric '{metric}'. "
|
|
864
|
+
f"Supported: {', '.join(self.supported_metrics)}"
|
|
865
|
+
)
|
|
866
|
+
|
|
867
|
+
# Check circuit breaker
|
|
868
|
+
async with self._circuit_breaker_lock:
|
|
869
|
+
await self._check_circuit_breaker("create_index", correlation_id)
|
|
870
|
+
|
|
871
|
+
try:
|
|
872
|
+
if self._client is None:
|
|
873
|
+
raise RuntimeHostError("Client is None after initialization check")
|
|
874
|
+
|
|
875
|
+
# Map metric string to Qdrant distance enum
|
|
876
|
+
distance_enum = _METRIC_MAP[metric_lower]
|
|
877
|
+
|
|
878
|
+
# Build vectors config
|
|
879
|
+
vectors_config = qdrant_models.VectorParams(
|
|
880
|
+
size=dimension,
|
|
881
|
+
distance=distance_enum,
|
|
882
|
+
)
|
|
883
|
+
|
|
884
|
+
# Apply HNSW config if provided
|
|
885
|
+
hnsw_config: qdrant_models.HnswConfigDiff | None = None
|
|
886
|
+
if index_config and index_config.hnsw_config:
|
|
887
|
+
hnsw_config = qdrant_models.HnswConfigDiff(
|
|
888
|
+
m=index_config.hnsw_config.m,
|
|
889
|
+
ef_construct=index_config.hnsw_config.ef_construction,
|
|
890
|
+
)
|
|
891
|
+
|
|
892
|
+
# Create collection
|
|
893
|
+
self._client.create_collection(
|
|
894
|
+
collection_name=index_name,
|
|
895
|
+
vectors_config=vectors_config,
|
|
896
|
+
hnsw_config=hnsw_config,
|
|
897
|
+
)
|
|
898
|
+
|
|
899
|
+
# Reset circuit breaker on success
|
|
900
|
+
async with self._circuit_breaker_lock:
|
|
901
|
+
await self._reset_circuit_breaker()
|
|
902
|
+
|
|
903
|
+
# Map metric string to enum
|
|
904
|
+
metric_enum = {
|
|
905
|
+
"cosine": EnumVectorDistanceMetric.COSINE,
|
|
906
|
+
"euclidean": EnumVectorDistanceMetric.EUCLIDEAN,
|
|
907
|
+
"dot_product": EnumVectorDistanceMetric.DOT_PRODUCT,
|
|
908
|
+
}.get(metric_lower, EnumVectorDistanceMetric.COSINE)
|
|
909
|
+
|
|
910
|
+
return ModelVectorIndexResult(
|
|
911
|
+
success=True,
|
|
912
|
+
index_name=index_name,
|
|
913
|
+
dimension=dimension,
|
|
914
|
+
metric=metric_enum,
|
|
915
|
+
created_at=datetime.now(UTC),
|
|
916
|
+
)
|
|
917
|
+
except (InfraUnavailableError, RuntimeHostError, ValueError):
|
|
918
|
+
raise
|
|
919
|
+
except Exception as e:
|
|
920
|
+
ctx = ModelInfraErrorContext.with_correlation(
|
|
921
|
+
correlation_id=correlation_id,
|
|
922
|
+
transport_type=EnumInfraTransportType.QDRANT,
|
|
923
|
+
operation="create_index",
|
|
924
|
+
target_name=index_name,
|
|
925
|
+
)
|
|
926
|
+
async with self._circuit_breaker_lock:
|
|
927
|
+
await self._record_circuit_failure("create_index", correlation_id)
|
|
928
|
+
raise InfraConnectionError(
|
|
929
|
+
f"Failed to create index: {type(e).__name__}", context=ctx
|
|
930
|
+
) from e
|
|
931
|
+
|
|
932
|
+
async def delete_index(
|
|
933
|
+
self,
|
|
934
|
+
index_name: str,
|
|
935
|
+
) -> ModelVectorIndexResult:
|
|
936
|
+
"""Delete a vector index/collection.
|
|
937
|
+
|
|
938
|
+
Args:
|
|
939
|
+
index_name: Name of the index to delete.
|
|
940
|
+
|
|
941
|
+
Returns:
|
|
942
|
+
ModelVectorIndexResult containing deletion result.
|
|
943
|
+
|
|
944
|
+
Raises:
|
|
945
|
+
RuntimeHostError: If handler not initialized.
|
|
946
|
+
InfraConnectionError: If deletion fails.
|
|
947
|
+
"""
|
|
948
|
+
correlation_id = uuid4()
|
|
949
|
+
self._ensure_initialized("delete_index", correlation_id)
|
|
950
|
+
|
|
951
|
+
# Check circuit breaker
|
|
952
|
+
async with self._circuit_breaker_lock:
|
|
953
|
+
await self._check_circuit_breaker("delete_index", correlation_id)
|
|
954
|
+
|
|
955
|
+
try:
|
|
956
|
+
if self._client is None:
|
|
957
|
+
raise RuntimeHostError("Client is None after initialization check")
|
|
958
|
+
|
|
959
|
+
self._client.delete_collection(collection_name=index_name)
|
|
960
|
+
|
|
961
|
+
# Reset circuit breaker on success
|
|
962
|
+
async with self._circuit_breaker_lock:
|
|
963
|
+
await self._reset_circuit_breaker()
|
|
964
|
+
|
|
965
|
+
return ModelVectorIndexResult(
|
|
966
|
+
success=True,
|
|
967
|
+
index_name=index_name,
|
|
968
|
+
dimension=0, # Unknown after deletion
|
|
969
|
+
metric=EnumVectorDistanceMetric.COSINE, # Default
|
|
970
|
+
created_at=None,
|
|
971
|
+
)
|
|
972
|
+
except (InfraUnavailableError, RuntimeHostError):
|
|
973
|
+
raise
|
|
974
|
+
except Exception as e:
|
|
975
|
+
ctx = ModelInfraErrorContext.with_correlation(
|
|
976
|
+
correlation_id=correlation_id,
|
|
977
|
+
transport_type=EnumInfraTransportType.QDRANT,
|
|
978
|
+
operation="delete_index",
|
|
979
|
+
target_name=index_name,
|
|
980
|
+
)
|
|
981
|
+
async with self._circuit_breaker_lock:
|
|
982
|
+
await self._record_circuit_failure("delete_index", correlation_id)
|
|
983
|
+
raise InfraConnectionError(
|
|
984
|
+
f"Failed to delete index: {type(e).__name__}", context=ctx
|
|
985
|
+
) from e
|
|
986
|
+
|
|
987
|
+
async def health_check(self) -> ModelVectorHealthStatus:
|
|
988
|
+
"""Check handler health and connectivity to Qdrant.
|
|
989
|
+
|
|
990
|
+
Implements caching to avoid overwhelming the backend with frequent
|
|
991
|
+
health checks. Cache TTL is configured via _HEALTH_CACHE_TTL_SECONDS.
|
|
992
|
+
|
|
993
|
+
Returns:
|
|
994
|
+
ModelVectorHealthStatus containing health status.
|
|
995
|
+
"""
|
|
996
|
+
# Return cached result if recent
|
|
997
|
+
current_time = time.time()
|
|
998
|
+
if (
|
|
999
|
+
self._cached_health is not None
|
|
1000
|
+
and current_time - self._health_cache_time < _HEALTH_CACHE_TTL_SECONDS
|
|
1001
|
+
):
|
|
1002
|
+
return self._cached_health
|
|
1003
|
+
|
|
1004
|
+
start_time = time.time()
|
|
1005
|
+
|
|
1006
|
+
if not self._initialized or self._client is None:
|
|
1007
|
+
return ModelVectorHealthStatus(
|
|
1008
|
+
healthy=False,
|
|
1009
|
+
latency_ms=0,
|
|
1010
|
+
details={},
|
|
1011
|
+
indices=[],
|
|
1012
|
+
last_error="Handler not initialized",
|
|
1013
|
+
)
|
|
1014
|
+
|
|
1015
|
+
try:
|
|
1016
|
+
# List collections to verify connectivity
|
|
1017
|
+
collections_response = self._client.get_collections()
|
|
1018
|
+
collection_names = [c.name for c in collections_response.collections]
|
|
1019
|
+
|
|
1020
|
+
latency_ms = int((time.time() - start_time) * 1000)
|
|
1021
|
+
|
|
1022
|
+
health = ModelVectorHealthStatus(
|
|
1023
|
+
healthy=True,
|
|
1024
|
+
latency_ms=latency_ms,
|
|
1025
|
+
details={
|
|
1026
|
+
"version": ModelSchemaValue.from_value(_HANDLER_VERSION),
|
|
1027
|
+
"backend": ModelSchemaValue.from_value("qdrant"),
|
|
1028
|
+
},
|
|
1029
|
+
indices=collection_names,
|
|
1030
|
+
last_error=None,
|
|
1031
|
+
)
|
|
1032
|
+
|
|
1033
|
+
# Cache the result
|
|
1034
|
+
self._cached_health = health
|
|
1035
|
+
self._health_cache_time = current_time
|
|
1036
|
+
|
|
1037
|
+
return health
|
|
1038
|
+
except Exception as e:
|
|
1039
|
+
latency_ms = int((time.time() - start_time) * 1000)
|
|
1040
|
+
return ModelVectorHealthStatus(
|
|
1041
|
+
healthy=False,
|
|
1042
|
+
latency_ms=latency_ms,
|
|
1043
|
+
details={},
|
|
1044
|
+
indices=[],
|
|
1045
|
+
last_error=f"Health check failed: {type(e).__name__}",
|
|
1046
|
+
)
|
|
1047
|
+
|
|
1048
|
+
async def describe(self) -> ModelVectorHandlerMetadata: # type: ignore[override]
|
|
1049
|
+
"""Return handler metadata and capabilities.
|
|
1050
|
+
|
|
1051
|
+
Returns:
|
|
1052
|
+
ModelVectorHandlerMetadata containing handler metadata.
|
|
1053
|
+
"""
|
|
1054
|
+
return ModelVectorHandlerMetadata(
|
|
1055
|
+
handler_type="qdrant",
|
|
1056
|
+
capabilities=[
|
|
1057
|
+
"store_embedding",
|
|
1058
|
+
"store_embeddings_batch",
|
|
1059
|
+
"query_similar",
|
|
1060
|
+
"delete_embedding",
|
|
1061
|
+
"delete_embeddings_batch",
|
|
1062
|
+
"create_index",
|
|
1063
|
+
"delete_index",
|
|
1064
|
+
"health_check",
|
|
1065
|
+
"filter_metadata",
|
|
1066
|
+
"score_threshold",
|
|
1067
|
+
],
|
|
1068
|
+
supported_metrics=[
|
|
1069
|
+
EnumVectorDistanceMetric.COSINE,
|
|
1070
|
+
EnumVectorDistanceMetric.EUCLIDEAN,
|
|
1071
|
+
EnumVectorDistanceMetric.DOT_PRODUCT,
|
|
1072
|
+
],
|
|
1073
|
+
)
|
|
1074
|
+
|
|
1075
|
+
|
|
1076
|
+
__all__: list[str] = ["HandlerQdrant"]
|