import falcon.asgi import falcon.media from socketify import ASGI clients = set([]) remaining_clients = 16 async def broadcast(message): # some clients got disconnected if we tried to to all async :/ # tasks = [ws.send_text(message) for ws in client] # return await asyncio.wait(tasks, return_when=ALL_COMPLETED) for ws in clients: await ws.send_text(message) class SomeResource: async def on_get(self, req, resp): resp.status = falcon.HTTP_200 # This is the default status resp.content_type = falcon.MEDIA_TEXT # Default is JSON, so override resp.text = "Connect via ws protocol!" async def on_websocket(self, req, ws): global remaining_clients try: await ws.accept() clients.add(ws) remaining_clients -= 1 print("remaining_clients", remaining_clients) if remaining_clients == 0: await broadcast("ready") while True: payload = await ws.receive_text() if payload: await broadcast(payload) except falcon.WebSocketDisconnected: clients.remove(ws) remaining_clients += 1 print("remaining_clients", remaining_clients) app = falcon.asgi.App() app.ws_options.max_receive_queue = 20_000_000# this virtual disables queue but adds overhead app.ws_options.enable_buffered_receiver = False # this disable queue but for now only available on cirospaciari/falcon app.add_route("/", SomeResource()) # python3 -m gunicorn falcon_server:app -b 127.0.0.1:4001 -w 1 -k uvicorn.workers.UvicornWorker # pypy3 -m gunicorn falcon_server:app -b 127.0.0.1:4001 -w 1 -k uvicorn.workers.UvicornH11Worker if __name__ == "__main__": ASGI(app).listen(4001, lambda config: print(f"Listening on port http://localhost:{config.port} now\n")).run() # 126550