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.
§Consent: off by default, allowlisted functions only
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§
- Scheduler
Status - Snapshot of the scheduler’s last tick, for the
/scheduler/statusroute.
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_SCHEDULERvalue -> enabled? Only an explicit1turns it on.- spawn_
scheduler - Spawn the background refresh loop: every
tick, reload the model, refresh any dueCALLmeasures, 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_blockingpattern.
Type Aliases§
- Allowlist
- Operator allowlist of external-function digests (see
fn_digest). - Shared
Status