Source code for softs.market.protocol

"""Wire protocol for broker <-> client/supplier communication."""

from dataclasses import dataclass, field

import msgpack
import yaml


[docs] @dataclass class EndpointConfig: frontend: str = "ipc:///tmp/softs_frontend.sock" backend: str = "ipc:///tmp/softs_backend.sock"
[docs] @classmethod def from_yaml(cls, path: str) -> "EndpointConfig": with open(path) as f: return cls(**yaml.safe_load(f))
class ClientCmd: """Commands on the client <-> broker channel (frontend).""" HELLO = b"HELLO" ORDER = b"ORDER" CANCEL = b"CANCEL" DISCARD = b"DISCARD" STATS = b"STATS" FULFILLED = b"FULFILLED" # broker -> client FAILED = b"FAILED" # broker -> client: order permanently failed, free its slot class SupplierCmd: """Commands on the supplier <-> broker channel (backend).""" HELLO = b"HELLO" GOODBYE = b"GOODBYE" READY = b"READY" DONE = b"DONE" WORK = b"WORK" # broker -> supplier TERMINATE = b"TERMINATE" # broker -> supplier class OrderState: QUEUED = b"QUEUED" DISPATCHED = b"DISPATCHED" COMPLETED = b"COMPLETED" FAILED = b"FAILED" CANCELLED = b"CANCELLED" # -- Peer tracking -- @dataclass class ClientInfo: peer_id: int last_seen: float = 0.0 @dataclass class SupplierInfo: peer_id: int product_ids: list[str] = field(default_factory=list) last_seen: float = 0.0 # -- Message payloads (validated via dataclass construction) -- @dataclass class OrderRequest: """Client places an order for a product at a specific address/offset.""" order_id: str product_id: str address: str offset: int @dataclass class OrderCancel: order_id: str @dataclass class OrderWork: """Broker assigns work to a supplier.""" order_id: str product_id: str address: str offset: int @dataclass class OrderDone: """Supplier reports completion.""" order_id: str success: bool = True @dataclass class Order: order_id: str product_id: str address: str offset: int client_id: bytes supplier_id: bytes = b"" status = OrderState.QUEUED dispatched_at: float = 0.0 attempts: int = 0
[docs] @dataclass class BrokerStats: pending_orders: int available_suppliers: int connected_clients: int connected_suppliers: int total_completed: int product_ids: list[str]
# -- Wire encoding -- def encode_payload(data: dict) -> bytes: return msgpack.packb(data, use_bin_type=True) # type: ignore def decode_payload(data: bytes) -> dict: return msgpack.unpackb(data, raw=False) def make_request(cmd: bytes, payload: dict) -> list[bytes]: return [cmd, encode_payload(payload)] def parse_request(frames: list[bytes]) -> tuple[bytes, dict]: if len(frames) < 2: raise ValueError(f"Expected at least 2 frames, got {len(frames)}") return frames[0], decode_payload(frames[1]) if frames[1] else {} def make_reply(ok: bool, error: str | None = None, **data) -> bytes: return encode_payload({"ok": ok, "error": error, **data})