Skip to content

feat(incremental): debounce artifact auto re-export #1884

Description

@DeusData

Debounce the artifact auto re-export so a re-export doesn't run on every incremental index.

Design accepted on 2026-08-20 on PR #870 by @moofone. Re-filed as an issue because the hook point that PR targeted no longer exists on main — export moved out of dump_and_persist into export_after_publish (src/pipeline/pipeline.c:2529-2544), whose signature (cbm_pipeline_t *p, const char *final_path) has no access to changed_total, file_count or stamps[] — all of which the debounce needs, and all local to cbm_pipeline_run_incremental. Reaching them needs new cross-module plumbing, so this is a design task rather than a rebase, and it deserves its own issue instead of blocking on a stale branch.

Accepted shape

Skip the per-run re-export unless one of:

  • changed_total exceeds a threshold, or
  • cumulative drift since the last export exceeds a threshold (@moofone added this trigger mid-review), or
  • the artifact is older than a max age.

Changes requested against the original, to carry forward

  • MAX_AGE ~1h, not 24h.
  • Deletions must count toward drift, with a test.
  • A run-summary line naming the blocking threshold, so a skipped export is explainable rather than mysterious.
  • README documentation — the original added two env knobs and changed a user-visible default cadence with no docs.

Defect to fix in any implementation

parse_iso8601_utc (src/pipeline/artifact.c:244) range-checks month/day/hour/min/sec but never the year. In pipeline_incremental.c:800 the result feeds (exported_epoch + 1) * CBM_NS_PER_SEC; since INT64_MAX / 1e9 ≈ year 2262, a hostile or corrupt "indexed_at":"9999-01-01T00:00:00Z" yields ≈2.53e20 and overflows signed int64 — reachable on the first index after a clone. Release builds wrap; the Makefile.cbm diag UBSan lane traps. sscanf("%d") on an out-of-range year is itself UB. Range-check the year.

Credit to @moofone for the design and for adding the cumulative-drift trigger during review.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions