clients is no longer a global variable

This commit is contained in:
Christoph Stahl 2023-01-26 10:57:57 +01:00
parent 5ca9b3f9e9
commit c12c6776b1

View file

@ -74,7 +74,7 @@ class Config:
:type sources: Source
:param sources_prio: A list defining the order of the search results.
:type sources_prio: list[str]
:param preview_duration: The duration in seconds the playbackclients shows
:param preview_duration: The duration in seconds the playback clients shows
a preview for the next song. This is accounted for in the calculation
of the ETA for songs later in the queue.
:type preview_duration: int
@ -119,9 +119,6 @@ class State:
)
clients: dict[str, State] = {}
async def send_state(state: State, sid: str) -> None:
"""
Send the current state (queue and recent-list) to sid.
@ -160,7 +157,7 @@ async def handle_state(sid: str) -> None:
"""
async with sio.session(sid) as session:
room = session["room"]
state = clients[room]
state = app["clients"][room]
await send_state(state, sid)
@ -198,7 +195,7 @@ async def handle_append(sid: str, data: dict[str, Any]) -> None:
"""
async with sio.session(sid) as session:
room = session["room"]
state = clients[room]
state = app["clients"][room]
source_obj = state.config.sources[data["source"]]
entry = await source_obj.get_entry(data["performer"], data["ident"])
@ -239,7 +236,7 @@ async def handle_append(sid: str, data: dict[str, Any]) -> None:
await sio.emit(
"get-meta-info",
entry,
room=clients[room].sid,
room=app["clients"][room].sid,
)
@ -263,7 +260,7 @@ async def handle_meta_info(sid: str, data: dict[str, Any]) -> None:
"""
async with sio.session(sid) as session:
room = session["room"]
state = clients[room]
state = app["clients"][room]
state.queue.update(
data["uuid"],
@ -294,7 +291,7 @@ async def handle_get_first(sid: str) -> None:
"""
async with sio.session(sid) as session:
room = session["room"]
state = clients[room]
state = app["clients"][room]
current = await state.queue.peek()
current.started_at = datetime.datetime.now().timestamp()
@ -323,7 +320,7 @@ async def handle_pop_then_get_next(sid: str) -> None:
"""
async with sio.session(sid) as session:
room = session["room"]
state = clients[room]
state = app["clients"][room]
if sid != state.sid:
return
@ -386,7 +383,7 @@ async def handle_register_client(sid: str, data: dict[str, Any]) -> None:
client_id = "".join(
[random.choice(string.ascii_letters) for _ in range(length)]
)
if client_id in clients:
if client_id in app["clients"]:
client_id = gen_id(length + 1)
return client_id
@ -394,8 +391,8 @@ async def handle_register_client(sid: str, data: dict[str, Any]) -> None:
async with sio.session(sid) as session:
session["room"] = room
if room in clients:
old_state: State = clients[room]
if room in app["clients"]:
old_state: State = app["clients"][room]
if data["secret"] == old_state.secret:
logger.info("Got new client connection for %s", room)
old_state.sid = sid
@ -408,7 +405,7 @@ async def handle_register_client(sid: str, data: dict[str, Any]) -> None:
await sio.emit(
"client-registered", {"success": True, "room": room}, room=sid
)
await send_state(clients[room], sid)
await send_state(app["clients"][room], sid)
else:
logger.warning("Got wrong secret for %s", room)
await sio.emit(
@ -419,7 +416,7 @@ async def handle_register_client(sid: str, data: dict[str, Any]) -> None:
initial_entries = [Entry(**entry) for entry in data["queue"]]
initial_recent = [Entry(**entry) for entry in data["recent"]]
clients[room] = State(
app["clients"][room] = State(
secret=data["secret"],
queue=Queue(initial_entries),
recent=initial_recent,
@ -430,7 +427,7 @@ async def handle_register_client(sid: str, data: dict[str, Any]) -> None:
await sio.emit(
"client-registered", {"success": True, "room": room}, room=sid
)
await send_state(clients[room], sid)
await send_state(app["clients"][room], sid)
@sio.on("sources")
@ -457,7 +454,7 @@ async def handle_sources(sid: str, data: dict[str, Any]) -> None:
"""
async with sio.session(sid) as session:
room = session["room"]
state = clients[room]
state = app["clients"][room]
if sid != state.sid:
return
@ -494,7 +491,7 @@ async def handle_config_chunk(sid: str, data: dict[str, Any]) -> None:
"""
async with sio.session(sid) as session:
room = session["room"]
state = clients[room]
state = app["clients"][room]
if sid != state.sid:
return
@ -526,7 +523,7 @@ async def handle_config(sid: str, data: dict[str, Any]) -> None:
"""
async with sio.session(sid) as session:
room = session["room"]
state = clients[room]
state = app["clients"][room]
if sid != state.sid:
return
@ -551,11 +548,11 @@ async def handle_register_web(sid: str, data: dict[str, Any]) -> bool:
:returns: True, if the room exist, False otherwise
:rtype: bool
"""
if data["room"] in clients:
if data["room"] in app["clients"]:
async with sio.session(sid) as session:
session["room"] = data["room"]
sio.enter_room(sid, session["room"])
state = clients[session["room"]]
state = app["clients"][session["room"]]
await send_state(state, sid)
return True
return False
@ -578,7 +575,7 @@ async def handle_register_admin(sid: str, data: dict[str, Any]) -> bool:
"""
async with sio.session(sid) as session:
room = session["room"]
state = clients[room]
state = app["clients"][room]
is_admin: bool = data["secret"] == state.secret
async with sio.session(sid) as session:
@ -602,12 +599,14 @@ async def handle_skip_current(sid: str) -> None:
async with sio.session(sid) as session:
room = session["room"]
is_admin = session["admin"]
state = clients[room]
state = app["clients"][room]
if is_admin:
old_entry = await state.queue.popleft()
state.recent.append(old_entry)
await sio.emit("skip-current", old_entry, room=clients[room].sid)
await sio.emit(
"skip-current", old_entry, room=app["clients"][room].sid
)
await send_state(state, room)
@ -628,7 +627,7 @@ async def handle_move_up(sid: str, data: dict[str, Any]) -> None:
async with sio.session(sid) as session:
room = session["room"]
is_admin = session["admin"]
state = clients[room]
state = app["clients"][room]
if is_admin:
await state.queue.move_up(data["uuid"])
await send_state(state, room)
@ -651,7 +650,7 @@ async def handle_skip(sid: str, data: dict[str, Any]) -> None:
async with sio.session(sid) as session:
room = session["room"]
is_admin = session["admin"]
state = clients[room]
state = app["clients"][room]
if is_admin:
entry = state.queue.find_by_uuid(data["uuid"])
@ -699,7 +698,7 @@ async def handle_search(sid: str, data: dict[str, Any]) -> None:
"""
async with sio.session(sid) as session:
room = session["room"]
state = clients[room]
state = app["clients"][room]
query = data["query"]
results_list = await asyncio.gather(
@ -722,24 +721,26 @@ async def handle_search(sid: str, data: dict[str, Any]) -> None:
async def cleanup() -> None:
""" Clean up the unused playback clients
"""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():
for sid, state in app["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():
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]
del app["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()
@ -751,10 +752,15 @@ async def cleanup() -> None:
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()))
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
async def background_tasks(
iapp: web.Application,
) -> AsyncGenerator[None, None]:
"""Create all the background tasks
For now, this is only the cleanup task
"""
@ -766,6 +772,7 @@ async def background_tasks(iapp: web.Application) -> AsyncGenerator[None, None]:
iapp["repeated_cleanup"].cancel()
await iapp["repeated_cleanup"]
def main() -> None:
"""
Configure and start the server.
@ -785,6 +792,7 @@ def main() -> None:
app.router.add_route("*", "/{room}", root_handler)
app.router.add_route("*", "/{room}/", root_handler)
app["clients"] = {}
app.cleanup_ctx.append(background_tasks)
web.run_app(app, host=args.host, port=args.port)