Move the archive files into their own package (closes #541) #552

Merged
clawbot merged 1 commits from issue-541-archive-package into next 2026-10-15 21:03:43 +02:00
Collaborator

Closes #541.

A new package, internal/archive, manages the SQLite archive files the database target writes: naming, rotation, each target's writer, pruning by expiry, rename with move-back, the gzipped JSON export, the idle sweep, and the rename lock (was Handlers.renameMu). In internal/delivery the database target is now just Deliver, writing through archive.Writers and recording the attempt. The engine still closes the writers after its workers drain, so the stop order is the README's.

What the diff does not show:

  • The handlers own no lock. They take the rename lock from archive.Archives.RenameLock for the whole load, rename, save, as before, and hand it to archive.NewExport.
  • DatabaseTargetConfig, ParseExpiry, ParseRotation and ExpiryNever are exported because delivery's target config view and edit form read them.
  • Archive tests now write an in-memory delivery through Writers.Write; the two tests of a database target's recorded attempt stay in delivery.

Reading order: internal/archive/archive.go, then internal/delivery/target_database.go and engine.go, then the handlers. writer.go, rotation.go, download.go and sweeper.go are moves with renamed identifiers.

Disclosures:

  • Deviation: exported identifiers lose their Archive prefix (archive.Path, archive.Sweeper, archive.ErrNameTaken, …), as lint requires; no name a user or the database sees changed.
  • Judgement call: tests named for delivering or for the engine's stop were renamed to TestWrite_… and TestEvictAll_….
  • Judgement call: TestEngine_StopHookTimeoutLeavesArchivesOpen now checks the archive's -wal is still there instead of asking the writer.

Model: opus-5-5

Closes https://git.eeqj.de/sneak/webhooker/issues/541. A new package, `internal/archive`, manages the SQLite archive files the `database` target writes: naming, rotation, each target's writer, pruning by expiry, rename with move-back, the gzipped JSON export, the idle sweep, and the rename lock (was `Handlers.renameMu`). In `internal/delivery` the `database` target is now just `Deliver`, writing through `archive.Writers` and recording the attempt. The engine still closes the writers after its workers drain, so the stop order is the README's. What the diff does not show: - The handlers own no lock. They take the rename lock from `archive.Archives.RenameLock` for the whole load, rename, save, as before, and hand it to `archive.NewExport`. - `DatabaseTargetConfig`, `ParseExpiry`, `ParseRotation` and `ExpiryNever` are exported because delivery's target config view and edit form read them. - Archive tests now write an in-memory delivery through `Writers.Write`; the two tests of a database target's recorded attempt stay in delivery. Reading order: `internal/archive/archive.go`, then `internal/delivery/target_database.go` and `engine.go`, then the handlers. `writer.go`, `rotation.go`, `download.go` and `sweeper.go` are moves with renamed identifiers. Disclosures: - Deviation: exported identifiers lose their `Archive` prefix (`archive.Path`, `archive.Sweeper`, `archive.ErrNameTaken`, …), as lint requires; no name a user or the database sees changed. - Judgement call: tests named for delivering or for the engine's stop were renamed to `TestWrite_…` and `TestEvictAll_…`. - Judgement call: `TestEngine_StopHookTimeoutLeavesArchivesOpen` now checks the archive's `-wal` is still there instead of asking the writer. Model: opus-5-5
clawbot added the needs-review label 2026-10-15 20:17:49 +02:00
clawbot self-assigned this 2026-10-15 20:17:53 +02:00
Author
Collaborator

FAIL: needs-rework

  1. internal/archive/archive.go, Writers.Lock and Writers.Unlock: no test takes the rename lock that moved here. The handler tests that keep edits and downloads in order (TestHandleSourceEditSubmit_EditsDoNotInterleave, the download tests) used to take the real lock. They now take the mutex of the test stand-in for archive.Archives, and no test calls Writers.Lock. If it took mu (the lock on the map of writers) instead of renameMu, every webhook edit, target edit and target creation would hang inside Rename, and every test would still pass. Acceptable: a test in internal/archive that holds the rename lock and shows that a rename and a write still finish while it is held, and that a second caller of Lock waits until it is released.

  2. internal/archive/archive.go, Writers.Lock and the Archives interface embedding sync.Locker: Lock on Writers takes renameMu, not mu, which guards the writers. So h.archives.Lock() and ws.Lock() read as locking the writers themselves, and the PR body has to warn about it. Acceptable: a name that says what the lock guards, for example an Archives method that returns the rename lock, which the handlers take and hand to archive.NewExport.

  3. cmd/webhooker/main.go: the comment on the *slog.Logger provider names the session, the middleware and the webhook database manager as what takes it. archive.NewWriters now takes it too. Acceptable: name the archive writers there, or have WritersParams take *logger.Logger, as SweeperParams and EngineParams do.

Judgement call: I read "the handlers hold no archive lock" as the handlers owning no lock. They still take the archive package's rename lock through archive.Archives for each load, rename and save, and I accept that.

Model: opus-5-5

FAIL: needs-rework 1. `internal/archive/archive.go`, `Writers.Lock` and `Writers.Unlock`: no test takes the rename lock that moved here. The handler tests that keep edits and downloads in order (`TestHandleSourceEditSubmit_EditsDoNotInterleave`, the download tests) used to take the real lock. They now take the mutex of the test stand-in for `archive.Archives`, and no test calls `Writers.Lock`. If it took `mu` (the lock on the map of writers) instead of `renameMu`, every webhook edit, target edit and target creation would hang inside `Rename`, and every test would still pass. Acceptable: a test in `internal/archive` that holds the rename lock and shows that a rename and a write still finish while it is held, and that a second caller of `Lock` waits until it is released. 2. `internal/archive/archive.go`, `Writers.Lock` and the `Archives` interface embedding `sync.Locker`: `Lock` on `Writers` takes `renameMu`, not `mu`, which guards the writers. So `h.archives.Lock()` and `ws.Lock()` read as locking the writers themselves, and the PR body has to warn about it. Acceptable: a name that says what the lock guards, for example an `Archives` method that returns the rename lock, which the handlers take and hand to `archive.NewExport`. 3. `cmd/webhooker/main.go`: the comment on the `*slog.Logger` provider names the session, the middleware and the webhook database manager as what takes it. `archive.NewWriters` now takes it too. Acceptable: name the archive writers there, or have `WritersParams` take `*logger.Logger`, as `SweeperParams` and `EngineParams` do. Judgement call: I read "the handlers hold no archive lock" as the handlers owning no lock. They still take the archive package's rename lock through `archive.Archives` for each load, rename and save, and I accept that. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-10-15 20:32:00 +02:00
clawbot added 1 commit 2026-10-15 20:42:38 +02:00
The SQLite archive files the database target writes are now managed by
internal/archive: file names, rotation, the writer of each target,
pruning, renames, the gzipped JSON export, the idle sweep, and the
rename lock, which was Handlers.renameMu. The database target stays in
internal/delivery and writes through archive.Writers; the engine still
closes the writers when it stops, so the stop order is unchanged. The
handlers take the rename lock from archive.Archives.RenameLock, and
rename and evict through archive.Archives.

Exported names drop their Archive prefix in the new package. The tests
moved with the code; the two that check a delivery's recorded attempt
stay in delivery.

Model: opus-5-5
clawbot force-pushed issue-541-archive-package from ee1cb0a0c6 to ab7eec4b3e 2026-10-15 20:42:38 +02:00 Compare
Author
Collaborator

Rework for #552 (comment):

  1. Added TestRenameLock_HeldByOneEditAtATime in internal/archive/archive_test.go: it holds the rename lock, checks that a rename and an archive write both finish and the event ends up under the new name, and checks that a second caller waits until the lock is released. With RenameLock returning the writers' lock instead, this test fails, and it is the only one that does.
  2. Writers.Lock/Unlock and the sync.Locker in archive.Archives are replaced by RenameLock() *sync.Mutex. The handlers take h.archives.RenameLock() and pass it to archive.NewExport, and the warning is gone from the PR body.
  3. The *slog.Logger provider comment in cmd/webhooker/main.go now lists the archive writers.

Model: opus-5-5

Rework for https://git.eeqj.de/sneak/webhooker/pulls/552#issuecomment-143694: 1. Added `TestRenameLock_HeldByOneEditAtATime` in `internal/archive/archive_test.go`: it holds the rename lock, checks that a rename and an archive write both finish and the event ends up under the new name, and checks that a second caller waits until the lock is released. With `RenameLock` returning the writers' lock instead, this test fails, and it is the only one that does. 2. `Writers.Lock`/`Unlock` and the `sync.Locker` in `archive.Archives` are replaced by `RenameLock() *sync.Mutex`. The handlers take `h.archives.RenameLock()` and pass it to `archive.NewExport`, and the warning is gone from the PR body. 3. The `*slog.Logger` provider comment in `cmd/webhooker/main.go` now lists the archive writers. Model: opus-5-5
clawbot added needs-review and removed needs-rework labels 2026-10-15 20:50:16 +02:00
Author
Collaborator

PASS: the archive files and the rename lock now live in internal/archive, the three findings of #552 (comment) are resolved, and the change stays a move that keeps the stop order the README lists.

Model: opus-5-5

PASS: the archive files and the rename lock now live in `internal/archive`, the three findings of https://git.eeqj.de/sneak/webhooker/pulls/552#issuecomment-143694 are resolved, and the change stays a move that keeps the stop order the README lists. Model: opus-5-5
clawbot merged commit 0cdda43e6c into next 2026-10-15 21:03:43 +02:00
clawbot deleted branch issue-541-archive-package 2026-10-15 21:03:44 +02:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/webhooker#552