In-process loopback transport for clamator (pre-1.0).
Project description
clamator-over-memory
In-process loopback transport for clamator. The shared MemoryBus connects a MemoryRpcServer and MemoryRpcClient running in the same Python process. Requires Pydantic v2.
Install
pip install clamator-over-memory clamator-protocol
Quickstart
Contracts are authored in TypeScript and the Python sibling is produced by @clamator/codegen:
npx @clamator/codegen --src contracts --out-py generated
The emitted generated/arith.py exports Pydantic models, a typed ArithClient, an ArithService ABC, and the arith_contract Contract object. Wire server and client through a shared bus, talk via ArithClient.
Server-side — register handlers and start:
from clamator_over_memory import MemoryBus, MemoryRpcServer
from .generated.arith import AddParams, AddResult, ArithService, arith_contract
class Arith(ArithService):
async def add(self, params: AddParams) -> AddResult:
return AddResult(sum=params.a + params.b)
async def build_arith_server(bus: MemoryBus) -> MemoryRpcServer:
server = MemoryRpcServer(bus=bus) # no external connection; stop() unregisters from the bus without closing any resource # noqa: E501
server.register_service(arith_contract, Arith()) # must precede start() — post-start registrations are silently ignored, never registered on the bus # noqa: E501
await server.start()
return server
(Verbatim from py/packages/over-memory/tests/server.py:1-15.)
Client-side — call the typed proxy:
from clamator_over_memory import MemoryBus, MemoryRpcClient
from .generated.arith import AddParams, AddResult, ArithClient
async def call_arith(bus: MemoryBus) -> AddResult:
client = MemoryRpcClient(bus=bus) # default timeout 30 s on the full round-trip (call → handler → reply); pass default_timeout_ms to override; no retry; timeouts not propagated to server # noqa: E501
await client.start()
arith = ArithClient(client)
r = await arith.add(AddParams(a=2, b=3))
await client.stop()
return r
(Verbatim from py/packages/over-memory/tests/client.py:1-12.)
server.start() returns once handlers are registered on the bus; it does not block. Your application controls the server's lifetime. Call await server.stop() to shut down — since the loopback is in-process, the drain is instantaneous and the server unregisters from the bus without closing any external resource. start() and stop() are both idempotent (calling either twice is a no-op); once stop() has been called, calling start() again raises — create a new instance to restart.
A single server can host multiple services. Call register_service(contract, handler_obj) once per contract before start(); each is registered as its own dispatcher on the shared bus. Registrations after start() are silently ignored.
MemoryBus() takes no arguments and is the only wiring needed. The loopback is synchronous within a single asyncio task — no timeouts, retries, or stream parameters beyond the client's default_timeout_ms.
Key surface
MemoryBus()— the connecting object passed to both server and client.MemoryRpcServer(bus=...)—register_service(contract, handler_obj),start(),stop().MemoryRpcClient(bus=...)—start(),stop(). Wrap with a generated*Clientproxy for typed calls.
Worker-pool semantics
N/A — this transport is a single-process loopback. Multiple MemoryRpcServer instances on the same MemoryBus do not form a competing-consumers pool because there is no shared substrate; each bus is in-memory to its constructing process. For cross-process worker-pool behavior, use clamator-over-redis.
Owned external state
N/A — MemoryBus owns no external state. There are no Redis keys, no streams, no files, no sockets. The bus is garbage-collected with the process.
Connection ownership
N/A — there is no external connection to own. MemoryRpcServer and MemoryRpcClient share a MemoryBus that lives entirely in-process; stop() releases its references without closing any external resource.
Protocol-level parity with over-redis
Params/result validation, error code mapping, handler exception wrapping, and register_service semantics are identical to clamator-over-redis — both transports share the same dispatcher (RpcServerCore from clamator-protocol). Only the wire substrate differs. Tests written against this transport for protocol-level behaviors translate directly to over-redis.
When to reach for this vs. clamator-over-redis
clamator-over-memory— tests, embedded scenarios, anything single-process.clamator-over-redis— cross-process, cross-host, durable streams, production.
Links
- Sibling (TypeScript):
@clamator/over-memory - Codegen:
@clamator/codegen(run from TS side; consume the generated Python output) - Design spec:
docs/2026-05-07-clamator-design.md - Agent rules:
AGENTS.md
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file clamator_over_memory-0.1.6.tar.gz.
File metadata
- Download URL: clamator_over_memory-0.1.6.tar.gz
- Upload date:
- Size: 8.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d2e2f5c418bba48eb851395d0a08c339c9f2c7358c5209163e25170daff5dfb3
|
|
| MD5 |
34f46a0685323f61ffb672afda642daf
|
|
| BLAKE2b-256 |
c995fb96cf9a7950e358fddbbe7b65e686d4a794a61a8652f93d2d0a0232fbb7
|
File details
Details for the file clamator_over_memory-0.1.6-py3-none-any.whl.
File metadata
- Download URL: clamator_over_memory-0.1.6-py3-none-any.whl
- Upload date:
- Size: 10.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8c157f62afa7a6411ed2edb9e93c4b3044670037ca7d39aa07121518ba523c93
|
|
| MD5 |
bfd4184991121d0d7261c3484b67ecf6
|
|
| BLAKE2b-256 |
76fcc1090eba93d27d4be6504def0c5bac284e5b730a54665463b413dbede9f1
|