Files
library-desk/docs/scheduler-tasks.md
T
jpmschweitzerandClaude Fable 5 b4a5a92fee fix: send Scheduler API Bearer auth from the task registrar
The Scheduler's task-management endpoints (GET/POST /tasks, PUT
/tasks/{name}) are guarded by verify_api_key, but execute() built a bare
httpx.Client with no Authorization header: the existence probe 401'd
(misread as 'task absent') and every POST/PUT registration failed, so
--execute was never runnable end-to-end against the real Scheduler.

--execute now requires SCHEDULER_API_KEY from the environment (never
stored) and sends Authorization: Bearer on all registrar HTTP calls.
Deploy notes updated alongside the LIBRARY_API_KEY requirement.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QbFZyDvYksazX6nYQYZ67L
2026-07-14 15:13:16 +02:00

5.4 KiB

Scheduler Task Definitions (Phase C deploy checklist)

Production task payloads for the homelab's database-driven Scheduler service. These are definitions only — nothing in this repo registers them automatically. Register them as part of the deploy checklist, either via the Scheduler UI/API or with the helper script:

# Preview exactly what would be sent (default):
SCHEDULER_URL=http://<scheduler-host>:8090 \
    .venv/bin/python scripts/register_scheduler_tasks.py

# Actually register/update the tasks (deploy checklist step):
SCHEDULER_URL=http://<scheduler-host>:8090 \
SCHEDULER_API_KEY=<scheduler-api-key> \
    .venv/bin/python scripts/register_scheduler_tasks.py --execute

Conventions:

  • The Scheduler's task-management endpoints (GET/POST /tasks, PUT /tasks/{name}) require Authorization: Bearer $SCHEDULER_API_KEY. The registrar reads SCHEDULER_API_KEY from the environment for its own HTTP calls (--execute refuses to run without it); the key is never stored. This is separate from LIBRARY_API_KEY below, which the Scheduler container needs at task execution time.

  • All tasks call the production library-desk container (http://library-desk:8089) with the explicit production tenant user=jpmschweitzer (there is no default tenant — Phase B).

  • ${LIBRARY_API_KEY} is a literal placeholder stored in the task's auth.token field. The Scheduler's rest_api_executor substitutes ${ENV_VAR} placeholders from its own environment at execution time (it substitutes url/payload/auth — NOT plain headers), so the raw key is never stored in the scheduled_tasks.config JSONB column. The Scheduler container must have LIBRARY_API_KEY in its environment. Never commit or register the real value.

  • The JSON body goes in config.payload (the executor ignores a body key).

  • Schedule fields use the Scheduler's convention: -1 = every, day_of_week: 0 = Monday … 6 = Sunday.


1. Nightly integrity check — 04:30 daily

Read-only report: pages without vectors, orphaned vectors, unexpected Qdrant collections, Document nodes without wiki pages. Caches its result in Redis for the weekly quality report.

{
  "task_name": "library_integrity_check",
  "service": "library-desk",
  "executor": "rest_api_executor",
  "priority": 60,
  "description": "Nightly read-only integrity check for the library (vectors/graph/wiki/collections)",
  "enabled": true,
  "max_retries": 2,
  "timeout_seconds": 900,
  "minute": 30,
  "hour": 4,
  "day_of_month": -1,
  "month": -1,
  "day_of_week": -1,
  "config": {
    "method": "POST",
    "url": "http://library-desk:8089/maintenance/integrity-check",
    "headers": {
      "Content-Type": "application/json"
    },
    "payload": {
      "user": "jpmschweitzer"
    },
    "auth": {
      "type": "bearer",
      "token": "${LIBRARY_API_KEY}"
    }
  }
}

2. Weekly quality report — Sunday 03:00

Runs the duplicate scan, flags stale/metadata-poor pages, folds in the latest integrity results, and writes the dated report page to users/jpmschweitzer/system/quality-reports/YYYY-MM-DD.

{
  "task_name": "library_quality_report",
  "service": "library-desk",
  "executor": "rest_api_executor",
  "priority": 60,
  "description": "Weekly library quality report (dedup, stale pages, missing metadata, integrity) written to the wiki",
  "enabled": true,
  "max_retries": 2,
  "timeout_seconds": 1800,
  "minute": 0,
  "hour": 3,
  "day_of_month": -1,
  "month": -1,
  "day_of_week": 6,
  "config": {
    "method": "POST",
    "url": "http://library-desk:8089/maintenance/quality-report",
    "headers": {
      "Content-Type": "application/json"
    },
    "payload": {
      "user": "jpmschweitzer",
      "stale_days": 30,
      "dedup_threshold": 0.9,
      "write_page": true
    },
    "auth": {
      "type": "bearer",
      "token": "${LIBRARY_API_KEY}"
    }
  }
}

3. Daily Paperless orphan cleanup — 05:00

Hits the existing cleanup endpoint (query parameters, empty payload). dry_run=false deletes vectors/graph nodes for documents that were removed from Paperless-ngx.

{
  "task_name": "library_paperless_orphan_cleanup",
  "service": "library-desk",
  "executor": "rest_api_executor",
  "priority": 60,
  "description": "Daily cleanup of vectors/graph nodes for documents deleted from Paperless-ngx",
  "enabled": true,
  "max_retries": 2,
  "timeout_seconds": 900,
  "minute": 0,
  "hour": 5,
  "day_of_month": -1,
  "month": -1,
  "day_of_week": -1,
  "config": {
    "method": "POST",
    "url": "http://library-desk:8089/maintenance/cleanup/paperless?user=jpmschweitzer&dry_run=false",
    "payload": {},
    "auth": {
      "type": "bearer",
      "token": "${LIBRARY_API_KEY}"
    }
  }
}

4. Disable test_example_task

Not a new task: the leftover example task must be disabled (not deleted, so its history is preserved).

PUT ${SCHEDULER_URL}/tasks/test_example_task
Content-Type: application/json

{"enabled": false}

  • knowledge_consolidation — every 30 minutes, POST /consolidate/knowledge (already registered; after the Phase C consolidation repair its runs log searches_processed and duration_ms, and searches are no longer consumed while the LLM is unavailable).
  • Redis job-set cleanup — runs in-process inside library-desk (hourly job_cleanup_loop started at app startup); no Scheduler task needed.