Skip to content

fix(engine): list a workspace's DM conversations in D1-safe chunks - #519

Merged
khaliqgant merged 1 commit into
mainfrom
fix/dm-all-d1-chunks
Oct 11, 2026
Merged

khaliqgant merged 1 commit into
mainfrom
fix/dm-all-d1-chunks

Conversation

@khaliqgant

@khaliqgant khaliqgant commented Oct 11, 2026 •

Copy link
Copy Markdown
Member

Why

GET /v1/dm/conversations/all returns 500 internal_error in production for a workspace with many DM conversations. A sanitized tail of relaycast-cloud-api from 2026-10-11 05:13 to 08:00Z showed 20 of 20 /all requests failing (client fleet-watchdog, workspace key). The same route backs the Relay Connect observer's room list, so observer links for that workspace cannot load. #518 made that failure show as "temporarily unavailable" instead of "revoked", but the read itself still fails.

listAllDmConversations (engine/dmAll.ts) bound every conversation and channel id of the workspace into single IN clauses. Cloudflare D1 allows at most 100 bound parameters per statement, so any workspace with more than about 100 DM conversations fails every call. The engine already has the fix pattern: queryInChunks with D1_SAFE_IN_QUERY_CHUNK_SIZE (90), which action.ts, agent.ts and attachments.ts use. dmAll.ts's filtered-count query already chunks; these four lookups did not.

What

The four lookups in listAllDmConversations (participants, per-channel message counts, latest message ids, latest messages) now run through queryInChunks. Grouping by channel within a chunk stays complete, because one channel's rows never span chunks. No other behaviour changes.

Test

New conformance test in connectObserver.test.ts:

  • creates 105 DM conversations
  • installs D1's 100-bound-parameter guard on the SQL Drizzle emits (the same harness pattern delivery.test.ts uses for its D1 regression)
  • requests /v1/dm/conversations/all with the workspace key and with a Connect observer token
  • asserts 200, all 105 conversations, message_count: 1 and the right last_message for each

On current main (unfixed) the test fails with expected 500 to be 200, reproducing production; with this change it passes.

Verification (local, Node 22 as in CI)

  • npx vitest run in packages/engine: 117 files, 1369 passed
  • npm run typecheck -w @relaycast/engine: clean
  • npm run lint -w @relaycast/engine: clean
  • git diff --check: clean

Rollout

Authorized by Khaliq: after review, release @relaycast/engine through the reviewed publish-npm workflow, then bump it in relaycast-cloud and deploy through that repo's normal gates. Then live-verify /all and observer loading.

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Note

Low Risk
Targeted read-path change reusing an established chunking helper; behavior is unchanged except fixing failures above the D1 bind limit.

Overview
Fixes GET /v1/dm/conversations/all returning internal_error when a workspace has more than ~100 DM conversations on Cloudflare D1 (100 bound parameters per statement).

listAllDmConversations in dmAll.ts now runs the four follow-up lookups—participants, per-channel message counts, latest message IDs, and latest message bodies—through queryInChunks instead of one giant IN (...) per query. Response shape and aggregation logic are unchanged; Relay Connect observer room lists use the same route.

A conformance test creates 105 DMs, patches SQLite prepare to enforce D1’s bind cap, and asserts 200 plus correct counts for both workspace key and observer credentials.

Reviewed by Cursor Bugbot for commit a5def39. Bugbot is set up for automated code reviews on this repo. Configure here.


Agent Relay sessions

  • claude session 2bc8f2ec · opened via gh pr create · last active 2026-10-11

listAllDmConversations bound every conversation and channel id of the
workspace into single IN clauses. D1 allows at most 100 bound parameters
per statement, so GET /v1/dm/conversations/all failed with internal_error
for any workspace with more than about 100 DM conversations, for workspace
keys and Relay Connect observers alike (prod: 20/20 requests 500).

The participant, message-count, latest-id and latest-message lookups now
run through queryInChunks (D1_SAFE_IN_QUERY_CHUNK_SIZE), as action.ts,
agent.ts and attachments.ts already do. Per-channel grouping stays complete
because one channel's rows never span chunks.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

Session-Id: 2bc8f2ec-40dd-4818-8b2d-1b4952383604
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-11T08:14:18.265722Z a5def39 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: f62a6391-b248-4e40-b6ad-a34f30f5d76c

📥 Commits

Reviewing files that changed from the base of the PR and between 51f7f6e and a5def39.


📒 Files selected for processing (4)
  • CHANGELOG.md
  • packages/engine/CHANGELOG.md
  • packages/engine/src/__tests__/conformance/connectObserver.test.ts
  • packages/engine/src/engine/dmAll.ts

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.



📝 Walkthrough

Walkthrough

DM conversation enrichment queries now use D1-safe chunks. A conformance test checks retrieval of 105 conversations with workspace and observer credentials. Changelog entries document the fix.

Changes

DM conversation listing

Layer / File(s) Summary
Chunk DM conversation enrichment queries
packages/engine/src/engine/dmAll.ts, packages/engine/src/__tests__/conformance/connectObserver.test.ts, packages/engine/CHANGELOG.md, CHANGELOG.md
Participant, message-count, latest-message-ID, and latest-message lookups now use D1-safe chunks. The conformance test checks that workspace and observer credentials retrieve all 105 conversations with the expected participants, message counts, and latest-message text. The changelogs record the fix.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Medium

Suggested reviewers: willwashburn


Merge Risk: ⚪ Minimal · up to a5def

The change is mergeable based on the available evidence. Listings above D1’s parameter limit are covered by the new test; the hosted deployment plan remains undocumented here.

Pre-merge checks | Passed 4 | Failed 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 2 files. (2 skipped: 2 … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check Passed The title clearly and concisely describes the main change: chunking workspace DM conversation queries for D1 safety.
Description check Passed The description directly explains the D1 parameter-limit failure, the implementation, the regression test, verification, and rollout plan.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.

Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 2 files. (2 skipped: 2 unsupported.)


  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR


🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

A rabbit counts each chat with care
In smaller batches through the air
One hundred bounds no longer stall
The latest words arrive for all
The burrow hums: “We fetched them all!”

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

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Devin Review

@khaliqgant
khaliqgant merged commit 7fb95e6 into main Oct 11, 2026
10 checks passed
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