Add live (redis and websockets)

Add modernised ipynb_tools
Add scheduler
Fix crs in settings
Lots of small fixes
This commit is contained in:
phil 2023-12-21 10:51:31 +05:30
parent 461c31fb6f
commit 47df53f4d1
15 changed files with 1614 additions and 61 deletions

View file

@ -2,14 +2,16 @@
Geographical json stores, served under /gj
Used for displaying features on maps
"""
from json import JSONDecodeError
import logging
from typing import Annotated
from asyncio import CancelledError
from fastapi import FastAPI, HTTPException, Response, status, responses, Header
from fastapi import (FastAPI, HTTPException, Response, Header, WebSocket, WebSocketDisconnect,
status, responses)
from .redis_tools import store as redis_store
# from gisaf.live import live_server
from .live import live_server
from .registry import registry
@ -19,28 +21,54 @@ api = FastAPI(
default_response_class=responses.ORJSONResponse,
)
@api.get('/live/{store}')
async def live_layer(store: str):
class ConnectionManager:
active_connections: list[WebSocket]
def __init__(self):
self.active_connections = []
async def connect(self, websocket: WebSocket):
await websocket.accept()
self.active_connections.append(websocket)
def disconnect(self, websocket: WebSocket):
self.active_connections.remove(websocket)
async def send_personal_message(self, message: str, websocket: WebSocket):
await websocket.send_text(message)
async def broadcast(self, message: str):
for connection in self.active_connections:
await connection.send_text(message)
manager = ConnectionManager()
@api.websocket('/live/{store}')
async def live_layer(store: str, websocket: WebSocket):
"""
Websocket for live layer updates
"""
ws = web.WebSocketResponse()
await ws.prepare(request)
async for msg in ws:
if msg.type == WSMsgType.TEXT:
if msg.data == 'close':
await ws.close()
await websocket.accept()
try:
while True:
try:
msg_data = await websocket.receive_json()
except JSONDecodeError:
msg_text = await websocket.receive_text()
if msg_text == 'close':
await websocket.close()
continue
# else:
if 'message' in msg_data:
if msg_data['message'] == 'subscribeLiveLayer':
live_server.add_subscription(websocket, store)
elif msg_data['message'] == 'unsubscribeLiveLayer':
live_server.remove_subscription(websocket, store)
else:
msg_data = msg.json()
if 'message' in msg_data:
if msg_data['message'] == 'subscribeLiveLayer':
live_server.add_subscription(ws, store)
elif msg_data['message'] == 'unsubscribeLiveLayer':
live_server.remove_subscription(ws, store)
elif msg.type == WSMsgType.ERROR:
logger.exception(ws.exception())
logger.debug('websocket connection closed')
return ws
logger.warning(f'Got websocket message with no message field: {msg_data}')
except WebSocketDisconnect:
logger.debug('Websocket disconnected')
# logger.debug('websocket connection closed')
@api.get('/{store_name}')
async def get_geojson(store_name,