scheduler
Maintain Gnosi's backend scheduler lifecycle, persistence and task dispatch. Use for scheduler startup or task-state regressions, not private development-agent orchestration.
- License 许可
- AGPL-3.0
- 所属仓库
- ismigar/Gnosi
- 最近更新
- 2026-11-12
- Stars
- ★ 1
- Forks
- 0
01 前言 Front Matter
- name
- scheduler
- description
- Maintain Gnosi's backend scheduler lifecycle, persistence and task dispatch. Use for scheduler startup or task-state regressions, not private development-agent orchestration.
03 SKILL.md 正文
SKILL: Backend Background Scheduler
This skill defines the technical protocol for managing the Gnosi background task orchestrator (SchedulerManager).
ID: SCHEDULER-CORE-20260408 Core Logic:
backend/scheduler/manager.pyStatus: ACTIVE
1. Objectives and Scope
- Main Objective: Maintain a stable and efficient background loop for orchestrating Reader flows and maintenance tasks.
- Success Criteria:
- Tasks execute at their defined intervals.
- Errors in one task do not stop the main scheduler loop.
- Task state (last run, results) is persisted correctly.
2. Core Principles
A. Background Loop
Construction loads configuration but does not start the thread. The application
lifespan calls start() unless GNOSI_DISABLE_SCHEDULER disables it. The daemon
loop checks enabled tasks every 60 seconds using last_run and
interval_minutes; do not describe a separate persisted next_run timer.
B. Non-blocking Execution
The scheduler loop is outside the HTTP event loop. run_task_now() executes its
handler synchronously in its caller; individual domain jobs may start their own
workers. Do not assume every task gets another thread or promise concurrent
execution from this manager. Preserve domain-specific overlap and job policies.
The automatic loop waits 30 seconds by default before dispatching overdue work,
so the HTTP server and active vault can become responsive first. Override this
with GNOSI_SCHEDULER_STARTUP_DELAY_SECONDS; setting it to zero is appropriate
for deterministic tests. Manual task submissions do not inherit this delay.
The lifespan itself schedules external integrations only after yielding startup,
with a five-second grace period controlled by
GNOSI_INTEGRATION_STARTUP_DELAY_SECONDS. IMAP connection attempts therefore
cannot keep the HTTP port closed.
C. State Persistence
The configured SCHEDULER path holds task definitions and lifecycle metadata.
A per-device recovery mirror lives at
GNOSI_DATA_DIR/system/scheduler_config.local.json; the manager resolves it
through the canonical LOCAL_DATA path mapping. Execution history uses the
management database. Preserve both configuration sources when investigating a
cloud-placeholder read failure; do not replace an unreadable file with defaults.
3. Operations and CLI
Manual Trigger
Tasks can be triggered manually via the REST API, bypassing the scheduled wait:
# A Personal Access Token is required once the backend runs with
# GNOSI_REQUIRE_AUTH (create one in Settings). Without enforcement it is optional.
curl -X POST http://localhost:5002/api/schedulers/{task_name}/run \
-H "Authorization: Bearer $GNOSI_API_TOKEN"
4. Restrictions and Edge Cases
- Daemon State: Keep startup/shutdown in the app lifespan. Unit tests must not start the scheduler or fire overdue integrations.
- Config Integrity: Preserve configured paths and the recovery mirror. Missing tasks may be merged from defaults; unreadable configuration is not evidence that persisted user settings were empty.
- Path Sensitivity: Background tasks must use absolute paths (via
paths_config.py) to avoid resolution errors when running as a service. - Host lock:
start()uses a local POSIX file lock when available; it is not a distributed multi-host lock. Preserve the non-POSIX fallback behavior. - Verification: Run
backend/tests/test_scheduler_maintenance_scope.py; its isolated child also selects the task-handler domain contracts before any backend configuration import. Use synthetic scheduler API and lifespan fixtures. Manual API execution is a real operation, not a documentation check. - Startup responsiveness: Do not dispatch overdue integrations in the same instant that the application lifespan is opening the HTTP service. Keep the bounded startup grace period interruptible through the scheduler stop event; never implement it as an unconditional sleep.
5. Learning Cycle (Live Memory)
| Date | Error / Learning | Root Cause | Solution / Refinement |
|---|---|---|---|
| 2026-04-07 | Idle Scheduler | Missing loop implementation | Refactored SchedulerManager to include an active while loop and thread spawning. |
| 2026-04-08 | Doc Displacement | Fragmentation | Moved directive from local docs/ to consolidated Skill. |
| 2026-09-04 | Web unavailable during background catch-up | Enabled RSS, mail and maintenance tasks all dispatched on the scheduler's first cycle and competed with HTTP startup | Added an interruptible 30-second automatic-dispatch grace period while preserving immediate manual runs. |
| 2026-09-04 | A scheduler test replaced threading.Event with a narrower recorder and failed strict typing |
The production attribute is intentionally a concrete synchronization primitive | Test the pure delay policy directly and retain the real event for lifecycle behavior. |
| 2026-09-04 | The scheduler grace expired before Uvicorn opened its port | Scheduler and IMAP startup preceded cache warmup and the lifespan yield | Moved external integration startup to a tracked post-yield task and cancel it during shutdown. |
| 2026-09-04 | A post-yield lifecycle test expected a zero-delay task after one event-loop turn | asyncio.sleep(0) itself yields once before the deferred body continues |
Give the tracked task two explicit loop turns in the isolated ordering contract. |
04 同仓库更多 Skills
zotero-sync-compatibility
Preserve the historical Zotero reference-table configuration path after Gnosi replaced bidirectional Zotero synchronization with its native reference manager.
zotero-schema
Generate Gnosi's Python and TypeScript item-type constants from the repository-pinned Zotero schema, or perform an explicitly requested pinned schema refresh. Use for mapping or generated-constant maintenance, not runtime downloads.
vault-core
Preserve Gnosi vault identifiers, internal links and active-vault context during file or metadata changes. Use for vault integrity work, not blanket normalization or cleanup of user documents.
translate-row
Translate configured table-row fields and Markdown into language children, updating existing translations in place. Use for the explicit translate-row action or maintenance of its provider adapters.
translate-page
Translate a Vault page title and Markdown body into language children, updating existing translations and preserving Gnosi directives. Use for the explicit translate-page action or Markdown segmentation maintenance.
technical-documentation
Generate and validate Gnosi's engineering portal from reviewed guides and deterministic source catalogs. Use for source-traceable documentation updates and pre-PR gates; never translate generated catalogs with a model.