Skip to content

fix(i18n): queue remote message translations#2046

Merged
riderx merged 15 commits into
mainfrom
codex/translation-cache-queue
May 7, 2026
Merged

fix(i18n): queue remote message translations#2046
riderx merged 15 commits into
mainfrom
codex/translation-cache-queue

Conversation

@riderx
Copy link
Copy Markdown
Member

@riderx riderx commented May 6, 2026

Summary (AI generated)

  • Move message catalog translation queue consumption into a dedicated Cloudflare worker under cloudflare_workers/translation.
  • Keep the API worker as the request/cache/enqueue path only, with no Workers AI binding and no queue consumer handler.
  • Add separate translation worker deploy scripts and a GitHub Actions deploy job.
  • Keep the 5-minute Cloudflare D1/cache flow and Cloudflare Queue batching without adding Postgres changes.

Motivation (AI generated)

The translation flow needs async queue behavior so production requests do not timeout while Workers AI translates the full message catalog. Splitting the consumer into its own worker keeps product API deployment smaller and makes the translation worker independently deployable.

Business Impact (AI generated)

This keeps non-English app translations reliable without adding load to Postgres or blocking normal API traffic. It also reduces operational risk by isolating Workers AI translation failures from the core API worker.

Test Plan (AI generated)

  • bunx eslint cloudflare_workers/api/index.ts cloudflare_workers/translation/index.ts supabase/functions/_backend/public/translation.ts tests/translation-queue.unit.test.ts
  • bunx vitest run tests/translation-queue.unit.test.ts
  • bun lint
  • bun typecheck
  • bunx wrangler deploy --config cloudflare_workers/api/wrangler.jsonc --env=alpha --dry-run --outdir /tmp/capgo-api-dry-run --minify
  • bunx wrangler deploy --config cloudflare_workers/translation/wrangler.jsonc --env=alpha --dry-run --outdir /tmp/capgo-translation-dry-run --minify
  • bunx wrangler deploy --config cloudflare_workers/api/wrangler.jsonc --env=prod --dry-run --outdir /tmp/capgo-api-prod-dry-run --minify --upload-source-maps
  • bunx wrangler deploy --config cloudflare_workers/api/wrangler.jsonc --env=preprod --dry-run --outdir /tmp/capgo-api-preprod-dry-run --minify
  • bunx wrangler deploy --config cloudflare_workers/translation/wrangler.jsonc --env=prod --dry-run --outdir /tmp/capgo-translation-prod-dry-run --minify --upload-source-maps
  • bunx wrangler deploy --config cloudflare_workers/translation/wrangler.jsonc --env=preprod --dry-run --outdir /tmp/capgo-translation-preprod-dry-run --minify
  • GitHub CI for latest push

Generated with AI

Summary by CodeRabbit

  • New Features

    • Added a cache-first, queue-backed translation pipeline with a Cloudflare translation worker that batches UI messages, validates target languages, preserves placeholders, and returns ready or pending translation payloads with proper retry semantics.
  • Tests

    • Added unit tests for batching, index normalization, placeholder preservation, and pending/ready TTL behaviors.
  • Chores

    • Updated deployment workflows, Cloudflare bindings/configs, and CI to deploy and manage the new translation queue and worker.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Replaces in-process AI translation with a cache-first D1-backed translation store and a translation queue. API computes a source checksum, returns cached/ready payloads or 202 pending, and enqueues work. Adds a Cloudflare translation worker to consume queue batches, call an AI binding, preserve placeholders, and update store/cache. Tests and deployment wiring added.

Changes

Translation queue + cache-backed workflow

