56 lines
2.0 KiB
Markdown
56 lines
2.0 KiB
Markdown
# Internal: Storage
|
|
|
|
## Purpose
|
|
|
|
Explain the object-store interface and S3 implementation used by Narratio.
|
|
Remote key layout and lifecycle belong in [Operations](../operations.md), while
|
|
operator-selected storage fields and credential mechanisms belong in
|
|
[Configuration](../config.md).
|
|
|
|
## Primary Contract
|
|
|
|
`storage.ObjectStore` interface:
|
|
|
|
- `List(ctx, prefix)`
|
|
- `Read(ctx, key)` returns an object body and the generation observed with it
|
|
- `Download(ctx, key, localPath)`
|
|
- `Upload(ctx, localPath, key, opts)`
|
|
- `UploadConditional(ctx, source, key, opts, condition)`
|
|
- `Exists(ctx, key)`
|
|
|
|
Key invariant:
|
|
- callers pass full bucket-relative keys;
|
|
- storage implementations do not infer campaign/session/run prefixes.
|
|
|
|
## Composition
|
|
|
|
`NewObjectStoreFromConfig` constructs the S3-backed implementation from
|
|
resolved configuration. The application loads configured filesystem secrets
|
|
before calling it. The storage adapter consumes already-resolved values; it does
|
|
not own discovery, defaults, or configuration validation.
|
|
|
|
## S3 Backend Behavior
|
|
|
|
- normalizes object keys.
|
|
- `List` paginates and returns normalized `ObjectInfo`.
|
|
- A truncated S3 listing must supply a new, non-empty continuation token;
|
|
otherwise listing fails with bucket and prefix context instead of looping.
|
|
- `Download` writes local files with parent directory creation.
|
|
- `Upload` streams local file and returns remote metadata.
|
|
- `Read` binds a returned body to its S3 ETag. `UploadConditional` maps an ETag
|
|
match or absence precondition directly to the provider request and reports a
|
|
failed precondition without performing a local check-then-write replacement.
|
|
- `Exists` maps not-found responses to `false`.
|
|
|
|
## Invariants
|
|
|
|
- storage layer is stateless regarding manifest/stage progression.
|
|
- publish ordering semantics are owned by stage/app code, not storage adapters.
|
|
|
|
## Implementation And Tests
|
|
|
|
- Contract and S3 adapter: `internal/adapters/storage`
|
|
- Composition: `internal/app/object_store.go`
|
|
- Tests: `internal/adapters/storage/*_test.go`,
|
|
`internal/app/object_store_test.go`
|