SDK · 08

Synapse - transport adapters

A Synapse is the message bus. The application picks a backend, passes the adapter to the Dendrite, and never touches the wire format again. All adapters subclass the same abstract Synapse base.

abstract basecosmonapse.Synapse

The contract every transport adapter must satisfy. Adapters are responsible for ordering, dedup window, ack semantics, and durability - the SDK assumes at-least-once delivery and in-order per key.

synapse.pyi
class Synapse(ABC):
    async def connect(self) -> None: ...
    async def close(self)   -> None: ...

    async def publish(self, subject: str, signal: Signal) -> None: ...

    async def subscribe(
        self,
        subject:    str,
        handler:    Callable[[Signal], Awaitable[None]],
        *,
        queue_group: str | None = None,
    ) -> Subscription: ...

    async def request(
        self,
        subject: str,
        signal:  Signal,
        *,
        timeout_s: float = 5.0,
    ) -> Signal: ...

Bundled adapters

ClassProcess boundaryUse when
MemorySynapsesingle processTests, tightly-coupled callers, embedded supervisor processes.
DevSynapselocal host, many processesClient side of cosmo synapse start. TCP + NDJSON; single-host dev only; zero external deps.
NatsSynapseclusterProduction default. Native wildcards and queue groups; low latency. Needs the [nats] extra.
KafkaSynapseclusterDurable audit log. Trickier request/reply; recommended when retention matters more than latency.

URL factory

functionsynapse_from_url(url: str) -> Synapse

Map a cosmo:// / nats:// / kafka:// URL to a non-connected adapter instance. Raises ValueError for any other scheme. MemorySynapse has no URL - build it directly.

async functionconnect_synapse(url: str) -> Synapse

Same as synapse_from_url but immediately calls connect().

urls.py
from cosmonapse import synapse_from_url, connect_synapse, MemorySynapse

# Build (does not connect):
syn = synapse_from_url("cosmo://localhost:7070")    # DevSynapse
syn = synapse_from_url("nats://nats:4222")            # NatsSynapse
syn = synapse_from_url("kafka://broker:9092")         # KafkaSynapse

# memory:// has no URL  -  it is process-local, so build it directly:
syn = MemorySynapse()

# Build + connect in one call:
syn = await connect_synapse("cosmo://127.0.0.1:7070")
URL schemeResolves to
cosmo://host:portDevSynapse client (talks to cosmo synapse start)
nats://host:portNatsSynapse
kafka://host:portKafkaSynapse
(no URL)MemorySynapse - construct directly, it is process-local

Subjects

Subjects follow cosmonapse.<namespace>.<TYPE>. Queue groups load-balance within a group; subscribers with no queue_group form the Doppler population (every matching message goes to each one). Application code must never construct subjects directly - let the Dendrite resolve them.

Have a feature in mind?

The protocol, SDKs, and CLI are still pre-1.0. If something here is missing, ambiguous, or wrong - open an issue and propose a change. Every breaking change is debated in DECISIONS.md first.