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,647 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2025 OmniNode Team
|
|
3
|
+
"""Generic Snapshot Service for Point-in-Time State Capture.
|
|
4
|
+
|
|
5
|
+
This module provides the ServiceSnapshot class, a high-level service for
|
|
6
|
+
managing point-in-time snapshots of entity state. The service handles:
|
|
7
|
+
|
|
8
|
+
- Snapshot creation with automatic sequence numbering
|
|
9
|
+
- Retrieval and querying with subject filtering
|
|
10
|
+
- Structural diffing between snapshots
|
|
11
|
+
- Fork operations for creating derived snapshots
|
|
12
|
+
|
|
13
|
+
Architecture Context:
|
|
14
|
+
ServiceSnapshot is the business logic layer for snapshots:
|
|
15
|
+
- Uses ProtocolSnapshotStore for persistence (injectable backend)
|
|
16
|
+
- Manages sequence number generation with locking
|
|
17
|
+
- Provides convenience methods (diff, fork) over raw storage
|
|
18
|
+
|
|
19
|
+
Thread Safety:
|
|
20
|
+
The service uses asyncio.Lock for sequence number generation, ensuring
|
|
21
|
+
coroutine-safe operations. For multi-process deployments, the store
|
|
22
|
+
implementation must provide atomic sequence generation.
|
|
23
|
+
|
|
24
|
+
Related Tickets:
|
|
25
|
+
- OMN-1246: ServiceSnapshot Infrastructure Primitive
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
from __future__ import annotations
|
|
29
|
+
|
|
30
|
+
import asyncio
|
|
31
|
+
import builtins
|
|
32
|
+
from datetime import datetime
|
|
33
|
+
from uuid import UUID
|
|
34
|
+
|
|
35
|
+
from omnibase_core.container import ModelONEXContainer
|
|
36
|
+
from omnibase_core.enums import EnumCoreErrorCode
|
|
37
|
+
from omnibase_core.types import JsonType
|
|
38
|
+
from omnibase_infra.errors import ProtocolConfigurationError, RuntimeHostError
|
|
39
|
+
from omnibase_infra.models.snapshot import (
|
|
40
|
+
ModelSnapshot,
|
|
41
|
+
ModelSnapshotDiff,
|
|
42
|
+
ModelSubjectRef,
|
|
43
|
+
)
|
|
44
|
+
from omnibase_infra.protocols import ProtocolSnapshotStore
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class SnapshotNotFoundError(RuntimeHostError):
|
|
48
|
+
"""Raised when a requested snapshot does not exist.
|
|
49
|
+
|
|
50
|
+
Used when diff or fork operations reference a snapshot ID that
|
|
51
|
+
cannot be found in the store. This indicates a caller error
|
|
52
|
+
(invalid ID) rather than an infrastructure failure.
|
|
53
|
+
|
|
54
|
+
Example:
|
|
55
|
+
>>> raise SnapshotNotFoundError(
|
|
56
|
+
... "Base snapshot not found",
|
|
57
|
+
... snapshot_id=base_id,
|
|
58
|
+
... )
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
def __init__(
|
|
62
|
+
self,
|
|
63
|
+
message: str,
|
|
64
|
+
snapshot_id: UUID | None = None,
|
|
65
|
+
**extra_context: object,
|
|
66
|
+
) -> None:
|
|
67
|
+
"""Initialize SnapshotNotFoundError.
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
message: Human-readable error message
|
|
71
|
+
snapshot_id: The UUID of the snapshot that was not found
|
|
72
|
+
**extra_context: Additional context information
|
|
73
|
+
"""
|
|
74
|
+
if snapshot_id is not None:
|
|
75
|
+
extra_context["snapshot_id"] = str(snapshot_id)
|
|
76
|
+
super().__init__(
|
|
77
|
+
message=message,
|
|
78
|
+
error_code=EnumCoreErrorCode.RESOURCE_NOT_FOUND,
|
|
79
|
+
context=None,
|
|
80
|
+
**extra_context,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class ServiceSnapshot:
|
|
85
|
+
"""Generic snapshot service with injectable persistence backend.
|
|
86
|
+
|
|
87
|
+
Provides a high-level interface for snapshot management, including
|
|
88
|
+
creation, retrieval, diffing, and fork operations. Uses a protocol-
|
|
89
|
+
based store for persistence, allowing different backends (PostgreSQL,
|
|
90
|
+
in-memory, etc.) to be injected.
|
|
91
|
+
|
|
92
|
+
Concurrency:
|
|
93
|
+
Uses asyncio.Lock for sequence number generation to prevent
|
|
94
|
+
duplicate sequence numbers within a single process. For
|
|
95
|
+
distributed deployments, the store must provide atomic
|
|
96
|
+
sequence generation.
|
|
97
|
+
|
|
98
|
+
Attributes:
|
|
99
|
+
_store: The persistence backend implementing ProtocolSnapshotStore.
|
|
100
|
+
_container: ONEX container for dependency injection.
|
|
101
|
+
_lock: Asyncio lock for coroutine-safe sequence generation.
|
|
102
|
+
|
|
103
|
+
Example:
|
|
104
|
+
>>> from omnibase_core.container import ModelONEXContainer
|
|
105
|
+
>>> from omnibase_infra.services.snapshot import ServiceSnapshot
|
|
106
|
+
>>> from omnibase_infra.services.snapshot import StoreSnapshotInMemory
|
|
107
|
+
>>> from omnibase_infra.models.snapshot import ModelSubjectRef
|
|
108
|
+
>>>
|
|
109
|
+
>>> # Create service with in-memory store (for testing)
|
|
110
|
+
>>> store = StoreSnapshotInMemory()
|
|
111
|
+
>>> container = ModelONEXContainer()
|
|
112
|
+
>>> service = ServiceSnapshot(store=store, container=container)
|
|
113
|
+
>>>
|
|
114
|
+
>>> # Create a snapshot
|
|
115
|
+
>>> subject = ModelSubjectRef(
|
|
116
|
+
... subject_type="agent",
|
|
117
|
+
... subject_id="agent-001",
|
|
118
|
+
... )
|
|
119
|
+
>>> snapshot_id = await service.create(
|
|
120
|
+
... subject=subject,
|
|
121
|
+
... data={"status": "active", "config": {"timeout": 30}},
|
|
122
|
+
... )
|
|
123
|
+
>>>
|
|
124
|
+
>>> # Retrieve latest snapshot
|
|
125
|
+
>>> latest = await service.get_latest(subject=subject)
|
|
126
|
+
>>> latest.data["status"]
|
|
127
|
+
'active'
|
|
128
|
+
"""
|
|
129
|
+
|
|
130
|
+
def __init__(
|
|
131
|
+
self,
|
|
132
|
+
store: ProtocolSnapshotStore,
|
|
133
|
+
container: ModelONEXContainer,
|
|
134
|
+
) -> None:
|
|
135
|
+
"""Initialize the snapshot service.
|
|
136
|
+
|
|
137
|
+
Args:
|
|
138
|
+
store: Persistence backend implementing ProtocolSnapshotStore.
|
|
139
|
+
container: ONEX container for dependency injection.
|
|
140
|
+
"""
|
|
141
|
+
self._store = store
|
|
142
|
+
self._container = container
|
|
143
|
+
self._lock = asyncio.Lock()
|
|
144
|
+
|
|
145
|
+
async def create(
|
|
146
|
+
self,
|
|
147
|
+
subject: ModelSubjectRef,
|
|
148
|
+
data: dict[str, JsonType],
|
|
149
|
+
*,
|
|
150
|
+
parent_id: UUID | None = None,
|
|
151
|
+
) -> UUID:
|
|
152
|
+
"""Create and persist a new snapshot.
|
|
153
|
+
|
|
154
|
+
Creates a snapshot with automatic sequence number assignment and
|
|
155
|
+
content hashing. The sequence number is generated atomically
|
|
156
|
+
using the store's get_next_sequence_number method.
|
|
157
|
+
|
|
158
|
+
Args:
|
|
159
|
+
subject: Reference identifying the entity being snapshotted.
|
|
160
|
+
data: The snapshot payload as a JSON-compatible dictionary.
|
|
161
|
+
parent_id: Optional parent snapshot ID for lineage tracking.
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
The UUID of the created snapshot.
|
|
165
|
+
|
|
166
|
+
Raises:
|
|
167
|
+
InfraConnectionError: If the store is unavailable.
|
|
168
|
+
InfraTimeoutError: If the operation times out.
|
|
169
|
+
|
|
170
|
+
Example:
|
|
171
|
+
>>> subject = ModelSubjectRef(
|
|
172
|
+
... subject_type="workflow",
|
|
173
|
+
... subject_id="wf-123",
|
|
174
|
+
... )
|
|
175
|
+
>>> snapshot_id = await service.create(
|
|
176
|
+
... subject=subject,
|
|
177
|
+
... data={"state": "running", "step": 5},
|
|
178
|
+
... )
|
|
179
|
+
"""
|
|
180
|
+
async with self._lock:
|
|
181
|
+
sequence_number = await self._store.get_next_sequence_number(subject)
|
|
182
|
+
|
|
183
|
+
content_hash = ModelSnapshot.compute_content_hash(data)
|
|
184
|
+
|
|
185
|
+
snapshot = ModelSnapshot(
|
|
186
|
+
subject=subject,
|
|
187
|
+
data=data,
|
|
188
|
+
sequence_number=sequence_number,
|
|
189
|
+
content_hash=content_hash,
|
|
190
|
+
parent_id=parent_id,
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
return await self._store.save(snapshot)
|
|
194
|
+
|
|
195
|
+
async def get(self, snapshot_id: UUID) -> ModelSnapshot | None:
|
|
196
|
+
"""Retrieve a snapshot by ID.
|
|
197
|
+
|
|
198
|
+
Args:
|
|
199
|
+
snapshot_id: The unique identifier of the snapshot.
|
|
200
|
+
|
|
201
|
+
Returns:
|
|
202
|
+
The snapshot if found, None otherwise.
|
|
203
|
+
|
|
204
|
+
Raises:
|
|
205
|
+
InfraConnectionError: If the store is unavailable.
|
|
206
|
+
InfraTimeoutError: If the operation times out.
|
|
207
|
+
|
|
208
|
+
Example:
|
|
209
|
+
>>> snapshot = await service.get(snapshot_id)
|
|
210
|
+
>>> if snapshot:
|
|
211
|
+
... print(f"Found: {snapshot.data}")
|
|
212
|
+
"""
|
|
213
|
+
return await self._store.load(snapshot_id)
|
|
214
|
+
|
|
215
|
+
async def get_latest(
|
|
216
|
+
self,
|
|
217
|
+
subject: ModelSubjectRef | None = None,
|
|
218
|
+
) -> ModelSnapshot | None:
|
|
219
|
+
"""Get the most recent snapshot by sequence_number.
|
|
220
|
+
|
|
221
|
+
Retrieves the snapshot with the highest sequence number,
|
|
222
|
+
optionally filtered by subject. Note: ordering is by
|
|
223
|
+
sequence_number, not created_at timestamp.
|
|
224
|
+
|
|
225
|
+
Args:
|
|
226
|
+
subject: Optional filter by subject reference.
|
|
227
|
+
|
|
228
|
+
- If provided: Returns the latest snapshot for that specific
|
|
229
|
+
subject (highest sequence_number within that subject).
|
|
230
|
+
- If None: Returns the globally latest snapshot across ALL
|
|
231
|
+
subjects (highest sequence_number in the entire store).
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
The most recent snapshot matching criteria, or None if no
|
|
235
|
+
snapshots exist.
|
|
236
|
+
|
|
237
|
+
Raises:
|
|
238
|
+
InfraConnectionError: If the store is unavailable.
|
|
239
|
+
InfraTimeoutError: If the operation times out.
|
|
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 ``list(after=timestamp)`` if you need time-based
|
|
247
|
+
ordering across subjects.
|
|
248
|
+
|
|
249
|
+
Examples:
|
|
250
|
+
>>> # Get latest for a specific subject
|
|
251
|
+
>>> subject = ModelSubjectRef(
|
|
252
|
+
... subject_type="node",
|
|
253
|
+
... subject_id="node-xyz",
|
|
254
|
+
... )
|
|
255
|
+
>>> latest = await service.get_latest(subject=subject)
|
|
256
|
+
>>> if latest:
|
|
257
|
+
... print(f"Sequence: {latest.sequence_number}")
|
|
258
|
+
|
|
259
|
+
>>> # Get globally latest across ALL subjects
|
|
260
|
+
>>> global_latest = await service.get_latest(subject=None)
|
|
261
|
+
>>> # Returns snapshot with highest sequence_number in store
|
|
262
|
+
>>> # Note: This is NOT necessarily the most recent by created_at
|
|
263
|
+
|
|
264
|
+
>>> # Alternative: Get most recent by wall-clock time
|
|
265
|
+
>>> from datetime import datetime, timedelta, UTC
|
|
266
|
+
>>> one_second_ago = datetime.now(UTC) - timedelta(seconds=1)
|
|
267
|
+
>>> recent = await service.list(after=one_second_ago, limit=1)
|
|
268
|
+
>>> time_based_latest = recent[0] if recent else None
|
|
269
|
+
"""
|
|
270
|
+
return await self._store.load_latest(subject)
|
|
271
|
+
|
|
272
|
+
async def list(
|
|
273
|
+
self,
|
|
274
|
+
subject: ModelSubjectRef | None = None,
|
|
275
|
+
limit: int = 50,
|
|
276
|
+
after: datetime | None = None,
|
|
277
|
+
) -> list[ModelSnapshot]:
|
|
278
|
+
"""List snapshots with optional filtering and pagination.
|
|
279
|
+
|
|
280
|
+
Returns snapshots ordered by sequence_number descending
|
|
281
|
+
(most recent first).
|
|
282
|
+
|
|
283
|
+
Args:
|
|
284
|
+
subject: Optional filter by subject reference.
|
|
285
|
+
limit: Maximum number of snapshots to return (default 50).
|
|
286
|
+
after: Only return snapshots created after this time.
|
|
287
|
+
|
|
288
|
+
Returns:
|
|
289
|
+
List of snapshots ordered by sequence_number descending.
|
|
290
|
+
Empty list if no snapshots match criteria.
|
|
291
|
+
|
|
292
|
+
Raises:
|
|
293
|
+
InfraConnectionError: If the store is unavailable.
|
|
294
|
+
InfraTimeoutError: If the operation times out.
|
|
295
|
+
|
|
296
|
+
Example:
|
|
297
|
+
>>> from datetime import datetime, timedelta, UTC
|
|
298
|
+
>>> one_hour_ago = datetime.now(UTC) - timedelta(hours=1)
|
|
299
|
+
>>> recent = await service.list(limit=10, after=one_hour_ago)
|
|
300
|
+
>>> for snap in recent:
|
|
301
|
+
... print(f"{snap.id}: seq={snap.sequence_number}")
|
|
302
|
+
"""
|
|
303
|
+
return await self._store.query(subject=subject, limit=limit, after=after)
|
|
304
|
+
|
|
305
|
+
async def get_many(
|
|
306
|
+
self,
|
|
307
|
+
snapshot_ids: builtins.list[UUID],
|
|
308
|
+
*,
|
|
309
|
+
skip_missing: bool = False,
|
|
310
|
+
) -> builtins.list[ModelSnapshot]:
|
|
311
|
+
"""Load multiple snapshots in a single batch query.
|
|
312
|
+
|
|
313
|
+
Uses batch loading for efficient multi-row fetch, avoiding N+1
|
|
314
|
+
query patterns when loading multiple snapshots.
|
|
315
|
+
|
|
316
|
+
Args:
|
|
317
|
+
snapshot_ids: List of snapshot UUIDs to load.
|
|
318
|
+
skip_missing: If True, missing snapshots are silently skipped.
|
|
319
|
+
If False (default), raises SnapshotNotFoundError for any
|
|
320
|
+
missing snapshot.
|
|
321
|
+
|
|
322
|
+
Returns:
|
|
323
|
+
List of snapshots in the same order as snapshot_ids (when
|
|
324
|
+
skip_missing=False). When skip_missing=True, the returned
|
|
325
|
+
list may be shorter and only contains found snapshots.
|
|
326
|
+
|
|
327
|
+
Raises:
|
|
328
|
+
SnapshotNotFoundError: If any snapshot is not found and
|
|
329
|
+
skip_missing is False.
|
|
330
|
+
InfraConnectionError: If the store is unavailable.
|
|
331
|
+
InfraTimeoutError: If the operation times out.
|
|
332
|
+
|
|
333
|
+
Example:
|
|
334
|
+
>>> # Load multiple snapshots at once
|
|
335
|
+
>>> snapshots = await service.get_many([id1, id2, id3])
|
|
336
|
+
>>> assert len(snapshots) == 3
|
|
337
|
+
>>>
|
|
338
|
+
>>> # Skip missing snapshots
|
|
339
|
+
>>> snapshots = await service.get_many(
|
|
340
|
+
... [id1, unknown_id, id3],
|
|
341
|
+
... skip_missing=True,
|
|
342
|
+
... )
|
|
343
|
+
>>> # Returns only found snapshots
|
|
344
|
+
"""
|
|
345
|
+
if not snapshot_ids:
|
|
346
|
+
return []
|
|
347
|
+
|
|
348
|
+
# Use batch load for single database round-trip
|
|
349
|
+
results_dict = await self._store.load_many(snapshot_ids)
|
|
350
|
+
|
|
351
|
+
snapshots: builtins.list[ModelSnapshot] = []
|
|
352
|
+
for snapshot_id in snapshot_ids:
|
|
353
|
+
snapshot = results_dict.get(snapshot_id)
|
|
354
|
+
if snapshot is None:
|
|
355
|
+
if not skip_missing:
|
|
356
|
+
raise SnapshotNotFoundError(
|
|
357
|
+
f"Snapshot not found: {snapshot_id}",
|
|
358
|
+
snapshot_id=snapshot_id,
|
|
359
|
+
)
|
|
360
|
+
# skip_missing=True: silently skip
|
|
361
|
+
continue
|
|
362
|
+
|
|
363
|
+
snapshots.append(snapshot)
|
|
364
|
+
|
|
365
|
+
return snapshots
|
|
366
|
+
|
|
367
|
+
async def get_latest_many(
|
|
368
|
+
self,
|
|
369
|
+
subjects: builtins.list[ModelSubjectRef],
|
|
370
|
+
) -> builtins.list[ModelSnapshot | None]:
|
|
371
|
+
"""Load the latest snapshot for multiple subjects in a single batch query.
|
|
372
|
+
|
|
373
|
+
Uses batch loading for efficient multi-row fetch, avoiding N+1
|
|
374
|
+
query patterns when querying multiple subjects.
|
|
375
|
+
|
|
376
|
+
Args:
|
|
377
|
+
subjects: List of subject references to load latest snapshots for.
|
|
378
|
+
|
|
379
|
+
Returns:
|
|
380
|
+
List of snapshots (or None) in the same order as the input
|
|
381
|
+
subjects. Each entry is the latest snapshot for that subject,
|
|
382
|
+
or None if no snapshots exist for that subject.
|
|
383
|
+
|
|
384
|
+
Raises:
|
|
385
|
+
InfraConnectionError: If the store is unavailable.
|
|
386
|
+
InfraTimeoutError: If the operation times out.
|
|
387
|
+
|
|
388
|
+
Example:
|
|
389
|
+
>>> subjects = [
|
|
390
|
+
... ModelSubjectRef(subject_type="agent", subject_id=agent_id),
|
|
391
|
+
... ModelSubjectRef(subject_type="workflow", subject_id=workflow_id),
|
|
392
|
+
... ]
|
|
393
|
+
>>> snapshots = await service.get_latest_many(subjects)
|
|
394
|
+
>>> for subject, snapshot in zip(subjects, snapshots):
|
|
395
|
+
... if snapshot:
|
|
396
|
+
... print(f"{subject.subject_id}: seq={snapshot.sequence_number}")
|
|
397
|
+
"""
|
|
398
|
+
if not subjects:
|
|
399
|
+
return []
|
|
400
|
+
|
|
401
|
+
# Use batch load for single database round-trip
|
|
402
|
+
results_dict = await self._store.load_latest_many(subjects)
|
|
403
|
+
|
|
404
|
+
# Build result list maintaining input order
|
|
405
|
+
snapshots: builtins.list[ModelSnapshot | None] = []
|
|
406
|
+
for subject in subjects:
|
|
407
|
+
key = (subject.subject_type, subject.subject_id)
|
|
408
|
+
snapshots.append(results_dict.get(key))
|
|
409
|
+
|
|
410
|
+
return snapshots
|
|
411
|
+
|
|
412
|
+
async def diff(
|
|
413
|
+
self,
|
|
414
|
+
base_id: UUID,
|
|
415
|
+
target_id: UUID,
|
|
416
|
+
) -> ModelSnapshotDiff:
|
|
417
|
+
"""Compute structural diff between two snapshots.
|
|
418
|
+
|
|
419
|
+
Performs a shallow structural comparison between the base and
|
|
420
|
+
target snapshots, identifying keys that were added, removed,
|
|
421
|
+
or changed.
|
|
422
|
+
|
|
423
|
+
Both snapshots are loaded in parallel for better performance.
|
|
424
|
+
|
|
425
|
+
Args:
|
|
426
|
+
base_id: UUID of the base (original) snapshot.
|
|
427
|
+
target_id: UUID of the target (new) snapshot.
|
|
428
|
+
|
|
429
|
+
Returns:
|
|
430
|
+
A ModelSnapshotDiff describing the structural differences.
|
|
431
|
+
|
|
432
|
+
Raises:
|
|
433
|
+
SnapshotNotFoundError: If either snapshot is not found.
|
|
434
|
+
InfraConnectionError: If the store is unavailable.
|
|
435
|
+
InfraTimeoutError: If the operation times out.
|
|
436
|
+
|
|
437
|
+
Example:
|
|
438
|
+
>>> diff = await service.diff(base_id=snap1_id, target_id=snap2_id)
|
|
439
|
+
>>> print(f"Added: {diff.added}")
|
|
440
|
+
>>> print(f"Removed: {diff.removed}")
|
|
441
|
+
>>> for key, change in diff.changed.items():
|
|
442
|
+
... print(f"{key}: {change.from_value} -> {change.to_value}")
|
|
443
|
+
"""
|
|
444
|
+
# Load both snapshots in parallel for better performance
|
|
445
|
+
base_task = self._store.load(base_id)
|
|
446
|
+
target_task = self._store.load(target_id)
|
|
447
|
+
base, target = await asyncio.gather(base_task, target_task)
|
|
448
|
+
|
|
449
|
+
if base is None:
|
|
450
|
+
raise SnapshotNotFoundError(
|
|
451
|
+
f"Base snapshot not found: {base_id}",
|
|
452
|
+
snapshot_id=base_id,
|
|
453
|
+
)
|
|
454
|
+
if target is None:
|
|
455
|
+
raise SnapshotNotFoundError(
|
|
456
|
+
f"Target snapshot not found: {target_id}",
|
|
457
|
+
snapshot_id=target_id,
|
|
458
|
+
)
|
|
459
|
+
|
|
460
|
+
return ModelSnapshotDiff.compute(
|
|
461
|
+
base_data=base.data,
|
|
462
|
+
target_data=target.data,
|
|
463
|
+
base_id=base_id,
|
|
464
|
+
target_id=target_id,
|
|
465
|
+
)
|
|
466
|
+
|
|
467
|
+
async def fork(
|
|
468
|
+
self,
|
|
469
|
+
snapshot_id: UUID,
|
|
470
|
+
mutations: dict[str, JsonType] | None = None,
|
|
471
|
+
) -> ModelSnapshot:
|
|
472
|
+
"""Create a new snapshot from an existing one, with mutations.
|
|
473
|
+
|
|
474
|
+
Forks the source snapshot by applying mutations to its data
|
|
475
|
+
and creating a new snapshot with:
|
|
476
|
+
- A new UUID
|
|
477
|
+
- A new sequence number
|
|
478
|
+
- parent_id set to the source snapshot ID
|
|
479
|
+
- Merged data (source data + mutations)
|
|
480
|
+
|
|
481
|
+
Args:
|
|
482
|
+
snapshot_id: UUID of the source snapshot to fork.
|
|
483
|
+
mutations: Optional dictionary of changes to apply to the
|
|
484
|
+
source data. If None, creates an exact copy.
|
|
485
|
+
|
|
486
|
+
Returns:
|
|
487
|
+
The newly created fork snapshot.
|
|
488
|
+
|
|
489
|
+
Raises:
|
|
490
|
+
SnapshotNotFoundError: If the source snapshot is not found.
|
|
491
|
+
InfraConnectionError: If the store is unavailable.
|
|
492
|
+
InfraTimeoutError: If the operation times out.
|
|
493
|
+
|
|
494
|
+
Example:
|
|
495
|
+
>>> forked = await service.fork(
|
|
496
|
+
... snapshot_id=original_id,
|
|
497
|
+
... mutations={"status": "paused", "reason": "maintenance"},
|
|
498
|
+
... )
|
|
499
|
+
>>> forked.parent_id == original_id
|
|
500
|
+
True
|
|
501
|
+
>>> forked.data["status"]
|
|
502
|
+
'paused'
|
|
503
|
+
"""
|
|
504
|
+
source = await self._store.load(snapshot_id)
|
|
505
|
+
if source is None:
|
|
506
|
+
raise SnapshotNotFoundError(
|
|
507
|
+
f"Source snapshot not found: {snapshot_id}",
|
|
508
|
+
snapshot_id=snapshot_id,
|
|
509
|
+
)
|
|
510
|
+
|
|
511
|
+
# Get next sequence number for the subject
|
|
512
|
+
async with self._lock:
|
|
513
|
+
sequence_number = await self._store.get_next_sequence_number(source.subject)
|
|
514
|
+
|
|
515
|
+
# Create forked snapshot with mutations applied
|
|
516
|
+
forked = source.with_mutations(
|
|
517
|
+
mutations=mutations or {},
|
|
518
|
+
sequence_number=sequence_number,
|
|
519
|
+
)
|
|
520
|
+
|
|
521
|
+
await self._store.save(forked)
|
|
522
|
+
return forked
|
|
523
|
+
|
|
524
|
+
async def delete(self, snapshot_id: UUID) -> bool:
|
|
525
|
+
"""Delete a snapshot by ID.
|
|
526
|
+
|
|
527
|
+
Args:
|
|
528
|
+
snapshot_id: The unique identifier of the snapshot to delete.
|
|
529
|
+
|
|
530
|
+
Returns:
|
|
531
|
+
True if the snapshot was deleted, False if not found.
|
|
532
|
+
|
|
533
|
+
Raises:
|
|
534
|
+
InfraConnectionError: If the store is unavailable.
|
|
535
|
+
InfraTimeoutError: If the operation times out.
|
|
536
|
+
|
|
537
|
+
Example:
|
|
538
|
+
>>> deleted = await service.delete(old_snapshot_id)
|
|
539
|
+
>>> if deleted:
|
|
540
|
+
... print("Snapshot removed")
|
|
541
|
+
>>> else:
|
|
542
|
+
... print("Snapshot not found")
|
|
543
|
+
"""
|
|
544
|
+
return await self._store.delete(snapshot_id)
|
|
545
|
+
|
|
546
|
+
async def cleanup_expired(
|
|
547
|
+
self,
|
|
548
|
+
*,
|
|
549
|
+
max_age_seconds: int | None = None,
|
|
550
|
+
keep_latest_n: int | None = None,
|
|
551
|
+
subject: ModelSubjectRef | None = None,
|
|
552
|
+
) -> int:
|
|
553
|
+
"""Remove expired snapshots based on retention policy.
|
|
554
|
+
|
|
555
|
+
Provides a high-level interface for snapshot cleanup with multiple
|
|
556
|
+
retention strategies that can be combined:
|
|
557
|
+
|
|
558
|
+
- **Time-based** (max_age_seconds): Delete snapshots older than
|
|
559
|
+
the specified age. Useful for compliance or storage cost control.
|
|
560
|
+
- **Count-based** (keep_latest_n): Retain only the N most recent
|
|
561
|
+
snapshots per subject. Useful for audit trail limits.
|
|
562
|
+
- **Subject-scoped** (subject): Apply cleanup only to a specific
|
|
563
|
+
subject. Useful for per-entity retention policies.
|
|
564
|
+
|
|
565
|
+
When both max_age_seconds and keep_latest_n are provided, snapshots
|
|
566
|
+
must satisfy BOTH conditions to be deleted. This means:
|
|
567
|
+
- Snapshots in the latest N per subject are ALWAYS retained
|
|
568
|
+
- Snapshots outside the latest N are deleted ONLY if also older
|
|
569
|
+
than max_age_seconds
|
|
570
|
+
|
|
571
|
+
This dual-policy approach provides a safety net: even if you
|
|
572
|
+
configure aggressive age-based cleanup, you'll always retain
|
|
573
|
+
recent history for each subject.
|
|
574
|
+
|
|
575
|
+
Args:
|
|
576
|
+
max_age_seconds: Delete snapshots with created_at older than
|
|
577
|
+
this many seconds ago. If None, no age-based filtering.
|
|
578
|
+
keep_latest_n: Always retain the N most recent snapshots per
|
|
579
|
+
subject (by sequence_number). If None, no count-based
|
|
580
|
+
retention. Must be >= 1 if provided.
|
|
581
|
+
subject: If provided, apply cleanup only to this subject.
|
|
582
|
+
If None, apply cleanup globally across all subjects.
|
|
583
|
+
|
|
584
|
+
Returns:
|
|
585
|
+
Number of snapshots deleted.
|
|
586
|
+
|
|
587
|
+
Raises:
|
|
588
|
+
ProtocolConfigurationError: If keep_latest_n is provided but < 1.
|
|
589
|
+
InfraConnectionError: If the store is unavailable.
|
|
590
|
+
InfraTimeoutError: If the operation times out.
|
|
591
|
+
|
|
592
|
+
Example:
|
|
593
|
+
>>> from datetime import timedelta
|
|
594
|
+
>>> from omnibase_infra.models.snapshot import ModelSubjectRef
|
|
595
|
+
>>>
|
|
596
|
+
>>> # Delete snapshots older than 30 days
|
|
597
|
+
>>> deleted = await service.cleanup_expired(
|
|
598
|
+
... max_age_seconds=30 * 24 * 60 * 60,
|
|
599
|
+
... )
|
|
600
|
+
>>> print(f"Deleted {deleted} old snapshots")
|
|
601
|
+
>>>
|
|
602
|
+
>>> # Keep only last 10 snapshots per subject
|
|
603
|
+
>>> deleted = await service.cleanup_expired(
|
|
604
|
+
... keep_latest_n=10,
|
|
605
|
+
... )
|
|
606
|
+
>>> print(f"Trimmed {deleted} excess snapshots")
|
|
607
|
+
>>>
|
|
608
|
+
>>> # Combined: Delete if older than 7 days AND not in latest 5
|
|
609
|
+
>>> deleted = await service.cleanup_expired(
|
|
610
|
+
... max_age_seconds=7 * 24 * 60 * 60,
|
|
611
|
+
... keep_latest_n=5,
|
|
612
|
+
... )
|
|
613
|
+
>>>
|
|
614
|
+
>>> # Cleanup only for a specific subject
|
|
615
|
+
>>> subject = ModelSubjectRef(
|
|
616
|
+
... subject_type="workflow",
|
|
617
|
+
... subject_id=workflow_id,
|
|
618
|
+
... )
|
|
619
|
+
>>> deleted = await service.cleanup_expired(
|
|
620
|
+
... max_age_seconds=60 * 60, # 1 hour
|
|
621
|
+
... subject=subject,
|
|
622
|
+
... )
|
|
623
|
+
|
|
624
|
+
Scheduling Recommendations:
|
|
625
|
+
This method is typically called from a scheduled task or cron job:
|
|
626
|
+
|
|
627
|
+
- **Daily cleanup**: Run once per day with conservative settings
|
|
628
|
+
(e.g., max_age_seconds=30 days, keep_latest_n=100)
|
|
629
|
+
- **Aggressive cleanup**: For high-volume systems, run hourly
|
|
630
|
+
with tighter limits (e.g., max_age_seconds=7 days, keep_latest_n=10)
|
|
631
|
+
- **Per-subject cleanup**: Call during subject lifecycle events
|
|
632
|
+
(e.g., when a workflow completes, clean up its old snapshots)
|
|
633
|
+
|
|
634
|
+
Performance Notes:
|
|
635
|
+
For very large datasets, consider:
|
|
636
|
+
- Running cleanup during low-traffic periods
|
|
637
|
+
- Using subject-scoped cleanup in batches
|
|
638
|
+
- Adding an index on created_at if using time-based cleanup frequently
|
|
639
|
+
"""
|
|
640
|
+
return await self._store.cleanup_expired(
|
|
641
|
+
max_age_seconds=max_age_seconds,
|
|
642
|
+
keep_latest_n=keep_latest_n,
|
|
643
|
+
subject=subject,
|
|
644
|
+
)
|
|
645
|
+
|
|
646
|
+
|
|
647
|
+
__all__: list[str] = ["SnapshotNotFoundError", "ServiceSnapshot"]
|