Skip to content

Harden translation model retries#617

Merged
riderx merged 2 commits into
mainfrom
codex/translation-model-retry
May 1, 2026
Merged

Harden translation model retries#617
riderx merged 2 commits into
mainfrom
codex/translation-model-retry

Conversation

@riderx
Copy link
Copy Markdown
Member

@riderx riderx commented May 1, 2026

Summary

  • retry malformed model translation output inside the worker before failing a batch
  • accept common non-array JSON wrappers from model responses
  • use per-message queue retry with delay so a bad translation response does not fail the whole queue invocation
  • tighten the translation prompt to preserve Capgo/Capacitor/code terms and prefer culturally natural translation

Validation

  • bun run ci:verify:translation
  • cd apps/translation-worker && bunx wrangler deploy --dry-run
  • cd apps/translation-worker && bunx wrangler deploy --dry-run -e development

Summary by CodeRabbit

  • New Features

    • Added retry support for failed translation jobs with delay support.
    • Implemented multi-attempt translation processing for improved reliability.
  • Bug Fixes

    • Improved parsing to handle varied AI response formats and nested payloads.
    • Added stricter JSON validation and exact-output length checks.
    • Enhanced error handling and per-attempt diagnostic logging during translation.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 1, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6ddd0c3d-f858-4c73-8fac-34cda49cd5c6

📥 Commits

Reviewing files that changed from the base of the PR and between 33ce2ce and 28ddebc.

📒 Files selected for processing (1)
  • apps/translation-worker/src/index.ts

📝 Walkthrough

Walkthrough

Queue message type now includes optional id, attempts, and a retry({delaySeconds?}) hook; batch messages are readonly. Translation flow now extracts generic AI payloads (not just strings), validates JSON structure and exact output length, retries AI up to 3 times with per-attempt diagnostics, and uses message.retry on processing errors.

Changes

Cohort / File(s) Summary
Queue & Consumer
apps/translation-worker/src/index.ts
Added optional id and attempts to QueueMessage, and a retry({delaySeconds?}) hook; consumer error path now calls message.retry(...) with delay and logs instead of rethrowing.
AI Payload Extraction & Parsing
apps/translation-worker/src/index.ts
Replaced single-pass extractAiText with extractAiPayload accepting unknown; parseTranslationArray now accepts unknown and extracts nested arrays or JSON values, validating exact array length.
Batch Translation Retry & Diagnostics
apps/translation-worker/src/index.ts
translateBatch performs up to 3 AI attempts, tightens system prompt to require a JSON array of exactly batch.length strings, rejects prior-format responses on retries, logs truncated per-attempt outputs and diagnostics, and throws only after exhausting attempts.

Sequence Diagram(s)

sequenceDiagram
    participant QueueConsumer as Queue Consumer
    participant AI as AI Model
    participant Parser as Payload Parser
    participant RetryHook as message.retry

    QueueConsumer->>AI: send translateBatch prompt (require JSON array)
    AI-->>QueueConsumer: returns payload (string/array/object)
    QueueConsumer->>Parser: extractAiPayload / parseTranslationArray
    alt parse succeeds and length matches
        Parser-->>QueueConsumer: translations[]
        QueueConsumer->>QueueConsumer: proceed with success path
    else parse fails or length mismatch
        Parser-->>QueueConsumer: parse error
        QueueConsumer->>AI: retry (up to 3 attempts)
        alt after attempts exhausted
            QueueConsumer->>RetryHook: retry({delaySeconds})
            RetryHook-->>QueueConsumer: scheduled
        end
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I nudged the queue, then gave a hop,

Three tries for words before they stop,
Payloads pried and lengths kept true,
I tunneled logs and left a clue,
Hooray—retries and parse-time glue! 🥕

🚥 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Harden translation model retries' directly reflects the main objective of the PR: implementing robust retry logic for translation model responses with better error handling.
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.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/translation-model-retry

Review rate limit: 2/5 reviews remaining, refill in 26 minutes and 33 seconds.

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

@riderx riderx marked this pull request as ready for review May 1, 2026 19:23
@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.

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: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/translation-worker/src/index.ts`:
- Around line 862-888: The function translationArrayFromUnknown is incorrectly
treating the key 'texts' as a valid translation-wrapper; remove 'texts' from the
keys array so model-echoed input objects like { targetLanguage, texts: [...] }
are not accepted as successful translations. Edit translationArrayFromUnknown
(the for loop that iterates over
['translations','translated','translatedTexts','texts',...]) to drop 'texts'
from that list, leaving other keys intact; no changes needed to
parseTranslationArray beyond relying on the corrected
translationArrayFromUnknown.
- Around line 1706-1711: The console.error in the translated-page queue retry
path is logging the full user-controlled job payload (message.body) which can
include PII in query params; update the log in the error handler that currently
prints job: message.body to instead log only non-sensitive identifiers (e.g.,
message.id, message.attempts, TRANSLATION_QUEUE_RETRY_DELAY_SECONDS, and a
sanitized URL or URL origin/path with query params stripped) and include
errorMessage(error); you can add a small sanitizer helper (e.g., sanitizeJobUrl
or sanitizeMessageForLogging) and use it in the place where job: message.body is
passed to console.error in index.ts so no raw message.body is emitted.
- Around line 940-987: The loop currently calls env.AI.run(model, ...) without
catching exceptions, so transient throws abort retries; wrap the AI call in a
try/catch around env.AI.run(...) (inside the for loop) and on catch set
lastError to the thrown Error (or new Error(errorMessage(error))) and continue
to the next attempt so the existing retry logic runs; keep subsequent steps
using extractAiPayload(result) guarded (result may be undefined) and ensure the
same warning/log path uses aiPayloadPreview(payload) and other symbols
(TRANSLATION_MODEL_ATTEMPTS, parseTranslationArray, extractAiPayload,
assertTranslatedBatch, aiPayloadPreview) unchanged.
🪄 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: c3a28690-0a07-437d-94a0-faea77b3ff0d

📥 Commits

Reviewing files that changed from the base of the PR and between bbfb26f and 33ce2ce.

📒 Files selected for processing (1)
  • apps/translation-worker/src/index.ts

Comment thread apps/translation-worker/src/index.ts
Comment thread apps/translation-worker/src/index.ts
Comment thread apps/translation-worker/src/index.ts
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 1, 2026

@riderx riderx merged commit ef8e98b into main May 1, 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