Files
oak-editor/crates/oakstorage
Mike-Solar 4240df1d71 refactor(crates): implement std::error::Error for all module error enums
thiserror derive across oakundo/oakcommon/oaknode/oaktimeline/oaktask/
oakotio/oakcodec/oakaudio/oakrender/oakplugin/oakengine/oakstorage;
Display carries the module prefix and the Failed context, source()
stays default except oakotio's #[from] forwarding. code() mappings and
variants unchanged; each error.rs gains Display/object-safety/code
regression tests.
2026-08-14 05:45:05 +08:00
..

oakstorage Rust crate (declaration draft, for review)

Status: declaration draft. Signatures + doc comments are the spec; every body is todo!(). Manual: docs/zh/plans/riir/M10-oakstorage.md.

Scope

Project persistence — the single module that knows where projects come from and where they are saved to. Backends are pluggable via a manual vtable; shipping in this pass: ove-xml (the existing XML project format), otio (via the native oakotio crate), and database (PostgreSQL + SQLite). Consumers never branch on backend.

Architectural decisions

  1. URI dispatch, not file paths. Every entry point takes a URI: file:///…proj.ove / file:///…proj.otio / oakdb+sqlite:///path/to.db / oakdb+pg://host:port/dbname?user=…. The core resolves scheme + backend can_handle arbitration (M10 §2.3).
  2. Manual vtable backends (backend.rs StorageBackend trait = the M10 C vtable's Rust shape). The public C ABI vtable (oakstorage_backend_register) accepts foreign (C-side) backends; in-crate backends implement the Rust trait directly.
  3. The graph (de)serialization itself stays in oaknode — every backend calls the oaknode C ABI (oaknode_serializer_* family) through bridge::node to fetch/rebuild the in-memory graph; backends own framing: container bytes, schema, versioning, compression, sessions.
  4. Database backend shares one logical schema across PostgreSQL and SQLite via SeaORM (sea-orm crate, sqlx-postgres + sqlx-sqlite features): a private current-thread tokio runtime drives the async SeaORM API behind the synchronous C ABI; the entity set is minimal (projects table: id, name, payload blob, version, timestamps). Schema management (create-if-missing, migrate) is backend-internal. The graph payload is the same serialized form the ove-xml backend uses — one serialization truth, two containers.
  5. No callbacks/events (M10: synchronous commands only; the caller — oaktask/facade — owns progress reporting).
  6. Errors follow the project -MMCCCC scheme, module 10 (-100001 …); the M10 positive info codes (TOO_OLD/TOO_NEW/…) are kept verbatim.

Layout

src/
  lib.rs          crate doc + module map
  error.rs        error/info codes (M10 §2.1, -MMCCCC module 10)
  handle.rs       refcounted-handle scaffolding
  uri.rs          URI parsing/classification
  session.rs      StorageProject session (open/take/uri)
  registry.rs     backend registry (register/unregister/arbitrate)
  backend.rs      StorageBackend trait + C vtable marshalling
  backends/
    ove_xml.rs    built-in .ove XML backend (via bridge::node)
    otio.rs       built-in .otio backend (via oakotio)
  bridge/
    node.rs       oaknode C ABI imports (serializer family)
  ffi.rs          export layer (M10 §2.2 verbatim)
tests/            contract tests incl. the pluggability proof