Skip to main content

Module scheduler

Module scheduler 

Source
Expand description

Hosted refresh scheduler: a background tokio task mirroring the CLI’s standalone improv serve-refresh daemon (crates/cli/src/main.rs, cmd_serve_refresh), but running in-process alongside the API instead of as a separate process.

§Scope decision: CALL measures only, not SQL

The CLI daemon refreshes two measure kinds: external-function (CALL) measures via [improv_engine::external::refresh_external_measure], and SQL-sourced measures via improv_storage_sql::refresh_sql_measure, the latter needing a source connection (a rusqlite::Connection opened from an optional source.sqlite CLI argument). The hosted server has no per-request or per-server notion of a SQL source connection string — improv_core_model::SqlSource (the model’s SQL-measure metadata) carries only the query/column mapping, not a connection string, so inventing one here would be scope creep the model doesn’t support. The hosted scheduler therefore refreshes only CALL (external-function) measures automatically; SQL-sourced measures still need improv serve-refresh <db> <source.sqlite> or a manual refresh path.

Refreshing a CALL measure executes code stored in the model, so serving a shared model must not run it implicitly. The scheduler only starts when IMPROV_SCHEDULER=1, and then only runs functions whose fn_digest (sha256(name + "\0" + body), lowercase hex) is listed, one per line, in the file named by IMPROV_EXTFN_ALLOW. Anything else is skipped with a logged warning.

Structs§

SchedulerStatus
Snapshot of the scheduler’s last tick, for the /scheduler/status route.

Functions§

fn_digest
sha256(name + "\0" + body) as lowercase hex: the allowlist key.
parse_allowlist
Parse an allowlist file: one hex digest per line; blank lines and # comments ignored; case-insensitive.
scheduler_enabled
IMPROV_SCHEDULER value -> enabled? Only an explicit 1 turns it on.
spawn_scheduler
Spawn the background refresh loop: every tick, reload the model, refresh any due CALL measures, and save if anything changed. Never panics or exits on a tick error — it logs (eprintln!, matching the CLI daemon’s style) and tries again next tick.
tick_once 🔒
One scheduler tick: load the model, refresh due CALL measures, save if any were refreshed. Returns the ids refreshed. All I/O runs on a blocking thread, matching the request handlers’ spawn_blocking pattern.

Type Aliases§

Allowlist
Operator allowlist of external-function digests (see fn_digest).
SharedStatus