mirror of
https://github.com/yeicor-3d/yet-another-cad-viewer.git
synced 2025-12-19 22:24:17 +01:00
Add async buffered pubsub, websocket updates endpoint and initial fast hashing of objects
This commit is contained in:
@@ -4,12 +4,17 @@ import os
|
||||
import signal
|
||||
import sys
|
||||
from threading import Thread
|
||||
from typing import Optional
|
||||
from typing import Optional, Tuple
|
||||
|
||||
from OCP.TopoDS import TopoDS_Shape
|
||||
from aiohttp import web
|
||||
|
||||
from pubsub import BufferedPubSub
|
||||
from tessellate import _hashcode
|
||||
|
||||
FRONTEND_BASE_PATH = os.getenv('FRONTEND_BASE_PATH', '../dist')
|
||||
UPDATES_API_PATH = '/api/updates'
|
||||
OBJECTS_API_PATH = '/api/objects' # /{name}
|
||||
|
||||
|
||||
# noinspection PyUnusedLocal
|
||||
@@ -22,11 +27,13 @@ class Server:
|
||||
runner: web.AppRunner
|
||||
thread: Optional[Thread] = None
|
||||
do_shutdown = asyncio.Event()
|
||||
show_events = BufferedPubSub[Tuple[TopoDS_Shape, str]]()
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
# --- Routes ---
|
||||
# - API
|
||||
# self.app.router.add_route({'POST','GET'}, '/api/{collection}', api_handler)
|
||||
# - APIs
|
||||
self.app.router.add_route('GET', f'{UPDATES_API_PATH}', self.api_updates)
|
||||
self.app.router.add_route('GET', f'{OBJECTS_API_PATH}/{{name}}', self.api_objects)
|
||||
# - Static files from the frontend
|
||||
self.app.router.add_get('/{path:(.*/|)}', _index_handler) # Any folder -> index.html
|
||||
self.app.router.add_static('/', path=FRONTEND_BASE_PATH, name='static_frontend')
|
||||
@@ -74,10 +81,37 @@ class Server:
|
||||
# print('Shutting down server...')
|
||||
await runner.cleanup()
|
||||
|
||||
def show_object(self, obj: TopoDS_Shape):
|
||||
pass
|
||||
async def api_updates(self, request: web.Request) -> web.WebSocketResponse:
|
||||
"""Handles a publish-only websocket connection that send show_object events along with their hashes and URLs"""
|
||||
ws = web.WebSocketResponse()
|
||||
await ws.prepare(request)
|
||||
|
||||
print('New client connected')
|
||||
async for (obj, name) in self.show_events.subscribe():
|
||||
hash_code = _hashcode(obj)
|
||||
url = f'{UPDATES_API_PATH}/{name}'
|
||||
print('New object:', name, hash_code, url)
|
||||
await ws.send_json({'name': name, 'hash': hash_code, 'url': url})
|
||||
|
||||
# TODO: Start previous loop in a separate task and detect connection close to stop it
|
||||
|
||||
return ws
|
||||
|
||||
obj_counter = 0
|
||||
|
||||
def show_object(self, obj: TopoDS_Shape, name: Optional[str] = None):
|
||||
"""Publishes a CAD object to the server"""
|
||||
name = name or f'object_{self.obj_counter}'
|
||||
self.obj_counter += 1
|
||||
self.show_events.publish_nowait((obj, name))
|
||||
|
||||
async def api_objects(self, request: web.Request) -> web.Response:
|
||||
return web.Response(body='TODO: Serve the object file here')
|
||||
|
||||
|
||||
def get_app() -> web.Application:
|
||||
"""Required by aiohttp-devtools"""
|
||||
return Server().app
|
||||
from logo.logo import build_logo
|
||||
server = Server()
|
||||
server.show_object(build_logo())
|
||||
return server.app
|
||||
|
||||
Reference in New Issue
Block a user