feat: resident watch tasks with pause/resume/end

Long-running website monitoring: new cloud/resident.py layer on top of
the automations claim/quota model (no task state-machine change).
States running/paused/ended; pause preserves the content-hash cursor
and stops polling, resume re-checks from the cursor, end is terminal
(resume after end is 409, a new watch is required). Polling is a cheap
fetch + hash comparison; only a real change creates a queued model
task. Quota exhaustion pauses (quota_exceeded) instead of ending and
keeps the cursor. Driver is the worker run_loop round boundary;
server exposes create/list/get/update/pause/resume/end with audit.
Console UI intentionally not wired this round (see verification
summary for deviations).
This commit is contained in:
host committed 2026-11-01 19:01:39 +00:00
1 parent 622c51e7fb
commit 0722ca3fd8
6 files changed
+1516

No files matched your search

+31
View File
@@ -6582,6 +6582,33 @@ class Worker:
log_event(self.logger, "worker_push_due_failed",
message="push due processing failed: %s" % exc)
def process_due_resident_watches(self, now=None, fetcher=None):
"""常驻监听驱动(worker 轮次边界调用):到期监听逐条
走 resident.process_due_resident_watches,抢单 + 廉价
抓取 + 仅变化建任务。全部异常只记日志,不炸循环;
fetcher 缺省用 resident 默认抓取,单测可经
self.resident_fetcher 或参数注入假抓取。"""
if now is None:
now = time.time()
if fetcher is None:
fetcher = getattr(self, "resident_fetcher", None)
try:
from cloud.resident import process_due_resident_watches as _run
conn = _db_connect(self.db_path)
try:
polls = _run(conn, fetcher=fetcher, now=now)
finally:
conn.close()
except Exception as exc:
log_event(self.logger, "worker_resident_watch_failed",
message="resident watch processing failed: %s" % exc)
return []
for poll in polls:
log_event(self.logger, "worker_resident_watch_poll",
message="resident watch poll: %s %s"
% (poll["watch_id"], poll["status"]))
return polls
def run_loop(self, interval=300, max_seconds=None, stop_event=None,
drain_timeout=60, sweep_threshold=300):
"""常驻循环:每 interval 秒跑一轮 run_all,空闲也不退出。
@@ -6664,6 +6691,10 @@ class Worker:
# G11/G12 后台投递:摘要(每小时)与 outbox 重试,
# 轮次边界做,不中断在跑任务,失败只记日志。
self._process_push_due()
# 常驻监听驱动:同款轮次边界后台扫,到期监听
# 廉价抓取、仅变化建任务;服务端本身不起定时器,
# 这里就是常驻任务的实际驱动(见 resident 模块)。
self.process_due_resident_watches()
# 自动记忆提取:同款轮次边界后台扫,失败只记日志
# (process_auto_memories 内部已兜底,不炸循环)。
self.process_auto_memories()