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,530 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2025 OmniNode Team
|
|
3
|
+
"""Node Selector Service.
|
|
4
|
+
|
|
5
|
+
Provides selection logic for choosing a node from multiple candidates
|
|
6
|
+
that match capability-based discovery criteria.
|
|
7
|
+
|
|
8
|
+
Thread Safety:
|
|
9
|
+
Coroutine Safety (Single Event Loop):
|
|
10
|
+
This service uses an asyncio.Lock to protect round-robin state access.
|
|
11
|
+
All methods that access the state are async and properly synchronized.
|
|
12
|
+
Safe for concurrent use from multiple coroutines within the SAME event loop.
|
|
13
|
+
|
|
14
|
+
Multi-Threading (Multiple Event Loops):
|
|
15
|
+
NOT thread-safe across multiple event loops or threads.
|
|
16
|
+
Each event loop should have its own ServiceNodeSelector instance.
|
|
17
|
+
Do not share instances between threads.
|
|
18
|
+
|
|
19
|
+
State Management:
|
|
20
|
+
Round-Robin State Growth:
|
|
21
|
+
The round-robin state dictionary grows as new selection_key values are used.
|
|
22
|
+
To prevent unbounded growth, an LRU eviction mechanism is implemented:
|
|
23
|
+
- Default max entries: 1000 (configurable via max_round_robin_entries)
|
|
24
|
+
- When limit is reached, oldest 10% of entries are evicted
|
|
25
|
+
- Use reset_round_robin_state() for manual cleanup
|
|
26
|
+
- Call prune_round_robin_state() for explicit eviction
|
|
27
|
+
|
|
28
|
+
Related Tickets:
|
|
29
|
+
- OMN-1135: ServiceCapabilityQuery for capability-based discovery
|
|
30
|
+
|
|
31
|
+
Example:
|
|
32
|
+
>>> from omnibase_infra.services import ServiceNodeSelector, EnumSelectionStrategy
|
|
33
|
+
>>> selector = ServiceNodeSelector()
|
|
34
|
+
>>> selected = await selector.select(candidates, EnumSelectionStrategy.ROUND_ROBIN, "db")
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
from __future__ import annotations
|
|
38
|
+
|
|
39
|
+
import asyncio
|
|
40
|
+
import logging
|
|
41
|
+
import random
|
|
42
|
+
import time
|
|
43
|
+
from typing import TYPE_CHECKING, NamedTuple, Never
|
|
44
|
+
from uuid import UUID, uuid4
|
|
45
|
+
|
|
46
|
+
from omnibase_core.container import ModelONEXContainer
|
|
47
|
+
from omnibase_infra.enums import EnumSelectionStrategy
|
|
48
|
+
from omnibase_infra.errors import ModelInfraErrorContext, RuntimeHostError
|
|
49
|
+
|
|
50
|
+
if TYPE_CHECKING:
|
|
51
|
+
from omnibase_infra.models.projection import ModelRegistrationProjection
|
|
52
|
+
|
|
53
|
+
logger = logging.getLogger(__name__)
|
|
54
|
+
|
|
55
|
+
DEFAULT_SELECTION_KEY: str = "_default"
|
|
56
|
+
"""Default key for round-robin state tracking when no selection_key is provided."""
|
|
57
|
+
|
|
58
|
+
DEFAULT_MAX_ROUND_ROBIN_ENTRIES: int = 1000
|
|
59
|
+
"""Default maximum number of round-robin state entries before LRU eviction."""
|
|
60
|
+
|
|
61
|
+
EVICTION_PERCENTAGE: float = 0.1
|
|
62
|
+
"""Percentage of entries to evict when max limit is reached (10%)."""
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class RoundRobinEntry(NamedTuple):
|
|
66
|
+
"""Round-robin state entry with LRU tracking.
|
|
67
|
+
|
|
68
|
+
Attributes:
|
|
69
|
+
current_index: The last used index for this selection key.
|
|
70
|
+
last_access: Timestamp of last access for LRU eviction.
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
current_index: int
|
|
74
|
+
last_access: float
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class ServiceNodeSelector:
|
|
78
|
+
"""Selects a node from candidates using various strategies.
|
|
79
|
+
|
|
80
|
+
This service implements node selection logic for capability-based discovery.
|
|
81
|
+
When multiple nodes match a capability query, this selector chooses one
|
|
82
|
+
based on the configured strategy.
|
|
83
|
+
|
|
84
|
+
Note:
|
|
85
|
+
Coroutine-safe within a single event loop (uses asyncio.Lock).
|
|
86
|
+
NOT thread-safe across multiple event loops - create separate instances
|
|
87
|
+
per event loop or thread.
|
|
88
|
+
|
|
89
|
+
Strategies:
|
|
90
|
+
- FIRST: Return first candidate (deterministic)
|
|
91
|
+
- RANDOM: Random selection (stateless load distribution)
|
|
92
|
+
- ROUND_ROBIN: Sequential cycling (stateful, even distribution)
|
|
93
|
+
- LEAST_LOADED: Not implemented (raises RuntimeHostError)
|
|
94
|
+
|
|
95
|
+
State Management:
|
|
96
|
+
Round-robin state is tracked per selection_key. This allows independent
|
|
97
|
+
cycling for different dependency types (e.g., "db" vs "consul").
|
|
98
|
+
All state access is protected by an asyncio.Lock for coroutine safety.
|
|
99
|
+
|
|
100
|
+
To prevent unbounded memory growth, the round-robin state implements
|
|
101
|
+
LRU eviction. When the number of entries exceeds max_round_robin_entries,
|
|
102
|
+
the oldest 10% of entries (by last access time) are evicted.
|
|
103
|
+
|
|
104
|
+
Example:
|
|
105
|
+
>>> selector = ServiceNodeSelector()
|
|
106
|
+
>>>
|
|
107
|
+
>>> # First strategy - always returns first
|
|
108
|
+
>>> node = await selector.select(candidates, EnumSelectionStrategy.FIRST)
|
|
109
|
+
>>>
|
|
110
|
+
>>> # Round-robin with key tracking
|
|
111
|
+
>>> node1 = await selector.select(candidates, EnumSelectionStrategy.ROUND_ROBIN, "db")
|
|
112
|
+
>>> node2 = await selector.select(candidates, EnumSelectionStrategy.ROUND_ROBIN, "db")
|
|
113
|
+
>>> # node1 and node2 will be different if len(candidates) > 1
|
|
114
|
+
|
|
115
|
+
Attributes:
|
|
116
|
+
_round_robin_state: Internal state tracking index and last access per key.
|
|
117
|
+
_round_robin_lock: asyncio.Lock protecting state access.
|
|
118
|
+
_max_round_robin_entries: Maximum entries before LRU eviction triggers.
|
|
119
|
+
"""
|
|
120
|
+
|
|
121
|
+
def __init__(
|
|
122
|
+
self,
|
|
123
|
+
container: ModelONEXContainer | None = None,
|
|
124
|
+
max_round_robin_entries: int = DEFAULT_MAX_ROUND_ROBIN_ENTRIES,
|
|
125
|
+
) -> None:
|
|
126
|
+
"""Initialize the node selector with empty round-robin state and lock.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
container: Optional ONEX container for dependency injection.
|
|
130
|
+
Stored for interface compliance and future DI integration.
|
|
131
|
+
max_round_robin_entries: Maximum number of round-robin state entries
|
|
132
|
+
before LRU eviction. Defaults to 1000. Set to 0 for unlimited
|
|
133
|
+
(not recommended in production).
|
|
134
|
+
|
|
135
|
+
Note:
|
|
136
|
+
The container is stored for interface compliance with the standard ONEX
|
|
137
|
+
service pattern and to enable future DI-based enhancements (e.g., metrics
|
|
138
|
+
reporting, configuration injection). Currently, the selector operates
|
|
139
|
+
with stateless selection logic that doesn't require container services.
|
|
140
|
+
"""
|
|
141
|
+
self._container = container
|
|
142
|
+
self._round_robin_state: dict[str, RoundRobinEntry] = {}
|
|
143
|
+
self._round_robin_lock: asyncio.Lock = asyncio.Lock()
|
|
144
|
+
self._max_round_robin_entries = max_round_robin_entries
|
|
145
|
+
|
|
146
|
+
def _ensure_correlation_id(self, correlation_id: UUID | None) -> UUID:
|
|
147
|
+
"""Ensure correlation ID is present, generating one if missing.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
correlation_id: Optional correlation ID from caller.
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
The provided correlation ID, or a newly generated UUID4.
|
|
154
|
+
"""
|
|
155
|
+
return correlation_id or uuid4()
|
|
156
|
+
|
|
157
|
+
async def _prune_round_robin_state(self) -> int:
|
|
158
|
+
"""Prune oldest round-robin entries when limit is exceeded.
|
|
159
|
+
|
|
160
|
+
This method is called automatically when the state dictionary exceeds
|
|
161
|
+
max_round_robin_entries. It evicts the oldest 10% of entries based on
|
|
162
|
+
last access time.
|
|
163
|
+
|
|
164
|
+
Must be called while holding _round_robin_lock.
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
Number of entries evicted.
|
|
168
|
+
"""
|
|
169
|
+
if (
|
|
170
|
+
self._max_round_robin_entries <= 0
|
|
171
|
+
or len(self._round_robin_state) <= self._max_round_robin_entries
|
|
172
|
+
):
|
|
173
|
+
return 0
|
|
174
|
+
|
|
175
|
+
# Calculate how many to evict (10% of max, minimum 1)
|
|
176
|
+
evict_count = max(1, int(self._max_round_robin_entries * EVICTION_PERCENTAGE))
|
|
177
|
+
|
|
178
|
+
# Sort by last_access and get oldest entries
|
|
179
|
+
sorted_keys = sorted(
|
|
180
|
+
self._round_robin_state.keys(),
|
|
181
|
+
key=lambda k: self._round_robin_state[k].last_access,
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
# Evict oldest entries
|
|
185
|
+
keys_to_evict = sorted_keys[:evict_count]
|
|
186
|
+
for key in keys_to_evict:
|
|
187
|
+
del self._round_robin_state[key]
|
|
188
|
+
|
|
189
|
+
logger.debug(
|
|
190
|
+
"Pruned round-robin state entries (LRU eviction)",
|
|
191
|
+
extra={
|
|
192
|
+
"evicted_count": len(keys_to_evict),
|
|
193
|
+
"remaining_count": len(self._round_robin_state),
|
|
194
|
+
"max_entries": self._max_round_robin_entries,
|
|
195
|
+
},
|
|
196
|
+
)
|
|
197
|
+
return len(keys_to_evict)
|
|
198
|
+
|
|
199
|
+
async def prune_round_robin_state(self) -> int:
|
|
200
|
+
"""Explicitly prune oldest round-robin entries.
|
|
201
|
+
|
|
202
|
+
This is the public interface for triggering LRU eviction. Useful for
|
|
203
|
+
maintenance operations or when you want to proactively free memory.
|
|
204
|
+
|
|
205
|
+
Returns:
|
|
206
|
+
Number of entries evicted.
|
|
207
|
+
|
|
208
|
+
Example:
|
|
209
|
+
>>> selector = ServiceNodeSelector(max_round_robin_entries=100)
|
|
210
|
+
>>> # After many operations...
|
|
211
|
+
>>> evicted = await selector.prune_round_robin_state()
|
|
212
|
+
>>> print(f"Evicted {evicted} stale entries")
|
|
213
|
+
"""
|
|
214
|
+
async with self._round_robin_lock:
|
|
215
|
+
return await self._prune_round_robin_state()
|
|
216
|
+
|
|
217
|
+
async def select(
|
|
218
|
+
self,
|
|
219
|
+
candidates: list[ModelRegistrationProjection],
|
|
220
|
+
strategy: EnumSelectionStrategy,
|
|
221
|
+
selection_key: str | None = None,
|
|
222
|
+
correlation_id: UUID | None = None,
|
|
223
|
+
) -> ModelRegistrationProjection | None:
|
|
224
|
+
"""Select a node from candidates using the specified strategy.
|
|
225
|
+
|
|
226
|
+
Coroutine Safety:
|
|
227
|
+
This method is coroutine-safe when called concurrently from multiple
|
|
228
|
+
coroutines within the same event loop. The asyncio.Lock protects
|
|
229
|
+
round-robin state access.
|
|
230
|
+
|
|
231
|
+
Immutability:
|
|
232
|
+
A defensive copy of the candidates list is made at the start of
|
|
233
|
+
selection. This protects against caller modifications during async
|
|
234
|
+
operations and ensures consistent behavior.
|
|
235
|
+
|
|
236
|
+
Args:
|
|
237
|
+
candidates: List of nodes matching capability criteria. A defensive
|
|
238
|
+
copy is made internally - the original list is never modified
|
|
239
|
+
or accessed after the copy.
|
|
240
|
+
strategy: Selection strategy to use. Must be one of:
|
|
241
|
+
- FIRST: Return first candidate (deterministic)
|
|
242
|
+
- RANDOM: Random selection (stateless load distribution)
|
|
243
|
+
- ROUND_ROBIN: Sequential cycling (stateful, even distribution)
|
|
244
|
+
- LEAST_LOADED: Not yet implemented (raises RuntimeHostError)
|
|
245
|
+
selection_key: Key for round-robin state tracking. Defaults to "_default".
|
|
246
|
+
Different keys maintain independent round-robin sequences.
|
|
247
|
+
For FIRST and RANDOM strategies, this parameter is ignored.
|
|
248
|
+
correlation_id: Optional correlation ID for distributed tracing.
|
|
249
|
+
When provided, included in all log messages for request tracking.
|
|
250
|
+
Auto-generated as UUID4 if not provided.
|
|
251
|
+
|
|
252
|
+
Returns:
|
|
253
|
+
Selected node, or None if candidates is empty.
|
|
254
|
+
|
|
255
|
+
Raises:
|
|
256
|
+
RuntimeHostError: If LEAST_LOADED strategy is requested, or if an
|
|
257
|
+
unhandled strategy value is encountered. The latter should never
|
|
258
|
+
happen with properly typed code, as all enum values are explicitly
|
|
259
|
+
handled. The check exists for runtime safety and to ensure
|
|
260
|
+
exhaustive handling if new enum values are added. When raised for
|
|
261
|
+
unhandled strategies, includes full context (correlation_id,
|
|
262
|
+
strategy, selection_key, candidates_count) for debugging.
|
|
263
|
+
|
|
264
|
+
Example:
|
|
265
|
+
>>> selector = ServiceNodeSelector()
|
|
266
|
+
>>>
|
|
267
|
+
>>> # Empty candidates
|
|
268
|
+
>>> result = await selector.select([], EnumSelectionStrategy.FIRST)
|
|
269
|
+
>>> result is None
|
|
270
|
+
True
|
|
271
|
+
>>>
|
|
272
|
+
>>> # First strategy
|
|
273
|
+
>>> result = await selector.select(candidates, EnumSelectionStrategy.FIRST)
|
|
274
|
+
>>> result == candidates[0]
|
|
275
|
+
True
|
|
276
|
+
"""
|
|
277
|
+
# Ensure correlation_id is present for distributed tracing
|
|
278
|
+
cid = self._ensure_correlation_id(correlation_id)
|
|
279
|
+
|
|
280
|
+
# Defensive copy to protect against caller modifications during async operations
|
|
281
|
+
# This ensures consistent behavior even if the caller modifies the original list
|
|
282
|
+
candidates = list(candidates)
|
|
283
|
+
|
|
284
|
+
if not candidates:
|
|
285
|
+
logger.debug(
|
|
286
|
+
"No candidates provided for selection",
|
|
287
|
+
extra={"correlation_id": str(cid)},
|
|
288
|
+
)
|
|
289
|
+
return None
|
|
290
|
+
|
|
291
|
+
if len(candidates) == 1:
|
|
292
|
+
logger.debug(
|
|
293
|
+
"Single candidate, returning directly",
|
|
294
|
+
extra={
|
|
295
|
+
"entity_id": str(candidates[0].entity_id),
|
|
296
|
+
"correlation_id": str(cid),
|
|
297
|
+
},
|
|
298
|
+
)
|
|
299
|
+
return candidates[0]
|
|
300
|
+
|
|
301
|
+
if strategy == EnumSelectionStrategy.FIRST:
|
|
302
|
+
return self._select_first(candidates, cid)
|
|
303
|
+
elif strategy == EnumSelectionStrategy.RANDOM:
|
|
304
|
+
return self._select_random(candidates, cid)
|
|
305
|
+
elif strategy == EnumSelectionStrategy.ROUND_ROBIN:
|
|
306
|
+
return await self._select_round_robin(candidates, selection_key, cid)
|
|
307
|
+
elif strategy == EnumSelectionStrategy.LEAST_LOADED:
|
|
308
|
+
raise RuntimeHostError(
|
|
309
|
+
"LEAST_LOADED selection strategy is not yet implemented",
|
|
310
|
+
context=ModelInfraErrorContext(
|
|
311
|
+
operation="select",
|
|
312
|
+
correlation_id=cid,
|
|
313
|
+
),
|
|
314
|
+
strategy=strategy.value,
|
|
315
|
+
selection_key=selection_key,
|
|
316
|
+
candidates_count=len(candidates),
|
|
317
|
+
)
|
|
318
|
+
else:
|
|
319
|
+
# Type-safe exhaustiveness check: ensures all enum values are handled.
|
|
320
|
+
# If a new EnumSelectionStrategy value is added, the type checker will
|
|
321
|
+
# flag this as an error because strategy won't narrow to Never.
|
|
322
|
+
_: Never = strategy
|
|
323
|
+
raise RuntimeHostError(
|
|
324
|
+
f"Unhandled selection strategy: {strategy.value}",
|
|
325
|
+
context=ModelInfraErrorContext(
|
|
326
|
+
operation="select",
|
|
327
|
+
correlation_id=cid,
|
|
328
|
+
),
|
|
329
|
+
strategy=strategy.value,
|
|
330
|
+
selection_key=selection_key,
|
|
331
|
+
candidates_count=len(candidates),
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
def _select_first(
|
|
335
|
+
self,
|
|
336
|
+
candidates: list[ModelRegistrationProjection],
|
|
337
|
+
correlation_id: UUID,
|
|
338
|
+
) -> ModelRegistrationProjection:
|
|
339
|
+
"""Select the first candidate (deterministic).
|
|
340
|
+
|
|
341
|
+
Args:
|
|
342
|
+
candidates: Non-empty list of candidates.
|
|
343
|
+
correlation_id: Correlation ID for distributed tracing.
|
|
344
|
+
|
|
345
|
+
Returns:
|
|
346
|
+
First candidate in the list.
|
|
347
|
+
"""
|
|
348
|
+
selected = candidates[0]
|
|
349
|
+
logger.debug(
|
|
350
|
+
"Selected first candidate",
|
|
351
|
+
extra={
|
|
352
|
+
"entity_id": str(selected.entity_id),
|
|
353
|
+
"total_candidates": len(candidates),
|
|
354
|
+
"correlation_id": str(correlation_id),
|
|
355
|
+
},
|
|
356
|
+
)
|
|
357
|
+
return selected
|
|
358
|
+
|
|
359
|
+
def _select_random(
|
|
360
|
+
self,
|
|
361
|
+
candidates: list[ModelRegistrationProjection],
|
|
362
|
+
correlation_id: UUID,
|
|
363
|
+
) -> ModelRegistrationProjection:
|
|
364
|
+
"""Select a random candidate.
|
|
365
|
+
|
|
366
|
+
Args:
|
|
367
|
+
candidates: Non-empty list of candidates.
|
|
368
|
+
correlation_id: Correlation ID for distributed tracing.
|
|
369
|
+
|
|
370
|
+
Returns:
|
|
371
|
+
Randomly selected candidate.
|
|
372
|
+
"""
|
|
373
|
+
selected = random.choice(candidates)
|
|
374
|
+
logger.debug(
|
|
375
|
+
"Selected random candidate",
|
|
376
|
+
extra={
|
|
377
|
+
"entity_id": str(selected.entity_id),
|
|
378
|
+
"total_candidates": len(candidates),
|
|
379
|
+
"correlation_id": str(correlation_id),
|
|
380
|
+
},
|
|
381
|
+
)
|
|
382
|
+
return selected
|
|
383
|
+
|
|
384
|
+
async def _select_round_robin(
|
|
385
|
+
self,
|
|
386
|
+
candidates: list[ModelRegistrationProjection],
|
|
387
|
+
selection_key: str | None,
|
|
388
|
+
correlation_id: UUID,
|
|
389
|
+
) -> ModelRegistrationProjection:
|
|
390
|
+
"""Select the next candidate in round-robin sequence.
|
|
391
|
+
|
|
392
|
+
State is tracked per selection_key, allowing independent cycling
|
|
393
|
+
for different dependency types. Access is protected by asyncio.Lock.
|
|
394
|
+
|
|
395
|
+
Coroutine Safety:
|
|
396
|
+
This method is coroutine-safe when called concurrently from multiple
|
|
397
|
+
coroutines within the same event loop.
|
|
398
|
+
|
|
399
|
+
Implements LRU eviction: when state entries exceed max_round_robin_entries,
|
|
400
|
+
the oldest 10% (by last access time) are automatically evicted.
|
|
401
|
+
|
|
402
|
+
Note:
|
|
403
|
+
This is an internal method. Callers should use select() which
|
|
404
|
+
makes a defensive copy of the candidates list before calling this.
|
|
405
|
+
|
|
406
|
+
Args:
|
|
407
|
+
candidates: Non-empty list of candidates (already copied by select()).
|
|
408
|
+
selection_key: Key for state tracking. Defaults to "_default".
|
|
409
|
+
correlation_id: Correlation ID for distributed tracing.
|
|
410
|
+
|
|
411
|
+
Returns:
|
|
412
|
+
Next candidate in the round-robin sequence.
|
|
413
|
+
"""
|
|
414
|
+
key = selection_key or DEFAULT_SELECTION_KEY
|
|
415
|
+
|
|
416
|
+
async with self._round_robin_lock:
|
|
417
|
+
# Get current entry, default to index -1 (so first selection is index 0)
|
|
418
|
+
current_entry = self._round_robin_state.get(key)
|
|
419
|
+
last_index = current_entry.current_index if current_entry else -1
|
|
420
|
+
next_index = (last_index + 1) % len(candidates)
|
|
421
|
+
|
|
422
|
+
# Defensive bounds check - ensure index is valid for current candidates list
|
|
423
|
+
# This protects against edge cases where candidates list size changed
|
|
424
|
+
if next_index >= len(candidates):
|
|
425
|
+
next_index = 0
|
|
426
|
+
logger.warning(
|
|
427
|
+
"Round-robin index out of bounds, resetting to 0",
|
|
428
|
+
extra={
|
|
429
|
+
"selection_key": key,
|
|
430
|
+
"computed_index": (last_index + 1) % len(candidates),
|
|
431
|
+
"candidates_count": len(candidates),
|
|
432
|
+
"correlation_id": str(correlation_id),
|
|
433
|
+
},
|
|
434
|
+
)
|
|
435
|
+
|
|
436
|
+
# Update state with new entry (index + current timestamp for LRU)
|
|
437
|
+
self._round_robin_state[key] = RoundRobinEntry(
|
|
438
|
+
current_index=next_index,
|
|
439
|
+
last_access=time.monotonic(),
|
|
440
|
+
)
|
|
441
|
+
|
|
442
|
+
# Trigger LRU eviction if needed (while holding lock)
|
|
443
|
+
await self._prune_round_robin_state()
|
|
444
|
+
|
|
445
|
+
# Access candidate inside lock for transaction safety
|
|
446
|
+
selected = candidates[next_index]
|
|
447
|
+
logger.debug(
|
|
448
|
+
"Selected round-robin candidate",
|
|
449
|
+
extra={
|
|
450
|
+
"entity_id": str(selected.entity_id),
|
|
451
|
+
"selection_key": key,
|
|
452
|
+
"index": next_index,
|
|
453
|
+
"total_candidates": len(candidates),
|
|
454
|
+
"correlation_id": str(correlation_id),
|
|
455
|
+
},
|
|
456
|
+
)
|
|
457
|
+
return selected
|
|
458
|
+
|
|
459
|
+
async def reset_round_robin_state(self, selection_key: str | None = None) -> None:
|
|
460
|
+
"""Reset round-robin state for a specific key or all keys.
|
|
461
|
+
|
|
462
|
+
Access is protected by asyncio.Lock.
|
|
463
|
+
|
|
464
|
+
Args:
|
|
465
|
+
selection_key: Key to reset. If None, resets all keys.
|
|
466
|
+
|
|
467
|
+
Example:
|
|
468
|
+
>>> selector = ServiceNodeSelector()
|
|
469
|
+
>>> await selector.reset_round_robin_state("db") # Reset specific key
|
|
470
|
+
>>> await selector.reset_round_robin_state() # Reset all keys
|
|
471
|
+
"""
|
|
472
|
+
async with self._round_robin_lock:
|
|
473
|
+
if selection_key is not None:
|
|
474
|
+
if selection_key in self._round_robin_state:
|
|
475
|
+
del self._round_robin_state[selection_key]
|
|
476
|
+
logger.debug(
|
|
477
|
+
"Reset round-robin state for key",
|
|
478
|
+
extra={"selection_key": selection_key},
|
|
479
|
+
)
|
|
480
|
+
else:
|
|
481
|
+
self._round_robin_state.clear()
|
|
482
|
+
logger.debug("Reset all round-robin state")
|
|
483
|
+
|
|
484
|
+
async def get_round_robin_state(self) -> dict[str, int]:
|
|
485
|
+
"""Get a copy of the current round-robin state (indices only).
|
|
486
|
+
|
|
487
|
+
Access is protected by asyncio.Lock.
|
|
488
|
+
|
|
489
|
+
Returns:
|
|
490
|
+
Dictionary mapping selection keys to their last used index.
|
|
491
|
+
Note: Last access timestamps are not included for API simplicity.
|
|
492
|
+
|
|
493
|
+
Example:
|
|
494
|
+
>>> selector = ServiceNodeSelector()
|
|
495
|
+
>>> state = await selector.get_round_robin_state()
|
|
496
|
+
>>> print(state)
|
|
497
|
+
{'db': 2, 'consul': 0}
|
|
498
|
+
"""
|
|
499
|
+
async with self._round_robin_lock:
|
|
500
|
+
return {
|
|
501
|
+
key: entry.current_index
|
|
502
|
+
for key, entry in self._round_robin_state.items()
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
async def get_round_robin_state_full(self) -> dict[str, RoundRobinEntry]:
|
|
506
|
+
"""Get a copy of the current round-robin state with full details.
|
|
507
|
+
|
|
508
|
+
Access is protected by asyncio.Lock.
|
|
509
|
+
|
|
510
|
+
Returns:
|
|
511
|
+
Dictionary mapping selection keys to RoundRobinEntry objects
|
|
512
|
+
containing both index and last access timestamp.
|
|
513
|
+
|
|
514
|
+
Example:
|
|
515
|
+
>>> selector = ServiceNodeSelector()
|
|
516
|
+
>>> state = await selector.get_round_robin_state_full()
|
|
517
|
+
>>> for key, entry in state.items():
|
|
518
|
+
... print(f"{key}: idx={entry.current_index}, access={entry.last_access}")
|
|
519
|
+
"""
|
|
520
|
+
async with self._round_robin_lock:
|
|
521
|
+
return dict(self._round_robin_state)
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
__all__: list[str] = [
|
|
525
|
+
"DEFAULT_MAX_ROUND_ROBIN_ENTRIES",
|
|
526
|
+
"DEFAULT_SELECTION_KEY",
|
|
527
|
+
"EVICTION_PERCENTAGE",
|
|
528
|
+
"RoundRobinEntry",
|
|
529
|
+
"ServiceNodeSelector",
|
|
530
|
+
]
|