-
Notifications
You must be signed in to change notification settings - Fork 0
event envelope
Kadyapam edited this page May 30, 2026
·
7 revisions
The wire format for POST /api/events — what workers (and CLI in distributed mode) send to ingest events into the event log.
pub struct EventRequest {
pub execution_id: String, // bigint represented as decimal string
pub step: String, // e.g. "fetch_calendar"
pub name: String, // event_type, e.g. "step.enter", "call.done", "step.exit"
pub payload: serde_json::Value, // event-type-specific data
pub meta: Option<serde_json::Value>,
pub worker_id: Option<String>,
pub actionable: bool,
pub informative: bool,
}Matches the Python noetl/server EventEmitRequest shape line-for-line — both implementations enforce the same external contract.
As of 2026-05-30, four envelope shapes exist across the NoETL Rust + Python codebase:
| Source | Type | execution_id |
event name field | extra fields |
|---|---|---|---|---|
| noetl-server (this crate) | handlers::events::EventRequest |
String |
name |
payload, meta, worker_id, actionable, informative
|
| Python noetl/server | EventEmitRequest |
str |
event_type (enum) |
event_id, ... |
| noetl-worker | client::WorkerEvent |
i64 ← diverges |
event_type (free string) |
payload |
| noetl-executor | events::ExecutorEvent |
i64 ← diverges |
event_type (free string) |
step, status, created_at, context
|
The two servers agree. The worker and executor disagree on execution_id type AND on which fields are top-level vs nested in payload.
Current production behaviour: worker → server today works because:
- Pydantic (Python) coerces
i64→strleniently during JSON deserialization. - The Rust server's sqlx layer likely does the same coercion.
- The
namevsevent_typefield naming is bridged somewhere (possibly the worker actually sendsnamenotevent_typeand the localWorkerEventis misnamed; needs verification).
Tracked on noetl/ai-meta#30 — Appendix H Rust migration umbrella. Planned PR sequence:
-
Server-side: add a v2 endpoint (
POST /api/events/v2?) that acceptsExecutorEventshape directly, alongsideEventRequestfor backward compat. Both implementations (Rust + Python) need the v2 path. -
Worker-side (R-1.2 PR-2c+ follow-up): switch
client::ControlPlaneClient.emit_eventto sendExecutorEventto the v2 endpoint. Worker'sWorkerEventbecomes a thin wrapper / direct re-export ofexecutor::events::ExecutorEvent. - CLI-side: same switch in distributed mode.
- Sunset: deprecate the v1 endpoint after a release cycle once all clients moved.
Each step is independently reviewable + reversible. No big-bang cutover.
-
step+statusare first-class fields rather than buried inpayload— easier for the projector + dashboard queries. -
created_atis stamped at emit time → avoids server-clock skew when ordering events. -
execution_id: i64matches the Postgresbigintcolumn type directly → no String⇄i64 conversion in the ingest path. - Documented in executor-crate-architecture as the design target.
- Event envelope
- Event-sourced execution
- API surface
- Runtime shape (compiled + plug-in ring)
- Cursor / claim loop mode
- noetl/cli wiki
- noetl/worker wiki
- noetl/tools wiki
- noetl/noetl wiki — Python implementation (twin during migration)
- noetl/ops wiki