mirror of
https://github.com/PerpetualSoftware/pad.git
synced 2026-10-27 14:57:15 +00:00
48477f3b89
* test(storage): force the copy/upload race so the storage lock's test can go red (TASK-3779) The 25-round race between a cross-workspace copy and an upload (BUG-3653) passed with the storage advisory lock removed on Postgres: the long copy and the short upload never overlapped inside the check-to-commit window. testHookCopyAfterStorageCheck holds the copy after its storage check and before its inserts, with the lock held. The upload starts in that window. With the lock it waits for the copy to commit and is refused. Without it (mutant on test-pg) it commits while the copy is held, and the test fails naming that. Nil in production. Claude-Session: https://claude.ai/code/session_01Q9WssCjFuHjSfLABoW4tmS * test(storage): the forced race proves the upload reached the lock, and never strands a held copy (TASK-3779) Codex round 1: - The 500ms window could pass vacuously if the upload had not reached the lock yet. testHookAfterStorageOwnerRead is now armed once the copy is held, so it fires for the upload alone, just before it takes the lock, and the window starts there. - A failure before release left the copy parked holding its locks. Cleanup now releases it once and joins the copy goroutine. The test is Postgres-only: on SQLite the upload's BEGIN IMMEDIATE waits behind the held copy's writer lock before reaching the advisory lock it watches. Claude-Session: https://claude.ai/code/session_01Q9WssCjFuHjSfLABoW4tmS * test(storage): prove the upload waits on the advisory lock from pg_locks, and join it on cleanup (TASK-3779) Codex round 2: the owner-read hook fires a few statements before the lock wait, so it did not prove the upload was blocked on the lock. The test now polls pg_locks for an ungranted advisory lock in its own database while the copy is held: present with the lock, never present without it (the upload then commits past the cap and the test fails). Cleanup also joins the upload goroutine. Claude-Session: https://claude.ai/code/session_01Q9WssCjFuHjSfLABoW4tmS * test(storage): the waiter check matches the storage lock's own key (TASK-3779) Codex round 3: any ungranted advisory lock in the database counted as the upload's wait. The pg_locks query now matches objid to the low 32 bits of hashtext('pad:plan-limit:storage_bytes:' || owner), with objsubid 1. Claude-Session: https://claude.ai/code/session_01Q9WssCjFuHjSfLABoW4tmS * test(storage): match the storage lock's classid as well as its objid (TASK-3779) Codex round 4: objid alone is the low 32 bits of the key. Claude-Session: https://claude.ai/code/session_01Q9WssCjFuHjSfLABoW4tmS