for long running tasks I try to use tornado
some prototype
def tornadoSioWsServer():
# py4web.py run -s tornadoSioWsServer apps
import tornado.websocket
import time, urllib
from tornado.httputil import url_concat
import tornado.httpclient
import asyncio
import aioredis
ws_debug = True
connections = []
async def consumer(channel):
while await channel.wait_message():
msg = await channel.get(encoding='utf-8')
for connection in connections:
await connection.write_message(msg)
async def setup():
connection = await aioredis.create_redis('redis://localhost')
channel = await connection.subscribe('notifications')
asyncio.ensure_future(consumer(channel))
class web_socket_handler(tornado.websocket.WebSocketHandler):
# This class handles the websocket channel
@classmethod
def route_urls(cls):
return (r'/',cls, {})
def simple_init(self):
self.last = time.time()
self.stop = False
def open(self):
# client opens a connection
self.simple_init()
ws_debug and print(f"ws: {time.time() - self.last:.1f}: New client connected")
self.write_message(f"ws: {time.time() - self.last:.1f}: You are connected")
connections.append(self)
def on_message(self, message):
# Message received on the handler
ws_debug and print(f"ws: {time.time() - self.last:.1f}: received message {message}")
self.write_message(f"ws: {time.time() - self.last:.1f}: You said - {message}")
self.last = time.time()
def on_close(self):
# Channel is closed
ws_debug and print(f"ws: {time.time() - self.last:.1f}: connection is closed")
self.stop= True
connections.remove(self)
def check_origin(self, origin):
return True
# socketio pip install python-socketio
import socketio
sio_debug = False
sio = socketio.AsyncServer(async_mode='tornado')
def handle_request( response):
pass
@sio.event
async def connect(sid, environ):
sio_debug and print('sio: connect ', sid)
@sio.event
async def disconnect(sid):
sio_debug and print('sio: disconnect ', sid)
@sio.on('to_py4web')
async def echo(sid, data):
sio_debug and print('sio: from client: ', data)
http_client = tornado.httpclient.AsyncHTTPClient()
http_client.fetch(request, handle_request)
await sio.emit("py4web_echo", data)
class TornadoSioWsServer(ServerAdapter):
def run(self, handler): # pragma: no cover
import tornado.wsgi, tornado.httpserver, tornado.web, tornado.ioloop
container = tornado.wsgi.WSGIContainer(handler)
app= tornado.web.Application([
web_socket_handler.route_urls(),
(r"/
socket.io/", socketio.get_tornado_handler(sio) ),
(r".*", tornado.web.FallbackHandler, dict(fallback=container) ),
])
server = tornado.httpserver.HTTPServer(app)
server.listen(port=self.port,address=self.host)
tornado.ioloop.IOLoop.instance().start()
return TornadoSioWsServer