Cron cleanup

This commit is contained in:
Christoph Stahl 2023-01-25 15:47:04 +00:00
parent 8ac523bc26
commit 7556176229
2 changed files with 53 additions and 1 deletions

View file

@ -34,6 +34,7 @@ class AsyncServer:
def enter_room(self, sid: str, room: str) -> None: ... def enter_room(self, sid: str, room: str) -> None: ...
def leave_room(self, sid: str, room: str) -> None: ... def leave_room(self, sid: str, room: str) -> None: ...
def attach(self, app: Any) -> None: ... def attach(self, app: Any) -> None: ...
async def disconnect(self, sid: str) -> None: ...
class AsyncClient: class AsyncClient:

View file

@ -20,7 +20,9 @@ import random
import string import string
from argparse import ArgumentParser from argparse import ArgumentParser
from dataclasses import dataclass from dataclasses import dataclass
from dataclasses import field
from typing import Any from typing import Any
from typing import AsyncGenerator
from typing import Optional from typing import Optional
import socketio import socketio
@ -56,7 +58,7 @@ async def root_handler(request: Any) -> Any:
return web.FileResponse("syng/static/index.html") return web.FileResponse("syng/static/index.html")
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.WARNING)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -112,6 +114,9 @@ class State:
recent: list[Entry] recent: list[Entry]
sid: str sid: str
config: Config config: Config
last_seen: datetime.datetime = field(
init=False, default_factory=datetime.datetime.now
)
clients: dict[str, State] = {} clients: dict[str, State] = {}
@ -325,6 +330,7 @@ async def handle_pop_then_get_next(sid: str) -> None:
old_entry = await state.queue.popleft() old_entry = await state.queue.popleft()
state.recent.append(old_entry) state.recent.append(old_entry)
state.last_seen = datetime.datetime.now()
await send_state(state, room) await send_state(state, room)
current = await state.queue.peek() current = await state.queue.peek()
@ -715,6 +721,49 @@ async def handle_search(sid: str, data: dict[str, Any]) -> None:
) )
async def cleanup() -> None:
""" Clean up the unused playback clients
This runs every hour, and removes every client, that did not requested a song for four hours
"""
logger.info("Start Cleanup")
to_remove: list[str] = []
for sid, state in clients.items():
logger.info("Client %s, last seen: %s", sid, str(state.last_seen))
if state.last_seen + datetime.timedelta(hours=4) < datetime.datetime.now():
logger.info("No activity for 4 hours, removing %s", sid)
to_remove.append(sid)
for sid in to_remove:
await sio.disconnect(sid)
del clients[sid]
logger.info("End Cleanup")
# The internal loop counter does not use a regular timestamp, so we need to convert between
# regular datetime and the async loop time
now = datetime.datetime.now()
today = datetime.datetime(now.year, now.month, now.day)
next_run = today + datetime.timedelta(days=1)
offset = next_run.timestamp() - now.timestamp()
loop_next = asyncio.get_event_loop().time() + offset
logger.info("Next Cleanup at %s", str(next))
asyncio.get_event_loop().call_at(loop_next, lambda: asyncio.create_task(cleanup()))
async def background_tasks(iapp: web.Application) -> AsyncGenerator[None, None]:
""" Create all the background tasks
For now, this is only the cleanup task
"""
iapp["repeated_cleanup"] = asyncio.create_task(cleanup())
yield
iapp["repeated_cleanup"].cancel()
await iapp["repeated_cleanup"]
def main() -> None: def main() -> None:
""" """
Configure and start the server. Configure and start the server.
@ -734,6 +783,8 @@ def main() -> None:
app.router.add_route("*", "/{room}", root_handler) app.router.add_route("*", "/{room}", root_handler)
app.router.add_route("*", "/{room}/", root_handler) app.router.add_route("*", "/{room}/", root_handler)
app.cleanup_ctx.append(background_tasks)
web.run_app(app, host=args.host, port=args.port) web.run_app(app, host=args.host, port=args.port)