Skip to content

feat: versioned DatasetStorage for reading/writing datasets across protocol versions#9443

Open
koenvanderveen wants to merge 2 commits into
devfrom
koen/dataset-storage
Open

feat: versioned DatasetStorage for reading/writing datasets across protocol versions#9443
koenvanderveen wants to merge 2 commits into
devfrom
koen/dataset-storage

Conversation

@koenvanderveen

Copy link
Copy Markdown
Collaborator

Summary

Mirrors the syft-job migration/storage architecture (PR #9434) in syft-datasets, adding a versioned read/write layer so datasets can evolve their on-disk format while staying compatible with older peers.

  • DatasetStorage — the single choke point for all dataset filesystem IO. Reads select a ProtocolCodec by the on-disk protocol version and upgrade the object to the latest version in memory; writes downgrade to the target protocol and let the codec persist it. Nests a MigrationRegistry, peer_schemas, and codecs.
  • v<n> path segment — new datasets can live under public/syft_datasets/v<n>/<name>/ (and private/…). Protocol 0 = the last release (syft-client 0.1.117 / syft-dataset 0.1.20): flat layout, no v<n>, no canonical_name/version fields — read and written back byte-compatibly.
  • Versioned modelsDataset / PrivateDatasetConfig are now MigratableObjects under models/<object>/v1.py. Object schemas are unchanged since 0.1.117, so only v1 exists; the protocol bump is purely a path-layout + identity-field change. dataset.py is kept as a re-export shim.
  • DatasetRef — path-derived identity (owner, name, protocol_version); the dataset name comes from the path, not the spoofable file.
  • Broadcast write — a public dataset is a single copy read by the whole audience (unlike jobs, which target one peer), so the write protocol(s) come from the audience's versions (target_protocol_versions_for_peers), defaulting to the widest-compatible (oldest) protocol when no peers are known. peer_schemas is injectable but not yet populated by syft-client, so today datasets are written in protocol 0 and the v1 layout ships dormant (writing v1 now would hide datasets from 0.1.117 peers).
  • SyftDatasetManager routes all reads/writes through DatasetStorage and supports multi-version write (one on-disk copy per protocol version in the audience); get_all dedupes copies across layouts, preferring the newest protocol.
  • Release toolingscripts/export_release_artifact.py + generate_release_fixture.py; the protocol-0 / 0.1.20 artifacts and fixtures are derived as if that release had emitted them.
  • Tests mirror syft-job/tests/migrations (unit + p2p), including a byte-exact cross-release round-trip over hand-generated fixtures and a multi-version-write test. CI (unit-tests.yml dataset-tests job) and justfile (test-unit-datasets) wired.

Scope

Package core only, per discussion. syft-client wiring (advertising each peer's dataset protocol version and writing in it at create/share) is a follow-up — syft-client currently exchanges only a single client-version string, not per-package schemas.

Testing

  • uv run pytest packages/syft-datasets/tests40 passed
  • just test-unit-fast → 406 passed
  • tests/unit dataset + sync_manager + delete suites → green
  • pre-commit run --all-files → clean

…otocol versions

Mirror the syft-job migration/storage architecture in syft-datasets:

- DatasetStorage: single choke point for all dataset filesystem IO. Reads select
  a ProtocolCodec by on-disk protocol version and upgrade to the latest object
  version in memory; writes downgrade to the target protocol and the codec
  persists it. Nests a MigrationRegistry, peer_schemas, and codecs.
- On-disk protocol version: new datasets can live under a v<n> path segment
  (public/syft_datasets/v<n>/<name>/). Protocol 0 = the last release
  (syft-client 0.1.117 / syft-dataset 0.1.20): flat layout, no v<n>, no
  canonical_name/version fields; read + written back byte-compatibly.
- Versioned models: Dataset / PrivateDatasetConfig are now MigratableObjects
  under models/<object>/v1.py. Object schemas are unchanged since 0.1.117, so
  only v1 exists; the protocol bump is purely path-layout + identity fields.
- DatasetRef: path-derived identity (owner, name, protocol_version).
- Broadcast write: a public dataset is one copy read by the whole audience, so
  the write protocol(s) come from the audience's versions
  (target_protocol_versions_for_peers), defaulting to the widest-compatible
  (oldest) protocol when no peers are known. peer_schemas is injectable but not
  yet populated by syft-client, so today datasets are written in protocol 0 and
  the v1 layout ships dormant.
- SyftDatasetManager routes all reads/writes through DatasetStorage and supports
  multi-version write (one copy per protocol version in the audience); get_all
  dedupes copies across layouts preferring the newest protocol.
- migrations/history + release scripts (export_release_artifact.py,
  generate_release_fixture.py); protocol-0/0.1.20 artifacts and fixtures derived
  as if that release had emitted them.
- Tests mirror syft-job/tests/migrations (unit + p2p, incl. byte-exact
  cross-release round-trip and a multi-version-write test); CI + justfile wired.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The enclave inference example computed private dataset dirs using the
default protocol version (v1 segment), but datasets shared with 'any'
are written at the widest-compatible protocol (0, no segment). This
mismatch broke the log-sink path and the ensure_logs_dataset idempotency
check. Resolve the actual on-disk ref via DatasetStorage, falling back to
the widest-compatible protocol for datasets not yet synced.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant