Topics and streaming¶
Topic
¶
Topic(
name: str,
maxsize: int = DEFAULT_MAXSIZE,
policy: str = DROP_OLDEST,
backend: Any = None,
)
A named fan-out point shared by every worker loop in the process.
With a backend it is also shared across processes: emitting appends to a Redis stream, and a tail task in every other process feeds its local subscribers. The publishing process delivers locally itself and the tail skips its own node, so nobody sees a message twice.
Source code in python/aether/_streams.py
subscribers
property
¶
Local subscribers only. Other processes are not visible from here.
history
async
¶
Recent messages, oldest first. Durable topics only.
Source code in python/aether/_streams.py
consumer
¶
A member of a consumer group, for at-least-once processing.
Unlike subscribe, which is a broadcast to everyone, each message goes
to exactly one member of the group and stays pending until acked.
Source code in python/aether/_streams.py
subscribe
¶
subscribe(
maxsize: int | None = None, policy: str | None = None
) -> Subscription
Start receiving. Must be called from inside a running event loop.
The subscription binds to the loop it was created on, which is how a producer on another worker knows where to deliver.
Source code in python/aether/_streams.py
emit
async
¶
Deliver to every local subscriber. Returns how many received it.
On a durable topic the message is appended to the stream first, so that returning means it is recorded and other processes will see it. That costs a round trip, which is the trade being made by asking for durability.
Only awaits on a local subscriber when it uses the block policy and
is full.
Source code in python/aether/_streams.py
emit_nowait
¶
Deliver to local subscribers without ever waiting.
A block subscriber that is full is treated as drop_newest, because
the alternative here would be blocking a thread that must not block.
Refused on a durable topic: appending to the stream is an await, so this
could only ever deliver locally, and a call named emit that silently
skipped durability is worse than an error.
Source code in python/aether/_streams.py
Subscription
¶
Subscription(topic: Topic, maxsize: int, policy: str, loop)
One subscriber's view of a topic. Async-iterable, and closeable.
Source code in python/aether/_streams.py
close
¶
Stop the iterator and release anyone waiting on it.
Source code in python/aether/_streams.py
TopicFull
¶
Bases: Exception
A subscriber's buffer is full and its policy is error.
Backpressure policies¶
Server-Sent Events¶
SSE
¶
A streaming text/event-stream response.
ping sends a comment line when idle that long, which stops proxies
and load balancers from closing an idle connection. None disables it.
Source code in python/aether/_sse.py
Event
dataclass
¶
One event, when the defaults are not enough.
Yield plain values for the common case; yield this to set a name, an id for resumption, or a client retry hint.
event and id may not contain a line break or a NUL; both raise
ValueError. Checked here so the traceback points at the code that built
the event, and again at render time, because this is a mutable dataclass
and the fields can be reassigned afterwards.
WebSocket¶
WebSocket
¶
An open connection. Async-iterable over incoming messages.
Source code in python/aether/_websocket.py
receive
async
¶
Next message, or None once the peer has closed.
Source code in python/aether/_websocket.py
receive_json
async
¶
Source code in python/aether/_websocket.py
send
async
¶
Send a message.
str goes as text and bytes as binary. Anything else is serialized
to JSON, which covers dicts and pydantic models.
Source code in python/aether/_websocket.py
send_json
async
¶
WebSocketClosed
¶
Bases: Exception
A send was attempted after the peer went away.