dev-worker: Phase 1 of plan 01KYVX3VHNJGX2M1J3XFXR9Y7N: filesystem stor… #4

Merged
pchapman merged 1 commit from dev-worker/01KYVXD0JA0F2R8C29KCTY3GSR into main 2026-07-31 07:27:50 -05:00
Collaborator

Phase 1 of plan 01KYVX3VHNJGX2M1J3XFXR9Y7N: filesystem store package.

Created internal/store with a flat filesystem backend laying objects out at data//:

  • internal/store/store.go: Store interface (Put/Get/Stat/Delete), Stat struct (Size, ETag hex MD5, UTC ModTime), ErrNotFound sentinel, package docs.
  • internal/store/fs.go: FS implementation. Put streams via io.TeeReader through an MD5 hasher writing to a temp file renamed into place on success (crash-safe, no torn files), returning the hex ETag + byte count; bucket dirs created as needed; partial file removed on reader error. Stat returns size + recomputed hex MD5 ETag + UTC modTime. Get and Delete included. Concurrent safety via a key-scoped mutex map: same-key Puts serialized, different keys parallel.
  • internal/store/fs_test.go: tests for exact path/bytes write, Stat size+ETag, NotFound, read roundtrip, nested bucket dir, overwrite, partial-write cleanup, context cancellation, and two concurrency tests (same-key serialization proving whole-file atomicity, different-keys parallelism). All pass incl. -race.

Assumptions: layout is /data// with New(root) creating /data (matches .gitignore ignoring /data/). Stat recomputes MD5 from file content rather than caching on disk; a later increment is expected to persist size/ETag in the SQLite metadata layer. Added Get and Delete to the interface alongside the required Put/Stat since they're trivial and a read path is needed for round-trip tests.

go build ./...

(build succeeded, no output)

go test ./...

?   	pcsw/warehouse/cmd/warehouse	[no test files]
ok  	pcsw/warehouse/cmd/warehouse-admin	(cached)
ok  	pcsw/warehouse/internal/auth	(cached)
ok  	pcsw/warehouse/internal/db	(cached)
ok  	pcsw/warehouse/internal/server	(cached)
ok  	pcsw/warehouse/internal/store	(cached)

Opened by saga-dev-worker for mission 01KYVXD0JA0F2R8C29KCTY3GSR.

Phase 1 of plan 01KYVX3VHNJGX2M1J3XFXR9Y7N: filesystem store package. Created internal/store with a flat filesystem backend laying objects out at data/<bucket>/<key>: - internal/store/store.go: Store interface (Put/Get/Stat/Delete), Stat struct (Size, ETag hex MD5, UTC ModTime), ErrNotFound sentinel, package docs. - internal/store/fs.go: FS implementation. Put streams via io.TeeReader through an MD5 hasher writing to a temp file renamed into place on success (crash-safe, no torn files), returning the hex ETag + byte count; bucket dirs created as needed; partial file removed on reader error. Stat returns size + recomputed hex MD5 ETag + UTC modTime. Get and Delete included. Concurrent safety via a key-scoped mutex map: same-key Puts serialized, different keys parallel. - internal/store/fs_test.go: tests for exact path/bytes write, Stat size+ETag, NotFound, read roundtrip, nested bucket dir, overwrite, partial-write cleanup, context cancellation, and two concurrency tests (same-key serialization proving whole-file atomicity, different-keys parallelism). All pass incl. -race. Assumptions: layout is <root>/data/<bucket>/<key> with New(root) creating <root>/data (matches .gitignore ignoring /data/). Stat recomputes MD5 from file content rather than caching on disk; a later increment is expected to persist size/ETag in the SQLite metadata layer. Added Get and Delete to the interface alongside the required Put/Stat since they're trivial and a read path is needed for round-trip tests. ## go build ./... ``` (build succeeded, no output) ``` ## go test ./... ``` ? pcsw/warehouse/cmd/warehouse [no test files] ok pcsw/warehouse/cmd/warehouse-admin (cached) ok pcsw/warehouse/internal/auth (cached) ok pcsw/warehouse/internal/db (cached) ok pcsw/warehouse/internal/server (cached) ok pcsw/warehouse/internal/store (cached) ``` --- Opened by saga-dev-worker for mission `01KYVXD0JA0F2R8C29KCTY3GSR`.
Created internal/store with a flat filesystem backend laying objects out at data/<bucket>/<key>:
- internal/store/store.go: Store interface (Put/Get/Stat/Delete), Stat struct (Size, ETag hex MD5, UTC ModTime), ErrNotFound sentinel, package docs.
- internal/store/fs.go: FS implementation. Put streams via io.TeeReader through an MD5 hasher writing to a temp file renamed into place on success (crash-safe, no torn files), returning the hex ETag + byte count; bucket dirs created as needed; partial file removed on reader error. Stat returns size + recomputed hex MD5 ETag + UTC modTime. Get and Delete included. Concurrent safety via a key-scoped mutex map: same-key Puts serialized, different keys parallel.
- internal/store/fs_test.go: tests for exact path/bytes write, Stat size+ETag, NotFound, read roundtrip, nested bucket dir, overwrite, partial-write cleanup, context cancellation, and two concurrency tests (same-key serialization proving whole-file atomicity, different-keys parallelism). All pass incl. -race.

Assumptions: layout is <root>/data/<bucket>/<key> with New(root) creating <root>/data (matches .gitignore ignoring /data/). Stat recomputes MD5 from file content rather than caching on disk; a later increment is expected to persist size/ETag in the SQLite metadata layer. Added Get and Delete to the interface alongside the required Put/Stat since they're trivial and a read path is needed for round-trip tests.
pchapman deleted branch dev-worker/01KYVXD0JA0F2R8C29KCTY3GSR 2026-07-31 07:27:51 -05:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
pcsw/warehouse!4
No description provided.