Skip to main content

PondSocket - channel-based real-time framework with bring-your-own-server design.

Project description

pondsocket

PondSocket - channel-based real-time framework for Python. Bring-your-own-server design: the core knows nothing about HTTP frameworks or WebSocket libraries. You build the layered API (Server -> Endpoint -> Channel -> User), and an adapter (e.g. pondsocket-asgi) bridges it to your HTTP stack.

Install

pip install pondsocket
pip install "pondsocket[redis]"   # multi-node deployments

Concepts

PondSocket     top-level facade, holds endpoints
  └── Endpoint   one URL path, runs the connection auth handler, owns transports
        └── Lobby     one channel pattern (e.g. "/chat/:room_id"), holds shared middleware
              └── Channel    one live channel instance, holds users + presence

Five contexts, scoped to lifecycle moments

Context When What it decides / does
ConnectionContext HTTP upgrade accept / decline socket, set initial assigns
JoinContext per channel join accept / decline membership, track presence
EventContext per incoming event broadcast, reply, update presence/assigns, evict
OutgoingContext per recipient, per send transform payload or block delivery
LeaveContext user gone final cleanup (user already removed)

Minimal example

from pondsocket import ConnectionContext, EventContext, JoinContext, PondSocket


async def auth(ctx: ConnectionContext) -> None:
    if ctx.query.get("token") != "secret":
        ctx.decline(401, "Invalid token")
        return
    ctx.accept(user_id=ctx.query.get("uid", "anon"))


async def on_join(ctx: JoinContext) -> None:
    await ctx.accept()
    await ctx.track({"status": "online"})


async def on_message(ctx: EventContext) -> None:
    await ctx.broadcast(ctx.event_name, ctx.get_payload())


pond = PondSocket()
endpoint = pond.create_endpoint("/api/socket", auth)
lobby = endpoint.create_channel("/chat/:room_id", on_join)
lobby.on_message("message", on_message)

To actually serve traffic, wrap pond in an adapter — see pondsocket-asgi for the canonical one.

Distributed (multi-node)

from redis.asyncio import Redis
from pondsocket import PondSocket
from pondsocket.distributed import RedisPubSub

redis = Redis(host="localhost", port=6379)
pubsub = RedisPubSub(redis, owns_client=True)
pond = PondSocket(pubsub=pubsub)

Cross-node broadcasts and presence events propagate via Redis PSUBSCRIBE. node_id is auto-generated when a pubsub is configured. Each broadcast carries the nodeId so emitters filter their own echo.

See pondsocket.distributed.RedisPubSub for the implementation. The PubSub protocol is implementable for other backends.

Hooks & metrics

from pondsocket import Hooks, NoopMetrics, Options, PondSocket, TokenBucketRateLimiter

hooks = Hooks(
    rate_limiter=TokenBucketRateLimiter(rate=10, capacity=20),
    metrics=NoopMetrics(),
)
pond = PondSocket(options=Options(hooks=hooks))

Auto-fired by the framework: connection_opened/connection_closed, channel_created/channel_destroyed/channel_joined/channel_left, plus on_connect/on_disconnect/before_join/after_join/before_message/after_message.

Opt-in middleware factories for per-handler instrumentation:

from pondsocket import with_metrics, with_rate_limiter

lobby.on_message(
    "message",
    on_message,
    with_rate_limiter(hooks, key_fn=lambda msg: msg.user.id),
    with_metrics(hooks),
)

Testing

InMemoryTransport is a public test utility that satisfies the Transport protocol without any network I/O:

from pondsocket import InMemoryTransport

t = InMemoryTransport("alice")
await endpoint.register_transport(t)

await t.push_inbound(some_event)
sent = await t.receive_sent()

Public API

from pondsocket import ...

  • Core: PondSocket, Endpoint, Lobby, Channel, Options, Event, User, MessageEvent, RecipientSpec
  • Contexts: ConnectionContext, JoinContext, EventContext, LeaveContext, OutgoingContext
  • Transport: Transport (Protocol), InMemoryTransport, SSEServerTransport, TransportType, OnCloseCallback, OnMessageHandler
  • PubSub: PubSub (Protocol), LocalPubSub, format_topic, match_topic, PubSubClosedError
  • Hooks: Hooks, RateLimiter, MetricsCollector, NoopMetrics, TokenBucketRateLimiter, with_rate_limiter, with_metrics
  • Wire: event_to_json, event_to_wire, parse_inbound_text, wire_to_event, event_to_pubsub_bytes, pubsub_bytes_to_event
  • Errors: PondError, status constructors, error_event

License

GPL-3.0-or-later.

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

pondsocket-0.0.6.tar.gz (47.0 kB view details)

Uploaded Source

Built Distribution

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

pondsocket-0.0.6-py3-none-any.whl (41.6 kB view details)

Uploaded Python 3

File details

Details for the file pondsocket-0.0.6.tar.gz.

File metadata

  • Download URL: pondsocket-0.0.6.tar.gz
  • Upload date:
  • Size: 47.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.0

File hashes

Hashes for pondsocket-0.0.6.tar.gz
Algorithm Hash digest
SHA256 4b741164fcd5e5bf907c31cf59fddf9f9e08c151ab6a6a0a460ea1e3e4696009
MD5 5df5522ba9e3a4cb34acac060744f4cc
BLAKE2b-256 8933e338048920a55ca6f2c8e4e0fc418bb19712a20bb06a20d849944e4a4820

See more details on using hashes here.

File details

Details for the file pondsocket-0.0.6-py3-none-any.whl.

File metadata

  • Download URL: pondsocket-0.0.6-py3-none-any.whl
  • Upload date:
  • Size: 41.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.0

File hashes

Hashes for pondsocket-0.0.6-py3-none-any.whl
Algorithm Hash digest
SHA256 aca2558addd23ad7757b1259f1b58318b6cd2f3d9da366f187aba285ac78ec78
MD5 9fa4cff87c5c8772a5e8fc4977be8922
BLAKE2b-256 ac7a5c9981b7e2b7b441cfe21fb276499b0f1d3fdb637e63ae9ed81f84a688e2

See more details on using hashes here.

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