Skip to content

feat(webapp): mollifier API GET read-fallback — synthetic primitives + route wiring#3755

Draft
d-cs wants to merge 4 commits into
mollifier-phase-3-replayfrom
mollifier-phase-3-reads
Draft

feat(webapp): mollifier API GET read-fallback — synthetic primitives + route wiring#3755
d-cs wants to merge 4 commits into
mollifier-phase-3-replayfrom
mollifier-phase-3-reads

Conversation

@d-cs
Copy link
Copy Markdown
Collaborator

@d-cs d-cs commented May 26, 2026

Summary

Synthesise QUEUED/FAILED responses from the mollifier buffer when a TaskRun row hasn't landed in Postgres yet. Wires the synthesis into:

  • ApiRetrieveRunPresenter
  • v1 trace GET route
  • v1 spans GET route
  • attempts route gains a GET loader (fixes pre-existing Remix "no loader" 400)

The readFallback infra itself lives on the trigger PR (consumed by IdempotencyKeyConcern); this PR adds the route-level synthetic-rendering primitives.

Stacked on the replay PR.

Test plan

  • `pnpm run typecheck --filter webapp` passes
  • `pnpm run test --filter webapp test/mollifierSyntheticRedirectInfo.test.ts` passes
  • `pnpm run test --filter webapp test/mollifierSyntheticSpanRun.test.ts` passes

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 26, 2026

⚠️ No Changeset found

Latest commit: f4131eb

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 26, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 70c99824-2b82-4da9-9c2d-4cb7fc68d3a1

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch mollifier-phase-3-reads

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment thread apps/webapp/app/v3/mollifier/syntheticRedirectInfo.server.ts
@d-cs d-cs self-assigned this May 26, 2026
@d-cs d-cs force-pushed the mollifier-phase-3-replay branch from 31f4726 to b05929b Compare May 26, 2026 11:12
@d-cs d-cs force-pushed the mollifier-phase-3-reads branch from 1838229 to af0aeeb Compare May 26, 2026 11:12
@d-cs d-cs force-pushed the mollifier-phase-3-replay branch from b05929b to b89da52 Compare May 26, 2026 13:24
@d-cs d-cs force-pushed the mollifier-phase-3-reads branch 3 times, most recently from 0919f7a to f36c576 Compare May 26, 2026 15:12
@d-cs d-cs force-pushed the mollifier-phase-3-replay branch from 74fdf6d to c6fa61f Compare May 26, 2026 16:20
@d-cs d-cs force-pushed the mollifier-phase-3-reads branch from c8ab214 to 047b240 Compare May 26, 2026 16:20
d-cs and others added 3 commits May 26, 2026 17:32
…+ route wiring

Synthesise QUEUED/FAILED responses from the mollifier buffer when a
TaskRun row hasn't landed in Postgres yet. Wires the synthesis into:
- ApiRetrieveRunPresenter
- v1 trace GET route
- v1 spans GET route
- attempts route gains a GET loader (fixes pre-existing Remix 400)

Stacked on the trigger-time decisions PR. The readFallback infra
itself lives on the trigger PR (consumed by IdempotencyKeyConcern);
this PR adds the route-level synthetic-rendering primitives.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces the ad-hoc \`as Record<string, unknown>\` + \`typeof ===
"string"\` checks in \`findBufferedRunRedirectInfo\` with a Zod
\`safeParse\` against a schema for the subset of fields the redirect
needs (envSlug / projectSlug / orgSlug / optional spanId). Wrong-typed
or missing fields now collapse into a single parse-fail branch that
logs the structured issue list and returns null.

Adds a regression test for the structural-vs-typeof distinction:
\`environment.slug: 42\` (number) is now rejected, where the previous
\`typeof slug === "string"\` chain would silently accept any string-
typed value but had no defence against shape drift in other fields.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…l enum

\`SyntheticRun.machinePreset\` is a plain string sourced from the
mollifier snapshot, but \`SpanRun.machinePreset\` is the typed
\`MachinePresetName\` enum (micro / small-1x / small-2x / medium-1x /
medium-2x / large-1x / large-2x). The direct assignment failed
\`tsc --noEmit\` and CI typecheck. Validate via \`MachinePresetName.safeParse\`
and collapse unknown values to \`undefined\` so a stale preset
returned by the buffer doesn't bleed into the UI as a typed-but-unknown
value.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@d-cs d-cs force-pushed the mollifier-phase-3-reads branch from 047b240 to e57bc5e Compare May 26, 2026 16:32
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 5 potential issues.

View 1 additional finding in Devin Review.

Open in Devin Review

Comment thread apps/webapp/app/presenters/v3/ApiRetrieveRunPresenter.server.ts Outdated
Comment thread apps/webapp/app/routes/api.v1.runs.$runId.trace.ts Outdated
Comment thread apps/webapp/app/presenters/v3/ApiRetrieveRunPresenter.server.ts Outdated
Comment thread apps/webapp/app/routes/api.v1.runs.$runParam.attempts.ts
Comment thread apps/webapp/app/v3/mollifier/syntheticRedirectInfo.server.ts Outdated
Five Devin findings on PR #3755:

- ApiRetrieveRunPresenter.synthesiseFoundRunFromBuffer was assigning
  buffered.friendlyId to the FoundRun.id field. The id column on PG is
  the internal cuid; downstream log correlation reads taskRun.id and
  was getting the friendly token instead. Fixed to read the cuid that
  readFallback already derives via RunId.fromFriendlyId.

- api.v1.runs.$runId.trace.ts buffered branch hardcoded
  isPartial: true. Cancelled is a terminal state — the sibling spans
  route and syntheticTrace already gate this on !isCancelled. Match.

- synthesisePayload helper replaces the silent
  typeof === "string" coercion. Object-shaped payloads now JSON-
  stringify (matching how the trigger path would serialise them) with
  a warn log so format drift is visible. Truly unserialisable inputs
  fall back to "" with an error log instead of silently dropping.

- syntheticRedirectInfo now uses deserialiseMollifierSnapshot
  (the webapp-side wrapper) instead of deserialiseSnapshot from the
  redis-worker package directly. Both share the same implementation
  today, but pinning the wrapper means the two read-side modules can't
  drift if the snapshot encoding ever changes (e.g. msgpack).

- attempts route loader verifies the run belongs to the authenticated
  environment (PG-first, buffer fallback) before returning the
  parity-empty list. Other run-scoped endpoints (spans, trace,
  retrieve) 404 cross-env; matching that closes the
  exists-vs-doesn't-exist side channel.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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