feat: scheduler /watch — watched_topics + scheduler loop + /watch /unwatch /watches
Build & Deploy ResearchOwl / build-and-push (push) Successful in 5s

This commit is contained in:
ChemaVX
2026-05-04 07:48:05 +00:00
parent b33ae202b8
commit b5518ac95a
2 changed files with 304 additions and 55 deletions
+63
View File
@@ -99,6 +99,18 @@ CREATE TABLE IF NOT EXISTS api_usage (
cost_usd REAL NOT NULL,
created_at REAL NOT NULL
);
CREATE TABLE IF NOT EXISTS watched_topics (
id INTEGER PRIMARY KEY AUTOINCREMENT,
topic TEXT NOT NULL,
chat_id INTEGER NOT NULL,
interval_hours INTEGER NOT NULL DEFAULT 24,
next_run_at REAL NOT NULL,
last_run_at REAL,
enabled INTEGER NOT NULL DEFAULT 1,
created_at REAL NOT NULL,
UNIQUE(topic, chat_id)
);
"""
@@ -319,6 +331,57 @@ class ResearchDB:
row = await cursor.fetchone()
return dict(row) if row else {"sessions": 0, "total_cost": 0}
# --- Watched Topics ---
async def add_watch(self, topic: str, chat_id: int, interval_hours: int) -> int:
now = time.time()
cursor = await self.db.execute(
"""INSERT OR REPLACE INTO watched_topics
(topic, chat_id, interval_hours, next_run_at, created_at)
VALUES (?, ?, ?, ?, ?)""",
(topic, chat_id, interval_hours, now + interval_hours * 3600, now)
)
await self.db.commit()
return cursor.lastrowid
async def remove_watch(self, topic: str, chat_id: int) -> bool:
cursor = await self.db.execute(
"DELETE FROM watched_topics WHERE topic = ? AND chat_id = ?",
(topic, chat_id)
)
await self.db.commit()
return cursor.rowcount > 0
async def list_watches(self, chat_id: int) -> list[dict]:
cursor = await self.db.execute(
"SELECT * FROM watched_topics WHERE chat_id = ? ORDER BY created_at ASC",
(chat_id,)
)
rows = await cursor.fetchall()
return [dict(r) for r in rows]
async def get_due_watches(self) -> list[dict]:
cursor = await self.db.execute(
"SELECT * FROM watched_topics WHERE enabled = 1 AND next_run_at <= ?",
(time.time(),)
)
rows = await cursor.fetchall()
return [dict(r) for r in rows]
async def update_watch_run(self, watch_id: int):
cursor = await self.db.execute(
"SELECT interval_hours FROM watched_topics WHERE id = ?", (watch_id,)
)
row = await cursor.fetchone()
if not row:
return
now = time.time()
await self.db.execute(
"UPDATE watched_topics SET last_run_at = ?, next_run_at = ? WHERE id = ?",
(now, now + row[0] * 3600, watch_id)
)
await self.db.commit()
# --- Maintenance ---
async def purge_old_sessions(self, max_age_days: int = 30) -> dict: