Skip to content

feat(finalizer): run Worker finalization with Effect - #24

Merged
mrevanzak merged 4 commits into
finalizer/effect-domainfrom
finalizer/effect-worker
Aug 17, 2026
Merged

feat(finalizer): run Worker finalization with Effect#24
mrevanzak merged 4 commits into
finalizer/effect-domainfrom
finalizer/effect-worker

Conversation

@mrevanzak

@mrevanzak mrevanzak commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Add Worker Context.Tag services, Cloudflare live adapters, and test layers.
  • Run finalization through scoped leases, bounded retries, publication proof, and cleanup.
  • Move fetch, queue, and scheduled Worker entrypoints to Effect without changing the queue contract.

Validation

  • pnpm --filter @interview-web/finalizer test
  • pnpm --filter @interview-web/finalizer check-types

@access-time-code-pr-reviewer

access-time-code-pr-reviewer Bot commented Aug 17, 2026

Copy link
Copy Markdown

Review Summary

This PR migrates Worker finalization to Effect-based services and adapters, adding scoped lease renewal, bounded retries, publication verification, cleanup, and test layers. The refactor preserves the queue contract but introduces a retry bug where publication attempts reuse a consumed output stream, risking empty or truncated R2 objects after transient failures.

Key Changes:

  • Introduces Effect Context.Tag services and Cloudflare live/test layers for database, container, queue, and recordings operations.
  • Moves fetch, queue, scheduled reconciliation, and finalization processing onto Effect workflows.
  • Adds bounded retries, lease renewal, publication verification, deterministic output paths, and cleanup handling.
  • Adds and updates finalizer unit tests and worker integration tests.

Confidence Score: 5/5

Recommendation: Review findings before merge.

Rationale: The identified stream-reuse issue is directly tied to the changed publication retry logic and can cause corrupted or missing finalized recordings in production. The broader migration is sufficiently represented by the supplied changed-file context and validation commands.

Special Attention

- Re-fetch or recreate the container output stream for every publication retry. - Verify behavior when R2 put fails transiently or head returns inconclusive metadata. - Review lease renewal scope, retry boundaries, and cleanup behavior during failed finalization.

Important Files Changed

File Overview
packages/finalizer/src/worker/process.ts Orchestrates claiming, assembling, finalizing, publishing, verifying, and completing recording finalization; its publication retry currently reuses a one-shot output stream.
packages/finalizer/src/worker/container.ts Provides the Effect container client, including fetching finalized output streams and handling transient versus terminal container errors.
packages/finalizer/src/worker/recordings.ts Defines the Effect-backed R2 recording service and publication verification behavior.
packages/finalizer/src/worker/dispatch.ts Connects Worker entrypoints and reconciliation to the Effect service graph.

Sequence Diagram

sequenceDiagram
  participant W as Worker
  participant P as Finalization Process
  participant C as Container
  participant R as R2 Recordings
  participant D as Database
  W->>P: Start finalization
  P->>D: Claim job and renew lease
  P->>C: Upload parts and finalize job
  P->>C: Fetch output stream
  loop Publication retries
    P->>R: Put output stream
    R-->>P: Success or transient failure
    P->>R: Head and verify publication
  end
  Note over P,C: Retrying the same one-shot stream can publish empty or truncated data
  P->>D: Complete or release finalization
Loading
Audit history

@access-time-code-pr-reviewer access-time-code-pr-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


🤖 review-bot · openai/gpt-5.6-luna · standard · 159.5s · 1,225,888 tokens · diff: 10 files · preloaded context: 10 changed + 10 related · policy: github-pr-review, thermo-nuclear-code-quality-review · optional skills invoked: vercel-composition-patterns, vercel-react-best-practices

);
const outputKey = `recordings/${encodeURIComponent(sessionId)}/finalizations/attempt-${attempt}/output.${outputMediaType(manifest) === "video/mp4" ? "mp4" : "webm"}`;

