Periodic background indexing via scheduler; !rooms reads cache; v1.0.8
This commit is contained in:
parent
889b5dd31a
commit
1bfc35024c
4 changed files with 54 additions and 33 deletions
|
|
@ -14,7 +14,6 @@ rooms_per_message: 50
|
|||
# Voorkomt dat een enorme (gefedereerde) space-boom leidt tot duizenden berichten.
|
||||
max_rooms: 300
|
||||
|
||||
# Hoe lang (minuten) de opgehaalde lijst wordt gecached in de plugin-database.
|
||||
# Binnen deze periode gebruikt !rooms de cache i.p.v. de hele boom opnieuw op te
|
||||
# halen (minder traffic naar de homeserver en federatie). 0 = caching uit.
|
||||
cache_ttl_minutes: 15
|
||||
# Hoe vaak (minuten) de bot de ruimte-hierarchy opnieuw indexeert op de
|
||||
# achtergrond. !rooms toont altijd het laatste geindexeerde resultaat.
|
||||
refresh_interval_minutes: 15
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
maubot: 0.1.0
|
||||
id: nl.roomsoverview
|
||||
version: 1.0.7
|
||||
version: 1.0.8
|
||||
license: MIT
|
||||
modules:
|
||||
- roomsoverview
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,6 +1,7 @@
|
|||
import asyncio
|
||||
import json
|
||||
import time
|
||||
from functools import partial
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
from urllib.parse import quote
|
||||
|
||||
|
|
@ -58,12 +59,36 @@ class Config(BaseProxyConfig):
|
|||
helper.copy("max_depth")
|
||||
helper.copy("rooms_per_message")
|
||||
helper.copy("max_rooms")
|
||||
helper.copy("cache_ttl_minutes")
|
||||
helper.copy("refresh_interval_minutes")
|
||||
|
||||
|
||||
class RoomsOverviewPlugin(Plugin):
|
||||
async def start(self) -> None:
|
||||
self.config.load_and_update()
|
||||
space_id = str(self.config.get("space_id", "") or "")
|
||||
interval_minutes = max(1, int(self.config.get("refresh_interval_minutes", 15) or 15))
|
||||
if not space_id or space_id.startswith("!vervang-mij"):
|
||||
return
|
||||
self._refresh_lock = asyncio.Lock()
|
||||
self._scheduled_tasks = []
|
||||
# Direct eenmalig indexeren (prewarm), daarna periodiek.
|
||||
self._scheduled_tasks.append(
|
||||
self.sched.run_later(2, self._refresh_cache(space_id))
|
||||
)
|
||||
self._scheduled_tasks.append(
|
||||
self.sched.run_periodically(
|
||||
interval_minutes * 60,
|
||||
partial(self._refresh_cache, space_id),
|
||||
run_task_in_background=True,
|
||||
)
|
||||
)
|
||||
self.log.info(
|
||||
f"start: indexering gepland elke {interval_minutes} minuten"
|
||||
)
|
||||
|
||||
async def stop(self) -> None:
|
||||
for task in getattr(self, "_scheduled_tasks", []):
|
||||
task.cancel()
|
||||
|
||||
@classmethod
|
||||
def get_config_class(cls):
|
||||
|
|
@ -155,6 +180,19 @@ class RoomsOverviewPlugin(Plugin):
|
|||
break
|
||||
return rooms, True
|
||||
|
||||
async def _refresh_cache(self, space_id: str) -> None:
|
||||
"""Live ophalen en in de cache opslaan (gedeeld via lock, ook achtergrond)."""
|
||||
async with self._refresh_lock:
|
||||
entries, complete = await self._fetch_hierarchy(space_id)
|
||||
rooms = [
|
||||
r
|
||||
for r in entries
|
||||
if r.get("room_id") != space_id
|
||||
and (r.get("room_type") or "") != "m.space"
|
||||
]
|
||||
await self._store_cache(space_id, rooms, complete)
|
||||
self.log.info(f"indexering voltooid ({len(rooms)} rooms)")
|
||||
|
||||
async def _load_cache(
|
||||
self, space_id: str
|
||||
) -> Optional[Tuple[List[Dict[str, Any]], bool, int]]:
|
||||
|
|
@ -191,35 +229,19 @@ class RoomsOverviewPlugin(Plugin):
|
|||
|
||||
await evt.mark_read()
|
||||
|
||||
ttl_minutes = max(0, int(self.config.get("cache_ttl_minutes", 15) or 15))
|
||||
cached = await self._load_cache(space_id)
|
||||
now = int(time.time())
|
||||
if cached and ttl_minutes > 0 and now - cached[2] < ttl_minutes * 60:
|
||||
rooms, complete = cached[0], cached[1]
|
||||
self.log.info(
|
||||
f"rooms: cache hit voor {space_id} (age {now - cached[2]}s)"
|
||||
)
|
||||
else:
|
||||
entries, complete = await self._fetch_hierarchy(space_id)
|
||||
rooms = [
|
||||
r
|
||||
for r in entries
|
||||
if r.get("room_id") != space_id
|
||||
and (r.get("room_type") or "") != "m.space"
|
||||
]
|
||||
await self._store_cache(space_id, rooms, complete)
|
||||
if cached is None:
|
||||
# Nog nooit geïndexeerd: vraag een indexering aan en wacht erop
|
||||
# (lock deelt met de achtergrondtaak, dus geen dubbele fetches).
|
||||
await self._refresh_cache(space_id)
|
||||
cached = await self._load_cache(space_id)
|
||||
rooms, complete = cached[0], cached[1] if cached else ([], True)
|
||||
|
||||
if not rooms:
|
||||
if not complete:
|
||||
await evt.reply(
|
||||
"De ruimte-hierarchy kon niet worden opgehaald. Controleer de "
|
||||
"space_id en of de bot lid is van (of toegang heeft tot) de space."
|
||||
)
|
||||
else:
|
||||
await evt.reply(
|
||||
"Geen rooms gevonden. Controleer of de space_id klopt en of de bot "
|
||||
"lid is van (of toegang heeft tot) de space."
|
||||
)
|
||||
await evt.reply(
|
||||
"Er zijn (nog) geen rooms gevonden. Controleer de space_id en of de bot "
|
||||
"lid is van (of toegang heeft tot) de space."
|
||||
)
|
||||
return
|
||||
|
||||
def sort_key(r: Dict[str, Any]) -> str:
|
||||
|
|
@ -248,5 +270,5 @@ class RoomsOverviewPlugin(Plugin):
|
|||
for idx, chunk in enumerate(chunks, start=1):
|
||||
header = f"**Rooms overzicht ({total} rooms getoond, deel {idx}/{len(chunks)}):**\n\n"
|
||||
if idx == 1 and not complete:
|
||||
header += "*De lijst is mogelijk onvolledig: de ruimte-hierarchy kon niet volledig worden opgehaald.*\n\n"
|
||||
header += "*De lijst is mogelijk onvolledig: de laatste indexering was niet compleet.*\n\n"
|
||||
await evt.respond(header + "\n".join(chunk), markdown=True)
|
||||
Loading…
Reference in a new issue