omnibase_infra 0.2.5__py3-none-any.whl → 0.2.7__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/constants_topic_patterns.py +26 -0
- omnibase_infra/enums/__init__.py +3 -0
- omnibase_infra/enums/enum_consumer_group_purpose.py +92 -0
- omnibase_infra/enums/enum_handler_source_mode.py +16 -2
- omnibase_infra/errors/__init__.py +4 -0
- omnibase_infra/errors/error_binding_resolution.py +128 -0
- omnibase_infra/event_bus/configs/kafka_event_bus_config.yaml +0 -2
- omnibase_infra/event_bus/event_bus_inmemory.py +64 -10
- omnibase_infra/event_bus/event_bus_kafka.py +105 -47
- omnibase_infra/event_bus/mixin_kafka_broadcast.py +3 -7
- omnibase_infra/event_bus/mixin_kafka_dlq.py +12 -6
- omnibase_infra/event_bus/models/config/model_kafka_event_bus_config.py +0 -81
- omnibase_infra/event_bus/testing/__init__.py +26 -0
- omnibase_infra/event_bus/testing/adapter_protocol_event_publisher_inmemory.py +418 -0
- omnibase_infra/event_bus/testing/model_publisher_metrics.py +64 -0
- omnibase_infra/handlers/handler_consul.py +2 -0
- omnibase_infra/handlers/mixins/__init__.py +5 -0
- omnibase_infra/handlers/mixins/mixin_consul_service.py +274 -10
- omnibase_infra/handlers/mixins/mixin_consul_topic_index.py +585 -0
- omnibase_infra/handlers/models/model_filesystem_config.py +4 -4
- omnibase_infra/migrations/001_create_event_ledger.sql +166 -0
- omnibase_infra/migrations/001_drop_event_ledger.sql +18 -0
- omnibase_infra/mixins/mixin_node_introspection.py +189 -19
- omnibase_infra/models/__init__.py +8 -0
- omnibase_infra/models/bindings/__init__.py +59 -0
- omnibase_infra/models/bindings/constants.py +144 -0
- omnibase_infra/models/bindings/model_binding_resolution_result.py +103 -0
- omnibase_infra/models/bindings/model_operation_binding.py +44 -0
- omnibase_infra/models/bindings/model_operation_bindings_subcontract.py +152 -0
- omnibase_infra/models/bindings/model_parsed_binding.py +52 -0
- omnibase_infra/models/discovery/model_introspection_config.py +25 -17
- omnibase_infra/models/dispatch/__init__.py +8 -0
- omnibase_infra/models/dispatch/model_debug_trace_snapshot.py +114 -0
- omnibase_infra/models/dispatch/model_materialized_dispatch.py +141 -0
- omnibase_infra/models/handlers/model_handler_source_config.py +1 -1
- omnibase_infra/models/model_node_identity.py +126 -0
- omnibase_infra/models/projection/model_snapshot_topic_config.py +3 -2
- omnibase_infra/models/registration/__init__.py +9 -0
- omnibase_infra/models/registration/model_event_bus_topic_entry.py +59 -0
- omnibase_infra/models/registration/model_node_event_bus_config.py +99 -0
- omnibase_infra/models/registration/model_node_introspection_event.py +11 -0
- omnibase_infra/models/runtime/__init__.py +9 -0
- omnibase_infra/models/validation/model_coverage_metrics.py +2 -2
- omnibase_infra/nodes/__init__.py +9 -0
- omnibase_infra/nodes/contract_registry_reducer/__init__.py +29 -0
- omnibase_infra/nodes/contract_registry_reducer/contract.yaml +255 -0
- omnibase_infra/nodes/contract_registry_reducer/models/__init__.py +38 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_contract_registry_state.py +266 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_payload_cleanup_topic_references.py +55 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_payload_deactivate_contract.py +58 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_payload_mark_stale.py +49 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_payload_update_heartbeat.py +71 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_payload_update_topic.py +66 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_payload_upsert_contract.py +92 -0
- omnibase_infra/nodes/contract_registry_reducer/node.py +121 -0
- omnibase_infra/nodes/contract_registry_reducer/reducer.py +784 -0
- omnibase_infra/nodes/contract_registry_reducer/registry/__init__.py +9 -0
- omnibase_infra/nodes/contract_registry_reducer/registry/registry_infra_contract_registry_reducer.py +101 -0
- omnibase_infra/nodes/handlers/consul/contract.yaml +85 -0
- omnibase_infra/nodes/handlers/db/contract.yaml +72 -0
- omnibase_infra/nodes/handlers/graph/contract.yaml +127 -0
- omnibase_infra/nodes/handlers/http/contract.yaml +74 -0
- omnibase_infra/nodes/handlers/intent/contract.yaml +66 -0
- omnibase_infra/nodes/handlers/mcp/contract.yaml +69 -0
- omnibase_infra/nodes/handlers/vault/contract.yaml +91 -0
- omnibase_infra/nodes/node_ledger_projection_compute/__init__.py +50 -0
- omnibase_infra/nodes/node_ledger_projection_compute/contract.yaml +104 -0
- omnibase_infra/nodes/node_ledger_projection_compute/node.py +284 -0
- omnibase_infra/nodes/node_ledger_projection_compute/registry/__init__.py +29 -0
- omnibase_infra/nodes/node_ledger_projection_compute/registry/registry_infra_ledger_projection.py +118 -0
- omnibase_infra/nodes/node_ledger_write_effect/__init__.py +82 -0
- omnibase_infra/nodes/node_ledger_write_effect/contract.yaml +200 -0
- omnibase_infra/nodes/node_ledger_write_effect/handlers/__init__.py +22 -0
- omnibase_infra/nodes/node_ledger_write_effect/handlers/handler_ledger_append.py +372 -0
- omnibase_infra/nodes/node_ledger_write_effect/handlers/handler_ledger_query.py +597 -0
- omnibase_infra/nodes/node_ledger_write_effect/models/__init__.py +31 -0
- omnibase_infra/nodes/node_ledger_write_effect/models/model_ledger_append_result.py +54 -0
- omnibase_infra/nodes/node_ledger_write_effect/models/model_ledger_entry.py +92 -0
- omnibase_infra/nodes/node_ledger_write_effect/models/model_ledger_query.py +53 -0
- omnibase_infra/nodes/node_ledger_write_effect/models/model_ledger_query_result.py +41 -0
- omnibase_infra/nodes/node_ledger_write_effect/node.py +89 -0
- omnibase_infra/nodes/node_ledger_write_effect/protocols/__init__.py +13 -0
- omnibase_infra/nodes/node_ledger_write_effect/protocols/protocol_ledger_persistence.py +127 -0
- omnibase_infra/nodes/node_ledger_write_effect/registry/__init__.py +9 -0
- omnibase_infra/nodes/node_ledger_write_effect/registry/registry_infra_ledger_write.py +121 -0
- omnibase_infra/nodes/node_registration_orchestrator/registry/registry_infra_node_registration_orchestrator.py +7 -5
- omnibase_infra/nodes/reducers/models/__init__.py +7 -2
- omnibase_infra/nodes/reducers/models/model_payload_consul_register.py +11 -0
- omnibase_infra/nodes/reducers/models/model_payload_ledger_append.py +133 -0
- omnibase_infra/nodes/reducers/registration_reducer.py +1 -0
- omnibase_infra/protocols/__init__.py +3 -0
- omnibase_infra/protocols/protocol_dispatch_engine.py +152 -0
- omnibase_infra/runtime/__init__.py +60 -0
- omnibase_infra/runtime/binding_resolver.py +753 -0
- omnibase_infra/runtime/constants_security.py +70 -0
- omnibase_infra/runtime/contract_loaders/__init__.py +9 -0
- omnibase_infra/runtime/contract_loaders/operation_bindings_loader.py +789 -0
- omnibase_infra/runtime/emit_daemon/__init__.py +97 -0
- omnibase_infra/runtime/emit_daemon/cli.py +844 -0
- omnibase_infra/runtime/emit_daemon/client.py +811 -0
- omnibase_infra/runtime/emit_daemon/config.py +535 -0
- omnibase_infra/runtime/emit_daemon/daemon.py +812 -0
- omnibase_infra/runtime/emit_daemon/event_registry.py +477 -0
- omnibase_infra/runtime/emit_daemon/model_daemon_request.py +139 -0
- omnibase_infra/runtime/emit_daemon/model_daemon_response.py +191 -0
- omnibase_infra/runtime/emit_daemon/queue.py +618 -0
- omnibase_infra/runtime/event_bus_subcontract_wiring.py +466 -0
- omnibase_infra/runtime/handler_source_resolver.py +43 -2
- omnibase_infra/runtime/kafka_contract_source.py +984 -0
- omnibase_infra/runtime/models/__init__.py +13 -0
- omnibase_infra/runtime/models/model_contract_load_result.py +224 -0
- omnibase_infra/runtime/models/model_runtime_contract_config.py +268 -0
- omnibase_infra/runtime/models/model_runtime_scheduler_config.py +4 -3
- omnibase_infra/runtime/models/model_security_config.py +109 -0
- omnibase_infra/runtime/publisher_topic_scoped.py +294 -0
- omnibase_infra/runtime/runtime_contract_config_loader.py +406 -0
- omnibase_infra/runtime/service_kernel.py +76 -6
- omnibase_infra/runtime/service_message_dispatch_engine.py +558 -15
- omnibase_infra/runtime/service_runtime_host_process.py +770 -20
- omnibase_infra/runtime/transition_notification_publisher.py +3 -2
- omnibase_infra/runtime/util_wiring.py +206 -62
- omnibase_infra/services/mcp/service_mcp_tool_sync.py +27 -9
- omnibase_infra/services/session/config_consumer.py +25 -8
- omnibase_infra/services/session/config_store.py +2 -2
- omnibase_infra/services/session/consumer.py +1 -1
- omnibase_infra/topics/__init__.py +45 -0
- omnibase_infra/topics/platform_topic_suffixes.py +140 -0
- omnibase_infra/topics/util_topic_composition.py +95 -0
- omnibase_infra/types/typed_dict/__init__.py +9 -1
- omnibase_infra/types/typed_dict/typed_dict_envelope_build_params.py +115 -0
- omnibase_infra/utils/__init__.py +9 -0
- omnibase_infra/utils/util_consumer_group.py +232 -0
- omnibase_infra/validation/infra_validators.py +18 -1
- omnibase_infra/validation/validation_exemptions.yaml +192 -0
- {omnibase_infra-0.2.5.dist-info → omnibase_infra-0.2.7.dist-info}/METADATA +3 -3
- {omnibase_infra-0.2.5.dist-info → omnibase_infra-0.2.7.dist-info}/RECORD +139 -52
- {omnibase_infra-0.2.5.dist-info → omnibase_infra-0.2.7.dist-info}/entry_points.txt +1 -0
- {omnibase_infra-0.2.5.dist-info → omnibase_infra-0.2.7.dist-info}/WHEEL +0 -0
- {omnibase_infra-0.2.5.dist-info → omnibase_infra-0.2.7.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2026 OmniNode Team
|
|
3
|
+
"""Ledger append payload model for audit ledger reducer.
|
|
4
|
+
|
|
5
|
+
This payload implements ProtocolIntentPayload for use with ModelIntent.
|
|
6
|
+
It captures Kafka events for append-only audit ledger storage with
|
|
7
|
+
metadata extraction best-effort (nullable metadata ensures events are
|
|
8
|
+
never dropped due to parsing failures).
|
|
9
|
+
|
|
10
|
+
Design Rationale - Nullable Metadata:
|
|
11
|
+
The audit ledger serves as the system's source of truth. Events must NEVER
|
|
12
|
+
be dropped due to metadata extraction failures. By making all metadata fields
|
|
13
|
+
nullable, we guarantee:
|
|
14
|
+
1. Malformed events are captured with raw data intact
|
|
15
|
+
2. Parsing errors don't cause event loss
|
|
16
|
+
3. Metadata can be re-extracted later from raw event_value
|
|
17
|
+
4. The ledger remains complete even during schema evolution
|
|
18
|
+
|
|
19
|
+
Bytes Encoding:
|
|
20
|
+
Kafka event keys and values are bytes. Since bytes cannot safely cross
|
|
21
|
+
intent boundaries (serialization issues), they are base64-encoded at the
|
|
22
|
+
boundary. The Effect layer decodes before storage.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
from datetime import datetime
|
|
28
|
+
from typing import Literal
|
|
29
|
+
from uuid import UUID
|
|
30
|
+
|
|
31
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
32
|
+
|
|
33
|
+
from omnibase_core.types import JsonType
|
|
34
|
+
|
|
35
|
+
# NOTE: ModelIntentPayloadBase was removed in omnibase_core 0.6.2
|
|
36
|
+
# Using pydantic.BaseModel directly as the base class
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class ModelPayloadLedgerAppend(BaseModel):
|
|
40
|
+
"""Payload for audit ledger append intents.
|
|
41
|
+
|
|
42
|
+
This payload follows the ONEX intent payload pattern for use with ModelIntent.
|
|
43
|
+
All metadata fields are intentionally OPTIONAL to ensure the audit ledger
|
|
44
|
+
never drops events due to metadata extraction failures.
|
|
45
|
+
|
|
46
|
+
Attributes:
|
|
47
|
+
intent_type: Discriminator literal for intent routing. Always "ledger.append".
|
|
48
|
+
topic: Kafka topic the event originated from.
|
|
49
|
+
partition: Kafka partition number (idempotency key component).
|
|
50
|
+
kafka_offset: Kafka offset within partition (idempotency key component).
|
|
51
|
+
event_key: Base64-encoded event key bytes (None for keyless events).
|
|
52
|
+
event_value: Base64-encoded event value bytes (required - the raw event).
|
|
53
|
+
onex_headers: Extracted ONEX headers from Kafka message headers.
|
|
54
|
+
correlation_id: Correlation ID for distributed tracing (extracted, nullable).
|
|
55
|
+
envelope_id: Unique envelope identifier (extracted, nullable).
|
|
56
|
+
event_type: Event type discriminator (extracted, nullable).
|
|
57
|
+
source: Event source identifier (extracted, nullable).
|
|
58
|
+
event_timestamp: Event timestamp (extracted, nullable).
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
model_config = ConfigDict(frozen=True, extra="forbid", from_attributes=True)
|
|
62
|
+
|
|
63
|
+
intent_type: Literal["ledger.append"] = Field(
|
|
64
|
+
default="ledger.append",
|
|
65
|
+
description="Discriminator literal for intent routing.",
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
# Kafka position - required for idempotency
|
|
69
|
+
topic: str = Field(
|
|
70
|
+
...,
|
|
71
|
+
min_length=1,
|
|
72
|
+
description="Kafka topic the event originated from.",
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
partition: int = Field(
|
|
76
|
+
...,
|
|
77
|
+
ge=0,
|
|
78
|
+
description="Kafka partition number (idempotency key component).",
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
kafka_offset: int = Field(
|
|
82
|
+
...,
|
|
83
|
+
ge=0,
|
|
84
|
+
description="Kafka offset within partition (idempotency key component).",
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
# Raw event data as base64 strings (bytes never cross intents)
|
|
88
|
+
event_key: str | None = Field(
|
|
89
|
+
default=None,
|
|
90
|
+
description="Base64-encoded event key bytes (None for keyless events).",
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
event_value: str = Field(
|
|
94
|
+
...,
|
|
95
|
+
min_length=1,
|
|
96
|
+
description="Base64-encoded event value bytes (required - the raw event).",
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
onex_headers: dict[str, JsonType] = Field(
|
|
100
|
+
default_factory=dict,
|
|
101
|
+
description="Extracted ONEX headers from Kafka message headers.",
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
# Extracted metadata - ALL OPTIONAL (audit ledger must never drop events)
|
|
105
|
+
correlation_id: UUID | None = Field(
|
|
106
|
+
default=None,
|
|
107
|
+
description="Correlation ID for distributed tracing (extracted, nullable).",
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
envelope_id: UUID | None = Field(
|
|
111
|
+
default=None,
|
|
112
|
+
description="Unique envelope identifier (extracted, nullable).",
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
event_type: str | None = Field(
|
|
116
|
+
default=None,
|
|
117
|
+
description="Event type discriminator (extracted, nullable).",
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
source: str | None = Field(
|
|
121
|
+
default=None,
|
|
122
|
+
description="Event source identifier (extracted, nullable).",
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
event_timestamp: datetime | None = Field(
|
|
126
|
+
default=None,
|
|
127
|
+
description="Event timestamp (extracted, nullable).",
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
__all__ = [
|
|
132
|
+
"ModelPayloadLedgerAppend",
|
|
133
|
+
]
|
|
@@ -876,6 +876,7 @@ class RegistrationReducer:
|
|
|
876
876
|
service_name=service_name,
|
|
877
877
|
tags=tags,
|
|
878
878
|
health_check=health_check,
|
|
879
|
+
event_bus_config=event.event_bus, # Pass through from introspection event
|
|
879
880
|
)
|
|
880
881
|
|
|
881
882
|
# ModelIntent.payload expects ProtocolIntentPayload, which our model implements
|
|
@@ -8,6 +8,7 @@ components in the ONEX ecosystem.
|
|
|
8
8
|
Protocols:
|
|
9
9
|
- ProtocolCapabilityProjection: Interface for capability-based projection queries
|
|
10
10
|
- ProtocolCapabilityQuery: Interface for capability-based node discovery service
|
|
11
|
+
- ProtocolDispatchEngine: Interface for message dispatch engines
|
|
11
12
|
- ProtocolEventBusLike: Interface for event bus abstraction (used by introspection)
|
|
12
13
|
- ProtocolIdempotencyStore: Interface for idempotency checking and deduplication
|
|
13
14
|
- ProtocolMessageDispatcher: Interface for message dispatchers
|
|
@@ -63,6 +64,7 @@ from omnibase_infra.protocols.protocol_capability_projection import (
|
|
|
63
64
|
)
|
|
64
65
|
from omnibase_infra.protocols.protocol_capability_query import ProtocolCapabilityQuery
|
|
65
66
|
from omnibase_infra.protocols.protocol_container_aware import ProtocolContainerAware
|
|
67
|
+
from omnibase_infra.protocols.protocol_dispatch_engine import ProtocolDispatchEngine
|
|
66
68
|
from omnibase_infra.protocols.protocol_event_bus_like import ProtocolEventBusLike
|
|
67
69
|
from omnibase_infra.protocols.protocol_event_projector import ProtocolEventProjector
|
|
68
70
|
from omnibase_infra.protocols.protocol_idempotency_store import (
|
|
@@ -90,6 +92,7 @@ __all__: list[str] = [
|
|
|
90
92
|
"ProtocolEventBusLike",
|
|
91
93
|
"ProtocolEventProjector",
|
|
92
94
|
"ProtocolContainerAware",
|
|
95
|
+
"ProtocolDispatchEngine",
|
|
93
96
|
"ProtocolIdempotencyStore",
|
|
94
97
|
"ProtocolMessageDispatcher",
|
|
95
98
|
"ProtocolMessageTypeRegistry",
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Copyright (c) 2025 OmniNode Team
|
|
2
|
+
"""Protocol definition for dispatch engine interface.
|
|
3
|
+
|
|
4
|
+
This module defines the ProtocolDispatchEngine interface for dispatch engines
|
|
5
|
+
that route event envelopes to appropriate handlers based on topic. The primary
|
|
6
|
+
implementation is MessageDispatchEngine in the runtime module.
|
|
7
|
+
|
|
8
|
+
Architecture:
|
|
9
|
+
The dispatch engine sits between event bus consumption and handler execution:
|
|
10
|
+
|
|
11
|
+
Kafka/EventBus -> EventBusSubcontractWiring -> ProtocolDispatchEngine -> Handlers
|
|
12
|
+
|
|
13
|
+
The wiring layer uses this protocol for duck-typed dispatch engine injection,
|
|
14
|
+
enabling both production MessageDispatchEngine and test mocks.
|
|
15
|
+
|
|
16
|
+
Thread Safety:
|
|
17
|
+
Implementations MUST be thread-safe for concurrent async dispatch calls.
|
|
18
|
+
Multiple coroutines may invoke dispatch() simultaneously from event bus
|
|
19
|
+
callbacks.
|
|
20
|
+
|
|
21
|
+
Design Requirements:
|
|
22
|
+
- Use asyncio.Lock for shared mutable state (e.g., routing tables)
|
|
23
|
+
- Dispatch operations should be stateless where possible
|
|
24
|
+
- Handler invocations may run concurrently
|
|
25
|
+
|
|
26
|
+
Related:
|
|
27
|
+
- OMN-1621: Runtime consumes event_bus subcontract for contract-driven wiring
|
|
28
|
+
- EventBusSubcontractWiring: Uses this protocol for dispatch engine injection
|
|
29
|
+
- MessageDispatchEngine: Production implementation of this protocol
|
|
30
|
+
|
|
31
|
+
.. versionadded:: 0.2.5
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
from __future__ import annotations
|
|
35
|
+
|
|
36
|
+
__all__ = ["ProtocolDispatchEngine"]
|
|
37
|
+
|
|
38
|
+
from typing import TYPE_CHECKING, Protocol, runtime_checkable
|
|
39
|
+
|
|
40
|
+
if TYPE_CHECKING:
|
|
41
|
+
from omnibase_core.models.events.model_event_envelope import ModelEventEnvelope
|
|
42
|
+
from omnibase_infra.models.dispatch.model_dispatch_result import ModelDispatchResult
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@runtime_checkable
|
|
46
|
+
class ProtocolDispatchEngine(Protocol):
|
|
47
|
+
"""Protocol for dispatch engines that route event envelopes to handlers.
|
|
48
|
+
|
|
49
|
+
Dispatch engines are responsible for routing incoming event envelopes
|
|
50
|
+
to the appropriate handlers based on topic and message type. The protocol
|
|
51
|
+
enables duck-typed injection of dispatch engines into the event bus wiring
|
|
52
|
+
layer.
|
|
53
|
+
|
|
54
|
+
Protocol Verification:
|
|
55
|
+
Per ONEX conventions, protocol compliance is verified via duck typing
|
|
56
|
+
rather than isinstance checks:
|
|
57
|
+
|
|
58
|
+
.. code-block:: python
|
|
59
|
+
|
|
60
|
+
# Verify required method exists and is callable
|
|
61
|
+
if hasattr(engine, 'dispatch') and callable(engine.dispatch):
|
|
62
|
+
wiring = EventBusSubcontractWiring(
|
|
63
|
+
event_bus=event_bus,
|
|
64
|
+
dispatch_engine=engine,
|
|
65
|
+
environment="dev",
|
|
66
|
+
)
|
|
67
|
+
else:
|
|
68
|
+
raise TypeError("Object does not implement ProtocolDispatchEngine")
|
|
69
|
+
|
|
70
|
+
Example:
|
|
71
|
+
.. code-block:: python
|
|
72
|
+
|
|
73
|
+
from omnibase_infra.protocols import ProtocolDispatchEngine
|
|
74
|
+
from omnibase_core.models.events.model_event_envelope import ModelEventEnvelope
|
|
75
|
+
|
|
76
|
+
class MyDispatchEngine:
|
|
77
|
+
'''Custom dispatch engine implementation.'''
|
|
78
|
+
|
|
79
|
+
async def dispatch(
|
|
80
|
+
self,
|
|
81
|
+
topic: str,
|
|
82
|
+
envelope: ModelEventEnvelope[object],
|
|
83
|
+
) -> ModelDispatchResult | None:
|
|
84
|
+
'''Dispatch envelope to appropriate handler.'''
|
|
85
|
+
handler = self._resolve_handler(topic, envelope)
|
|
86
|
+
return await handler.handle(envelope)
|
|
87
|
+
|
|
88
|
+
# Verify protocol compliance via duck typing
|
|
89
|
+
engine = MyDispatchEngine()
|
|
90
|
+
assert hasattr(engine, 'dispatch') and callable(engine.dispatch)
|
|
91
|
+
|
|
92
|
+
Note:
|
|
93
|
+
Method bodies in this Protocol use ``...`` (Ellipsis) rather than
|
|
94
|
+
``raise NotImplementedError()``. This is the standard Python convention
|
|
95
|
+
for ``typing.Protocol`` classes per PEP 544.
|
|
96
|
+
|
|
97
|
+
.. versionadded:: 0.2.5
|
|
98
|
+
"""
|
|
99
|
+
|
|
100
|
+
async def dispatch(
|
|
101
|
+
self,
|
|
102
|
+
topic: str,
|
|
103
|
+
envelope: ModelEventEnvelope[object],
|
|
104
|
+
) -> ModelDispatchResult | None:
|
|
105
|
+
"""Dispatch an event envelope to the appropriate handler(s).
|
|
106
|
+
|
|
107
|
+
Routes the envelope to handlers registered for the given topic.
|
|
108
|
+
The dispatch engine resolves handlers based on topic patterns,
|
|
109
|
+
message types, and other routing criteria.
|
|
110
|
+
|
|
111
|
+
Typing Note (ModelEventEnvelope[object]):
|
|
112
|
+
The envelope parameter uses ``ModelEventEnvelope[object]`` instead of
|
|
113
|
+
``Any`` per CLAUDE.md guidance: "Use ``object`` for generic payloads".
|
|
114
|
+
|
|
115
|
+
This is intentional:
|
|
116
|
+
- CLAUDE.md mandates "NEVER use ``Any``" and specifies ``object`` for
|
|
117
|
+
generic payloads that can accept multiple event types
|
|
118
|
+
- The dispatch engine handles envelopes from multiple topics with
|
|
119
|
+
different payload types
|
|
120
|
+
- Handler implementations use ``isinstance()`` type guards for
|
|
121
|
+
payload-specific processing
|
|
122
|
+
|
|
123
|
+
Thread Safety:
|
|
124
|
+
This method MUST be safe for concurrent calls from multiple
|
|
125
|
+
coroutines. The event bus wiring layer may dispatch messages
|
|
126
|
+
from multiple topic subscriptions concurrently.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
topic: The full topic name from which the envelope was consumed.
|
|
130
|
+
Used for routing and logging context.
|
|
131
|
+
Example: "dev.onex.evt.node.introspected.v1"
|
|
132
|
+
envelope: The deserialized event envelope containing the payload.
|
|
133
|
+
The payload type varies by topic/event type.
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
ModelDispatchResult if the implementation returns dispatch metrics/results,
|
|
137
|
+
None if the implementation does not track results. Callers should not
|
|
138
|
+
depend on the return value for correctness.
|
|
139
|
+
|
|
140
|
+
Raises:
|
|
141
|
+
InfraDispatchError: If no handler is registered for the topic/message type.
|
|
142
|
+
OnexError: For handler execution failures (implementation-specific).
|
|
143
|
+
|
|
144
|
+
Example:
|
|
145
|
+
.. code-block:: python
|
|
146
|
+
|
|
147
|
+
# Event bus wiring callback
|
|
148
|
+
async def on_message(message: ProtocolEventMessage) -> None:
|
|
149
|
+
envelope = deserialize(message)
|
|
150
|
+
await dispatch_engine.dispatch(topic, envelope)
|
|
151
|
+
"""
|
|
152
|
+
...
|
|
@@ -90,10 +90,13 @@ from omnibase_infra.runtime.service_kernel import load_runtime_config
|
|
|
90
90
|
from omnibase_infra.runtime.service_kernel import main as kernel_main
|
|
91
91
|
from omnibase_infra.runtime.service_message_dispatch_engine import MessageDispatchEngine
|
|
92
92
|
from omnibase_infra.runtime.models import (
|
|
93
|
+
ModelContractLoadResult,
|
|
93
94
|
ModelProjectorNotificationConfig,
|
|
95
|
+
ModelRuntimeContractConfig,
|
|
94
96
|
ModelRuntimeSchedulerConfig,
|
|
95
97
|
ModelRuntimeSchedulerMetrics,
|
|
96
98
|
ModelRuntimeTick,
|
|
99
|
+
ModelSecurityConfig,
|
|
97
100
|
ModelStateTransitionNotification,
|
|
98
101
|
ModelTransitionNotificationPublisherMetrics,
|
|
99
102
|
)
|
|
@@ -182,6 +185,16 @@ from omnibase_infra.runtime.protocol_handler_plugin_loader import (
|
|
|
182
185
|
ProtocolHandlerPluginLoader,
|
|
183
186
|
)
|
|
184
187
|
|
|
188
|
+
# Binding expression resolver (OMN-1518)
|
|
189
|
+
from omnibase_infra.runtime.binding_resolver import (
|
|
190
|
+
BindingExpressionParser,
|
|
191
|
+
OperationBindingResolver,
|
|
192
|
+
MAX_EXPRESSION_LENGTH,
|
|
193
|
+
MAX_PATH_SEGMENTS,
|
|
194
|
+
VALID_CONTEXT_PATHS,
|
|
195
|
+
VALID_SOURCES,
|
|
196
|
+
)
|
|
197
|
+
|
|
185
198
|
# Handler discovery protocol and implementation (OMN-1133)
|
|
186
199
|
from omnibase_infra.runtime.protocol_handler_discovery import (
|
|
187
200
|
ProtocolHandlerDiscovery,
|
|
@@ -221,6 +234,27 @@ from omnibase_infra.runtime.transition_notification_outbox import (
|
|
|
221
234
|
TransitionNotificationOutbox,
|
|
222
235
|
)
|
|
223
236
|
|
|
237
|
+
# Topic-scoped publisher (OMN-1621)
|
|
238
|
+
from omnibase_infra.runtime.publisher_topic_scoped import PublisherTopicScoped
|
|
239
|
+
|
|
240
|
+
# Event bus subcontract wiring (OMN-1621)
|
|
241
|
+
from omnibase_infra.runtime.event_bus_subcontract_wiring import (
|
|
242
|
+
EventBusSubcontractWiring,
|
|
243
|
+
load_event_bus_subcontract,
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
# Runtime contract config loader (OMN-1519)
|
|
247
|
+
from omnibase_infra.runtime.runtime_contract_config_loader import (
|
|
248
|
+
RuntimeContractConfigLoader,
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
# Security constants (OMN-1519)
|
|
252
|
+
from omnibase_infra.runtime.constants_security import (
|
|
253
|
+
ALLOW_NAMESPACE_OVERRIDE_ENV_VAR,
|
|
254
|
+
SECURITY_CONFIG_PATH_ENV_VAR,
|
|
255
|
+
TRUSTED_HANDLER_NAMESPACE_PREFIXES,
|
|
256
|
+
)
|
|
257
|
+
|
|
224
258
|
# Registry contract source (OMN-1100)
|
|
225
259
|
from omnibase_infra.runtime.registry_contract_source import (
|
|
226
260
|
DEFAULT_CONSUL_HOST,
|
|
@@ -235,6 +269,9 @@ from omnibase_infra.runtime.registry_contract_source import (
|
|
|
235
269
|
store_contract_in_consul,
|
|
236
270
|
)
|
|
237
271
|
|
|
272
|
+
# Kafka contract source (OMN-1654)
|
|
273
|
+
from omnibase_infra.runtime.kafka_contract_source import KafkaContractSource
|
|
274
|
+
|
|
238
275
|
# Chain-aware dispatch (OMN-951) - must be imported LAST to avoid circular import
|
|
239
276
|
from omnibase_infra.runtime.chain_aware_dispatch import (
|
|
240
277
|
ChainAwareDispatcher,
|
|
@@ -266,9 +303,11 @@ __all__: list[str] = [
|
|
|
266
303
|
"MessageDispatchEngine",
|
|
267
304
|
# Message type registry (OMN-937)
|
|
268
305
|
"MessageTypeRegistryError",
|
|
306
|
+
"ModelContractLoadResult",
|
|
269
307
|
"ModelDomainConstraint",
|
|
270
308
|
"ModelMessageTypeEntry",
|
|
271
309
|
"ModelProjectorNotificationConfig",
|
|
310
|
+
"ModelRuntimeContractConfig",
|
|
272
311
|
"ModelRuntimeSchedulerConfig",
|
|
273
312
|
"ModelRuntimeSchedulerMetrics",
|
|
274
313
|
"ModelRuntimeTick",
|
|
@@ -354,6 +393,13 @@ __all__: list[str] = [
|
|
|
354
393
|
"load_handler_contract_config",
|
|
355
394
|
# Binding config resolver (OMN-765)
|
|
356
395
|
"BindingConfigResolver",
|
|
396
|
+
# Binding expression resolver (OMN-1518)
|
|
397
|
+
"BindingExpressionParser",
|
|
398
|
+
"OperationBindingResolver",
|
|
399
|
+
"MAX_EXPRESSION_LENGTH",
|
|
400
|
+
"MAX_PATH_SEGMENTS",
|
|
401
|
+
"VALID_CONTEXT_PATHS",
|
|
402
|
+
"VALID_SOURCES",
|
|
357
403
|
# Handler discovery protocol and implementation (OMN-1133)
|
|
358
404
|
"ContractHandlerDiscovery",
|
|
359
405
|
"ProtocolHandlerDiscovery",
|
|
@@ -371,6 +417,18 @@ __all__: list[str] = [
|
|
|
371
417
|
# Transition notification publisher and outbox (OMN-1139)
|
|
372
418
|
"TransitionNotificationOutbox",
|
|
373
419
|
"TransitionNotificationPublisher",
|
|
420
|
+
# Topic-scoped publisher (OMN-1621)
|
|
421
|
+
"PublisherTopicScoped",
|
|
422
|
+
# Event bus subcontract wiring (OMN-1621)
|
|
423
|
+
"EventBusSubcontractWiring",
|
|
424
|
+
"load_event_bus_subcontract",
|
|
425
|
+
# Runtime contract config loader (OMN-1519)
|
|
426
|
+
"RuntimeContractConfigLoader",
|
|
427
|
+
# Security constants and configuration (OMN-1519)
|
|
428
|
+
"ALLOW_NAMESPACE_OVERRIDE_ENV_VAR",
|
|
429
|
+
"ModelSecurityConfig",
|
|
430
|
+
"SECURITY_CONFIG_PATH_ENV_VAR",
|
|
431
|
+
"TRUSTED_HANDLER_NAMESPACE_PREFIXES",
|
|
374
432
|
# Registry contract source (OMN-1100)
|
|
375
433
|
"DEFAULT_CONSUL_HOST",
|
|
376
434
|
"DEFAULT_CONSUL_PORT",
|
|
@@ -382,4 +440,6 @@ __all__: list[str] = [
|
|
|
382
440
|
"delete_contract_from_consul",
|
|
383
441
|
"list_contracts_in_consul",
|
|
384
442
|
"store_contract_in_consul",
|
|
443
|
+
# Kafka contract source (OMN-1654)
|
|
444
|
+
"KafkaContractSource",
|
|
385
445
|
]
|