You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Introduce scheduler_config column to the job_configs table (ArroyoSystems#1064)
* Introduce `scheduler_config` column to the job_configs table
Adds a per-job scheduler configuration that overlays the controller's
global scheduler config at scheduling time. For the Kubernetes
scheduler, jobs can now override image, image_pull_policy,
image_pull_secrets, command, service_account_name, resources,
task_slots, env, volumes, volume_mounts, node_selector, tolerations,
labels, and annotations.
Persistence
* Postgres migration V31 (SQLite V9) adds a nullable JSONB
`scheduler_config` column to `job_configs`. NULL means "no
per-job config — use the controller's global scheduler config".
Wire format
* Payload is versioned: { "version": 1, "type": "kubernetes", ... }
* `version` is mandatory on the wire; mirrors the `state_context`
pattern (see V29). Unknown versions deserialize but are rejected by
`SchedulerConfig::ensure_supported_version()`.
Validation
* arroyo-api/src/jobs.rs::validate_scheduler_config rejects payloads
whose version is unknown or whose variant doesn't match the
controller's active scheduler (HTTP 400). Called early in
create_pipeline_inner so bad payloads short-circuit before SQL
compilation.
Read path
* Job API responses surface scheduler_config as raw serde_json::Value
(with #[schema(value_type = SchedulerConfig)] keeping the OpenAPI
spec strongly typed). No silent rewriting or dropping on read.
* Controller stores the raw JSON on JobConfig and deserializes at
the consumer (states::Scheduling) with fatal() on failure, mirroring
how env_vars is handled. A malformed row fails only that job's
state machine, not the whole updater loop.
K8s merge semantics (resolved_config)
* image, image_pull_policy, command, service_account_name,
task_slots, resources → replace
* labels, annotations, node_selector → merge map (per-job wins,
intrinsic labels still applied last)
* image_pull_secrets, volumes, volume_mounts, tolerations, env →
append (global first, per-job last)
* Address Micah's comments
* Pass the configs as an opaque blob through the API
* Use figment for config merging
* Introduce fatal error within the scehduler
* Move is_empty_overlay to the schedulers/mod.rs file
* Fix SQLite NOT NULL constraint on scheduler_config
The scheduler_config column is NOT NULL, but the API was passing
serde_json::Value::Null (the default of serde_json::Value) when the
client omitted the field. Postgres jsonb accepts a JSON null as a
valid value, but SQLite TEXT does not distinguish between SQL NULL
and JSON null, causing the integ tests to fail with:
NOT NULL constraint failed: job_configs.scheduler_config
Change PipelinePost.scheduler_config to Option<serde_json::Value>
(mirroring the env_vars pattern) and collapse None / Some(Null) into
an empty object at the API boundary so the column always carries a
valid JSON object.
0 commit comments