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.2.tar.gz (35.9 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.2-py3-none-any.whl (34.6 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: pondsocket-0.0.2.tar.gz
  • Upload date:
  • Size: 35.9 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.2.tar.gz
Algorithm Hash digest
SHA256 017cb2ee40fda261fa4ab2bb903e5179762545493df7e2cbf3e3084434c813bd
MD5 902bb19cc81466a192cdf7c822829343
BLAKE2b-256 a930ca8b4176f30905f26d42f26c735592f42ef49acd8bec27fe3dbdc07ba797

See more details on using hashes here.

File details

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

File metadata

  • Download URL: pondsocket-0.0.2-py3-none-any.whl
  • Upload date:
  • Size: 34.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.2-py3-none-any.whl
Algorithm Hash digest
SHA256 8f39136e9586738e85c72f19319bebd057b3b29a78bd9b831ff9ee95774ac471
MD5 fdf2ef9d85532ffeffa2eeca1988453b
BLAKE2b-256 3124a773caee44cd02bcad64a6e2b7e5d2f177ad0c667bd57e5587d99e2da99d

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