{"id":15792846,"url":"https://github.com/permitio/fastapi_websocket_pubsub","last_synced_at":"2025-05-14T15:06:08.499Z","repository":{"id":38193264,"uuid":"334475297","full_name":"permitio/fastapi_websocket_pubsub","owner":"permitio","description":"A fast and durable Pub/Sub channel over Websockets. FastAPI + WebSockets + PubSub ==  ⚡ 💪 ❤️","archived":false,"fork":false,"pushed_at":"2025-03-05T12:35:00.000Z","size":227,"stargazers_count":534,"open_issues_count":7,"forks_count":48,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-05-11T21:12:34.660Z","etag":null,"topics":["broadcast","fastapi","fastapi-websocket","publish","pubsub","pubsub-websocket","realtime","realtime-messaging","subscribe","websocket"],"latest_commit_sha":null,"homepage":"https://permit.io","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/permitio.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-01-30T17:46:45.000Z","updated_at":"2025-05-11T20:05:07.000Z","dependencies_parsed_at":"2023-02-04T07:00:49.089Z","dependency_job_id":"314319d7-2f06-4ac6-b279-21cd5f54c120","html_url":"https://github.com/permitio/fastapi_websocket_pubsub","commit_stats":{"total_commits":227,"total_committers":11,"mean_commits":"20.636363636363637","dds":0.4229074889867841,"last_synced_commit":"ef01e5ff0fadff1e9a2d0fb9c906c2cff3b89bd0"},"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/permitio%2Ffastapi_websocket_pubsub","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/permitio%2Ffastapi_websocket_pubsub/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/permitio%2Ffastapi_websocket_pubsub/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/permitio%2Ffastapi_websocket_pubsub/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/permitio","download_url":"https://codeload.github.com/permitio/fastapi_websocket_pubsub/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253633147,"owners_count":21939392,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["broadcast","fastapi","fastapi-websocket","publish","pubsub","pubsub-websocket","realtime","realtime-messaging","subscribe","websocket"],"created_at":"2024-10-04T23:05:31.614Z","updated_at":"2025-05-14T15:06:08.493Z","avatar_url":"https://github.com/permitio.png","language":"Python","readme":"\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://i.ibb.co/NV6wmy8/pubsub.png\" width=\"55%\" alt=\"pubsub\" border=\"0\"\u003e\n\u003c/p\u003e\n\n#\n\n# ⚡🗞️ FastAPI Websocket Pub/Sub \n\n\u003ca href=\"https://github.com/permitio/fastapi_websocket_pubsub/actions?query=workflow%3ATests\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://github.com/permitio/fastapi_websocket_pubsub/workflows/Tests/badge.svg?branch=master\" alt=\"Tests\"\u003e\n\u003c/a\u003e\n\n\u003ca href=\"https://pypi.org/project/fastapi-websocket-pubsub/\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/pypi/v/fastapi-websocket-pubsub?color=%2331C654\u0026label=PyPi%20package\" alt=\"Package\"\u003e\n\u003c/a\u003e\n\u003ca href=\"https://pepy.tech/project/fastapi-websocket-pubsub\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://static.pepy.tech/personalized-badge/fastapi-websocket-pubsub?period=total\u0026units=international_system\u0026left_color=black\u0026right_color=blue\u0026left_text=Downloads\" alt=\"Downloads\"\u003e\n\u003c/a\u003e\n\n\nA fast and durable Pub/Sub channel over Websockets.\nThe easiest way to create a live publish / subscribe multi-cast over the web.\n\nSupports and tested on Python \u003e= 3.7 \n\nAs seen at \u003ca href=\"https://www.youtube.com/watch?v=KP7tPeKhT3o\" target=\"_blank\"\u003ePyCon IL 2021\u003c/a\u003e and \u003ca href=\"https://www.youtube.com/watch?v=IuMZVWEUvGs\" target=\"_blank\"\u003eEuroPython 2021\u003c/a\u003e\n\n\n## Installation 🛠️\n```\npip install fastapi_websocket_pubsub\n```\n\n\n## Intro\nThe classic pub/sub pattern made easily accessible and scalable over the web and across your cloud in realtime; while enjoying the benefits of FastAPI (e.g. dependency injection).\n\nFastAPI + WebSockets + PubSub ==  ⚡💪 ❤️\n\n\n- Subscribe\n    - Clients subscribe to topics (arbitrary strings) and receive relevant events along with structured data (serialized with Pydantic).\n        ```python\n        # Callback to be called upon event being published on server\n        async def on_event(data):\n            print(\"We got an event! with data- \", data)\n        # Subscribe for the event \n        client.subscribe(\"my event\", on_event)\n        ```\n\n- Publish \n    - Directly from server code to connected clients. \n        ```python\n        app = FastAPI() \n        endpoint = PubSubEndpoint()\n        endpoint.register_route(app, path=\"/pubsub\")\n        endpoint.publish([\"my_event_topic\"], data=[\"my\", \"data\", 1])\n        ```\n    - From client to client (through the servers)\n        ```python \n        async with PubSubClient(server_uri=\"ws://localhost/pubsub\") as client:\n            endpoint.publish([\"my_event_topic\"], data=[\"my\", \"data\", 1])\n        ```    \n    - Across server instances (using [broadcaster](https://pypi.org/project/broadcaster/) and a backend medium (e.g. Redis, Kafka, ...))\n        - No matter which server a client connects to - it will get the messages it subscribes to\n        ```python\n        app = FastAPI() \n        endpoint = PubSubEndpoint(broadcaster=\"postgres://localhost:5432/\")\n        \n        @app.websocket(\"/pubsub\")\n        async def websocket_rpc_endpoint(websocket: WebSocket):\n            await endpoint.main_loop(websocket)\n        ```\n        see [examples/pubsub_broadcaster_server_example.py](examples/pubsub_broadcaster_server_example.py) for full usage example\n        Note: Requires install with dependencies e.g. `pip install fastapi_websocket_pubsub[redis]`, `pip install fastapi_websocket_pubsub[postgres]`, `pip install fastapi_websocket_pubsub[kafka]` or `pip install fastapi_websocket_pubsub[all]` to get support for all three backends\n\n\n\n## Usage example (server publishing following HTTP trigger):\nIn the code below, a client connects to the server and subscribes to a topic named \"triggered\".\nAside from PubSub websocket, the server also exposes a regular http route, which triggers publication of the event. \n\n### Server:\n```python\nimport asyncio\nimport uvicorn\nfrom fastapi import FastAPI\nfrom fastapi.routing import APIRouter\n\nfrom fastapi_websocket_pubsub import PubSubEndpoint\napp =  FastAPI()\n# Init endpoint\nendpoint = PubSubEndpoint()\n# register the endpoint on the app\nendpoint.register_route(app, \"/pubsub\")\n# Register a regular HTTP route\n@app.get(\"/trigger\")\nasync def trigger_events():\n    # Upon request trigger an event\n    endpoint.publish([\"triggered\"])\n```\n### Client:\n```python\nfrom fastapi_websocket_pubsub import PubSubClient\n# Callback to be called upon event being published on server\nasync def on_trigger(data):\n    print(\"Trigger URL was accessed\")\n\nasync with PubSubClient(server_uri=\"ws://localhost/pubsub\") as client:\n    # Subscribe for the event \n    client.subscribe(\"triggered\", on_trigger)\n\n```\n\n## More Examples\n- See the [examples](/examples) and [tests](/tests) folders for more server and client examples.\n- See [fastapi-websocket-rpc depends example](https://github.com/permitio/fastapi_websocket_rpc/blob/master/tests/fast_api_depends_test.py) to see how to combine with FASTAPI dependency injections\n\n## What can I do with this?\nThe combination of Websockets, and bi-directional Pub/Sub is  ideal to create realtime data propagation solution at scale over the web. \n - Update mechanism\n - Remote control mechanism\n - Data processing\n - Distributed computing\n - Realtime communications over the web   \n\n\n## Foundations:\n\n- Based on [fastapi-websocket-rpc](https://github.com/permitio/fastapi_websocket_rpc) for a robust realtime bidirectional channel\n\n- Based on [broadcaster](https://pypi.org/project/broadcaster/) for syncing server instances\n\n- Server Endpoint:\n\n    - Based on [FastAPI](https://github.com/tiangolo/fastapi): enjoy all the benefits of a full ASGI platform, including Async-io and dependency injections (for example to authenticate connections)\n\n    - Based on [Pydantic](https://pydantic-docs.helpmanual.io/): easily serialize structured data as part of RPC requests and responses. Simply Pass Pydantic data models as PubSub published data to have it available as part of an event. \n\n- Client :\n    - Based on [Tenacity](https://tenacity.readthedocs.io/en/latest/index.html): allowing configurable retries to keep to connection alive\n        - see WebSocketRpcClient.__init__'s retry_config \n\n    - Based on python [websockets](https://websockets.readthedocs.io/en/stable/intro.html) - a more comprehensive client than the one offered by FastAPI\n\n## Logging \nfastapi-websocket-pubsub uses fastapi-websocket-rpc for logging config.\nIt provides a helper logging module to control how it produces logs for you.\nSee [fastapi_websocket_rpc/logger.py](fastapi_websocket_rpc/logger.py).\nUse ```logging_config.set_mode``` or the 'WS_RPC_LOGGING' environment variable to choose the logging method you prefer.\nOr override completely via default logging config (e.g. 'logging.config.dictConfig'), all logger name start with: 'fastapi.ws_rpc.pubsub'\n\nexample:\n```python\n# set RPC to log like UVICORN\nfrom fastapi_websocket_rpc.logger import logging_config, LoggingModes\nlogging_config.set_mode(LoggingModes.UVICORN)\n```\n\n## Pull requests - welcome!\n- Please include tests for new features \n\n\n","funding_links":[],"categories":["Python"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpermitio%2Ffastapi_websocket_pubsub","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpermitio%2Ffastapi_websocket_pubsub","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpermitio%2Ffastapi_websocket_pubsub/lists"}