omnibase_infra 0.2.1__py3-none-any.whl → 0.2.3__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 +1 -1
- omnibase_infra/adapters/adapter_onex_tool_execution.py +451 -0
- omnibase_infra/capabilities/__init__.py +15 -0
- omnibase_infra/capabilities/capability_inference_rules.py +211 -0
- omnibase_infra/capabilities/contract_capability_extractor.py +221 -0
- omnibase_infra/capabilities/intent_type_extractor.py +160 -0
- omnibase_infra/cli/commands.py +1 -1
- omnibase_infra/configs/widget_mapping.yaml +176 -0
- omnibase_infra/contracts/handlers/filesystem/handler_contract.yaml +5 -2
- omnibase_infra/contracts/handlers/mcp/handler_contract.yaml +5 -2
- omnibase_infra/enums/__init__.py +6 -0
- omnibase_infra/enums/enum_handler_error_type.py +10 -0
- omnibase_infra/enums/enum_handler_source_mode.py +72 -0
- omnibase_infra/enums/enum_kafka_acks.py +99 -0
- omnibase_infra/errors/error_compute_registry.py +4 -1
- omnibase_infra/errors/error_event_bus_registry.py +4 -1
- omnibase_infra/errors/error_infra.py +3 -1
- omnibase_infra/errors/error_policy_registry.py +4 -1
- omnibase_infra/event_bus/event_bus_kafka.py +1 -1
- omnibase_infra/event_bus/models/config/model_kafka_event_bus_config.py +59 -10
- omnibase_infra/handlers/__init__.py +8 -1
- omnibase_infra/handlers/handler_consul.py +7 -1
- omnibase_infra/handlers/handler_db.py +10 -3
- omnibase_infra/handlers/handler_graph.py +10 -5
- omnibase_infra/handlers/handler_http.py +8 -2
- omnibase_infra/handlers/handler_intent.py +387 -0
- omnibase_infra/handlers/handler_mcp.py +745 -63
- omnibase_infra/handlers/handler_vault.py +11 -5
- omnibase_infra/handlers/mixins/mixin_consul_kv.py +4 -3
- omnibase_infra/handlers/mixins/mixin_consul_service.py +2 -1
- omnibase_infra/handlers/registration_storage/handler_registration_storage_postgres.py +7 -0
- omnibase_infra/handlers/service_discovery/handler_service_discovery_consul.py +308 -4
- omnibase_infra/handlers/service_discovery/models/model_service_info.py +10 -0
- omnibase_infra/mixins/mixin_async_circuit_breaker.py +3 -2
- omnibase_infra/mixins/mixin_node_introspection.py +42 -7
- omnibase_infra/mixins/mixin_retry_execution.py +1 -1
- omnibase_infra/models/discovery/model_introspection_config.py +11 -0
- omnibase_infra/models/handlers/__init__.py +48 -5
- omnibase_infra/models/handlers/model_bootstrap_handler_descriptor.py +162 -0
- omnibase_infra/models/handlers/model_contract_discovery_result.py +6 -4
- omnibase_infra/models/handlers/model_handler_descriptor.py +15 -0
- omnibase_infra/models/handlers/model_handler_source_config.py +220 -0
- omnibase_infra/models/mcp/__init__.py +15 -0
- omnibase_infra/models/mcp/model_mcp_contract_config.py +80 -0
- omnibase_infra/models/mcp/model_mcp_server_config.py +67 -0
- omnibase_infra/models/mcp/model_mcp_tool_definition.py +73 -0
- omnibase_infra/models/mcp/model_mcp_tool_parameter.py +35 -0
- omnibase_infra/models/registration/model_node_capabilities.py +11 -0
- omnibase_infra/models/registration/model_node_introspection_event.py +9 -0
- omnibase_infra/models/runtime/model_handler_contract.py +25 -9
- omnibase_infra/models/runtime/model_loaded_handler.py +9 -0
- omnibase_infra/nodes/architecture_validator/contract_architecture_validator.yaml +0 -5
- omnibase_infra/nodes/architecture_validator/registry/registry_infra_architecture_validator.py +17 -10
- omnibase_infra/nodes/effects/contract.yaml +0 -5
- omnibase_infra/nodes/node_registration_orchestrator/contract.yaml +7 -0
- omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_introspected.py +86 -1
- omnibase_infra/nodes/node_registration_orchestrator/introspection_event_router.py +3 -3
- omnibase_infra/nodes/node_registration_orchestrator/plugin.py +1 -1
- omnibase_infra/nodes/node_registration_orchestrator/registry/registry_infra_node_registration_orchestrator.py +9 -8
- omnibase_infra/nodes/node_registration_orchestrator/timeout_coordinator.py +4 -3
- omnibase_infra/nodes/node_registration_orchestrator/wiring.py +14 -13
- omnibase_infra/nodes/node_registration_storage_effect/contract.yaml +0 -5
- omnibase_infra/nodes/node_registration_storage_effect/node.py +4 -1
- omnibase_infra/nodes/node_registration_storage_effect/registry/registry_infra_registration_storage.py +47 -26
- omnibase_infra/nodes/node_registry_effect/contract.yaml +0 -5
- omnibase_infra/nodes/node_registry_effect/handlers/handler_partial_retry.py +2 -1
- omnibase_infra/nodes/node_service_discovery_effect/registry/registry_infra_service_discovery.py +28 -20
- omnibase_infra/plugins/examples/plugin_json_normalizer.py +2 -2
- omnibase_infra/plugins/examples/plugin_json_normalizer_error_handling.py +2 -2
- omnibase_infra/plugins/plugin_compute_base.py +16 -2
- omnibase_infra/protocols/__init__.py +2 -0
- omnibase_infra/protocols/protocol_container_aware.py +200 -0
- omnibase_infra/protocols/protocol_event_projector.py +1 -1
- omnibase_infra/runtime/__init__.py +90 -1
- omnibase_infra/runtime/binding_config_resolver.py +102 -37
- omnibase_infra/runtime/constants_notification.py +75 -0
- omnibase_infra/runtime/contract_handler_discovery.py +6 -1
- omnibase_infra/runtime/handler_bootstrap_source.py +507 -0
- omnibase_infra/runtime/handler_contract_config_loader.py +603 -0
- omnibase_infra/runtime/handler_contract_source.py +267 -186
- omnibase_infra/runtime/handler_identity.py +81 -0
- omnibase_infra/runtime/handler_plugin_loader.py +19 -2
- omnibase_infra/runtime/handler_registry.py +11 -3
- omnibase_infra/runtime/handler_source_resolver.py +326 -0
- omnibase_infra/runtime/mixin_semver_cache.py +25 -1
- omnibase_infra/runtime/mixins/__init__.py +7 -0
- omnibase_infra/runtime/mixins/mixin_projector_notification_publishing.py +566 -0
- omnibase_infra/runtime/mixins/mixin_projector_sql_operations.py +31 -10
- omnibase_infra/runtime/models/__init__.py +24 -0
- omnibase_infra/runtime/models/model_health_check_result.py +2 -1
- omnibase_infra/runtime/models/model_projector_notification_config.py +171 -0
- omnibase_infra/runtime/models/model_transition_notification_outbox_config.py +112 -0
- omnibase_infra/runtime/models/model_transition_notification_outbox_metrics.py +140 -0
- omnibase_infra/runtime/models/model_transition_notification_publisher_metrics.py +357 -0
- omnibase_infra/runtime/projector_plugin_loader.py +1 -1
- omnibase_infra/runtime/projector_shell.py +229 -1
- omnibase_infra/runtime/protocol_lifecycle_executor.py +6 -6
- omnibase_infra/runtime/protocols/__init__.py +10 -0
- omnibase_infra/runtime/registry/registry_protocol_binding.py +16 -15
- omnibase_infra/runtime/registry_contract_source.py +693 -0
- omnibase_infra/runtime/registry_policy.py +9 -326
- omnibase_infra/runtime/secret_resolver.py +4 -2
- omnibase_infra/runtime/service_kernel.py +11 -3
- omnibase_infra/runtime/service_message_dispatch_engine.py +4 -2
- omnibase_infra/runtime/service_runtime_host_process.py +589 -106
- omnibase_infra/runtime/transition_notification_outbox.py +1190 -0
- omnibase_infra/runtime/transition_notification_publisher.py +764 -0
- omnibase_infra/runtime/util_container_wiring.py +6 -5
- omnibase_infra/runtime/util_wiring.py +17 -4
- omnibase_infra/schemas/schema_transition_notification_outbox.sql +245 -0
- omnibase_infra/services/__init__.py +21 -0
- omnibase_infra/services/corpus_capture.py +7 -1
- omnibase_infra/services/mcp/__init__.py +31 -0
- omnibase_infra/services/mcp/mcp_server_lifecycle.py +449 -0
- omnibase_infra/services/mcp/service_mcp_tool_discovery.py +411 -0
- omnibase_infra/services/mcp/service_mcp_tool_registry.py +329 -0
- omnibase_infra/services/mcp/service_mcp_tool_sync.py +547 -0
- omnibase_infra/services/registry_api/__init__.py +40 -0
- omnibase_infra/services/registry_api/main.py +261 -0
- omnibase_infra/services/registry_api/models/__init__.py +66 -0
- omnibase_infra/services/registry_api/models/model_capability_widget_mapping.py +38 -0
- omnibase_infra/services/registry_api/models/model_pagination_info.py +48 -0
- omnibase_infra/services/registry_api/models/model_registry_discovery_response.py +73 -0
- omnibase_infra/services/registry_api/models/model_registry_health_response.py +49 -0
- omnibase_infra/services/registry_api/models/model_registry_instance_view.py +88 -0
- omnibase_infra/services/registry_api/models/model_registry_node_view.py +88 -0
- omnibase_infra/services/registry_api/models/model_registry_summary.py +60 -0
- omnibase_infra/services/registry_api/models/model_response_list_instances.py +43 -0
- omnibase_infra/services/registry_api/models/model_response_list_nodes.py +51 -0
- omnibase_infra/services/registry_api/models/model_warning.py +49 -0
- omnibase_infra/services/registry_api/models/model_widget_defaults.py +28 -0
- omnibase_infra/services/registry_api/models/model_widget_mapping.py +51 -0
- omnibase_infra/services/registry_api/routes.py +371 -0
- omnibase_infra/services/registry_api/service.py +837 -0
- omnibase_infra/services/service_capability_query.py +4 -4
- omnibase_infra/services/service_health.py +3 -2
- omnibase_infra/services/service_timeout_emitter.py +20 -3
- omnibase_infra/services/service_timeout_scanner.py +7 -3
- omnibase_infra/services/session/__init__.py +56 -0
- omnibase_infra/services/session/config_consumer.py +120 -0
- omnibase_infra/services/session/config_store.py +139 -0
- omnibase_infra/services/session/consumer.py +1007 -0
- omnibase_infra/services/session/protocol_session_aggregator.py +117 -0
- omnibase_infra/services/session/store.py +997 -0
- omnibase_infra/utils/__init__.py +19 -0
- omnibase_infra/utils/util_atomic_file.py +261 -0
- omnibase_infra/utils/util_db_transaction.py +239 -0
- omnibase_infra/utils/util_dsn_validation.py +1 -1
- omnibase_infra/utils/util_retry_optimistic.py +281 -0
- omnibase_infra/validation/__init__.py +3 -19
- omnibase_infra/validation/contracts/security.validation.yaml +114 -0
- omnibase_infra/validation/infra_validators.py +35 -24
- omnibase_infra/validation/validation_exemptions.yaml +140 -9
- omnibase_infra/validation/validator_chain_propagation.py +2 -2
- omnibase_infra/validation/validator_runtime_shape.py +1 -1
- omnibase_infra/validation/validator_security.py +473 -370
- {omnibase_infra-0.2.1.dist-info → omnibase_infra-0.2.3.dist-info}/METADATA +3 -3
- {omnibase_infra-0.2.1.dist-info → omnibase_infra-0.2.3.dist-info}/RECORD +161 -98
- {omnibase_infra-0.2.1.dist-info → omnibase_infra-0.2.3.dist-info}/WHEEL +0 -0
- {omnibase_infra-0.2.1.dist-info → omnibase_infra-0.2.3.dist-info}/entry_points.txt +0 -0
- {omnibase_infra-0.2.1.dist-info → omnibase_infra-0.2.3.dist-info}/licenses/LICENSE +0 -0
|
@@ -80,15 +80,12 @@ Integration Points:
|
|
|
80
80
|
|
|
81
81
|
from __future__ import annotations
|
|
82
82
|
|
|
83
|
-
import functools
|
|
84
83
|
import threading
|
|
85
84
|
import warnings
|
|
86
|
-
from collections.abc import Callable
|
|
87
85
|
from typing import TYPE_CHECKING
|
|
88
86
|
|
|
89
87
|
from pydantic import ValidationError
|
|
90
88
|
|
|
91
|
-
from omnibase_core.errors import ModelOnexError
|
|
92
89
|
from omnibase_core.models.primitives import ModelSemVer
|
|
93
90
|
from omnibase_infra.enums import EnumInfraTransportType, EnumPolicyType
|
|
94
91
|
from omnibase_infra.errors import PolicyRegistryError, ProtocolConfigurationError
|
|
@@ -892,330 +889,16 @@ class RegistryPolicy(MixinPolicyValidation, MixinSemverCache):
|
|
|
892
889
|
return matches[0][1]
|
|
893
890
|
|
|
894
891
|
# ==========================================================================
|
|
895
|
-
# Semver
|
|
892
|
+
# Semver Methods (inherited from MixinSemverCache)
|
|
896
893
|
# ==========================================================================
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
When to Increase Cache Size:
|
|
907
|
-
- Very large deployments with > 100 unique policy versions
|
|
908
|
-
- High-frequency lookups across many version combinations
|
|
909
|
-
- Observed cache eviction causing performance regression
|
|
910
|
-
|
|
911
|
-
Args:
|
|
912
|
-
maxsize: Maximum cache entries (default: 128).
|
|
913
|
-
Recommended range: 64-512 for most deployments.
|
|
914
|
-
Each entry uses ~100 bytes.
|
|
915
|
-
|
|
916
|
-
Raises:
|
|
917
|
-
ProtocolConfigurationError: If cache already initialized (first parse already occurred)
|
|
918
|
-
|
|
919
|
-
Example:
|
|
920
|
-
>>> # Configure before any registry operations
|
|
921
|
-
>>> RegistryPolicy.configure_semver_cache(maxsize=256)
|
|
922
|
-
>>> registry = RegistryPolicy()
|
|
923
|
-
|
|
924
|
-
Note:
|
|
925
|
-
For testing purposes, use _reset_semver_cache() to clear the cache
|
|
926
|
-
and allow reconfiguration.
|
|
927
|
-
"""
|
|
928
|
-
with cls._semver_cache_lock:
|
|
929
|
-
if cls._semver_cache is not None:
|
|
930
|
-
context = ModelInfraErrorContext.with_correlation(
|
|
931
|
-
transport_type=EnumInfraTransportType.RUNTIME,
|
|
932
|
-
operation="configure_semver_cache",
|
|
933
|
-
)
|
|
934
|
-
raise ProtocolConfigurationError(
|
|
935
|
-
"Cannot reconfigure semver cache after first use. "
|
|
936
|
-
"Set RegistryPolicy.SEMVER_CACHE_SIZE before creating any "
|
|
937
|
-
"registry instances, or use _reset_semver_cache() for testing.",
|
|
938
|
-
context=context,
|
|
939
|
-
)
|
|
940
|
-
cls.SEMVER_CACHE_SIZE = maxsize
|
|
941
|
-
|
|
942
|
-
@classmethod
|
|
943
|
-
def _reset_semver_cache(cls) -> None:
|
|
944
|
-
"""Reset semver cache. For testing only.
|
|
945
|
-
|
|
946
|
-
Clears the cached semver parser, allowing reconfiguration of cache size.
|
|
947
|
-
This should only be used in test fixtures to ensure test isolation.
|
|
948
|
-
|
|
949
|
-
Thread Safety:
|
|
950
|
-
This method is thread-safe and uses the class-level lock. The reset
|
|
951
|
-
operation is atomic - either the cache is fully reset or not at all.
|
|
952
|
-
|
|
953
|
-
In-flight Operations:
|
|
954
|
-
If other threads have already obtained a reference to the cache
|
|
955
|
-
via _get_semver_parser(), they will continue using the old cache
|
|
956
|
-
until they complete. This is safe because the old cache remains
|
|
957
|
-
a valid callable until garbage collected. New operations after
|
|
958
|
-
reset will get the new cache instance when created.
|
|
959
|
-
|
|
960
|
-
Memory Reclamation:
|
|
961
|
-
The old cache's internal LRU entries are explicitly cleared via
|
|
962
|
-
cache_clear() before the reference is released. This ensures
|
|
963
|
-
prompt memory reclamation rather than waiting for garbage
|
|
964
|
-
collection.
|
|
965
|
-
|
|
966
|
-
Concurrent Reset:
|
|
967
|
-
Multiple concurrent reset calls are safe. Each reset will clear
|
|
968
|
-
the current cache (if any) and set the reference to None. The
|
|
969
|
-
lock ensures only one reset executes at a time.
|
|
970
|
-
|
|
971
|
-
Example:
|
|
972
|
-
>>> # In test fixture
|
|
973
|
-
>>> RegistryPolicy._reset_semver_cache()
|
|
974
|
-
>>> RegistryPolicy.SEMVER_CACHE_SIZE = 64
|
|
975
|
-
>>> # Now cache will be initialized with size 64 on next use
|
|
976
|
-
"""
|
|
977
|
-
with cls._semver_cache_lock:
|
|
978
|
-
# Clear the inner LRU-cached function (has the actual cache)
|
|
979
|
-
inner_cache = cls._semver_cache_inner
|
|
980
|
-
if inner_cache is not None:
|
|
981
|
-
# Clear internal LRU cache entries before releasing reference.
|
|
982
|
-
# This ensures prompt memory reclamation rather than waiting
|
|
983
|
-
# for garbage collection of the orphaned function object.
|
|
984
|
-
# Note: cache_clear() is added by @lru_cache decorator but not
|
|
985
|
-
# reflected in Callable type annotation. This is a known mypy
|
|
986
|
-
# limitation with lru_cache wrappers.
|
|
987
|
-
inner_cache.cache_clear() # type: ignore[attr-defined]
|
|
988
|
-
cls._semver_cache = None
|
|
989
|
-
cls._semver_cache_inner = None
|
|
990
|
-
|
|
991
|
-
@classmethod
|
|
992
|
-
def _get_semver_parser(cls) -> Callable[[str], ModelSemVer]:
|
|
993
|
-
"""Get or create the semver parser with configured cache size.
|
|
994
|
-
|
|
995
|
-
This method implements lazy initialization of the LRU-cached semver parser.
|
|
996
|
-
The cache size is determined by SEMVER_CACHE_SIZE at initialization time.
|
|
997
|
-
|
|
998
|
-
Thread Safety:
|
|
999
|
-
Uses double-checked locking pattern for thread-safe lazy initialization.
|
|
1000
|
-
The fast path stores the cache reference in a local variable to prevent
|
|
1001
|
-
TOCTOU (time-of-check-time-of-use) race conditions where another thread
|
|
1002
|
-
could call _reset_semver_cache() between the None check and the return.
|
|
1003
|
-
|
|
1004
|
-
Cache Key Normalization:
|
|
1005
|
-
Version strings are normalized BEFORE being used as cache keys to ensure
|
|
1006
|
-
that equivalent versions (e.g., "1.0" and "1.0.0") share the same cache
|
|
1007
|
-
entry. This prevents cache fragmentation and improves hit rates.
|
|
1008
|
-
|
|
1009
|
-
Returns:
|
|
1010
|
-
Cached semver parsing function that returns ModelSemVer instances.
|
|
1011
|
-
The returned function accepts a version string and returns a ModelSemVer.
|
|
1012
|
-
|
|
1013
|
-
Raises:
|
|
1014
|
-
ProtocolConfigurationError: Raised by the returned parsing function if
|
|
1015
|
-
the version format is invalid (e.g., non-numeric components,
|
|
1016
|
-
negative numbers, or more than 3 version parts).
|
|
1017
|
-
|
|
1018
|
-
Performance:
|
|
1019
|
-
- First call: Creates LRU-cached function (one-time cost)
|
|
1020
|
-
- Subsequent calls: Returns cached function reference (O(1))
|
|
1021
|
-
- Cache hit rate improved by normalizing keys before lookup
|
|
1022
|
-
"""
|
|
1023
|
-
# Fast path: cache already initialized
|
|
1024
|
-
# CRITICAL: Store in local variable to prevent TOCTOU race condition.
|
|
1025
|
-
# Without this, another thread could call _reset_semver_cache() between
|
|
1026
|
-
# the None check and the return, causing this method to return None.
|
|
1027
|
-
cache = cls._semver_cache
|
|
1028
|
-
if cache is not None:
|
|
1029
|
-
return cache
|
|
1030
|
-
|
|
1031
|
-
# Slow path: initialize with lock
|
|
1032
|
-
with cls._semver_cache_lock:
|
|
1033
|
-
# Double-check after acquiring lock
|
|
1034
|
-
if cls._semver_cache is not None:
|
|
1035
|
-
return cls._semver_cache
|
|
1036
|
-
|
|
1037
|
-
# Create LRU-cached parser with configured size
|
|
1038
|
-
# The cache key is the NORMALIZED version string to prevent
|
|
1039
|
-
# fragmentation (e.g., "1.0" and "1.0.0" share the same entry)
|
|
1040
|
-
@functools.lru_cache(maxsize=cls.SEMVER_CACHE_SIZE)
|
|
1041
|
-
def _parse_semver_cached(normalized_version: str) -> ModelSemVer:
|
|
1042
|
-
"""Parse normalized semantic version string into ModelSemVer.
|
|
1043
|
-
|
|
1044
|
-
This function receives ALREADY NORMALIZED version strings.
|
|
1045
|
-
The normalization is done by the wrapper function before
|
|
1046
|
-
caching to ensure equivalent versions share cache entries.
|
|
1047
|
-
|
|
1048
|
-
Args:
|
|
1049
|
-
normalized_version: Pre-normalized version in "x.y.z" or
|
|
1050
|
-
"x.y.z-prerelease" format
|
|
1051
|
-
|
|
1052
|
-
Returns:
|
|
1053
|
-
ModelSemVer instance for comparison
|
|
1054
|
-
|
|
1055
|
-
Raises:
|
|
1056
|
-
ProtocolConfigurationError: If version format is invalid
|
|
1057
|
-
"""
|
|
1058
|
-
# ModelOnexError is imported at module level
|
|
1059
|
-
try:
|
|
1060
|
-
return ModelSemVer.parse(normalized_version)
|
|
1061
|
-
except ModelOnexError as e:
|
|
1062
|
-
context = ModelInfraErrorContext.with_correlation(
|
|
1063
|
-
transport_type=EnumInfraTransportType.RUNTIME,
|
|
1064
|
-
operation="parse_semver",
|
|
1065
|
-
)
|
|
1066
|
-
raise ProtocolConfigurationError(
|
|
1067
|
-
str(e),
|
|
1068
|
-
version=normalized_version,
|
|
1069
|
-
context=context,
|
|
1070
|
-
) from e
|
|
1071
|
-
except ValueError as e:
|
|
1072
|
-
context = ModelInfraErrorContext.with_correlation(
|
|
1073
|
-
transport_type=EnumInfraTransportType.RUNTIME,
|
|
1074
|
-
operation="parse_semver",
|
|
1075
|
-
)
|
|
1076
|
-
raise ProtocolConfigurationError(
|
|
1077
|
-
str(e),
|
|
1078
|
-
version=normalized_version,
|
|
1079
|
-
context=context,
|
|
1080
|
-
) from e
|
|
1081
|
-
|
|
1082
|
-
def _parse_semver_impl(version: str) -> ModelSemVer:
|
|
1083
|
-
"""Parse semantic version string into ModelSemVer.
|
|
1084
|
-
|
|
1085
|
-
Implementation moved here to support configurable cache size.
|
|
1086
|
-
See _parse_semver docstring for full documentation.
|
|
1087
|
-
|
|
1088
|
-
IMPORTANT: This wrapper normalizes version strings BEFORE
|
|
1089
|
-
passing to the LRU-cached parsing function. This ensures that
|
|
1090
|
-
equivalent versions (e.g., "1.0" and "1.0.0", "v1.0.0" and "1.0.0")
|
|
1091
|
-
share the same cache entry, improving cache hit rates.
|
|
1092
|
-
|
|
1093
|
-
All validation (empty strings, prerelease suffix, format) is
|
|
1094
|
-
delegated to _normalize_version to eliminate code duplication.
|
|
1095
|
-
"""
|
|
1096
|
-
# Delegate all validation to _normalize_version (single source of truth)
|
|
1097
|
-
# This eliminates duplicated validation logic (empty check, prerelease suffix)
|
|
1098
|
-
normalized = RegistryPolicy._normalize_version(version)
|
|
1099
|
-
|
|
1100
|
-
# Now call the cached function with the NORMALIZED version
|
|
1101
|
-
# This ensures "1.0", "1.0.0", "v1.0.0" all use the same cache entry
|
|
1102
|
-
return _parse_semver_cached(normalized)
|
|
1103
|
-
|
|
1104
|
-
# Store both the outer wrapper and inner cached function
|
|
1105
|
-
# The wrapper is what callers use (_semver_cache)
|
|
1106
|
-
# The inner function is needed for cache_clear() access (_semver_cache_inner)
|
|
1107
|
-
cls._semver_cache = _parse_semver_impl
|
|
1108
|
-
cls._semver_cache_inner = _parse_semver_cached
|
|
1109
|
-
return cls._semver_cache
|
|
1110
|
-
|
|
1111
|
-
@classmethod
|
|
1112
|
-
def _parse_semver(cls, version: str) -> ModelSemVer:
|
|
1113
|
-
"""Parse semantic version string into ModelSemVer for comparison.
|
|
1114
|
-
|
|
1115
|
-
This method implements SEMANTIC VERSION SORTING, not lexicographic sorting.
|
|
1116
|
-
This is critical for correct "latest version" selection.
|
|
1117
|
-
|
|
1118
|
-
Why This Matters (PR #36 feedback):
|
|
1119
|
-
Lexicographic sorting (string comparison):
|
|
1120
|
-
"1.10.0" < "1.9.0" WRONG (because '1' < '9' in strings)
|
|
1121
|
-
"10.0.0" < "2.0.0" WRONG (because '1' < '2' in strings)
|
|
1122
|
-
|
|
1123
|
-
Semantic version sorting (integer comparison):
|
|
1124
|
-
1.10.0 > 1.9.0 CORRECT (because 10 > 9 as integers)
|
|
1125
|
-
10.0.0 > 2.0.0 CORRECT (because 10 > 2 as integers)
|
|
1126
|
-
|
|
1127
|
-
Implementation:
|
|
1128
|
-
- Returns ModelSemVer instance with integer major, minor, patch
|
|
1129
|
-
- ModelSemVer implements comparison operators for correct ordering
|
|
1130
|
-
- Prerelease is parsed but NOT used in comparisons (major.minor.patch only)
|
|
1131
|
-
- "1.0.0-alpha" and "1.0.0" compare as EQUAL (same major.minor.patch)
|
|
1132
|
-
|
|
1133
|
-
Supported Formats:
|
|
1134
|
-
- Full: "1.2.3", "1.2.3-beta"
|
|
1135
|
-
- Partial: "1" -> (1, 0, 0), "1.2" -> (1, 2, 0)
|
|
1136
|
-
- Prerelease: "1.0.0-alpha", "2.1.0-rc.1"
|
|
1137
|
-
|
|
1138
|
-
Validation:
|
|
1139
|
-
- Rejects empty strings
|
|
1140
|
-
- Rejects non-numeric components
|
|
1141
|
-
- Rejects negative numbers
|
|
1142
|
-
- Rejects >3 version parts (e.g., "1.2.3.4")
|
|
1143
|
-
|
|
1144
|
-
Performance:
|
|
1145
|
-
This method uses an LRU cache with configurable size (default: 128)
|
|
1146
|
-
to avoid re-parsing the same version strings repeatedly, improving
|
|
1147
|
-
performance for lookups that compare multiple versions.
|
|
1148
|
-
|
|
1149
|
-
Cache Size Configuration:
|
|
1150
|
-
For large deployments, configure before first use:
|
|
1151
|
-
RegistryPolicy.configure_semver_cache(maxsize=256)
|
|
1152
|
-
|
|
1153
|
-
Cache Size Rationale (default 128):
|
|
1154
|
-
- Typical registry: 10-50 unique policy versions
|
|
1155
|
-
- Peak scenarios: 50-100 versions across multiple policy types
|
|
1156
|
-
- Each cache entry: ~200 bytes (string key + ModelSemVer instance)
|
|
1157
|
-
- Total memory: ~25.6KB worst case (negligible overhead)
|
|
1158
|
-
- Hit rate: >95% for repeated get() calls with version comparisons
|
|
1159
|
-
- Eviction: Rare in practice, LRU ensures least-used versions purged
|
|
1160
|
-
|
|
1161
|
-
Args:
|
|
1162
|
-
version: Semantic version string (e.g., "1.2.3" or "1.0.0-beta")
|
|
1163
|
-
|
|
1164
|
-
Returns:
|
|
1165
|
-
ModelSemVer instance for comparison.
|
|
1166
|
-
Components are INTEGERS (not strings) for correct semantic sorting.
|
|
1167
|
-
Prerelease is parsed and stored but ignored in version comparisons.
|
|
1168
|
-
|
|
1169
|
-
Raises:
|
|
1170
|
-
ProtocolConfigurationError: If version format is invalid
|
|
1171
|
-
|
|
1172
|
-
Examples:
|
|
1173
|
-
>>> RegistryPolicy._parse_semver("1.9.0")
|
|
1174
|
-
ModelSemVer(major=1, minor=9, patch=0, prerelease='')
|
|
1175
|
-
>>> RegistryPolicy._parse_semver("1.10.0")
|
|
1176
|
-
ModelSemVer(major=1, minor=10, patch=0, prerelease='')
|
|
1177
|
-
>>> RegistryPolicy._parse_semver("1.10.0") > RegistryPolicy._parse_semver("1.9.0")
|
|
1178
|
-
True
|
|
1179
|
-
>>> RegistryPolicy._parse_semver("10.0.0") > RegistryPolicy._parse_semver("2.0.0")
|
|
1180
|
-
True
|
|
1181
|
-
>>> RegistryPolicy._parse_semver("1.0.0-alpha")
|
|
1182
|
-
ModelSemVer(major=1, minor=0, patch=0, prerelease='alpha')
|
|
1183
|
-
>>> # Prerelease is parsed but NOT used in comparisons:
|
|
1184
|
-
>>> RegistryPolicy._parse_semver("1.0.0-alpha") == RegistryPolicy._parse_semver("1.0.0")
|
|
1185
|
-
True # Same major.minor.patch, prerelease ignored
|
|
1186
|
-
"""
|
|
1187
|
-
parser = cls._get_semver_parser()
|
|
1188
|
-
return parser(version)
|
|
1189
|
-
|
|
1190
|
-
@classmethod
|
|
1191
|
-
def _get_semver_cache_info(cls) -> functools._CacheInfo | None:
|
|
1192
|
-
"""Get cache statistics for the semver parser. For testing only.
|
|
1193
|
-
|
|
1194
|
-
Returns the cache_info() from the inner LRU-cached function.
|
|
1195
|
-
This allows tests to verify cache behavior without accessing
|
|
1196
|
-
internal implementation details.
|
|
1197
|
-
|
|
1198
|
-
Returns:
|
|
1199
|
-
functools._CacheInfo with hits, misses, maxsize, currsize,
|
|
1200
|
-
or None if cache not yet initialized.
|
|
1201
|
-
|
|
1202
|
-
Example:
|
|
1203
|
-
>>> RegistryPolicy._reset_semver_cache()
|
|
1204
|
-
>>> RegistryPolicy._parse_semver("1.0.0")
|
|
1205
|
-
>>> info = RegistryPolicy._get_semver_cache_info()
|
|
1206
|
-
>>> info.misses # First call is a miss
|
|
1207
|
-
1
|
|
1208
|
-
>>> RegistryPolicy._parse_semver("1.0.0")
|
|
1209
|
-
>>> info = RegistryPolicy._get_semver_cache_info()
|
|
1210
|
-
>>> info.hits # Second call is a hit
|
|
1211
|
-
1
|
|
1212
|
-
"""
|
|
1213
|
-
if cls._semver_cache_inner is None:
|
|
1214
|
-
return None
|
|
1215
|
-
# cache_info() is added by @lru_cache decorator
|
|
1216
|
-
# The return type is functools._CacheInfo
|
|
1217
|
-
result: functools._CacheInfo = cls._semver_cache_inner.cache_info() # type: ignore[attr-defined]
|
|
1218
|
-
return result
|
|
894
|
+
# The following methods are inherited from MixinSemverCache:
|
|
895
|
+
# - configure_semver_cache(maxsize: int) -> None
|
|
896
|
+
# - _reset_semver_cache() -> None
|
|
897
|
+
# - _get_semver_parser() -> Callable[[str], ModelSemVer]
|
|
898
|
+
# - _parse_semver(version: str) -> ModelSemVer
|
|
899
|
+
# - _get_semver_cache_info() -> functools._CacheInfo | None
|
|
900
|
+
#
|
|
901
|
+
# See MixinSemverCache for full documentation of these methods.
|
|
1219
902
|
|
|
1220
903
|
def _list_internal(self) -> list[tuple[str, str, str]]:
|
|
1221
904
|
"""Internal list method (assumes lock is held).
|
|
@@ -131,7 +131,7 @@ import time
|
|
|
131
131
|
from collections import defaultdict, deque
|
|
132
132
|
from datetime import UTC, datetime, timedelta
|
|
133
133
|
from pathlib import Path
|
|
134
|
-
from typing import TYPE_CHECKING, Protocol, runtime_checkable
|
|
134
|
+
from typing import TYPE_CHECKING, Protocol, cast, runtime_checkable
|
|
135
135
|
from uuid import UUID, uuid4
|
|
136
136
|
|
|
137
137
|
from pydantic import SecretStr
|
|
@@ -1847,7 +1847,9 @@ class SecretResolver:
|
|
|
1847
1847
|
}
|
|
1848
1848
|
|
|
1849
1849
|
try:
|
|
1850
|
-
result = await self._vault_handler.execute(
|
|
1850
|
+
result = await self._vault_handler.execute(
|
|
1851
|
+
cast("dict[str, object]", envelope)
|
|
1852
|
+
)
|
|
1851
1853
|
|
|
1852
1854
|
# Extract secret data from handler response
|
|
1853
1855
|
# Response format: {"status": "success", "payload": {"data": {...}, "metadata": {...}}}
|
|
@@ -830,7 +830,7 @@ async def bootstrap() -> int:
|
|
|
830
830
|
# when Consul integration is disabled, reducing startup time.
|
|
831
831
|
from omnibase_infra.handlers import HandlerConsul
|
|
832
832
|
|
|
833
|
-
consul_handler = HandlerConsul()
|
|
833
|
+
consul_handler = HandlerConsul(container)
|
|
834
834
|
await consul_handler.initialize(
|
|
835
835
|
{
|
|
836
836
|
"host": consul_host,
|
|
@@ -1376,24 +1376,32 @@ async def bootstrap() -> int:
|
|
|
1376
1376
|
|
|
1377
1377
|
except ProtocolConfigurationError as e:
|
|
1378
1378
|
# Configuration errors already have proper context and chaining
|
|
1379
|
+
error_code = getattr(getattr(e, "model", None), "error_code", None)
|
|
1380
|
+
error_code_name = getattr(error_code, "name", None)
|
|
1379
1381
|
logger.exception(
|
|
1380
1382
|
"ONEX runtime configuration failed (correlation_id=%s)",
|
|
1381
1383
|
correlation_id,
|
|
1382
1384
|
extra={
|
|
1383
1385
|
"error_type": type(e).__name__,
|
|
1384
|
-
"error_code":
|
|
1386
|
+
"error_code": str(error_code_name)
|
|
1387
|
+
if error_code_name is not None
|
|
1388
|
+
else None,
|
|
1385
1389
|
},
|
|
1386
1390
|
)
|
|
1387
1391
|
return 1
|
|
1388
1392
|
|
|
1389
1393
|
except RuntimeHostError as e:
|
|
1390
1394
|
# Runtime host errors already have proper structure
|
|
1395
|
+
error_code = getattr(getattr(e, "model", None), "error_code", None)
|
|
1396
|
+
error_code_name = getattr(error_code, "name", None)
|
|
1391
1397
|
logger.exception(
|
|
1392
1398
|
"ONEX runtime host error (correlation_id=%s)",
|
|
1393
1399
|
correlation_id,
|
|
1394
1400
|
extra={
|
|
1395
1401
|
"error_type": type(e).__name__,
|
|
1396
|
-
"error_code":
|
|
1402
|
+
"error_code": str(error_code_name)
|
|
1403
|
+
if error_code_name is not None
|
|
1404
|
+
else None,
|
|
1397
1405
|
},
|
|
1398
1406
|
)
|
|
1399
1407
|
return 1
|
|
@@ -1512,7 +1512,9 @@ class MessageDispatchEngine:
|
|
|
1512
1512
|
|
|
1513
1513
|
if context is not None:
|
|
1514
1514
|
# Context-aware sync dispatcher
|
|
1515
|
-
sync_ctx_dispatcher = cast(
|
|
1515
|
+
sync_ctx_dispatcher = cast(
|
|
1516
|
+
"_SyncContextAwareDispatcherFunc", dispatcher
|
|
1517
|
+
)
|
|
1516
1518
|
return await loop.run_in_executor(
|
|
1517
1519
|
None,
|
|
1518
1520
|
sync_ctx_dispatcher,
|
|
@@ -1524,7 +1526,7 @@ class MessageDispatchEngine:
|
|
|
1524
1526
|
else:
|
|
1525
1527
|
# Cast to sync-only type - safe because iscoroutinefunction check above
|
|
1526
1528
|
# guarantees this branch only executes for non-async callables
|
|
1527
|
-
sync_dispatcher = cast(_SyncDispatcherFunc, dispatcher)
|
|
1529
|
+
sync_dispatcher = cast("_SyncDispatcherFunc", dispatcher)
|
|
1528
1530
|
return await loop.run_in_executor(
|
|
1529
1531
|
None,
|
|
1530
1532
|
sync_dispatcher,
|