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,637 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2025 OmniNode Team
|
|
3
|
+
"""In-memory snapshot store for testing.
|
|
4
|
+
|
|
5
|
+
Provides an in-memory implementation of ProtocolSnapshotStore suitable for
|
|
6
|
+
unit tests and development scenarios. This store maintains all data in memory
|
|
7
|
+
with no persistence across process restarts.
|
|
8
|
+
|
|
9
|
+
Features:
|
|
10
|
+
- Content-hash based idempotency on save
|
|
11
|
+
- Sequence number tracking per subject (atomic)
|
|
12
|
+
- asyncio.Lock for coroutine safety
|
|
13
|
+
- Test helpers (clear, count) for easy cleanup
|
|
14
|
+
|
|
15
|
+
Thread Safety:
|
|
16
|
+
This implementation uses asyncio.Lock which is coroutine-safe but NOT
|
|
17
|
+
thread-safe. For multi-threaded scenarios, use a thread-safe store
|
|
18
|
+
implementation or wrap with appropriate locks.
|
|
19
|
+
|
|
20
|
+
Related Tickets:
|
|
21
|
+
- OMN-1246: ServiceSnapshot Infrastructure Primitive
|
|
22
|
+
|
|
23
|
+
Example:
|
|
24
|
+
>>> import asyncio
|
|
25
|
+
>>> from uuid import uuid4
|
|
26
|
+
>>> from omnibase_infra.models.snapshot import ModelSnapshot, ModelSubjectRef
|
|
27
|
+
>>> from omnibase_infra.services.snapshot import StoreSnapshotInMemory
|
|
28
|
+
>>>
|
|
29
|
+
>>> async def demo():
|
|
30
|
+
... store = StoreSnapshotInMemory()
|
|
31
|
+
... subject = ModelSubjectRef(subject_type="test", subject_id=uuid4())
|
|
32
|
+
... seq = await store.get_next_sequence_number(subject)
|
|
33
|
+
... snapshot = ModelSnapshot(subject=subject, data={"key": "value"}, sequence_number=seq)
|
|
34
|
+
... saved_id = await store.save(snapshot)
|
|
35
|
+
... loaded = await store.load(saved_id)
|
|
36
|
+
... assert loaded is not None
|
|
37
|
+
... assert loaded.data == {"key": "value"}
|
|
38
|
+
>>>
|
|
39
|
+
>>> asyncio.run(demo())
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
from __future__ import annotations
|
|
43
|
+
|
|
44
|
+
import asyncio
|
|
45
|
+
from datetime import UTC, datetime, timedelta
|
|
46
|
+
from uuid import UUID
|
|
47
|
+
|
|
48
|
+
from omnibase_infra.errors import ProtocolConfigurationError
|
|
49
|
+
from omnibase_infra.models.snapshot import ModelSnapshot, ModelSubjectRef
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class StoreSnapshotInMemory:
|
|
53
|
+
"""In-memory implementation of ProtocolSnapshotStore for testing.
|
|
54
|
+
|
|
55
|
+
Provides a fully-functional snapshot store that maintains all data in
|
|
56
|
+
memory. Useful for unit tests where persistence is not required.
|
|
57
|
+
|
|
58
|
+
Features:
|
|
59
|
+
- Content-hash based idempotency: Duplicate saves return existing ID
|
|
60
|
+
- Sequence number tracking: Atomic per-subject sequence generation
|
|
61
|
+
- asyncio.Lock: Safe for concurrent coroutine access
|
|
62
|
+
- Test helpers: clear() and count() for test cleanup and assertions
|
|
63
|
+
|
|
64
|
+
Attributes:
|
|
65
|
+
_snapshots: Dictionary mapping snapshot IDs to snapshots.
|
|
66
|
+
_sequences: Dictionary mapping subject keys to sequence counters.
|
|
67
|
+
_hash_index: Dictionary mapping content_hash to snapshot ID for O(1) dedup lookup.
|
|
68
|
+
_lock: asyncio.Lock for coroutine-safe operations.
|
|
69
|
+
|
|
70
|
+
Example:
|
|
71
|
+
>>> import asyncio
|
|
72
|
+
>>> from uuid import uuid4
|
|
73
|
+
>>> from omnibase_infra.models.snapshot import ModelSnapshot, ModelSubjectRef
|
|
74
|
+
>>>
|
|
75
|
+
>>> async def test_save_load():
|
|
76
|
+
... store = StoreSnapshotInMemory()
|
|
77
|
+
... subject = ModelSubjectRef(subject_type="agent", subject_id=uuid4())
|
|
78
|
+
...
|
|
79
|
+
... # Get sequence number and create snapshot
|
|
80
|
+
... seq = await store.get_next_sequence_number(subject)
|
|
81
|
+
... snapshot = ModelSnapshot(subject=subject, data={"status": "active"}, sequence_number=seq)
|
|
82
|
+
...
|
|
83
|
+
... # Save and verify
|
|
84
|
+
... saved_id = await store.save(snapshot)
|
|
85
|
+
... assert await store.count() == 1
|
|
86
|
+
...
|
|
87
|
+
... # Load and verify
|
|
88
|
+
... loaded = await store.load(saved_id)
|
|
89
|
+
... assert loaded is not None
|
|
90
|
+
... assert loaded.data["status"] == "active"
|
|
91
|
+
...
|
|
92
|
+
... # Cleanup
|
|
93
|
+
... store.clear()
|
|
94
|
+
... assert store.count() == 0
|
|
95
|
+
>>>
|
|
96
|
+
>>> asyncio.run(test_save_load())
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
def __init__(self) -> None:
|
|
100
|
+
"""Initialize empty in-memory store."""
|
|
101
|
+
self._snapshots: dict[UUID, ModelSnapshot] = {}
|
|
102
|
+
self._sequences: dict[str, int] = {} # subject_key -> sequence
|
|
103
|
+
self._hash_index: dict[
|
|
104
|
+
str, UUID
|
|
105
|
+
] = {} # content_hash -> snapshot_id (O(1) dedup)
|
|
106
|
+
self._lock = asyncio.Lock()
|
|
107
|
+
|
|
108
|
+
async def save(self, snapshot: ModelSnapshot) -> UUID:
|
|
109
|
+
"""Save snapshot. Returns existing ID if duplicate content_hash.
|
|
110
|
+
|
|
111
|
+
Implements idempotency by checking content_hash before saving.
|
|
112
|
+
If a snapshot with matching content_hash already exists, the
|
|
113
|
+
existing snapshot's ID is returned without creating a duplicate.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
snapshot: The snapshot to persist.
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
The snapshot ID (either newly saved or existing duplicate).
|
|
120
|
+
|
|
121
|
+
Example:
|
|
122
|
+
>>> import asyncio
|
|
123
|
+
>>> from uuid import uuid4
|
|
124
|
+
>>> from omnibase_infra.models.snapshot import ModelSnapshot, ModelSubjectRef
|
|
125
|
+
>>>
|
|
126
|
+
>>> async def test_idempotency():
|
|
127
|
+
... store = StoreSnapshotInMemory()
|
|
128
|
+
... subject = ModelSubjectRef(subject_type="test", subject_id=uuid4())
|
|
129
|
+
...
|
|
130
|
+
... # Save first snapshot
|
|
131
|
+
... snap1 = ModelSnapshot(subject=subject, data={"key": "value"}, sequence_number=1)
|
|
132
|
+
... id1 = await store.save(snap1)
|
|
133
|
+
...
|
|
134
|
+
... # Save duplicate (same content_hash)
|
|
135
|
+
... snap2 = ModelSnapshot(subject=subject, data={"key": "value"}, sequence_number=2)
|
|
136
|
+
... id2 = await store.save(snap2)
|
|
137
|
+
...
|
|
138
|
+
... # Returns existing ID due to content_hash match
|
|
139
|
+
... assert id1 == id2
|
|
140
|
+
... assert store.count() == 1
|
|
141
|
+
>>>
|
|
142
|
+
>>> asyncio.run(test_idempotency())
|
|
143
|
+
"""
|
|
144
|
+
async with self._lock:
|
|
145
|
+
# O(1) duplicate check via hash index
|
|
146
|
+
if snapshot.content_hash and snapshot.content_hash in self._hash_index:
|
|
147
|
+
return self._hash_index[snapshot.content_hash]
|
|
148
|
+
|
|
149
|
+
self._snapshots[snapshot.id] = snapshot
|
|
150
|
+
if snapshot.content_hash:
|
|
151
|
+
self._hash_index[snapshot.content_hash] = snapshot.id
|
|
152
|
+
return snapshot.id
|
|
153
|
+
|
|
154
|
+
async def load(self, snapshot_id: UUID) -> ModelSnapshot | None:
|
|
155
|
+
"""Load snapshot by ID.
|
|
156
|
+
|
|
157
|
+
Args:
|
|
158
|
+
snapshot_id: The unique identifier of the snapshot.
|
|
159
|
+
|
|
160
|
+
Returns:
|
|
161
|
+
The snapshot if found, None otherwise.
|
|
162
|
+
|
|
163
|
+
Example:
|
|
164
|
+
>>> import asyncio
|
|
165
|
+
>>> from uuid import uuid4
|
|
166
|
+
>>> from omnibase_infra.models.snapshot import ModelSnapshot, ModelSubjectRef
|
|
167
|
+
>>>
|
|
168
|
+
>>> async def test_load():
|
|
169
|
+
... store = StoreSnapshotInMemory()
|
|
170
|
+
... subject = ModelSubjectRef(subject_type="test", subject_id=uuid4())
|
|
171
|
+
... snapshot = ModelSnapshot(subject=subject, data={}, sequence_number=1)
|
|
172
|
+
...
|
|
173
|
+
... await store.save(snapshot)
|
|
174
|
+
... loaded = await store.load(snapshot.id)
|
|
175
|
+
... assert loaded is not None
|
|
176
|
+
...
|
|
177
|
+
... # Non-existent ID returns None
|
|
178
|
+
... missing = await store.load(uuid4())
|
|
179
|
+
... assert missing is None
|
|
180
|
+
>>>
|
|
181
|
+
>>> asyncio.run(test_load())
|
|
182
|
+
"""
|
|
183
|
+
return self._snapshots.get(snapshot_id)
|
|
184
|
+
|
|
185
|
+
async def load_many(self, snapshot_ids: list[UUID]) -> dict[UUID, ModelSnapshot]:
|
|
186
|
+
"""Load multiple snapshots by ID.
|
|
187
|
+
|
|
188
|
+
Uses batch lookup for efficient multi-row fetch.
|
|
189
|
+
|
|
190
|
+
Args:
|
|
191
|
+
snapshot_ids: List of snapshot UUIDs to load.
|
|
192
|
+
|
|
193
|
+
Returns:
|
|
194
|
+
Dictionary mapping snapshot ID to ModelSnapshot for found
|
|
195
|
+
snapshots. Missing IDs are not included in the result.
|
|
196
|
+
|
|
197
|
+
Example:
|
|
198
|
+
>>> import asyncio
|
|
199
|
+
>>> from uuid import uuid4
|
|
200
|
+
>>> from omnibase_infra.models.snapshot import ModelSnapshot, ModelSubjectRef
|
|
201
|
+
>>>
|
|
202
|
+
>>> async def test_load_many():
|
|
203
|
+
... store = StoreSnapshotInMemory()
|
|
204
|
+
... subject = ModelSubjectRef(subject_type="test", subject_id=uuid4())
|
|
205
|
+
... snap1 = ModelSnapshot(subject=subject, data={"v": 1}, sequence_number=1)
|
|
206
|
+
... snap2 = ModelSnapshot(subject=subject, data={"v": 2}, sequence_number=2)
|
|
207
|
+
... await store.save(snap1)
|
|
208
|
+
... await store.save(snap2)
|
|
209
|
+
...
|
|
210
|
+
... results = await store.load_many([snap1.id, snap2.id])
|
|
211
|
+
... assert len(results) == 2
|
|
212
|
+
... assert results[snap1.id].data["v"] == 1
|
|
213
|
+
>>>
|
|
214
|
+
>>> asyncio.run(test_load_many())
|
|
215
|
+
"""
|
|
216
|
+
return {
|
|
217
|
+
sid: self._snapshots[sid] for sid in snapshot_ids if sid in self._snapshots
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
async def load_latest(
|
|
221
|
+
self,
|
|
222
|
+
subject: ModelSubjectRef | None = None,
|
|
223
|
+
) -> ModelSnapshot | None:
|
|
224
|
+
"""Get most recent snapshot by sequence_number.
|
|
225
|
+
|
|
226
|
+
"Most recent" is determined by sequence_number, not created_at.
|
|
227
|
+
This ensures consistent ordering even with clock skew.
|
|
228
|
+
|
|
229
|
+
Args:
|
|
230
|
+
subject: Optional filter by subject reference.
|
|
231
|
+
|
|
232
|
+
- If provided: Returns the latest snapshot for that specific
|
|
233
|
+
subject (highest sequence_number within that subject).
|
|
234
|
+
- If None: Returns the globally latest snapshot across ALL
|
|
235
|
+
subjects (highest sequence_number in the entire store).
|
|
236
|
+
|
|
237
|
+
Returns:
|
|
238
|
+
The most recent snapshot matching criteria, or None if no
|
|
239
|
+
snapshots exist.
|
|
240
|
+
|
|
241
|
+
Note:
|
|
242
|
+
When ``subject=None``, "globally latest" means the snapshot with
|
|
243
|
+
the highest sequence_number across all subjects. Since sequence
|
|
244
|
+
numbers are per-subject (each subject starts at 1), this may NOT
|
|
245
|
+
correspond to the most recently created snapshot by wall-clock
|
|
246
|
+
time. Use ``query(after=timestamp)`` if you need time-based
|
|
247
|
+
ordering across subjects.
|
|
248
|
+
|
|
249
|
+
Example:
|
|
250
|
+
>>> import asyncio
|
|
251
|
+
>>> from uuid import uuid4
|
|
252
|
+
>>> from omnibase_infra.models.snapshot import ModelSnapshot, ModelSubjectRef
|
|
253
|
+
>>>
|
|
254
|
+
>>> async def test_load_latest():
|
|
255
|
+
... store = StoreSnapshotInMemory()
|
|
256
|
+
... subject = ModelSubjectRef(subject_type="test", subject_id=uuid4())
|
|
257
|
+
...
|
|
258
|
+
... # Save multiple snapshots for the subject
|
|
259
|
+
... snap1 = ModelSnapshot(subject=subject, data={"v": 1}, sequence_number=1)
|
|
260
|
+
... snap2 = ModelSnapshot(subject=subject, data={"v": 2}, sequence_number=2)
|
|
261
|
+
... await store.save(snap1)
|
|
262
|
+
... await store.save(snap2)
|
|
263
|
+
...
|
|
264
|
+
... # Get latest for specific subject
|
|
265
|
+
... latest = await store.load_latest(subject=subject)
|
|
266
|
+
... assert latest is not None
|
|
267
|
+
... assert latest.sequence_number == 2
|
|
268
|
+
...
|
|
269
|
+
... # Get globally latest across ALL subjects
|
|
270
|
+
... global_latest = await store.load_latest(subject=None)
|
|
271
|
+
... # Returns snapshot with highest sequence_number in store
|
|
272
|
+
>>>
|
|
273
|
+
>>> asyncio.run(test_load_latest())
|
|
274
|
+
"""
|
|
275
|
+
candidates = list(self._snapshots.values())
|
|
276
|
+
if subject:
|
|
277
|
+
subject_key = subject.to_key()
|
|
278
|
+
candidates = [s for s in candidates if s.subject.to_key() == subject_key]
|
|
279
|
+
|
|
280
|
+
if not candidates:
|
|
281
|
+
return None
|
|
282
|
+
|
|
283
|
+
return max(candidates, key=lambda s: s.sequence_number)
|
|
284
|
+
|
|
285
|
+
async def load_latest_many(
|
|
286
|
+
self,
|
|
287
|
+
subjects: list[ModelSubjectRef],
|
|
288
|
+
) -> dict[tuple[str, UUID], ModelSnapshot]:
|
|
289
|
+
"""Load the latest snapshot for multiple subjects.
|
|
290
|
+
|
|
291
|
+
Uses batch lookup for efficient multi-subject query.
|
|
292
|
+
|
|
293
|
+
Args:
|
|
294
|
+
subjects: List of subject references to load latest snapshots for.
|
|
295
|
+
|
|
296
|
+
Returns:
|
|
297
|
+
Dictionary mapping (subject_type, subject_id) tuple to the latest
|
|
298
|
+
ModelSnapshot for that subject. Subjects with no snapshots are
|
|
299
|
+
not included in the result.
|
|
300
|
+
|
|
301
|
+
Example:
|
|
302
|
+
>>> import asyncio
|
|
303
|
+
>>> from uuid import uuid4
|
|
304
|
+
>>> from omnibase_infra.models.snapshot import ModelSnapshot, ModelSubjectRef
|
|
305
|
+
>>>
|
|
306
|
+
>>> async def test_load_latest_many():
|
|
307
|
+
... store = StoreSnapshotInMemory()
|
|
308
|
+
... s1 = ModelSubjectRef(subject_type="agent", subject_id=uuid4())
|
|
309
|
+
... s2 = ModelSubjectRef(subject_type="workflow", subject_id=uuid4())
|
|
310
|
+
...
|
|
311
|
+
... snap1 = ModelSnapshot(subject=s1, data={"v": 1}, sequence_number=1)
|
|
312
|
+
... snap2 = ModelSnapshot(subject=s2, data={"v": 2}, sequence_number=1)
|
|
313
|
+
... await store.save(snap1)
|
|
314
|
+
... await store.save(snap2)
|
|
315
|
+
...
|
|
316
|
+
... results = await store.load_latest_many([s1, s2])
|
|
317
|
+
... assert len(results) == 2
|
|
318
|
+
>>>
|
|
319
|
+
>>> asyncio.run(test_load_latest_many())
|
|
320
|
+
"""
|
|
321
|
+
if not subjects:
|
|
322
|
+
return {}
|
|
323
|
+
|
|
324
|
+
# Group snapshots by subject key
|
|
325
|
+
snapshots_by_subject: dict[str, list[ModelSnapshot]] = {}
|
|
326
|
+
for snapshot in self._snapshots.values():
|
|
327
|
+
key = snapshot.subject.to_key()
|
|
328
|
+
if key not in snapshots_by_subject:
|
|
329
|
+
snapshots_by_subject[key] = []
|
|
330
|
+
snapshots_by_subject[key].append(snapshot)
|
|
331
|
+
|
|
332
|
+
# Get latest for each requested subject
|
|
333
|
+
result: dict[tuple[str, UUID], ModelSnapshot] = {}
|
|
334
|
+
for subject in subjects:
|
|
335
|
+
key = subject.to_key()
|
|
336
|
+
candidates = snapshots_by_subject.get(key, [])
|
|
337
|
+
if candidates:
|
|
338
|
+
latest = max(candidates, key=lambda s: s.sequence_number)
|
|
339
|
+
result[(subject.subject_type, subject.subject_id)] = latest
|
|
340
|
+
|
|
341
|
+
return result
|
|
342
|
+
|
|
343
|
+
async def query(
|
|
344
|
+
self,
|
|
345
|
+
subject: ModelSubjectRef | None = None,
|
|
346
|
+
limit: int = 50,
|
|
347
|
+
after: datetime | None = None,
|
|
348
|
+
) -> list[ModelSnapshot]:
|
|
349
|
+
"""Query with filtering, ordered by sequence_number desc.
|
|
350
|
+
|
|
351
|
+
Returns snapshots ordered by sequence_number descending (most
|
|
352
|
+
recent first).
|
|
353
|
+
|
|
354
|
+
Args:
|
|
355
|
+
subject: Optional filter by subject reference.
|
|
356
|
+
limit: Maximum results to return (default 50).
|
|
357
|
+
after: Only return snapshots created after this time.
|
|
358
|
+
|
|
359
|
+
Returns:
|
|
360
|
+
List of snapshots ordered by sequence_number descending.
|
|
361
|
+
Empty list if no snapshots match criteria.
|
|
362
|
+
|
|
363
|
+
Example:
|
|
364
|
+
>>> import asyncio
|
|
365
|
+
>>> from uuid import uuid4
|
|
366
|
+
>>> from omnibase_infra.models.snapshot import ModelSnapshot, ModelSubjectRef
|
|
367
|
+
>>>
|
|
368
|
+
>>> async def test_query():
|
|
369
|
+
... store = StoreSnapshotInMemory()
|
|
370
|
+
... subject = ModelSubjectRef(subject_type="test", subject_id=uuid4())
|
|
371
|
+
...
|
|
372
|
+
... # Save multiple snapshots
|
|
373
|
+
... for i in range(5):
|
|
374
|
+
... snap = ModelSnapshot(subject=subject, data={"i": i}, sequence_number=i+1)
|
|
375
|
+
... await store.save(snap)
|
|
376
|
+
...
|
|
377
|
+
... # Query with limit
|
|
378
|
+
... results = await store.query(subject=subject, limit=3)
|
|
379
|
+
... assert len(results) == 3
|
|
380
|
+
... # Ordered by sequence_number descending
|
|
381
|
+
... assert results[0].sequence_number == 5
|
|
382
|
+
>>>
|
|
383
|
+
>>> asyncio.run(test_query())
|
|
384
|
+
"""
|
|
385
|
+
candidates = list(self._snapshots.values())
|
|
386
|
+
|
|
387
|
+
if subject:
|
|
388
|
+
subject_key = subject.to_key()
|
|
389
|
+
candidates = [s for s in candidates if s.subject.to_key() == subject_key]
|
|
390
|
+
|
|
391
|
+
if after:
|
|
392
|
+
candidates = [s for s in candidates if s.created_at > after]
|
|
393
|
+
|
|
394
|
+
# Sort by sequence_number descending
|
|
395
|
+
candidates.sort(key=lambda s: s.sequence_number, reverse=True)
|
|
396
|
+
|
|
397
|
+
return candidates[:limit]
|
|
398
|
+
|
|
399
|
+
async def delete(self, snapshot_id: UUID) -> bool:
|
|
400
|
+
"""Delete snapshot. Returns True if deleted.
|
|
401
|
+
|
|
402
|
+
Args:
|
|
403
|
+
snapshot_id: The unique identifier of the snapshot to delete.
|
|
404
|
+
|
|
405
|
+
Returns:
|
|
406
|
+
True if the snapshot was deleted, False if not found.
|
|
407
|
+
|
|
408
|
+
Example:
|
|
409
|
+
>>> import asyncio
|
|
410
|
+
>>> from uuid import uuid4
|
|
411
|
+
>>> from omnibase_infra.models.snapshot import ModelSnapshot, ModelSubjectRef
|
|
412
|
+
>>>
|
|
413
|
+
>>> async def test_delete():
|
|
414
|
+
... store = StoreSnapshotInMemory()
|
|
415
|
+
... subject = ModelSubjectRef(subject_type="test", subject_id=uuid4())
|
|
416
|
+
... snapshot = ModelSnapshot(subject=subject, data={}, sequence_number=1)
|
|
417
|
+
...
|
|
418
|
+
... await store.save(snapshot)
|
|
419
|
+
... assert store.count() == 1
|
|
420
|
+
...
|
|
421
|
+
... deleted = await store.delete(snapshot.id)
|
|
422
|
+
... assert deleted is True
|
|
423
|
+
... assert store.count() == 0
|
|
424
|
+
...
|
|
425
|
+
... # Deleting non-existent returns False
|
|
426
|
+
... deleted_again = await store.delete(snapshot.id)
|
|
427
|
+
... assert deleted_again is False
|
|
428
|
+
>>>
|
|
429
|
+
>>> asyncio.run(test_delete())
|
|
430
|
+
"""
|
|
431
|
+
async with self._lock:
|
|
432
|
+
if snapshot_id in self._snapshots:
|
|
433
|
+
snapshot = self._snapshots[snapshot_id]
|
|
434
|
+
# Remove from hash index if content_hash exists
|
|
435
|
+
if snapshot.content_hash and snapshot.content_hash in self._hash_index:
|
|
436
|
+
del self._hash_index[snapshot.content_hash]
|
|
437
|
+
del self._snapshots[snapshot_id]
|
|
438
|
+
return True
|
|
439
|
+
return False
|
|
440
|
+
|
|
441
|
+
async def get_next_sequence_number(self, subject: ModelSubjectRef) -> int:
|
|
442
|
+
"""Get next sequence number for subject (atomic).
|
|
443
|
+
|
|
444
|
+
Sequence numbers are monotonically increasing per subject,
|
|
445
|
+
starting at 1 for new subjects.
|
|
446
|
+
|
|
447
|
+
Args:
|
|
448
|
+
subject: The subject reference for which to get the next
|
|
449
|
+
sequence number.
|
|
450
|
+
|
|
451
|
+
Returns:
|
|
452
|
+
The next sequence number (starts at 1 for new subjects).
|
|
453
|
+
|
|
454
|
+
Example:
|
|
455
|
+
>>> import asyncio
|
|
456
|
+
>>> from uuid import uuid4
|
|
457
|
+
>>> from omnibase_infra.models.snapshot import ModelSubjectRef
|
|
458
|
+
>>>
|
|
459
|
+
>>> async def test_sequence():
|
|
460
|
+
... store = StoreSnapshotInMemory()
|
|
461
|
+
... subject = ModelSubjectRef(subject_type="test", subject_id=uuid4())
|
|
462
|
+
...
|
|
463
|
+
... seq1 = await store.get_next_sequence_number(subject)
|
|
464
|
+
... seq2 = await store.get_next_sequence_number(subject)
|
|
465
|
+
... seq3 = await store.get_next_sequence_number(subject)
|
|
466
|
+
...
|
|
467
|
+
... assert seq1 == 1
|
|
468
|
+
... assert seq2 == 2
|
|
469
|
+
... assert seq3 == 3
|
|
470
|
+
>>>
|
|
471
|
+
>>> asyncio.run(test_sequence())
|
|
472
|
+
"""
|
|
473
|
+
async with self._lock:
|
|
474
|
+
key = subject.to_key()
|
|
475
|
+
seq = self._sequences.get(key, 0) + 1
|
|
476
|
+
self._sequences[key] = seq
|
|
477
|
+
return seq
|
|
478
|
+
|
|
479
|
+
async def cleanup_expired(
|
|
480
|
+
self,
|
|
481
|
+
*,
|
|
482
|
+
max_age_seconds: int | None = None,
|
|
483
|
+
keep_latest_n: int | None = None,
|
|
484
|
+
subject: ModelSubjectRef | None = None,
|
|
485
|
+
) -> int:
|
|
486
|
+
"""Remove expired snapshots based on retention policy.
|
|
487
|
+
|
|
488
|
+
Supports multiple retention strategies:
|
|
489
|
+
- Time-based: Delete snapshots older than max_age_seconds
|
|
490
|
+
- Count-based: Keep only the N most recent per subject
|
|
491
|
+
- Subject-scoped: Apply policy only to a specific subject
|
|
492
|
+
|
|
493
|
+
When both max_age_seconds and keep_latest_n are provided, snapshots
|
|
494
|
+
must satisfy BOTH conditions to be deleted.
|
|
495
|
+
|
|
496
|
+
Args:
|
|
497
|
+
max_age_seconds: Delete snapshots older than this many seconds.
|
|
498
|
+
keep_latest_n: Always retain the N most recent per subject.
|
|
499
|
+
subject: If provided, apply cleanup only to this subject.
|
|
500
|
+
|
|
501
|
+
Returns:
|
|
502
|
+
Number of snapshots deleted.
|
|
503
|
+
|
|
504
|
+
Raises:
|
|
505
|
+
ProtocolConfigurationError: If keep_latest_n is provided but < 1.
|
|
506
|
+
|
|
507
|
+
Example:
|
|
508
|
+
>>> import asyncio
|
|
509
|
+
>>> from uuid import uuid4
|
|
510
|
+
>>> from datetime import UTC, datetime, timedelta
|
|
511
|
+
>>> from omnibase_infra.models.snapshot import ModelSnapshot, ModelSubjectRef
|
|
512
|
+
>>>
|
|
513
|
+
>>> async def test_cleanup():
|
|
514
|
+
... store = StoreSnapshotInMemory()
|
|
515
|
+
... subject = ModelSubjectRef(subject_type="test", subject_id=uuid4())
|
|
516
|
+
...
|
|
517
|
+
... # Create old snapshots
|
|
518
|
+
... for i in range(10):
|
|
519
|
+
... snap = ModelSnapshot(subject=subject, data={"i": i}, sequence_number=i+1)
|
|
520
|
+
... await store.save(snap)
|
|
521
|
+
...
|
|
522
|
+
... # Keep only last 5
|
|
523
|
+
... deleted = await store.cleanup_expired(keep_latest_n=5)
|
|
524
|
+
... assert deleted == 5
|
|
525
|
+
... assert store.count() == 5
|
|
526
|
+
>>>
|
|
527
|
+
>>> asyncio.run(test_cleanup())
|
|
528
|
+
"""
|
|
529
|
+
if keep_latest_n is not None and keep_latest_n < 1:
|
|
530
|
+
raise ProtocolConfigurationError(
|
|
531
|
+
"keep_latest_n must be >= 1",
|
|
532
|
+
keep_latest_n=keep_latest_n,
|
|
533
|
+
)
|
|
534
|
+
|
|
535
|
+
# If neither policy is specified, no-op
|
|
536
|
+
if max_age_seconds is None and keep_latest_n is None:
|
|
537
|
+
return 0
|
|
538
|
+
|
|
539
|
+
async with self._lock:
|
|
540
|
+
# Calculate cutoff time for age-based filtering
|
|
541
|
+
cutoff_time: datetime | None = None
|
|
542
|
+
if max_age_seconds is not None:
|
|
543
|
+
cutoff_time = datetime.now(UTC) - timedelta(seconds=max_age_seconds)
|
|
544
|
+
|
|
545
|
+
# Group snapshots by subject for keep_latest_n logic
|
|
546
|
+
snapshots_by_subject: dict[str, list[ModelSnapshot]] = {}
|
|
547
|
+
for snapshot in self._snapshots.values():
|
|
548
|
+
subject_key = snapshot.subject.to_key()
|
|
549
|
+
# Filter by subject if specified
|
|
550
|
+
if subject is not None and subject_key != subject.to_key():
|
|
551
|
+
continue
|
|
552
|
+
if subject_key not in snapshots_by_subject:
|
|
553
|
+
snapshots_by_subject[subject_key] = []
|
|
554
|
+
snapshots_by_subject[subject_key].append(snapshot)
|
|
555
|
+
|
|
556
|
+
# Identify snapshots to delete
|
|
557
|
+
ids_to_delete: set[UUID] = set()
|
|
558
|
+
|
|
559
|
+
for subject_key, snapshots in snapshots_by_subject.items():
|
|
560
|
+
# Sort by sequence_number descending (newest first)
|
|
561
|
+
sorted_snapshots = sorted(
|
|
562
|
+
snapshots,
|
|
563
|
+
key=lambda s: s.sequence_number,
|
|
564
|
+
reverse=True,
|
|
565
|
+
)
|
|
566
|
+
|
|
567
|
+
for i, snapshot in enumerate(sorted_snapshots):
|
|
568
|
+
should_delete = False
|
|
569
|
+
|
|
570
|
+
# Check age-based policy
|
|
571
|
+
if cutoff_time is not None and snapshot.created_at < cutoff_time:
|
|
572
|
+
should_delete = True
|
|
573
|
+
|
|
574
|
+
# Check count-based policy (skip if in latest N)
|
|
575
|
+
if keep_latest_n is not None and i < keep_latest_n:
|
|
576
|
+
# Always keep the latest N, even if old
|
|
577
|
+
should_delete = False
|
|
578
|
+
elif keep_latest_n is not None and i >= keep_latest_n:
|
|
579
|
+
# If using keep_latest_n without max_age, delete excess
|
|
580
|
+
if max_age_seconds is None:
|
|
581
|
+
should_delete = True
|
|
582
|
+
# Otherwise, should_delete is already set by age check
|
|
583
|
+
|
|
584
|
+
if should_delete:
|
|
585
|
+
ids_to_delete.add(snapshot.id)
|
|
586
|
+
|
|
587
|
+
# Perform deletion
|
|
588
|
+
deleted_count = 0
|
|
589
|
+
for snapshot_id in ids_to_delete:
|
|
590
|
+
if snapshot_id in self._snapshots:
|
|
591
|
+
snapshot = self._snapshots[snapshot_id]
|
|
592
|
+
# Remove from hash index if content_hash exists
|
|
593
|
+
if (
|
|
594
|
+
snapshot.content_hash
|
|
595
|
+
and snapshot.content_hash in self._hash_index
|
|
596
|
+
):
|
|
597
|
+
del self._hash_index[snapshot.content_hash]
|
|
598
|
+
del self._snapshots[snapshot_id]
|
|
599
|
+
deleted_count += 1
|
|
600
|
+
|
|
601
|
+
return deleted_count
|
|
602
|
+
|
|
603
|
+
# Test helpers
|
|
604
|
+
|
|
605
|
+
def clear(self) -> None:
|
|
606
|
+
"""Clear all data (for test cleanup).
|
|
607
|
+
|
|
608
|
+
Removes all snapshots and resets sequence counters.
|
|
609
|
+
This is a synchronous method for convenient test cleanup.
|
|
610
|
+
|
|
611
|
+
Example:
|
|
612
|
+
>>> store = StoreSnapshotInMemory()
|
|
613
|
+
>>> # ... populate store ...
|
|
614
|
+
>>> store.clear()
|
|
615
|
+
>>> assert store.count() == 0
|
|
616
|
+
"""
|
|
617
|
+
self._snapshots.clear()
|
|
618
|
+
self._sequences.clear()
|
|
619
|
+
self._hash_index.clear()
|
|
620
|
+
|
|
621
|
+
def count(self) -> int:
|
|
622
|
+
"""Get total snapshot count.
|
|
623
|
+
|
|
624
|
+
Returns the number of snapshots currently stored.
|
|
625
|
+
This is a synchronous method for convenient test assertions.
|
|
626
|
+
|
|
627
|
+
Returns:
|
|
628
|
+
Number of snapshots in the store.
|
|
629
|
+
|
|
630
|
+
Example:
|
|
631
|
+
>>> store = StoreSnapshotInMemory()
|
|
632
|
+
>>> assert store.count() == 0
|
|
633
|
+
"""
|
|
634
|
+
return len(self._snapshots)
|
|
635
|
+
|
|
636
|
+
|
|
637
|
+
__all__: list[str] = ["StoreSnapshotInMemory"]
|