prefect server in zig
1# timestamp handling in prefect
2
3**status**: mostly resolved. `next_scheduled_start_time` added, timestamp parsing works.
4preserved as reference for python/zig differences and .serve() vs workers distinction.
5
6## python implementation
7
8### storage
9- **PostgreSQL**: `TIMESTAMP(timezone=True)` - native timezone-aware
10- **SQLite**: `DATETIME()` naive, manually converts to/from UTC
11
12### format
13all timestamps are UTC timezone-aware. JSON serialization uses ISO 8601:
14```
152024-01-22T15:30:45.123456+00:00
16```
17
18### key fields for flow_run
19- `expected_start_time` - when the run was originally scheduled
20- `next_scheduled_start_time` - **used for scheduling queries** (we're missing this!)
21- `start_time` - actual start
22- `end_time` - actual end
23- `state_timestamp` - when state last changed
24
25### get_scheduled_flow_runs query
26```sql
27WHERE fr.state_type = 'SCHEDULED'
28 AND fr.next_scheduled_start_time <= :scheduled_before
29ORDER BY fr.next_scheduled_start_time ASC
30```
31
32## our implementation
33
34### storage
35- **SQLite**: `TEXT` with format `2024-01-22T15:30:45.123456Z`
36- using SQLite `strftime('%Y-%m-%dT%H:%M:%fZ', 'now')` for defaults
37
38### issues (resolved)
39
401. ~~**missing `next_scheduled_start_time`**~~ ✓ added to flow_run table
41
422. ~~**string comparison is fragile**~~ ✓ timestamp parsing handles multiple formats
43
443. **bandaid fix** - normalizing client timestamps (space→T, +00:00→Z) works and is acceptable
45
46## .serve() vs workers
47
48### .serve() (Runner)
49- creates deployment, starts local polling loop
50- calls `POST /deployments/get_scheduled_flow_runs` every N seconds
51- executes flows locally in the same process
52- **NOT a worker**
53
54### workers
55- standalone daemon process
56- connects to work pools/queues
57- work pool workers: `POST /work_pools/{name}/get_scheduled_flow_runs`
58- task workers: WebSocket `WS /task_runs/subscriptions/scheduled`
59
60### we test
61- `test_cron_scheduler` - server-side scheduler creates runs (correct)
62- `test_worker_execution` - mislabeled! tests `.serve()` Runner, not a worker
63- `test_serve_with_schedule` - verifies deployment has schedule attached (correct)