Layer / File(s) Summary
Public Types & Constants
supabase/functions/_backend/public/translation.ts
Adds exported types and constants: CACHE_TTL_SECONDS, TranslationMessagesResponsePayload, TranslationStoreStatus, TranslationStoreEntry, TranslationQueuePayload, MessageEntry, sourceMessageCatalog, SUPPORTED_LANGUAGES, and exposes new test utils.
Utilities & Batching
supabase/functions/_backend/public/translation.ts
Adds checksum/util helpers (sha256Hex, recordOf), buildBatches, buildTranslationCacheRequests, normalizeBatchIndex, and batch-index helpers.
Store & Queue Accessors / Bindings
supabase/functions/_backend/utils/cloudflare.ts, cloudflare_workers/api/wrangler.jsonc
Extends Bindings with TRANSLATION_MESSAGES_QUEUE?: Queue<unknown> and adds queue producer bindings to API wrangler configs.
D1 Translation Store: schema & lifecycle
supabase/functions/_backend/public/translation.ts
Implements D1 store initialization, row parsing/normalization, TTL rules for pending vs ready, expiration cleanup, read/upsert helpers, and staleness detection.
Batch claim / concurrency helpers
supabase/functions/_backend/public/translation.ts
Adds conditional SQL claim/release semantics (claimTranslationBatch, releaseTranslationBatchClaim), batch-index conversions, and TTL computation.
Queue coordination & enqueue logic
supabase/functions/_backend/public/translation.ts, cloudflare_workers/api/wrangler.jsonc
Implements enqueueTranslationBatch, queueTranslationIfNeeded with store-claim/cleanup on enqueue failure, and queue producer wiring in API envs.
API handler: cache-first flow
supabase/functions/_backend/public/translation.ts
Refactors POST /messages to compute checksum, validate target language, check cache, read D1 store (ready/pending), requeue stale pending entries, insert pending row and enqueue new work, and return 200 or 202 accordingly.
Cloudflare Worker: translation consumer
cloudflare_workers/translation/index.ts, cloudflare_workers/translation/wrangler.jsonc
New translation worker: request/response shapes, keepTranslation & parsing utilities, translateBatch (with retries and schema), processTranslationQueueBatch (claim/release, merge batches, write pending/ready), HTTP consumer endpoint, queue() handler, AI binding and D1/queue bindings in wrangler config, and exported test utils.
Deployment / CI
.github/workflows/build_and_deploy.yml, package.json
Adds deploy_translation_worker workflow job, new package scripts deploy:cloudflare:translation:prod/preprod, inserts translation step into Cloudflare deploy sequence, and adds per-plugin wrapper scripts.
Tests
tests/translation-queue.unit.test.ts
Adds unit tests covering batch splitting (max 60), placeholder preservation, batch-index normalization/mapping, and TTL differences for pending vs ready entries.

Sequence Diagram

sequenceDiagram
    participant Client
    participant API as Supabase<br/>API
    participant Cache
    participant Store as Translation<br/>Store (D1)
    participant Queue as Translation<br/>Queue
    participant Worker as Cloudflare<br/>Worker
    participant AI as AI<br/>Service

    Client->>API: POST /messages (targetLanguage)
    API->>API: compute checksum
    API->>Cache: check checksum+lang
    alt Cache hit
        Cache-->>API: ready payload
        API-->>Client: 200 + payload
    else Cache miss
        API->>Store: read entry by checksum+lang
        alt Store ready
            Store-->>API: ready payload
            API->>Cache: populate cache
            API-->>Client: 200 + payload
        else Store pending
            alt pending fresh
                API-->>Client: 202 Pending
            else pending stale
                API->>Queue: enqueue/requeue batch
                API->>Store: touch entry
                API-->>Client: 202 Pending
            end
        else No entry
            API->>Store: insert pending entry
            API->>Queue: enqueue initial batch
            API-->>Client: 202 Pending
        end
    end

    par Async processing
        Queue-->>Worker: deliver MessageBatch
        Worker->>AI: request translations (retries)
        AI-->>Worker: translation results
        Worker->>Worker: merge batches, preserve placeholders
        Worker->>Store: write/update entry (pending→ready)
        Worker->>Cache: write ready payload
        Worker-->>Queue: ack
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • Cap-go/capgo#2031: Overlapping changes to the translation backend, AI integration, and worker flow.

Poem

🐰 A hop, a queue, a careful stitch,

Batches bundled, placeholders rich;
Cache waits patient, store keeps track,
Worker hums, then brings them back;
Translated lines hop home in bliss.

🚥 Pre-merge checks | ✅ 4 | ❌ 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%. 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 'fix(i18n): queue remote message translations' clearly and concisely describes the main change—moving translation queue consumption into a dedicated worker.
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.
Description check ✅ Passed The PR description follows the template structure with Summary, Motivation, Business Impact, and a comprehensive Test Plan with multiple checked test commands.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/translation-cache-queue

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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

@codspeed-hq
Copy link
Copy Markdown
Contributor

codspeed-hq Bot commented May 6, 2026

Merging this PR will not alter performance

✅ 28 untouched benchmarks


Comparing codex/translation-cache-queue (a03ad5c) with main (cc61384)

Open in CodSpeed

