4b6817381b
Benchmark image — build + push to ECR (any adapter) / build + push (push) Waiting to run
CI / quality (ubuntu-latest) (push) Waiting to run
CI / test (tools-runtime) (push) Waiting to run
CI / test (e2e-general) (push) Waiting to run
CI / test (cli-runtime) (push) Waiting to run
CI / test (e2e-provider-and-openclaw) (push) Waiting to run
CI / test (integrations-and-misc) (push) Waiting to run
CI / coverage-report (push) Blocked by required conditions
CI / test-kubernetes (push) Waiting to run
CI / should-run-thorough (push) Waiting to run
CI / test-thorough (cloudwatch-demo) (push) Blocked by required conditions
CI / test-thorough (flink-ecs) (push) Blocked by required conditions
CI / test-thorough (upstream-lambda) (push) Blocked by required conditions
CI / test-thorough (prefect-ecs-fargate) (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Release / build-binaries (zip, opensre.exe, onefile, windows-latest, windows-x64) (push) Blocked by required conditions
Release / publish-release (push) Blocked by required conditions
Release / publish-main-release (push) Blocked by required conditions
Release / prepare (push) Waiting to run
Release / verify (push) Blocked by required conditions
Release / build-python-dist (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, macos-15-intel, darwin-x64) (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, macos-latest, darwin-arm64) (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04, linux-x64) (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04-arm, linux-arm64) (push) Blocked by required conditions
Synthetic Deterministic Tests / Synthetic offline (deterministic) (push) Waiting to run
Interactive Shell Live (PR + post-merge) / turn-checks (no-LLM) (push) Waiting to run
Interactive Shell Live (PR + post-merge) / turn-live shard ${{ matrix.shard_index }} (push) Waiting to run
CI (OpenClaw E2E) / openclaw test (push) Has been cancelled
136 lines
5.3 KiB
Plaintext
136 lines
5.3 KiB
Plaintext
---
|
|
title: "Scheduled Deliveries (Cron)"
|
|
description: "Cron-driven recurring reports to Telegram, Slack, and Discord"
|
|
---
|
|
|
|
# Scheduled Deliveries
|
|
|
|
OpenSRE can deliver recurring reports to messaging providers on a cron schedule. This enables daily reliability digests, weekly alert audits, synthetic test summaries, and custom investigations — all delivered automatically without manual CLI invocations.
|
|
|
|
## Quick Start
|
|
|
|
```bash
|
|
# Add a daily summary to Telegram at 09:00 IST on weekdays
|
|
opensre cron add --kind daily_summary --cron "0 9 * * 1-5" \
|
|
--tz Asia/Kolkata --provider telegram --chat-id <chat_id>
|
|
|
|
# List configured tasks
|
|
opensre cron list
|
|
|
|
# Run a task immediately (for debugging)
|
|
opensre cron run <task_id>
|
|
|
|
# Start the scheduler daemon
|
|
opensre cron start
|
|
```
|
|
|
|
## CLI Commands
|
|
|
|
### `opensre cron add`
|
|
|
|
Create a new scheduled delivery task.
|
|
|
|
| Option | Required | Description |
|
|
|--------|----------|-------------|
|
|
| `--kind` | Yes | Task kind: `daily_summary`, `weekly_audit`, `incident_window_replay`, `synthetic_run`, `custom_investigation` |
|
|
| `--cron` | Yes | Cron expression (5 fields: minute hour day month day_of_week) |
|
|
| `--tz` | No | IANA timezone (default: `UTC`). Examples: `Europe/London`, `US/Eastern`, `Asia/Kolkata` |
|
|
| `--provider` | Yes | Messaging provider: `telegram`, `slack`, `discord` |
|
|
| `--chat-id` | Yes | Target chat/channel ID for the provider |
|
|
| `--window` | No | Lookback window in hours (default: `24`) |
|
|
|
|
### `opensre cron list`
|
|
|
|
Display all configured scheduled tasks in a table.
|
|
|
|
### `opensre cron remove <task_id>`
|
|
|
|
Delete a scheduled task by its ID.
|
|
|
|
### `opensre cron run <task_id>`
|
|
|
|
Execute a task immediately (ad-hoc one-shot). Useful for debugging delivery without waiting for the next cron tick.
|
|
|
|
### `opensre cron logs <task_id>`
|
|
|
|
Show execution history for a task (newest first). Displays start time, status, message ID, and any errors.
|
|
|
|
### `opensre cron start`
|
|
|
|
Start the blocking scheduler daemon. Loads all enabled tasks and fires them according to their cron schedules. Blocks until `SIGINT` or `SIGTERM`.
|
|
|
|
## Cron Syntax
|
|
|
|
Standard 5-field cron expressions:
|
|
|
|
```
|
|
┌───────────── minute (0-59)
|
|
│ ┌───────────── hour (0-23)
|
|
│ │ ┌───────────── day of month (1-31)
|
|
│ │ │ ┌───────────── month (1-12)
|
|
│ │ │ │ ┌───────────── day of week (0-6, Mon-Sun)
|
|
│ │ │ │ │
|
|
* * * * *
|
|
```
|
|
|
|
Examples:
|
|
- `0 9 * * 1-5` — weekdays at 09:00
|
|
- `0 8 * * 1` — Mondays at 08:00
|
|
- `*/30 * * * *` — every 30 minutes
|
|
- `0 0 1 * *` — first day of each month at midnight
|
|
|
|
Cron expressions are validated at `cron add` time using APScheduler's `CronTrigger`. Invalid expressions are rejected immediately.
|
|
|
|
## Timezone Behavior
|
|
|
|
- All fire times are internally converted to UTC for dedup consistency
|
|
- The `--tz` option accepts any IANA timezone (e.g., `Europe/London`, `US/Eastern`)
|
|
- DST transitions are handled correctly — the UTC-normalized dedup key ensures no duplicate or missed deliveries across clock changes
|
|
|
|
## Dedup Semantics
|
|
|
|
The scheduler uses a SQLite-backed claim store with a `UNIQUE(task_id, fire_time)` constraint:
|
|
|
|
1. When a cron tick fires, `EVENT_JOB_SUBMITTED` captures `scheduled_run_times[0]` and the job uses that UTC-normalized `fire_time` for the claim key
|
|
2. The executor attempts an `INSERT OR IGNORE` into the claim table
|
|
3. If the insert succeeds (rowcount = 1), this instance won the claim and delivers
|
|
4. If the insert is ignored (rowcount = 0), another instance already claimed it — skip
|
|
|
|
This ensures exactly-once delivery even when multiple scheduler instances run concurrently (e.g., on a laptop and a hosted process).
|
|
|
|
## Credential Resolution
|
|
|
|
Credentials are resolved lazily at delivery time in this priority order:
|
|
|
|
1. **Integration store** — `~/.opensre/integrations.json` (configured via `opensre integrations`)
|
|
2. **Environment variables** — `TELEGRAM_BOT_TOKEN`, `SLACK_BOT_TOKEN`, `DISCORD_BOT_TOKEN`
|
|
3. **Task params** — credentials stored in the task definition (not recommended)
|
|
|
|
This means you don't need to pass credentials at `cron add` time — they're picked up from your existing integration configuration.
|
|
|
|
## Task Kinds
|
|
|
|
| Kind | Behavior |
|
|
|------|----------|
|
|
| `daily_summary` | Runs the investigation pipeline with a daily summary source. Falls back to "no incidents" on empty result, or "pipeline unavailable" on failure. |
|
|
| `weekly_audit` | Runs the pipeline with a weekly audit source. Same fallback behavior. |
|
|
| `incident_window_replay` | Replays the investigation pipeline over the configured window. Raises on failure (operator should know). |
|
|
| `synthetic_run` | Runs the pipeline with a synthetic source. Raises on failure. |
|
|
| `custom_investigation` | Runs a custom investigation with user-provided params. Credential keys are stripped before forwarding to the pipeline. |
|
|
|
|
## Persistence
|
|
|
|
- **Task definitions** are stored in `~/.opensre/scheduler_tasks.json` (JSON + filelock)
|
|
- **Execution history** is stored in `~/.opensre/scheduler.db` (SQLite with WAL mode)
|
|
- Both survive process restarts — `opensre cron list` and `opensre cron logs` read from disk
|
|
|
|
## REPL
|
|
|
|
The `/cron` slash command in the interactive shell forwards to the CLI:
|
|
|
|
```
|
|
/cron list
|
|
/cron add --kind daily_summary --cron "0 9 * * *" --provider telegram --chat-id <id>
|
|
/cron run <task_id>
|
|
```
|