Skip to main content

WebSocket connection lifecycle, room broadcast, and routing for real-time services

Project description

csrd WebSocket Library

Status: Active implementation (v0.1.0) — core manager/router primitives available.

Real-time WebSocket connection lifecycle, room broadcast, and routing primitives for the csrd ecosystem.

Overview

This package provides reusable WebSocket infrastructure for building real-time services on FastAPI. It handles connection registration, room membership, message routing, and optional policy hooks — but does not define domain-specific protocols.

Design reference

  • Design doc: ../../docs/WEBSOCKET_LIBRARY_DESIGN.md
  • Implementation plan: ../../docs/WEBSOCKET_LIBRARY_IMPLEMENTATION_PLAN.md

Current API

from csrd.realtime import (
    ConnectionContext,
    ConnectionManager,
    MessageEnvelope,
    MessageRouter,
)

Status

Current milestone includes:

  • ConnectionManager (connect/disconnect, room membership, room/global broadcast)
  • MessageRouter (event dispatch + optional policy hooks)
  • ConnectionContext and MessageEnvelope
  • Typed errors for policy/validation/connection lookup

Minimal FastAPI wiring example

from fastapi import FastAPI, WebSocket
from starlette.websockets import WebSocketDisconnect
from contextlib import suppress

from csrd.realtime import (
    ConnectionContext,
    ConnectionManager,
    ConnectionNotFoundError,
    MessageEnvelope,
    MessageRouter,
)

app = FastAPI()
manager = ConnectionManager()
router = MessageRouter()


@app.websocket("/ws")
async def ws_endpoint(ws: WebSocket):
    await ws.accept()
    connection_id = ws.query_params.get("connection_id", "anon")
    context = ConnectionContext(connection_id=connection_id)
    await manager.connect(ws, context)

    try:
        while True:
            data = await ws.receive_json()
            envelope = MessageEnvelope.model_validate(data)
            await router.dispatch(connection_id, envelope, manager)
    except WebSocketDisconnect:
        pass
    finally:
        with suppress(ConnectionNotFoundError):
            await manager.disconnect(connection_id)

Optional context adapter pattern

csrd-realtime stays standalone, but supports optional context binding around each dispatch via RealtimeContextAdapter.

Use this to bridge into csrd-context/logging contextvars without adding a hard dependency from realtime core.

from csrd.realtime import MessageRouter, RealtimeContextAdapter


def bind_ws_context(dispatch_context):
    # Example: set your contextvars and return reset token(s)
    token = some_contextvar.set(
        {
            "connection_id": dispatch_context.connection_id,
            "tenant_id": dispatch_context.connection.tenant_id,
            "event_type": dispatch_context.event_type,
            "trace_id": dispatch_context.trace_id,
        }
    )
    return token


def reset_ws_context(token):
    some_contextvar.reset(token)


router = MessageRouter(
    context_adapter=RealtimeContextAdapter(bind=bind_ws_context, reset=reset_ws_context)
)

Operational defaults (current)

  • Backpressure model: direct send_json per message (no per-connection queue in v0.1.x).
  • Failure behavior: if a send fails, ConnectionManager evicts that connection (best-effort fan-out).
  • Timeout behavior: manager applies bounded send timeout by default (send_timeout_seconds=5.0).
  • Router behavior: handler exceptions are surfaced to caller by default; set MessageRouter(raise_handler_exceptions=False) for log-and-continue mode.

Tenant and room naming guidance

Room names are consumer-defined strings. Use a namespaced format to avoid cross-tenant collisions.

Recommended patterns:

  • tenant:{tenant_id}:session:{session_id} for gameplay sessions
  • tenant:{tenant_id}:party:{party_id} for party-level channels
  • tenant:{tenant_id}:system for scoped system broadcasts

Guidance:

  • Always resolve tenant_id server-side from auth context.
  • Never trust client-provided room names without authorization checks.
  • Keep room IDs stable and deterministic so reconnect/join logic is predictable.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

csrd_realtime-0.5.26.tar.gz (17.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

csrd_realtime-0.5.26-py3-none-any.whl (10.4 kB view details)

Uploaded Python 3

File details

Details for the file csrd_realtime-0.5.26.tar.gz.

File metadata

  • Download URL: csrd_realtime-0.5.26.tar.gz
  • Upload date:
  • Size: 17.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for csrd_realtime-0.5.26.tar.gz
Algorithm Hash digest
SHA256 59db044bf100b44cd76b564f7442db4921779bdd42994ff210adcb04c22d93de
MD5 78a21246e6be3caf1251c394f446ee0f
BLAKE2b-256 ef1888c2f937e7fc6e4f2405a1f1c28bd9a8356c9f7f76d94042579274ef75bb

See more details on using hashes here.

Provenance

The following attestation bundles were made for csrd_realtime-0.5.26.tar.gz:

Publisher: release.yml on csrd-api/fastapi-common

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file csrd_realtime-0.5.26-py3-none-any.whl.

File metadata

  • Download URL: csrd_realtime-0.5.26-py3-none-any.whl
  • Upload date:
  • Size: 10.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for csrd_realtime-0.5.26-py3-none-any.whl
Algorithm Hash digest
SHA256 01142afd63780c2d8b94872c2959ab3a4adb2f5fddcbe9bdb8a5852b72a7c4bd
MD5 57a8aba2058e7073e93451b129bf27c5
BLAKE2b-256 94541240bde71833baf29fb1f80fe7f6d9088f1c5555ac9a819eb4b73a15b9bc

See more details on using hashes here.

Provenance

The following attestation bundles were made for csrd_realtime-0.5.26-py3-none-any.whl:

Publisher: release.yml on csrd-api/fastapi-common

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page