253 lines
5.7 KiB
Markdown
253 lines
5.7 KiB
Markdown
# Cron Jobs in Poimen Workflows
|
|||
|
|
|
||
|
|
## Quick Summary
|
||
|
|
|
||
|
|
**llm-router** detects if user is asking for scheduled/recurring work and generates either:
|
||
|
|
- **WorkflowSpec** (one-time execution)
|
||
|
|
- **CronWorkflowSpec** (scheduled execution)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## CRON EXAMPLES
|
||
|
|
|
||
|
|
### Example 1: Daily Security Scan
|
||
|
|
|
||
|
|
**User says**: "Run security scan on all repos every day at 2 AM"
|
||
|
|
|
||
|
|
**llm-router detects**:
|
||
|
|
- is_scheduled: true
|
||
|
|
- schedule: "0 2 * * *" (2 AM every day)
|
||
|
|
- activities_needed: [Clone, SecurityScan, SendAlert]
|
||
|
|
|
||
|
|
**llm-router generates**:
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"type": "CronWorkflow",
|
||
|
|
"name": "daily-security-scan",
|
||
|
|
"schedule": "0 2 * * *",
|
||
|
|
"timezone": "UTC",
|
||
|
|
"input": {"repos": [...]},
|
||
|
|
"states": [
|
||
|
|
{"name": "Clone", "type": "Task", "resource": "CloneRepoActivity", ...},
|
||
|
|
{"name": "SecurityScan", "type": "Task", "resource": "SecurityScanActivity", ...},
|
||
|
|
{"name": "SendAlert", "type": "Task", "resource": "SendNotificationActivity", ...}
|
||
|
|
]
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Temporal** executes this:
|
||
|
|
- At 2 AM UTC every day
|
||
|
|
- Runs RoutingWorkflow with this spec
|
||
|
|
- Each run is independent (tracks execution history)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Example 2: Hourly Health Check
|
||
|
|
|
||
|
|
**User says**: "Check API health every hour"
|
||
|
|
|
||
|
|
**llm-router generates**:
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"type": "CronWorkflow",
|
||
|
|
"schedule": "0 * * * *",
|
||
|
|
"timezone": "UTC",
|
||
|
|
"states": [
|
||
|
|
{"name": "HealthCheck", "type": "Task", "resource": "HealthCheckActivity", ...},
|
||
|
|
{"name": "RecordMetrics", "type": "Task", "resource": "RecordMetricsActivity", ...}
|
||
|
|
]
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Execution**: Every hour, automatically
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Example 3: Weekly Performance Baseline
|
||
|
|
|
||
|
|
**User says**: "Compare performance with baseline every Sunday at 3 AM"
|
||
|
|
|
||
|
|
**llm-router generates**:
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"type": "CronWorkflow",
|
||
|
|
"schedule": "0 3 * * 0",
|
||
|
|
"timezone": "America/New_York",
|
||
|
|
"states": [...]
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Execution**: Every Sunday at 3 AM in New York timezone
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## CRON SCHEDULE SYNTAX
|
||
|
|
|
||
|
|
```
|
||
|
|
┌───────────── minute (0 - 59)
|
||
|
|
│ ┌───────────── hour (0 - 23)
|
||
|
|
│ │ ┌───────────── day of month (1 - 31)
|
||
|
|
│ │ │ ┌───────────── month (1 - 12)
|
||
|
|
│ │ │ │ ┌───────────── day of week (0 - 6, 0 = Sunday)
|
||
|
|
│ │ │ │ │
|
||
|
|
│ │ │ │ │
|
||
|
|
* * * * *
|
||
|
|
|
||
|
|
Common Examples:
|
||
|
|
0 2 * * * → Every day at 2:00 AM
|
||
|
|
0 */6 * * * → Every 6 hours
|
||
|
|
0 9 * * 1-5 → Weekdays at 9 AM (Mon-Fri)
|
||
|
|
0 0 1 * * → First day of month at midnight
|
||
|
|
0 0 * * 0 → Every Sunday at midnight
|
||
|
|
*/15 * * * * → Every 15 minutes
|
||
|
|
30 2 * * 0 → Every Sunday at 2:30 AM
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## EXECUTION TRACKING
|
||
|
|
|
||
|
|
Temporal automatically tracks all cron executions:
|
||
|
|
|
||
|
|
```
|
||
|
|
Workflow: daily-security-scan
|
||
|
|
|
||
|
|
Run 1: 2025-02-01 02:00:00 UTC → COMPLETED (5m 32s)
|
||
|
|
Run 2: 2025-02-02 02:00:00 UTC → COMPLETED (4m 58s)
|
||
|
|
Run 3: 2025-02-03 02:00:00 UTC → FAILED (timeout in SecurityScan)
|
||
|
|
Run 4: 2025-02-04 02:00:00 UTC → COMPLETED (6m 15s)
|
||
|
|
Run 5: 2025-02-05 02:00:00 UTC → COMPLETED (5m 01s)
|
||
|
|
```
|
||
|
|
|
||
|
|
Retrieve with:
|
||
|
|
```bash
|
||
|
|
temporal workflow list --query "ExecutionStatus='Completed' AND WorkflowType='RoutingWorkflow'"
|
||
|
|
temporal workflow describe --workflow-id daily-security-scan
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## HOW llm-router DETECTS CRON
|
||
|
|
|
||
|
|
LLM looks for keywords in user message:
|
||
|
|
|
||
|
|
```
|
||
|
|
"every day at 2 AM" → "0 2 * * *"
|
||
|
|
"every 6 hours" → "0 */6 * * *"
|
||
|
|
"daily" → "0 0 * * *"
|
||
|
|
"weekly" → "0 0 * * 0" (Sunday)
|
||
|
|
"every Monday" → "0 0 * * 1"
|
||
|
|
"every 15 minutes" → "*/15 * * * *"
|
||
|
|
"weekdays at 9 AM" → "0 9 * * 1-5"
|
||
|
|
"first of month" → "0 0 1 * *"
|
||
|
|
"midnight" → "0 0"
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## DIFFERENCES: One-Time vs Cron
|
||
|
|
|
||
|
|
| Aspect | One-Time | Cron |
|
||
|
|
|--------|----------|------|
|
||
|
|
| **Type** | WorkflowSpec | CronWorkflowSpec |
|
||
|
|
| **Triggered by** | API call, CLI | Schedule |
|
||
|
|
| **Execution** | Runs once, returns immediately | Runs on schedule, indefinitely |
|
||
|
|
| **Input** | Varies per call | Fixed for all runs |
|
||
|
|
| **History** | Single execution | Multiple executions tracked |
|
||
|
|
| **Cancellation** | Can't cancel | Can stop/restart cron |
|
||
|
|
| **Use Case** | Ad-hoc analysis | Background monitoring |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## API ENDPOINTS (Proposed)
|
||
|
|
|
||
|
|
### Submit Cron Workflow
|
||
|
|
```bash
|
||
|
|
POST /api/v1/cron/workflows
|
||
|
|
{
|
||
|
|
"type": "CronWorkflow",
|
||
|
|
"schedule": "0 2 * * *",
|
||
|
|
"timezone": "UTC",
|
||
|
|
"states": [...]
|
||
|
|
}
|
||
|
|
|
||
|
|
Response:
|
||
|
|
{
|
||
|
|
"workflow_id": "daily-security-scan",
|
||
|
|
"schedule": "0 2 * * *",
|
||
|
|
"next_run": "2025-02-02 02:00:00 UTC",
|
||
|
|
"created": "2025-02-01 15:30:00 UTC"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Get Cron Status
|
||
|
|
```bash
|
||
|
|
GET /api/v1/cron/workflows/daily-security-scan/status
|
||
|
|
|
||
|
|
Response:
|
||
|
|
{
|
||
|
|
"workflow_id": "daily-security-scan",
|
||
|
|
"schedule": "0 2 * * *",
|
||
|
|
"is_active": true,
|
||
|
|
"last_run": {
|
||
|
|
"time": "2025-02-01 02:00:00 UTC",
|
||
|
|
"status": "COMPLETED",
|
||
|
|
"duration": "5m 32s"
|
||
|
|
},
|
||
|
|
"next_run": "2025-02-02 02:00:00 UTC",
|
||
|
|
"execution_history": [...]
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### List Cron Workflows
|
||
|
|
```bash
|
||
|
|
GET /api/v1/cron/workflows
|
||
|
|
|
||
|
|
Response:
|
||
|
|
{
|
||
|
|
"workflows": [
|
||
|
|
{
|
||
|
|
"workflow_id": "daily-security-scan",
|
||
|
|
"schedule": "0 2 * * *",
|
||
|
|
"is_active": true,
|
||
|
|
"created": "2025-02-01 15:30:00 UTC"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"workflow_id": "hourly-health-check",
|
||
|
|
"schedule": "0 * * * *",
|
||
|
|
"is_active": true,
|
||
|
|
"created": "2025-02-01 16:00:00 UTC"
|
||
|
|
}
|
||
|
|
]
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Cancel Cron Workflow
|
||
|
|
```bash
|
||
|
|
DELETE /api/v1/cron/workflows/daily-security-scan
|
||
|
|
|
||
|
|
Response:
|
||
|
|
{
|
||
|
|
"status": "cancelled",
|
||
|
|
"workflow_id": "daily-security-scan",
|
||
|
|
"cancelled_at": "2025-02-01 16:30:00 UTC"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## SUMMARY
|
||
|
|
|
||
|
|
✅ **llm-router handles both**:
|
||
|
|
- One-time workflows (instant execution)
|
||
|
|
- Cron workflows (scheduled, recurring)
|
||
|
|
|
||
|
|
✅ **Same RoutingWorkflow executor** for both
|
||
|
|
|
||
|
|
✅ **Temporal manages scheduling** (native support)
|
||
|
|
|
||
|
|
✅ **Full execution history** tracked
|
||
|
|
|
||
|
|
This completes the architecture! 🎉
|
||
|
|
|