1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184# Petit - Task Orchestrator
A minimal, lightweight task orchestrator with cron-like scheduling written in Rust.
## Project Structure
```
src/
โโโ api/ # HTTP REST API (axum-based)
โ โโโ mod.rs # Router and server setup
โ โโโ handlers.rs # Request handlers
โ โโโ responses.rs # Response types (JSON serialization)
โ โโโ errors.rs # API error types
โโโ config/ # YAML configuration loading and job builders
โโโ core/ # Core types: Job, Task, DAG, Schedule, Retry policies
โโโ events/ # Event bus for task/job lifecycle events
โโโ execution/ # Task executors and DAG execution engine
โโโ scheduler/ # Cron-based scheduler engine
โโโ storage/ # Storage backends (in-memory, SQLite)
โโโ testing/ # Test harness and mock utilities
โโโ tui/ # Terminal UI dashboard (ratatui-based)
โ โโโ app.rs # Application state and logic
โ โโโ event.rs # Event loop (keyboard, tick)
โ โโโ reader.rs # Read-only SQLite interface
โ โโโ theme.rs # Color theme definitions
โ โโโ ui/ # UI components (tabs, widgets)
โโโ lib.rs # Public API exports
โโโ main.rs # CLI entry point (pt binary)
tests/
โโโ integration.rs # Integration test runner
โโโ integration/
โโโ api.rs # HTTP API integration tests
โโโ recovery.rs # Recovery scenario tests
โโโ resources.rs # Resource contention tests
โโโ workflow.rs # End-to-end workflow tests
```
## Development Commands
Use the Makefile for all development tasks:
```bash
make fmt # Format code with rustfmt
make fmt-check # Check formatting without modifying
make lint # Run clippy with warnings as errors
make test # Run all tests
make bench # Run benchmarks
make check # Quick compile check
make build # Build release binary
make ci # Run all CI checks (fmt-check, lint, test)
make all # Same as ci
```
## Running the Application
### CLI (pt binary)
```bash
# Run scheduler with jobs from a directory (API server starts by default)
cargo run -- run ./jobs
# Run scheduler without API server (requires api feature, enabled by default)
cargo run -- run ./jobs --no-api
# Run scheduler with custom API settings
cargo run -- run ./jobs --api-port 8080 --api-host 0.0.0.0
# Trigger a specific job once and exit
cargo run -- trigger ./jobs my_job
```
**Note:** The `--no-api`, `--api-port`, and `--api-host` flags require the `api` feature to be enabled (which is the default). If compiling with `--no-default-features`, these flags will not be available.
### TUI Dashboard
The TUI provides a read-only dashboard for monitoring the scheduler:
```bash
# Build and run the TUI (requires sqlite feature)
cargo run --bin petit-tui --features tui -- --db ./petit.db
```
### Running Scheduler + TUI Together
The scheduler and TUI are separate processes that share a SQLite database:
```bash
# Terminal 1: Start the scheduler with SQLite storage
cargo run -- run --jobs ./jobs --db ./petit.db --api
# Terminal 2: Start the TUI dashboard (read-only)
cargo run --bin petit-tui --features tui -- --db ./petit.db
```
The TUI connects to the database in read-only mode and polls for updates.
## Code Style
- Run `make fmt` before committing
- All clippy warnings are treated as errors (`-D warnings`)
- Use `--all-features` when running checks to include all features
## CI/CD
GitHub Actions runs on every push and PR to main:
- **Format check**: Verifies code is formatted with rustfmt
- **Lint**: Runs clippy with all features enabled
- **Test**: Runs the full test suite
## Features
- `api` - Enables HTTP REST API and related CLI flags (`--no-api`, `--api-port`, `--api-host`). **Enabled by default.**
- `sqlite` - Enables SQLite storage backend and `--db` CLI flag
- `tui` - Enables terminal UI dashboard (includes sqlite)
### Building Without Default Features
```bash
# Build without API support (no API server or API-related CLI flags)
cargo build --no-default-features
# Build with only SQLite support (no API)
cargo build --no-default-features --features sqlite
```
## Testing
Tests are co-located with source files. The `testing` module provides:
- `TestHarness` for integration tests
- `MockTaskContext` for unit tests
- `ExecutionTracker` for verifying task execution order
Integration tests in `tests/integration/` cover:
- API endpoints (`api.rs`)
- Workflow execution (`workflow.rs`)
- Recovery scenarios (`recovery.rs`)
- Resource contention (`resources.rs`)
## Benchmarks
The project includes benchmarks using [criterion](https://docs.rs/criterion) for measuring performance of core components.
### Running Benchmarks
```bash
make bench # Run all benchmarks
cargo bench dag # Run DAG-related benchmarks only
cargo bench scheduler # Run scheduler benchmarks only
cargo bench storage # Run storage benchmarks only
```
### Benchmark Structure
```
benches/
โโโ dag_execution.rs # DAG construction, topological sort, ready task detection
โโโ scheduler.rs # Cron parsing, next occurrence calculations
โโโ storage.rs # Storage backend CRUD and query operations
```
### Available Benchmarks
- **dag_execution**: Measures DAG construction, validation, and topological sorting for various DAG shapes (linear, wide, diamond)
- **scheduler**: Measures next N occurrence calculations for cron and interval schedules
- **storage**: Measures in-memory storage list operations (jobs, runs, task states)
## API Endpoints
When the `api` feature is enabled (default), an HTTP REST API server starts automatically unless `--no-api` is specified. The following endpoints are available:
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/api/health` | GET | Health check |
| `/api/scheduler/state` | GET | Get scheduler state |
| `/api/scheduler/pause` | POST | Pause scheduler |
| `/api/scheduler/resume` | POST | Resume scheduler |
| `/api/jobs` | GET | List all jobs |
| `/api/jobs/{id}` | GET | Get job details |
| `/api/jobs/{id}/trigger` | POST | Trigger a job |
| `/api/jobs/{id}/runs` | GET | List runs for a job |
| `/api/runs/{id}` | GET | Get run details |
| `/api/runs/{id}/tasks` | GET | List task states for a run |