Skip to content

feat(datagen): close the fold/overview gaps and raise typed store errors - #223

Merged
beinan merged 5 commits into
lance-format:mainfrom
YangjunZ:datagen/fold-trajectory-sets
Jul 29, 2026
Merged

feat(datagen): close the fold/overview gaps and raise typed store errors#223
beinan merged 5 commits into
lance-format:mainfrom
YangjunZ:datagen/fold-trajectory-sets

Conversation

@YangjunZ

@YangjunZ YangjunZ commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Four changes the datagen delta-log needed before a Python client could drive it end to end.

  • Trajectory started / completed sets — the fold now projects both, so a caller can
    derive the driver frames that were opened and never closed. That difference is what
    attributes a crash to a step.
  • Field value-kind stability — a field that starts out int is rejected if a later event
    writes it as str, instead of silently reshaping the folded state. DatagenItemId is also
    exported so callers compose fan-out child ids through the store's own path format rather
    than by string splicing.
  • Whole-store run overview + blob projectionoverview() aggregates one store into
    root-granularity status counts, completed-step counts, and a failure roll-up grouped by
    run_id, each bucket carrying a capped deterministic sample of failing root item ids.
    fold_item gains a lazy/eager blob switch; lazy stays the default, so folding an item does
    not read blob payloads unless asked.
  • Typed Python errorsto_py_err flattened every ContextError to RuntimeError,
    discarding a distinction the enum already carried. Callers retrying an append could not
    tell a transport fault from a request the store rejected outright, so a deterministic
    rejection burned the whole retry budget. There is now a ContextStoreError hierarchy with
    one leaf per variant; it is rooted at RuntimeError, so except RuntimeError keeps
    catching everything it used to.

Note for remote deployments: overview() is a new endpoint (GET /datagen/{name}/overview),
so remote mode needs a server upgrade. The existing fold calls stay wire-compatible, and
embedded mode bypasses client/server entirely.

Yangjun Zhang and others added 4 commits July 28, 2026 19:54
`DatagenTrajectory` already tracks `started` and `completed` position sets
alongside `ordered`, but `folded_item_to_dto` projected only `ordered`, so
neither set was reachable from the API, the client, or Python.

Spec resume needs both: `completed` gates STEP_COMPLETED re-emission,
`started` gates STEP_STARTED, and `started \ completed` is exactly the set of
driver frames that were open when a writer died.

Add `DatagenStreamPositionDto` and carry both sets on `FoldedDatagenItemDto`,
projected in a deterministic order (the core sets are unordered). Both fields
are `#[serde(default, skip_serializing_if = "Vec::is_empty")]`, so this is a
backward-compatible wire addition: an older server simply yields empty sets
rather than failing to decode.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…temId

Two follow-ups on the datagen fold/binding surface:

- fold now rejects a field whose value kind drifts between writes, for both
  FIELD_SET (last-writer-wins) and FIELD_APPEND (within one list). Previously
  only the SET-vs-APPEND mix was caught, so a field could silently hold
  mixed-kind values.
- DatagenItemId is registered as a pyclass and re-exported from the Python
  package, so callers compose and parse sub-item ids through the store's own
  path format instead of hand-splicing strings.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two gaps in the datagen delta-log read surface:

* `DatagenRunOverview` aggregates a whole store (one experiment) into
  root-granularity status counts, per-step completion counts, and a
  failure roll-up grouped by `run_id`. Each run bucket carries its own
  error-type counts plus a capped, deterministic sample of failing root
  item ids to drill into. Exposed as `DatagenStore::overview`,
  `GET /datagen/{name}/overview`, and `DatagenStore.overview()` in Python.

* `DatagenBlobProjection` makes the blob projection explicit. `fold_item`
  stays lazy (bytes absent, resolved through `get_blob`);
  `fold_item_with`/`fold_item_with_blobs`/`fold_item(load_blobs=True)`
  materialize them inline, reading the payload column only when asked.

Also fixes the lint CI failure by wrapping the PyO3 `DatagenItemId` in a
thin Python class, matching the existing `DatagenStreamWriter` pattern.

The wire additions are backward compatible: new DTO fields default, so no
lockstep server upgrade is required.
…eError

`to_py_err` flattened every `ContextError` to `PyRuntimeError`, discarding the
distinction the enum already carries. Callers that retry appends could not tell a
transport fault from a request the store rejected outright, so a deterministic
rejection burned the whole retry budget before failing.

Add a `ContextStoreError` hierarchy (rooted at `RuntimeError`, so `except
RuntimeError` keeps working) with one leaf per `ContextError` variant, and route
the `DatagenStore` methods through it. `InternalError` and
`CompactionInProgressError` are the retryable pair; the rest are verdicts.
@YangjunZ YangjunZ changed the title feat(datagen): project fold trajectory started/completed sets to the API feat(datagen): close the fold/overview gaps and raise typed store errors Jul 29, 2026
…es them

CI type-checks without a built `_internal`, so every name imported from it needs
the per-name `pyright: ignore` the rest of this module already uses. Re-exporting
the error classes directly leaked the unresolved symbols into `__init__`.
@beinan
beinan merged commit f658683 into lance-format:main Jul 29, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants