ropemother 0.1.0.dev8__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.
- ropemother/__init__.py +46 -0
- ropemother/bootstrap/__init__.py +11 -0
- ropemother/bootstrap/buffer.py +127 -0
- ropemother/bootstrap/policy.py +105 -0
- ropemother/broker/__init__.py +37 -0
- ropemother/broker/asyncbase.py +58 -0
- ropemother/broker/asyncdirect.py +349 -0
- ropemother/broker/asyncendpoints.py +106 -0
- ropemother/broker/base.py +59 -0
- ropemother/broker/direct.py +338 -0
- ropemother/broker/directcore.py +863 -0
- ropemother/broker/dispatch.py +66 -0
- ropemother/broker/endpoints.py +152 -0
- ropemother/broker/subscription.py +34 -0
- ropemother/capture/__init__.py +52 -0
- ropemother/capture/controller.py +207 -0
- ropemother/capture/filehistory.py +239 -0
- ropemother/capture/filesink.py +72 -0
- ropemother/capture/history.py +405 -0
- ropemother/capture/historyselection.py +69 -0
- ropemother/capture/historyservice.py +763 -0
- ropemother/capture/jsonrecords.py +251 -0
- ropemother/capture/memorysink.py +64 -0
- ropemother/capture/runtime.py +33 -0
- ropemother/capture/sink.py +64 -0
- ropemother/capture/writer.py +83 -0
- ropemother/client/__init__.py +58 -0
- ropemother/client/asyncendpointfactory.py +146 -0
- ropemother/client/asyncendpointprovisioner.py +383 -0
- ropemother/client/asyncrequest.py +405 -0
- ropemother/client/endpointfactory.py +141 -0
- ropemother/client/endpointfactorybase.py +378 -0
- ropemother/client/lifecycle.py +75 -0
- ropemother/client/procedure.py +151 -0
- ropemother/client/request.py +568 -0
- ropemother/client/requestoptions.py +23 -0
- ropemother/exceptions.py +61 -0
- ropemother/fixtures/__init__.py +30 -0
- ropemother/fixtures/scriptedinput.py +437 -0
- ropemother/format/__init__.py +60 -0
- ropemother/format/defaults.py +42 -0
- ropemother/format/formattable.py +39 -0
- ropemother/format/portableformat.py +191 -0
- ropemother/format/registry.py +201 -0
- ropemother/message/__init__.py +37 -0
- ropemother/message/messageidentity.py +23 -0
- ropemother/message/records.py +121 -0
- ropemother/message/registrationtable.py +185 -0
- ropemother/message/selectors.py +191 -0
- ropemother/message/symbols.py +241 -0
- ropemother/message/typeformats.py +239 -0
- ropemother/playground.py +7841 -0
- ropemother/service/__init__.py +61 -0
- ropemother/service/__main__.py +19 -0
- ropemother/service/asyncservice.py +184 -0
- ropemother/service/broker.py +278 -0
- ropemother/service/brokerextension.py +31 -0
- ropemother/service/brokerhistory.py +78 -0
- ropemother/service/connector.py +91 -0
- ropemother/service/descriptor.py +104 -0
- ropemother/service/environment.py +161 -0
- ropemother/service/host.py +272 -0
- ropemother/service/listener.py +47 -0
- ropemother/service/resource.py +58 -0
- ropemother/service/service.py +200 -0
- ropemother/service/socketlistener.py +280 -0
- ropemother/transport/__init__.py +46 -0
- ropemother/transport/asyncclient.py +694 -0
- ropemother/transport/asyncconnection.py +101 -0
- ropemother/transport/asyncsession.py +304 -0
- ropemother/transport/asyncsessionrunner.py +108 -0
- ropemother/transport/asyncsocketconnection.py +102 -0
- ropemother/transport/client.py +679 -0
- ropemother/transport/codec.py +743 -0
- ropemother/transport/connection.py +105 -0
- ropemother/transport/endpointregistration.py +86 -0
- ropemother/transport/frames.py +150 -0
- ropemother/transport/session.py +293 -0
- ropemother/transport/sessionrunner.py +107 -0
- ropemother/transport/sessionstate.py +119 -0
- ropemother/transport/socketconnection.py +81 -0
- ropemother/transport/socketframing.py +98 -0
- ropemother/transport/zeromq/__init__.py +11 -0
- ropemother/transport/zeromq/address.py +29 -0
- ropemother/transport/zeromq/connection.py +169 -0
- ropemother/util/__init__.py +57 -0
- ropemother/util/compositeblobserializer.py +110 -0
- ropemother/util/lengthprefixed.py +112 -0
- ropemother/util/onelinejson.py +62 -0
- ropemother/util/serializer.py +101 -0
- ropemother/util/symbol.py +34 -0
- ropemother/util/typedid.py +66 -0
- ropemother-0.1.0.dev8.dist-info/METADATA +462 -0
- ropemother-0.1.0.dev8.dist-info/RECORD +97 -0
- ropemother-0.1.0.dev8.dist-info/WHEEL +5 -0
- ropemother-0.1.0.dev8.dist-info/licenses/LICENSE +9 -0
- ropemother-0.1.0.dev8.dist-info/top_level.txt +1 -0
ropemother/__init__.py
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# ropemother/__init__.py
|
|
3
|
+
|
|
4
|
+
"""A module for publish-subscribe broadcast messaging."""
|
|
5
|
+
|
|
6
|
+
from importlib import import_module
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
__author__ = "Joe Granville"
|
|
10
|
+
__email__ = "874605+jwgranville@users.noreply.github.com"
|
|
11
|
+
__date__ = "2026-07-05T15:40:19+00:00"
|
|
12
|
+
__license__ = "MIT"
|
|
13
|
+
__version__ = "0.1.0.dev8"
|
|
14
|
+
__status__ = "Development"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
_EXPORTS = {
|
|
18
|
+
"AsyncDirectMessageBus": "ropemother.broker.asyncdirect",
|
|
19
|
+
"CAPTURE_PORTABLE_FORMAT": "ropemother.format.portableformat",
|
|
20
|
+
"CaptureMode": "ropemother.broker.directcore",
|
|
21
|
+
"DirectMessageBus": "ropemother.broker.direct",
|
|
22
|
+
"InMemoryCaptureSink": "ropemother.capture.memorysink",
|
|
23
|
+
"JSONLinesCaptureSink": "ropemother.capture.filesink",
|
|
24
|
+
"JSON_PORTABLE_FORMAT": "ropemother.format.portableformat",
|
|
25
|
+
"MessageBusBaseException": "ropemother.exceptions",
|
|
26
|
+
"PayloadSerializationError": "ropemother.exceptions",
|
|
27
|
+
"PortableFormat": "ropemother.format.portableformat",
|
|
28
|
+
"RAW_BYTES_PORTABLE_FORMAT": "ropemother.format.portableformat",
|
|
29
|
+
"ReceivedMessage": "ropemother.message.records",
|
|
30
|
+
"connect_async_message_bus": "ropemother.service.environment",
|
|
31
|
+
"connect_message_bus": "ropemother.service.environment",
|
|
32
|
+
"exact_topic": "ropemother.message.selectors",
|
|
33
|
+
"topic_tree": "ropemother.message.selectors",
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
__all__ = list(_EXPORTS)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def __getattr__(name: str) -> Any:
|
|
40
|
+
if name not in _EXPORTS:
|
|
41
|
+
raise AttributeError(name)
|
|
42
|
+
|
|
43
|
+
module = import_module(_EXPORTS[name])
|
|
44
|
+
value = getattr(module, name)
|
|
45
|
+
globals()[name] = value
|
|
46
|
+
return value
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# ropemother/bootstrap/__init__.py
|
|
3
|
+
|
|
4
|
+
"""Implements startup message buffering policy."""
|
|
5
|
+
|
|
6
|
+
__author__ = "Joe Granville"
|
|
7
|
+
__email__ = "874605+jwgranville@users.noreply.github.com"
|
|
8
|
+
__date__ = "2026-07-01T20:13:04+00:00"
|
|
9
|
+
__license__ = "MIT"
|
|
10
|
+
__version__ = "0.1.0.dev8"
|
|
11
|
+
__status__ = "Development"
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# ropemother/bootstrap/buffer.py
|
|
3
|
+
|
|
4
|
+
"""Support for bootstrap buffering of capture records at startup."""
|
|
5
|
+
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
|
|
8
|
+
from ropemother.capture.sink import CaptureSink
|
|
9
|
+
from ropemother.capture.writer import CaptureRecord, CaptureRecordWriter
|
|
10
|
+
from ropemother.exceptions import MessageBusBaseException
|
|
11
|
+
from ropemother.format.registry import PortableFormatRegistration
|
|
12
|
+
from ropemother.message.records import CapturedMessage
|
|
13
|
+
from ropemother.message.symbols import MessageSymbolRegistration
|
|
14
|
+
|
|
15
|
+
__author__ = "Joe Granville"
|
|
16
|
+
__email__ = "874605+jwgranville@users.noreply.github.com"
|
|
17
|
+
__date__ = "2026-07-02T07:00:19+00:00"
|
|
18
|
+
__license__ = "MIT"
|
|
19
|
+
__version__ = "0.1.0.dev8"
|
|
20
|
+
__status__ = "Development"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
DEFAULT_BOOTSTRAP_BUFFER_BYTES = 4 * 1024 * 1024
|
|
24
|
+
DEFAULT_BOOTSTRAP_BUFFER_RECORD_LIMIT = 256
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class BootstrapBufferError(MessageBusBaseException):
|
|
28
|
+
"""Base exception for bootstrap buffer errors."""
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class InvalidBootstrapBufferLimitError(ValueError, BootstrapBufferError):
|
|
33
|
+
"""Raised when bootstrap buffer limits are invalid."""
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class BootstrapBufferLimitExceededError(BufferError, BootstrapBufferError):
|
|
38
|
+
"""Raised when bootstrap buffering exceeds configured limits."""
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@dataclass(frozen=True, kw_only=True)
|
|
43
|
+
class BootstrapBufferLimits:
|
|
44
|
+
"""Record and payload byte limits for bootstrap buffering."""
|
|
45
|
+
max_records: int = DEFAULT_BOOTSTRAP_BUFFER_RECORD_LIMIT
|
|
46
|
+
max_payload_bytes: int = DEFAULT_BOOTSTRAP_BUFFER_BYTES
|
|
47
|
+
|
|
48
|
+
def __post_init__(self) -> None:
|
|
49
|
+
if self.max_records < 1:
|
|
50
|
+
raise InvalidBootstrapBufferLimitError(
|
|
51
|
+
"bootstrap buffer record limit must be positive"
|
|
52
|
+
)
|
|
53
|
+
if self.max_payload_bytes < 0:
|
|
54
|
+
raise InvalidBootstrapBufferLimitError(
|
|
55
|
+
"bootstrap buffer payload byte limit must not be negative"
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class BootstrapBuffer(CaptureRecordWriter):
|
|
60
|
+
"""Temporary capture record writer used during broker bootstrap."""
|
|
61
|
+
_limits: BootstrapBufferLimits
|
|
62
|
+
_records: list[CaptureRecord]
|
|
63
|
+
_payload_bytes: int
|
|
64
|
+
|
|
65
|
+
def __init__(self, *, limits: BootstrapBufferLimits | None = None) -> None:
|
|
66
|
+
if limits is None:
|
|
67
|
+
limits = BootstrapBufferLimits()
|
|
68
|
+
|
|
69
|
+
self._limits = limits
|
|
70
|
+
self._records = []
|
|
71
|
+
self._payload_bytes = 0
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def pending_record_count(self) -> int:
|
|
75
|
+
return len(self._records)
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def pending_payload_bytes(self) -> int:
|
|
79
|
+
return self._payload_bytes
|
|
80
|
+
|
|
81
|
+
def pending_records(self) -> tuple[CaptureRecord, ...]:
|
|
82
|
+
return tuple(self._records)
|
|
83
|
+
|
|
84
|
+
def clear(self) -> None:
|
|
85
|
+
self._records.clear()
|
|
86
|
+
self._payload_bytes = 0
|
|
87
|
+
|
|
88
|
+
def flush_to(self, capture_sink: CaptureSink) -> None:
|
|
89
|
+
for record in self._records:
|
|
90
|
+
capture_sink.write_record(record)
|
|
91
|
+
|
|
92
|
+
self.clear()
|
|
93
|
+
|
|
94
|
+
def write_message_record(self, message: CapturedMessage) -> None:
|
|
95
|
+
self._append_record(message)
|
|
96
|
+
|
|
97
|
+
def write_format_registration(
|
|
98
|
+
self, registration: PortableFormatRegistration
|
|
99
|
+
) -> None:
|
|
100
|
+
self._append_record(registration)
|
|
101
|
+
|
|
102
|
+
def write_symbol_registration(
|
|
103
|
+
self, registration: MessageSymbolRegistration
|
|
104
|
+
) -> None:
|
|
105
|
+
self._append_record(registration)
|
|
106
|
+
|
|
107
|
+
def _append_record(self, record: CaptureRecord) -> None:
|
|
108
|
+
candidate_payload_bytes = self._payload_byte_count(record)
|
|
109
|
+
next_record_count = len(self._records) + 1
|
|
110
|
+
next_payload_bytes = self._payload_bytes + candidate_payload_bytes
|
|
111
|
+
|
|
112
|
+
if next_record_count > self._limits.max_records:
|
|
113
|
+
raise BootstrapBufferLimitExceededError(
|
|
114
|
+
"bootstrap buffer record limit exceeded"
|
|
115
|
+
)
|
|
116
|
+
if next_payload_bytes > self._limits.max_payload_bytes:
|
|
117
|
+
raise BootstrapBufferLimitExceededError(
|
|
118
|
+
"bootstrap buffer payload byte limit exceeded"
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
self._records.append(record)
|
|
122
|
+
self._payload_bytes = next_payload_bytes
|
|
123
|
+
|
|
124
|
+
def _payload_byte_count(self, record: CaptureRecord) -> int:
|
|
125
|
+
if isinstance(record, CapturedMessage):
|
|
126
|
+
return len(record.serialized_payload.payload_bytes)
|
|
127
|
+
return 0
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# ropemother/bootstrap/policy.py
|
|
3
|
+
|
|
4
|
+
"""Bootstrap traffic policy objects."""
|
|
5
|
+
|
|
6
|
+
from abc import ABC, abstractmethod
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from enum import StrEnum
|
|
9
|
+
|
|
10
|
+
from ropemother.exceptions import MessageBusBaseException
|
|
11
|
+
from ropemother.message.records import BusMessage, BusOperation
|
|
12
|
+
|
|
13
|
+
__author__ = "Joe Granville"
|
|
14
|
+
__email__ = "874605+jwgranville@users.noreply.github.com"
|
|
15
|
+
__date__ = "2026-07-02T07:03:33+00:00"
|
|
16
|
+
__license__ = "MIT"
|
|
17
|
+
__version__ = "0.1.0.dev8"
|
|
18
|
+
__status__ = "Development"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
DEFAULT_LIFECYCLE_TOPIC_ROOT = "lifecycle"
|
|
22
|
+
DEFAULT_LIFECYCLE_OPERATIONS = frozenset({BusOperation.PUBLISH})
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class BootstrapPolicyError(MessageBusBaseException):
|
|
26
|
+
"""Base exception for bootstrap policy errors."""
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class BootstrapMessageRejectedError(RuntimeError, BootstrapPolicyError):
|
|
31
|
+
"""Raised when bootstrap message traffic is rejected."""
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class LifecycleMessageType(StrEnum):
|
|
36
|
+
"""Built-in lifecycle message types allowed during bootstrap."""
|
|
37
|
+
STARTED = "started"
|
|
38
|
+
READY = "ready"
|
|
39
|
+
FAILED = "failed"
|
|
40
|
+
STOPPING = "stopping"
|
|
41
|
+
STOPPED = "stopped"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
DEFAULT_LIFECYCLE_MESSAGE_TYPES = frozenset(
|
|
45
|
+
message_type.value for message_type in LifecycleMessageType
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass(frozen=True, kw_only=True)
|
|
50
|
+
class BootstrapDecision:
|
|
51
|
+
"""Decision result for bootstrap message traffic."""
|
|
52
|
+
accepted: bool
|
|
53
|
+
reason: str = ""
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class BootstrapPolicy(ABC):
|
|
57
|
+
"""Policy interface for deciding bootstrap message traffic."""
|
|
58
|
+
@abstractmethod
|
|
59
|
+
def decide_message(self, message: BusMessage) -> BootstrapDecision:
|
|
60
|
+
pass
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class RejectBootstrapPolicy(BootstrapPolicy):
|
|
64
|
+
"""Bootstrap policy that rejects all message traffic."""
|
|
65
|
+
def decide_message(self, message: BusMessage) -> BootstrapDecision:
|
|
66
|
+
decision = BootstrapDecision(
|
|
67
|
+
accepted=False,
|
|
68
|
+
reason="bootstrap message traffic is not allowed",
|
|
69
|
+
)
|
|
70
|
+
return decision
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@dataclass(frozen=True, kw_only=True)
|
|
74
|
+
class LifecycleBootstrapPolicy(BootstrapPolicy):
|
|
75
|
+
"""Bootstrap policy that permits selected lifecycle messages."""
|
|
76
|
+
topic_root: str = DEFAULT_LIFECYCLE_TOPIC_ROOT
|
|
77
|
+
msg_types: frozenset[str] = DEFAULT_LIFECYCLE_MESSAGE_TYPES
|
|
78
|
+
operations: frozenset[BusOperation] = DEFAULT_LIFECYCLE_OPERATIONS
|
|
79
|
+
|
|
80
|
+
def decide_message(self, message: BusMessage) -> BootstrapDecision:
|
|
81
|
+
if message.bus_operation not in self.operations:
|
|
82
|
+
decision = BootstrapDecision(
|
|
83
|
+
accepted=False,
|
|
84
|
+
reason="bootstrap message operation is not allowed",
|
|
85
|
+
)
|
|
86
|
+
elif not _topic_matches_root(message.msg_topic, self.topic_root):
|
|
87
|
+
decision = BootstrapDecision(
|
|
88
|
+
accepted=False,
|
|
89
|
+
reason="bootstrap message topic is not allowed",
|
|
90
|
+
)
|
|
91
|
+
elif message.msg_type not in self.msg_types:
|
|
92
|
+
decision = BootstrapDecision(
|
|
93
|
+
accepted=False,
|
|
94
|
+
reason="bootstrap message type is not allowed",
|
|
95
|
+
)
|
|
96
|
+
else:
|
|
97
|
+
decision = BootstrapDecision(accepted=True)
|
|
98
|
+
|
|
99
|
+
return decision
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _topic_matches_root(msg_topic: str, topic_root: str) -> bool:
|
|
103
|
+
matches_root = msg_topic == topic_root
|
|
104
|
+
matches_child = msg_topic.startswith(topic_root + ".")
|
|
105
|
+
return matches_root or matches_child
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# ropemother/broker/__init__.py
|
|
3
|
+
|
|
4
|
+
"""Supports and implements runtime publish-subscribe services."""
|
|
5
|
+
|
|
6
|
+
from importlib import import_module
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
__author__ = "Joe Granville"
|
|
10
|
+
__email__ = "874605+jwgranville@users.noreply.github.com"
|
|
11
|
+
__date__ = "2026-06-30T18:59:10+00:00"
|
|
12
|
+
__license__ = "MIT"
|
|
13
|
+
__version__ = "0.1.0.dev8"
|
|
14
|
+
__status__ = "Development"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
_EXPORTS = {
|
|
18
|
+
"AsyncDirectMessageBus": "ropemother.broker.asyncdirect",
|
|
19
|
+
"AsyncEmitter": "ropemother.broker.asyncendpoints",
|
|
20
|
+
"AsyncReceiver": "ropemother.broker.asyncendpoints",
|
|
21
|
+
"CaptureMode": "ropemother.broker.directcore",
|
|
22
|
+
"DirectMessageBus": "ropemother.broker.direct",
|
|
23
|
+
"Emitter": "ropemother.broker.endpoints",
|
|
24
|
+
"Receiver": "ropemother.broker.endpoints",
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
__all__ = list(_EXPORTS)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def __getattr__(name: str) -> Any:
|
|
31
|
+
if name not in _EXPORTS:
|
|
32
|
+
raise AttributeError(name)
|
|
33
|
+
|
|
34
|
+
module = import_module(_EXPORTS[name])
|
|
35
|
+
value = getattr(module, name)
|
|
36
|
+
globals()[name] = value
|
|
37
|
+
return value
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# ropemother/broker/asyncbase.py
|
|
3
|
+
|
|
4
|
+
"""Asynchronous abstract interface for message bus implementation."""
|
|
5
|
+
|
|
6
|
+
import abc
|
|
7
|
+
|
|
8
|
+
from ropemother.broker.asyncendpoints import AsyncEmitter, AsyncReceiver
|
|
9
|
+
from ropemother.capture.sink import CaptureSink
|
|
10
|
+
from ropemother.client.asyncendpointfactory import AsyncMessageEndpointFactory
|
|
11
|
+
from ropemother.format.portableformat import (
|
|
12
|
+
PortableFormat,
|
|
13
|
+
JSON_PORTABLE_FORMAT,
|
|
14
|
+
)
|
|
15
|
+
from ropemother.message.selectors import (
|
|
16
|
+
OptionalSymbolInput,
|
|
17
|
+
SubscriptionTopicInput,
|
|
18
|
+
SymbolCollectionInput,
|
|
19
|
+
)
|
|
20
|
+
from ropemother.message.typeformats import SupportedTypeFormatsInput
|
|
21
|
+
|
|
22
|
+
__author__ = "Joe Granville"
|
|
23
|
+
__email__ = "874605+jwgranville@users.noreply.github.com"
|
|
24
|
+
__date__ = "2026-08-20T17:37:34+00:00"
|
|
25
|
+
__license__ = "MIT"
|
|
26
|
+
__version__ = "0.1.0.dev8"
|
|
27
|
+
__status__ = "Development"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class AsyncMessageBus(AsyncMessageEndpointFactory):
|
|
31
|
+
"""Abstract broker interface for async message bus implementations."""
|
|
32
|
+
@abc.abstractmethod
|
|
33
|
+
def register_emitter(
|
|
34
|
+
self,
|
|
35
|
+
*,
|
|
36
|
+
msg_topic: str,
|
|
37
|
+
msg_producer: str,
|
|
38
|
+
msg_type: str,
|
|
39
|
+
additional_msg_types: SymbolCollectionInput = (),
|
|
40
|
+
allow_unlisted_type_formats: bool = False,
|
|
41
|
+
payload_format: PortableFormat = JSON_PORTABLE_FORMAT,
|
|
42
|
+
supported_type_formats: SupportedTypeFormatsInput | None = None,
|
|
43
|
+
) -> AsyncEmitter:
|
|
44
|
+
...
|
|
45
|
+
|
|
46
|
+
@abc.abstractmethod
|
|
47
|
+
def subscribe(
|
|
48
|
+
self,
|
|
49
|
+
*,
|
|
50
|
+
msg_topic: SubscriptionTopicInput,
|
|
51
|
+
msg_producer: OptionalSymbolInput = None,
|
|
52
|
+
msg_type: OptionalSymbolInput = None,
|
|
53
|
+
) -> AsyncReceiver:
|
|
54
|
+
...
|
|
55
|
+
|
|
56
|
+
@abc.abstractmethod
|
|
57
|
+
def set_capture_sink(self, capture_sink: CaptureSink) -> None:
|
|
58
|
+
...
|