@riderx riderx force-pushed the codex/translation-cache-queue branch from 369b334 to 67a5dea Compare May 6, 2026 14:37
@riderx riderx marked this pull request as ready for review May 6, 2026 14:53
@chatgpt-codex-connector
Copy link
Copy Markdown

💡 Codex Review

await cacheHelper.putJson(readyRequest, {
checksum,
messages: mergedMessages,
model,

P1 Badge Store queued translations in shared storage, not edge cache

The queue worker writes ready translations via CacheHelper.putJson, but CacheHelper uses Cloudflare's Cache API, which is data-center local. In this flow, translation generation runs from the queue consumer path while reads happen from end-user /messages requests, so when those hit different colos the user-facing request will keep missing ready and can stay stuck at 202 pending despite successful translation elsewhere. This regression appears in processTranslationQueueBatch because queued results are persisted only to edge-local cache instead of a globally shared store.


await queueTranslationIfNeeded(c, cacheHelper, pendingRequest, {
batchIndex: 0,
checksum,
model,
targetLanguage,

P2 Badge Fail fast when AI binding is unavailable on /messages

The public handler now always queues work and returns 202 pending without checking whether c.env.AI exists, while the actual missing-binding check happens later in the queue consumer path. In environments where Workers AI is not configured, queued jobs repeatedly fail and users are left polling a translation that can never become ready, instead of receiving an immediate 503 translation_unavailable as before.

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@riderx riderx force-pushed the codex/translation-cache-queue branch from 67a5dea to 6333699 Compare May 6, 2026 15:15
@riderx
Copy link
Copy Markdown
Member Author

riderx commented May 6, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@riderx
Copy link
Copy Markdown
Member Author

riderx commented May 6, 2026

Addressed the two Codex review points in 6333699: translation progress/ready state is now stored in shared database cache instead of edge-only Cache API, and /translation/messages returns translation_unavailable immediately when Workers AI is not bound.

@riderx riderx marked this pull request as draft May 6, 2026 16:37
@chatgpt-codex-connector
Copy link
Copy Markdown

💡 Codex Review

const existingEntry = await readTranslationStoreEntry(c, payload.checksum, payload.targetLanguage)
if (existingEntry)
return existingEntry

P2 Badge Make translation job enqueue atomic per checksum/language

When two /translation/messages requests for the same cold language arrive concurrently, both can pass this existence check before either writes, then both execute writeTranslationStoreEntry() and enqueueTranslationBatch(). That creates duplicate batch-0 queue messages for one (targetLanguage, checksum) job, which drives redundant Workers AI calls and queue churn in production. Use an atomic claim (for example INSERT ... ON CONFLICT DO NOTHING and enqueue only if the insert actually created the row) so only one request schedules the job.

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@riderx riderx marked this pull request as ready for review May 6, 2026 17:00
@riderx riderx marked this pull request as draft May 6, 2026 17:03
@riderx riderx marked this pull request as ready for review May 6, 2026 17:22
@riderx
Copy link
Copy Markdown
Member Author

riderx commented May 6, 2026

@coderabbitai review

Also addressed the latest Codex atomic enqueue point in 5f0d80a: cold translation jobs now claim (targetLanguage, checksum) with a D1 INSERT OR IGNORE, and only the request that creates the pending row enqueues batch 0.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

Tip

For best results, initiate chat on the files or code changes.

@riderx, triggering a review to pick up the latest commits, including the atomic enqueue fix in 5f0d80a where cold translation jobs now claim (targetLanguage, checksum) via INSERT OR IGNORE and only the winning request enqueues batch 0.

[review]

@riderx
Copy link
Copy Markdown
Member Author

riderx commented May 6, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@riderx
Copy link
Copy Markdown
Member Author

riderx commented May 6, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (4)
supabase/functions/_backend/public/translation.ts (3)

355-361: 💤 Low value

Remove unnecessary type assertion.

Per static analysis, the type assertion as D1Database | undefined is redundant since c.env.DB_STOREAPPS already has the correct type from the Bindings interface.

♻️ Proposed fix
 function getTranslationStore(c: Context) {
-  const store = c.env.DB_STOREAPPS as D1Database | undefined
+  const store = c.env.DB_STOREAPPS
   if (!store)
     quickError(503, 'translation_unavailable', 'Cloudflare D1 translation store is not configured')
 
   return store
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@supabase/functions/_backend/public/translation.ts` around lines 355 - 361,
The local variable declaration in getTranslationStore currently uses a redundant
type assertion on c.env.DB_STOREAPPS; remove the "as D1Database | undefined" so
that store is directly assigned from c.env.DB_STOREAPPS (relying on the Bindings
type), keep the existing null-check and quickError call (quickError(503,
'translation_unavailable', ...)) and return store as before to avoid changing
runtime behavior.

363-369: 💤 Low value

Remove unnecessary type assertion.

Per static analysis, the type assertion as Queue<Required<TranslationQueuePayload>> | undefined is redundant.

♻️ Proposed fix
 function getTranslationQueue(c: Context) {
-  const queue = c.env.TRANSLATION_MESSAGES_QUEUE as Queue<Required<TranslationQueuePayload>> | undefined
+  const queue = c.env.TRANSLATION_MESSAGES_QUEUE
   if (!queue)
     quickError(503, 'translation_unavailable', 'Cloudflare translation queue is not configured')
 
   return queue
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@supabase/functions/_backend/public/translation.ts` around lines 363 - 369,
The type assertion on c.env.TRANSLATION_MESSAGES_QUEUE in getTranslationQueue is
redundant; remove the "as Queue<Required<TranslationQueuePayload>> | undefined"
and simply assign const queue = c.env.TRANSLATION_MESSAGES_QUEUE (or, if you
want an explicit type, use a proper TS annotation: const queue:
Queue<Required<TranslationQueuePayload>> | undefined =
c.env.TRANSLATION_MESSAGES_QUEUE) and leave the quickError check and return
unchanged.

371-390: ⚖️ Poor tradeoff

Consider optimizing repeated DDL and cleanup operations.

ensureTranslationStore executes CREATE TABLE IF NOT EXISTS and CREATE INDEX IF NOT EXISTS on every D1 access path. Similarly, deleteExpiredTranslationStoreEntries runs a DELETE query on every read/write. While D1 handles these efficiently, this adds latency to every translation request.

Consider:

  1. Using a module-level flag to skip DDL after first call within a worker instance
  2. Running cleanup less frequently (e.g., probabilistically or via separate cron)

Also applies to: 434-436

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@supabase/functions/_backend/public/translation.ts` around lines 371 - 390,
The ensureTranslationStore function currently runs CREATE TABLE/INDEX on every
call and deleteExpiredTranslationStoreEntries runs DELETE on every operation,
causing extra latency; modify ensureTranslationStore to use a module-level
boolean (e.g., translationStoreInitialized) that is checked and set after the
first successful DDL run to skip subsequent CREATEs within the same worker, and
change deleteExpiredTranslationStoreEntries to run cleanup less frequently —
implement a probabilistic trigger (e.g., Math.random() threshold) inside the
function or move cleanup to a separate scheduled job — ensure you reference and
update the functions ensureTranslationStore and
deleteExpiredTranslationStoreEntries and keep DDL/cleanup as fallback if the
flag/probability path skips execution.
cloudflare_workers/api/index.ts (1)

175-192: ⚡ Quick win

Consider logging errors before retrying for observability.

The empty catch block silently swallows errors before retrying, which makes debugging failed translation batches difficult. Adding a log statement would improve observability without changing the retry behavior.

♻️ Proposed improvement for error logging
       catch {
+        console.error('Translation queue consumer error for message', message.id)
         message.retry({ delaySeconds: 30 })
       }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cloudflare_workers/api/index.ts` around lines 175 - 192, The catch block in
the queue method swallows errors; update the async function queue so the catch
captures the error (e.g., catch (err)) and logs useful context before retrying:
include the thrown error (err), the message payload (message.body) and any
response status if available from translation_messages.fetch, then call
message.retry({ delaySeconds: 30 }); reference the queue function,
translation_messages.fetch call, message.ack and message.retry to locate where
to add the logging (use console.error or your existing logger).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@cloudflare_workers/api/index.ts`:
- Around line 175-192: The catch block in the queue method swallows errors;
update the async function queue so the catch captures the error (e.g., catch
(err)) and logs useful context before retrying: include the thrown error (err),
the message payload (message.body) and any response status if available from
translation_messages.fetch, then call message.retry({ delaySeconds: 30 });
reference the queue function, translation_messages.fetch call, message.ack and
message.retry to locate where to add the logging (use console.error or your
existing logger).

In `@supabase/functions/_backend/public/translation.ts`:
- Around line 355-361: The local variable declaration in getTranslationStore
currently uses a redundant type assertion on c.env.DB_STOREAPPS; remove the "as
D1Database | undefined" so that store is directly assigned from
c.env.DB_STOREAPPS (relying on the Bindings type), keep the existing null-check
and quickError call (quickError(503, 'translation_unavailable', ...)) and return
store as before to avoid changing runtime behavior.
- Around line 363-369: The type assertion on c.env.TRANSLATION_MESSAGES_QUEUE in
getTranslationQueue is redundant; remove the "as
Queue<Required<TranslationQueuePayload>> | undefined" and simply assign const
queue = c.env.TRANSLATION_MESSAGES_QUEUE (or, if you want an explicit type, use
a proper TS annotation: const queue: Queue<Required<TranslationQueuePayload>> |
undefined = c.env.TRANSLATION_MESSAGES_QUEUE) and leave the quickError check and
return unchanged.
- Around line 371-390: The ensureTranslationStore function currently runs CREATE
TABLE/INDEX on every call and deleteExpiredTranslationStoreEntries runs DELETE
on every operation, causing extra latency; modify ensureTranslationStore to use
a module-level boolean (e.g., translationStoreInitialized) that is checked and
set after the first successful DDL run to skip subsequent CREATEs within the
same worker, and change deleteExpiredTranslationStoreEntries to run cleanup less
frequently — implement a probabilistic trigger (e.g., Math.random() threshold)
inside the function or move cleanup to a separate scheduled job — ensure you
reference and update the functions ensureTranslationStore and
deleteExpiredTranslationStoreEntries and keep DDL/cleanup as fallback if the
flag/probability path skips execution.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8f53538d-e58f-4314-8352-d1a54413be4e

📥 Commits

Reviewing files that changed from the base of the PR and between 8c586bb and 5f0d80a.

📒 Files selected for processing (5)
  • cloudflare_workers/api/index.ts
  • cloudflare_workers/api/wrangler.jsonc
  • supabase/functions/_backend/public/translation.ts
  • supabase/functions/_backend/utils/cloudflare.ts
  • tests/translation-queue.unit.test.ts

@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@riderx
Copy link
Copy Markdown
Member Author

riderx commented May 6, 2026

Addressed CodeRabbit nitpicks in 637e0205f: removed the redundant D1/queue casts, skipped repeated D1 DDL after the worker-local init succeeds, throttled expired-row cleanup, and added queue consumer error logging before retry.

Latest GitHub CI is green and there are no open review threads.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dc2d456973

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread supabase/functions/_backend/public/translation.ts Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
supabase/functions/_backend/public/translation.ts (1)

380-382: ⚡ Quick win

Precompute the source checksum once per isolate.

The source catalog is static during runtime; re-hashing on every request adds avoidable CPU on a hot path.

♻️ Suggested refactor
 export const sourceMessageCatalog = sourceMessages as Record<string, string>
+const sourceCatalogChecksumPromise = sha256Hex(JSON.stringify(sourceMessageCatalog))
 let translationStoreInitialized = false
 let lastTranslationStoreCleanupAt = 0
@@
 export async function currentSourceChecksum() {
-  return sha256Hex(JSON.stringify(sourceMessageCatalog))
+  return sourceCatalogChecksumPromise
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@supabase/functions/_backend/public/translation.ts` around lines 380 - 382,
Precompute the checksum at module load and have currentSourceChecksum return the
cached value to avoid re-hashing on every request: compute a const like
precomputedSourceChecksum = sha256Hex(JSON.stringify(sourceMessageCatalog))
(ensuring sourceMessageCatalog is already initialized) and change the
currentSourceChecksum function to simply return that cached
precomputedSourceChecksum; reference sha256Hex, sourceMessageCatalog and
currentSourceChecksum when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@supabase/functions/_backend/public/translation.ts`:
- Around line 409-411: The cache write call cacheHelper.putJson in the ready
flow is best-effort and must not abort the response; wrap the
cacheHelper.putJson(readyRequest, payload, CACHE_TTL_SECONDS) call inside a
try/catch, on error log the failure (include readyRequest and the error) and
continue without rethrowing, then still set the response Cache-Control header
via c.header('Cache-Control', `public, max-age=0,
s-maxage=${CACHE_TTL_SECONDS}`); apply the same try/catch pattern to the other
occurrence of cacheHelper.putJson noted in the review (around the ready flow at
the second spot).

---

Nitpick comments:
In `@supabase/functions/_backend/public/translation.ts`:
- Around line 380-382: Precompute the checksum at module load and have
currentSourceChecksum return the cached value to avoid re-hashing on every
request: compute a const like precomputedSourceChecksum =
sha256Hex(JSON.stringify(sourceMessageCatalog)) (ensuring sourceMessageCatalog
is already initialized) and change the currentSourceChecksum function to simply
return that cached precomputedSourceChecksum; reference sha256Hex,
sourceMessageCatalog and currentSourceChecksum when making the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9b0b3483-585b-4731-b027-bbe49d4f786f

📥 Commits

Reviewing files that changed from the base of the PR and between dc2d456 and b6ee855.

📒 Files selected for processing (1)
  • supabase/functions/_backend/public/translation.ts

Comment thread supabase/functions/_backend/public/translation.ts Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b6ee85553a

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread supabase/functions/_backend/public/translation.ts Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cloudflare_workers/translation/index.ts`:
- Around line 278-355: Before translating or enqueuing the next batch, make
batch ownership idempotent by performing a compare-and-set (lease) on the
translation store keyed by (checksum, targetLanguage, nextBatchIndex); in the
handler around normalizeBatchIndex/body.batchIndex and before calling
translateBatch or enqueueTranslationBatch, read the current storedEntry and
attempt an atomic update that claims the nextBatchIndex only if it still equals
the expected value (use or add a helper like compareAndSetTranslationEntry or a
D1 UPDATE ... WHERE nextBatchIndex = ? returning success); if the CAS fails
(meaning nextBatchIndex has advanced) then treat the message as stale and return
immediately (do not call translateBatch or enqueueTranslationBatch), and if CAS
succeeds proceed to translateBatch and then update the store via
writeTranslationStoreEntry and enqueue the following batch.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cbe396bd-291f-4c4d-ba84-d5bb4d879000

📥 Commits

Reviewing files that changed from the base of the PR and between b6ee855 and b09671f.

📒 Files selected for processing (3)
  • cloudflare_workers/translation/index.ts
  • supabase/functions/_backend/public/translation.ts
  • tests/translation-queue.unit.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/translation-queue.unit.test.ts

Comment thread cloudflare_workers/translation/index.ts Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
cloudflare_workers/translation/index.ts (1)

266-268: 💤 Low value

Add explicit return after quickError for clarity.

While quickError likely throws (standard Hono pattern), adding an explicit return makes the control flow unambiguous and helps readers and static analysis tools understand that ai is guaranteed to be defined afterwards.

Suggested change
   const ai = c.env.AI as AiBinding | undefined
   if (!ai)
-    quickError(503, 'translation_unavailable', 'Workers AI binding is not configured')
+    return quickError(503, 'translation_unavailable', 'Workers AI binding is not configured')
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cloudflare_workers/translation/index.ts` around lines 266 - 268, The guard
that checks c.env.AI uses quickError but doesn't explicitly return; make the
control flow unambiguous by returning the call to quickError when ai is falsy
(e.g., change the branch so it does "return quickError(...)" or add an explicit
"return" immediately after the quickError call) so that after the check ai is
guaranteed defined; update the statement referencing ai and quickError
accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@cloudflare_workers/translation/index.ts`:
- Around line 266-268: The guard that checks c.env.AI uses quickError but
doesn't explicitly return; make the control flow unambiguous by returning the
call to quickError when ai is falsy (e.g., change the branch so it does "return
quickError(...)" or add an explicit "return" immediately after the quickError
call) so that after the check ai is guaranteed defined; update the statement
referencing ai and quickError accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6e87791d-5007-406c-977a-7fc375f96208

📥 Commits

Reviewing files that changed from the base of the PR and between b09671f and 81cd5ab.

📒 Files selected for processing (3)
  • cloudflare_workers/translation/index.ts
  • supabase/functions/_backend/public/translation.ts
  • tests/translation-queue.unit.test.ts
✅ Files skipped from review due to trivial changes (1)
  • tests/translation-queue.unit.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • supabase/functions/_backend/public/translation.ts

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 81cd5ab7fc

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread supabase/functions/_backend/public/translation.ts Outdated
Comment thread supabase/functions/_backend/public/translation.ts Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b08f1d96f0

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread cloudflare_workers/translation/index.ts Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6f3674f5ed

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread cloudflare_workers/translation/index.ts Outdated
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 7, 2026

@riderx riderx merged commit b44a7a2 into main May 7, 2026
101 of 104 checks passed
@riderx riderx deleted the codex/translation-cache-queue branch May 7, 2026 11:35
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