Realtime messaging with Redis PUB/SUB.
Project description
Shoutout
Realtime messaging with Redis PUB/SUB.
Shout-out is designed to work with FastAPI websocket, while running behind Gunicorn with multiple Uvicorn workers. Where a centralized caching layer (Redis) is required to maintain state (messages) across workers.
You can also use Shoutout as a standalone asynchronous application.
Usage
Standalone
import asyncio
from shoutout.broadcast import Broadcast
broadcast = Broadcast("redis://localhost:6379")
async def main():
await broadcast.connect()
async with broadcast.subscribe("hello") as subscriber:
if subscriber:
await broadcast.publish("hello", message={
"channel": "hello", "message": "Hello World!"})
async for _, msg in subscriber:
print(msg)
break
if __name__ == "__main__":
asyncio.run(main())
The example above is complete and should run as is.
FastAPI
from fastapi import FastAPI, WebSocket
from fastapi.responses import HTMLResponse
from shoutout.broadcast import Broadcast
from starlette.concurrency import run_until_first_complete
broadcast = Broadcast("redis://localhost:6379")
app = FastAPI(on_startup=[broadcast.connect], on_shutdown=[broadcast.disconnect])
async def ws_receiver(websocket):
async for message in websocket.iter_text():
await broadcast.publish(channel="shout", message={"msg": message})
async def ws_sender(websocket):
async with broadcast.subscribe(channel="shout") as subscriber:
if subscriber:
async for _, msg in subscriber:
await websocket.send_json(msg)
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
await websocket.accept()
await run_until_first_complete(
(ws_receiver, {"websocket": websocket}),
(ws_sender, {"websocket": websocket}),
)
html = """
<!DOCTYPE html>
<html>
<head>
<title>Chat</title>
</head>
<body>
<h1>WebSocket Chat</h1>
<form action="" onsubmit="sendMessage(event)">
<input type="text" id="messageText" autocomplete="off"/>
<button>Send</button>
</form>
<ul id='messages'>
</ul>
<script>
var ws = new WebSocket("ws://localhost:8000/ws");
ws.onmessage = function(event) {
var messages = document.getElementById('messages')
var message = document.createElement('li')
var content = document.createTextNode(event.data)
message.appendChild(content)
messages.appendChild(message)
};
function sendMessage(event) {
var input = document.getElementById("messageText")
ws.send(input.value)
input.value = ''
event.preventDefault()
}
</script>
</body>
</html>
"""
@app.get("/")
async def get():
return HTMLResponse(html)
The example above is complete and should run as is.
Run it:
uvicorn main:app --reload
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file shoutout-py-0.1.0.tar.gz.
File metadata
- Download URL: shoutout-py-0.1.0.tar.gz
- Upload date:
- Size: 3.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.1.4 CPython/3.8.2 Linux/5.4.0-52-generic
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b320ada17e0b07611b5cb82027fd5278ef8d133741f638f203d50e8feda640cc
|
|
| MD5 |
62f0481c326d66125ca18a42d022e2cb
|
|
| BLAKE2b-256 |
24533d32b38a928d9cbc7473863e818ce07a376233e9eab390b6c52438a9fd17
|
File details
Details for the file shoutout_py-0.1.0-py3-none-any.whl.
File metadata
- Download URL: shoutout_py-0.1.0-py3-none-any.whl
- Upload date:
- Size: 3.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.1.4 CPython/3.8.2 Linux/5.4.0-52-generic
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8b39e292e8d87407db98ec3311099d0d6450482dbf32fe72527c184b9582bc23
|
|
| MD5 |
86755661005f94c73512e36b015755f0
|
|
| BLAKE2b-256 |
2e3480346af23d7034cd8e74f5c11c26035735671292ba0110c694c3cf76085e
|