fix(finalizer): boot the container and publish remuxed output - #28
Merged
Conversation
The committed ESM server.js bundle crashed on boot with `Dynamic require of "events" is not supported` from ws, so the container exited 1 and the worker mapped the proxy 500 as `part upload: 500`. Stop committing the bundle, emit CJS to output/, and build that in the image. R2 then rejected the remux stream (`known length` TypeError → RecordingsUnavailable). Buffer fetch streams before put.
Review SummaryThis PR fixes finalizer container boot failures by bundling the server as CommonJS in a multi-stage Docker image and addresses Cloudflare R2 uploads that reject unknown-length streams. It also re-dispatches finalization for sessions stuck in the finalizing state, but the changed recording APIs and submission routes remain unauthenticated, creating critical data exposure and deletion risks. Key Changes:
Confidence Score: 5/5Recommendation: Request changes before merge. Rationale: The critical authorization issues and upload-orphan risk are directly evidenced by the changed API and route implementations, while the finalizer behavior is covered by focused tests and the supplied test results. Special Attention- Add authentication and authorization to recording procedures, including operator scoping and candidate download capabilities. - Protect GET and DELETE recording submission operations from unauthenticated callers. - Validate recording session and segment ownership before writing upload blobs, or reliably delete blobs when acknowledgement fails. - Decompose the 1,533-line live recording module into focused persistence, upload, recovery, polling, and finalization components. - Verify migration renames and consolidation are safe for existing deployed databases.Important Files Changed
Sequence DiagramsequenceDiagram
participant Caller
participant API as Recording API
participant DB
participant R2
participant Finalizer
Caller->>API: List or request recording by session ID
API->>DB: Query recording metadata
API-->>Caller: Data or recording output without auth check
Caller->>API: Upload segment
API->>R2: Write blob
API->>DB: Acknowledge session/segment
alt Acknowledgement rejected
API-->>Caller: Error
Note over R2: Orphaned object remains
else Finalizing session
API->>Finalizer: Dispatch finalization
Finalizer->>R2: Publish remuxed output
end
Audit history |
R2 rejects unknown-length streams, so put was buffering the remuxed body. Pass the known output size through a FixedLengthStream instead so large recordings publish without exhausting Worker memory.
Queue drops after maxRetries leave rows in finalizing with no consumer. Claim can reclaim an expired lease, so retry the dispatch from finalize.
Alchemy applies migrations through D1's HTTP query API, which splits on semicolons and rejects CREATE TRIGGER. Replace the incremental history with one CREATE TABLE migration that uses CHECK constraints instead.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
server.jsbundle. Emit CJS tooutput/and build that in a multi-stage image so the container no longer crashes on boot withDynamic require of "events" is not supported(worker mapped that aspart upload: 500).R2.put. Workers R2 rejects unknown-length streams (FixedLengthStreamTypeError →RecordingsUnavailable).Test plan
pnpm --filter @interview-web/finalizer test— 51/51node output/server.cjsanswersGET /health204makeRecordings.putregression: fetch stream is buffered toUint8Arraybefore R2pnpm devand finalize session56e71174-72a0-4bea-8b2b-4913e6c79a36(or a new recording) — should pass container boot and R2 publish