yield* Effect.forkScoped(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Warning

The lease-renewal fiber can fail with LeaseLost without interrupting the parent finalization effect, so processing may continue after losing ownership. Make renewal failure fail/interupt the attempt, and handle the resulting retry explicitly.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/finalizer/src/worker/process.ts
Line: 62
Severity: warning
Comment: The lease-renewal fiber can fail with LeaseLost without interrupting the parent finalization effect, so processing may continue after losing ownership. Make renewal failure fail/interupt the attempt, and handle the resulting retry explicitly.

How can I resolve this? If you propose a fix, please make it concise.

Think this is incorrect? Reply false positive: <reason>.

@@ -443,7 +235,9 @@ export async function reconciliationBatch(db: FinalizerDb) {
}
export default {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Warning

The new Effect-based worker modules coexist with duplicate legacy orchestration in this file, while the production entrypoint uses only the new path. Remove the duplicate implementation or make these exports thin adapters to one canonical flow; otherwise fixes can diverge between paths.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/finalizer/src/worker.ts
Line: 236
Severity: warning
Comment: The new Effect-based worker modules coexist with duplicate legacy orchestration in this file, while the production entrypoint uses only the new path. Remove the duplicate implementation or make these exports thin adapters to one canonical flow; otherwise fixes can diverge between paths.

How can I resolve this? If you propose a fix, please make it concise.

Think this is incorrect? Reply false positive: <reason>.

@mrevanzak mrevanzak changed the title finalizer/effect worker feat(finalizer): run Worker finalization with Effect Aug 17, 2026
@mrevanzak
mrevanzak force-pushed the finalizer/effect-worker branch from ba69d8f to e9f5786 Compare August 17, 2026 07:16

@access-time-code-pr-reviewer access-time-code-pr-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


🤖 review-bot · openai/gpt-5.6-luna · standard · 120.6s · 729,492 tokens · diff: 10 files · preloaded context: 10 changed + 10 related · policy: github-pr-review, thermo-nuclear-code-quality-review · optional skills invoked: none

size: output.size,
};
const published = yield* Effect.gen(function* () {
const written = yield* recordings.put(outputKey, output.body, {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Warning

output.body is a one-shot ReadableStream, but the surrounding publication operation retries on OutputPublicationNotProven. After the first failed upload consumes or disturbs the stream, retries reuse the same body and can fail or upload invalid data. Re-fetch the output stream for each attempt or provide a replayable body before applying the retry schedule.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/finalizer/src/worker/process.ts
Line: 104
Severity: warning
Comment: `output.body` is a one-shot ReadableStream, but the surrounding publication operation retries on `OutputPublicationNotProven`. After the first failed upload consumes or disturbs the stream, retries reuse the same body and can fail or upload invalid data. Re-fetch the output stream for each attempt or provide a replayable body before applying the retry schedule.

How can I resolve this? If you propose a fix, please make it concise.

Think this is incorrect? Reply false positive: <reason>.

@access-time-code-pr-reviewer access-time-code-pr-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


🤖 review-bot · openai/gpt-5.6-luna · standard · 125.3s · 778,305 tokens · diff: 10 files · preloaded context: 10 changed + 10 related · policy: github-pr-review, thermo-nuclear-code-quality-review · optional skills invoked: none

);
}
return true;
}).pipe(Effect.retry(retrySchedule));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Warning

The publication retry reuses output.body, a one-shot ReadableStream. If the first R2 put fails after consuming any bytes, retries pass a locked/exhausted stream and finalization fails instead of recovering. Retry by reacquiring the container output stream for each publication attempt, or otherwise provide a fresh body per retry.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/finalizer/src/worker/process.ts
Line: 128
Severity: warning
Comment: The publication retry reuses `output.body`, a one-shot ReadableStream. If the first R2 put fails after consuming any bytes, retries pass a locked/exhausted stream and finalization fails instead of recovering. Retry by reacquiring the container output stream for each publication attempt, or otherwise provide a fresh body per retry.

How can I resolve this? If you propose a fix, please make it concise.

Think this is incorrect? Reply false positive: <reason>.

@mrevanzak
mrevanzak force-pushed the finalizer/effect-worker branch from e9f5786 to 7733ad8 Compare August 17, 2026 07:21

@access-time-code-pr-reviewer access-time-code-pr-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


🤖 review-bot · openai/gpt-5.6-luna · standard · 128.3s · 739,791 tokens · diff: 10 files · preloaded context: 10 changed + 10 related · policy: github-pr-review, thermo-nuclear-code-quality-review · optional skills invoked: performance

outputMediaType: outputMediaType(manifest),
segments: manifest.segments.map((segment) => ({
partIndexes: segment.parts.map((part) => part.sequence),
segmentIndex: segment.index,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Warning

The publication effect retries recordings.put while reusing the same one-shot ReadableStream. If R2 consumes the stream and a transient upload error occurs, retrying with the disturbed stream fails and finalization is released instead of retried. Fetch a fresh container output stream inside each publication retry attempt, or otherwise recreate the body per attempt.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/finalizer/src/worker/process.ts
Line: 91
Severity: warning
Comment: The publication effect retries `recordings.put` while reusing the same one-shot `ReadableStream`. If R2 consumes the stream and a transient upload error occurs, retrying with the disturbed stream fails and finalization is released instead of retried. Fetch a fresh container output stream inside each publication retry attempt, or otherwise recreate the body per attempt.

How can I resolve this? If you propose a fix, please make it concise.

Think this is incorrect? Reply false positive: <reason>.

@mrevanzak
mrevanzak force-pushed the finalizer/effect-worker branch from 7733ad8 to 81d1bef Compare August 17, 2026 07:26

@access-time-code-pr-reviewer access-time-code-pr-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


🤖 review-bot · openai/gpt-5.6-luna · standard · 110.1s · 536,617 tokens · diff: 10 files · preloaded context: 10 changed + 10 related · policy: github-pr-review, thermo-nuclear-code-quality-review · optional skills invoked: vercel-composition-patterns, vercel-react-best-practices

size: output.size,
};
const published = yield* Effect.gen(function* () {
const written = yield* recordings.put(outputKey, output.body, {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Warning

output.body is a one-shot ReadableStream, but this entire publication block is retried at line 128. If recordings.put fails after consuming the stream, retries reuse an exhausted body and can repeatedly fail, releasing an otherwise valid finalization. Re-fetch/create a fresh output stream for each publication attempt, or move only replayable operations inside the retry.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/finalizer/src/worker/process.ts
Line: 104
Severity: warning
Comment: `output.body` is a one-shot ReadableStream, but this entire publication block is retried at line 128. If `recordings.put` fails after consuming the stream, retries reuse an exhausted body and can repeatedly fail, releasing an otherwise valid finalization. Re-fetch/create a fresh output stream for each publication attempt, or move only replayable operations inside the retry.

How can I resolve this? If you propose a fix, please make it concise.

Think this is incorrect? Reply false positive: <reason>.

@access-time-code-pr-reviewer access-time-code-pr-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


🤖 review-bot · openai/gpt-5.6-luna · standard · 231.5s · 1,684,203 tokens · diff: 10 files · preloaded context: 10 changed + 10 related · policy: github-pr-review, thermo-nuclear-code-quality-review · optional skills invoked: vercel-composition-patterns

size: output.size,
};
const published = yield* Effect.gen(function* () {
const written = yield* recordings.put(outputKey, output.body, {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Warning

output.body is a one-shot ReadableStream, but this recordings.put runs inside a retry. After a transient R2 failure, retrying reuses the consumed/disturbed stream and publication will fail permanently. Re-fetch a fresh container output stream for each attempt or make the body replayable before applying the retry.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/finalizer/src/worker/process.ts
Line: 104
Severity: warning
Comment: `output.body` is a one-shot ReadableStream, but this `recordings.put` runs inside a retry. After a transient R2 failure, retrying reuses the consumed/disturbed stream and publication will fail permanently. Re-fetch a fresh container output stream for each attempt or make the body replayable before applying the retry.

How can I resolve this? If you propose a fix, please make it concise.

Think this is incorrect? Reply false positive: <reason>.

@mrevanzak
mrevanzak force-pushed the finalizer/effect-worker branch from 81d1bef to 07f0bd1 Compare August 17, 2026 07:43

@access-time-code-pr-reviewer access-time-code-pr-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


🤖 review-bot · openai/gpt-5.6-luna · standard · 91.2s · 745,973 tokens · diff: 10 files · preloaded context: 10 changed + 10 related · policy: github-pr-review, thermo-nuclear-code-quality-review · optional skills invoked: none

size: output.size,
};
const published = yield* Effect.gen(function* () {
const written = yield* recordings.put(outputKey, output.body, {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Warning

The same ReadableStream is reused across the publication Effect.retry at line 128. If R2 put fails after consuming or locking the stream, retries pass the disturbed stream again and fail instead of recovering. Buffer or tee/recreate the stream per retry, or retry only before consuming it.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/finalizer/src/worker/process.ts
Line: 104
Severity: warning
Comment: The same ReadableStream is reused across the publication Effect.retry at line 128. If R2 put fails after consuming or locking the stream, retries pass the disturbed stream again and fail instead of recovering. Buffer or tee/recreate the stream per retry, or retry only before consuming it.

How can I resolve this? If you propose a fix, please make it concise.

Think this is incorrect? Reply false positive: <reason>.

@access-time-code-pr-reviewer access-time-code-pr-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


🤖 review-bot · openai/gpt-5.6-luna · standard · 136.0s · 748,753 tokens · diff: 10 files · preloaded context: 10 changed + 10 related · policy: github-pr-review, thermo-nuclear-code-quality-review · optional skills invoked: performance

size: output.size,
};
const published = yield* Effect.gen(function* () {
const written = yield* recordings.put(outputKey, output.body, {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Warning

The publication retry reuses output.body, a one-shot ReadableStream. After a transient R2 error or an inconclusive head, subsequent retries pass the already-consumed stream to recordings.put, so retries can fail or publish an empty/truncated object. Re-fetch the container output for each publication attempt (or otherwise provide a fresh stream) instead of retrying the same stream.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/finalizer/src/worker/process.ts
Line: 104
Severity: warning
Comment: The publication retry reuses `output.body`, a one-shot ReadableStream. After a transient R2 error or an inconclusive `head`, subsequent retries pass the already-consumed stream to `recordings.put`, so retries can fail or publish an empty/truncated object. Re-fetch the container output for each publication attempt (or otherwise provide a fresh stream) instead of retrying the same stream.

How can I resolve this? If you propose a fix, please make it concise.

Think this is incorrect? Reply false positive: <reason>.

@mrevanzak
mrevanzak merged commit a2f1d24 into main Aug 17, 2026
3 of 5 checks passed
@mrevanzak
mrevanzak deleted the finalizer/effect-worker branch August 17, 2026 08:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant