# How Read Frog’s Background Service Worker Manages Translation Queues and Asynchronous Tasks

> Discover how Read Frog's background service worker efficiently manages translation queues and async tasks using a dual-queue system and IndexedDB caching for optimal performance and rate limit adherence.

- Repository: [MengXi/read-frog](https://github.com/mengxi-ream/read-frog)
- Tags: internals
- Published: 2026-03-07

---

**Read Frog’s background service worker employs a dual-queue system—combining a rate-limited `RequestQueue` with a throughput-optimized `BatchQueue`—to process translation signals asynchronously, while leveraging IndexedDB caching to eliminate redundant API calls and respect provider rate limits.**

The Read Frog browser extension (mengxi-ream/read-frog) centralizes its AI translation workloads within a dedicated background service worker located at [`src/entrypoints/background/translation-queues.ts`](https://github.com/mengxi-ream/read-frog/blob/main/src/entrypoints/background/translation-queues.ts). This architectural choice isolates heavy computational work from the UI thread, enabling the extension to handle high-volume translation requests, batch them for efficiency, and manage dynamic configuration changes without service interruption.

## Dual Queue Architecture for Rate Control and Batching

The background service worker instantiates two complementary queue abstractions built atop the generic utilities in `src/utils/request/`. These queues cooperate to balance provider rate limits with throughput optimization.

### RequestQueue: Individual Request Throttling

The `RequestQueue` manages rate-limited, retry-aware execution of individual translation thunks. Instantiated with configurable `rate` (requests per second), `capacity` (burst allowance), timeout, and retry settings, this queue prevents overwhelming AI providers like OpenAI or Anthropic. When the system determines a job cannot be batched, it creates a single-text thunk and enqueues it through this rate-limited pipeline, ensuring respectful API usage even under heavy load.

### BatchQueue: Intelligent Job Grouping

The `BatchQueue` receives `TranslateBatchData` objects containing text, language configuration, provider details, scheduling timestamps, and content hashes. For batch-eligible jobs, it constructs a combined prompt by joining texts with `\n\n` + `BATCH_SEPARATOR` + `\n\n`, then enqueues the resulting thunk on the underlying `RequestQueue`. The batching logic respects `maxCharactersPerBatch` and `maxItemsPerBatch` limits; if thresholds are exceeded or batching fails, the system automatically falls back to individual `RequestQueue` submissions.

## Signal Processing via Chrome Extension Messaging

The worker registers listeners using the thin `onMessage` wrapper around Chrome extension messaging (defined in [`src/utils/message.ts`](https://github.com/mengxi-ream/read-frog/blob/main/src/utils/message.ts)). These handlers translate UI signals into queued asynchronous tasks, enabling real-time communication between content scripts and the background worker.

### enqueueTranslateRequest: Page-Level Translation Pipeline

When the content script emits an `enqueueTranslateRequest` signal, the worker first queries `db.translationCache.get(hash)` to check for cached results. For LLM providers, it optionally generates article summaries via `getOrGenerateSummary`, which itself uses the `RequestQueue` for caching and throttling to avoid redundant summary generation. Finally, the worker enqueues the validated request on the `BatchQueue` (or fallback `RequestQueue`) and persists the successful result back to IndexedDB.

### enqueueSubtitlesTranslateRequest: Video Content Handling

The `enqueueSubtitlesTranslateRequest` handler mirrors the page-level flow for video subtitle translation, utilizing identical queue machinery and cache logic defined in [`src/entrypoints/background/translation-queues.ts`](https://github.com/mengxi-ream/read-frog/blob/main/src/entrypoints/background/translation-queues.ts). This ensures consistent rate limiting and batching behavior across different content types while maintaining separate data pipelines for web text versus timed subtitle data.

### Dynamic Configuration Updates

The worker exposes runtime configuration endpoints that adjust behavior without requiring a service restart. The `setTranslateRequestQueueConfig` and `setSubtitlesRequestQueueConfig` handlers dynamically update `RequestQueue` parameters including `rate` and `capacity`, while `setTranslateBatchQueueConfig` and `setSubtitlesBatchQueueConfig` modify batch size limits and processing delays in real time.

## Asynchronous Coordination and Caching Strategy

The background service worker achieves robust asynchronous coordination through three core mechanisms that ensure reliable task execution.

### Thunk-Based Scheduling with Promise Resolution

Both `RequestQueue.enqueue` and `BatchQueue.enqueue` return **Promises** that resolve with translation results or batch result arrays. The queues manage `scheduleAt` timestamps to delay execution until specified times, while comprehensive error handling captures execution context—including batch keys and retry counts—for debugging and telemetry.

### IndexedDB Caching Layer

Before initiating any network calls to `executeTranslate` (located in [`src/utils/host/translate/execute-translate.ts`](https://github.com/mengxi-ream/read-frog/blob/main/src/utils/host/translate/execute-translate.ts)), the worker performs hash-based lookups in `db.translationCache` and `db.articleSummaryCache` (defined in [`src/utils/db/dexie/db.ts`](https://github.com/mengxi-ream/read-frog/blob/main/src/utils/db/dexie/db.ts)). Cache hits return immediately, bypassing the queue entirely and eliminating redundant async work. This pre-queue cache check occurs in the message handlers before any thunk creation.

## Practical Implementation Examples

Enqueue a page-level translation from a content script:

```typescript
chrome.runtime.sendMessage({
  type: "enqueueTranslateRequest",
  data: {
    text: "Hello world",
    langConfig: { sourceCode: "en", targetCode: "es" },
    providerConfig: { id: "openai", model: "gpt-4o" },
    scheduleAt: Date.now(),
    hash: "a1b2c3d4",
    articleTitle: "Greeting",
    articleTextContent: "Full article body …",
  },
});

```

Dynamically change the request-queue rate limit after user settings update:

```typescript
chrome.runtime.sendMessage({
  type: "setTranslateRequestQueueConfig",
  data: { rate: 5, capacity: 20 },
});

```

Adjust batch size for subtitles processing without restarting the worker:

```typescript
chrome.runtime.sendMessage({
  type: "setSubtitlesBatchQueueConfig",
  data: { maxCharactersPerBatch: 2000, maxItemsPerBatch: 10 },
});

```

## Summary

- The background service worker in [`src/entrypoints/background/translation-queues.ts`](https://github.com/mengxi-ream/read-frog/blob/main/src/entrypoints/background/translation-queues.ts) orchestrates all translation work using cooperating `RequestQueue` and `BatchQueue` instances.
- **Rate limiting** and **retry logic** are enforced at the individual request level, while **batching** reduces API call volume by grouping compatible jobs with a `BATCH_SEPARATOR` delimiter.
- **Signal processing** occurs through Chrome extension messaging handlers that check IndexedDB caches before queuing new work, preventing unnecessary API calls.
- **Dynamic configuration** allows runtime adjustment of queue parameters—including `maxCharactersPerBatch` and request rates—without service interruption.
- The architecture supports both web page content and video subtitles through unified queue machinery while maintaining separate message handlers for each content type.

## Frequently Asked Questions

### How does the background service worker prevent duplicate translation API calls?

The worker checks `db.translationCache.get(hash)` immediately upon receiving an `enqueueTranslateRequest` signal. If a cached result exists for the content hash, the Promise resolves with the stored translation without entering the `RequestQueue` or `BatchQueue`, eliminating redundant network requests to the translation provider.

### What happens when a translation job fails or exceeds rate limits?

The `RequestQueue` implements configurable retry logic with exponential backoff. Failed thunks are automatically re-enqueued up to the configured retry limit, with detailed error context (batch key, retry count) captured for debugging. If batch processing fails, the `BatchQueue` falls back to individual request queuing to maximize delivery success.

### Can batch processing settings be adjusted without restarting the extension?

Yes. The worker listens for `setTranslateBatchQueueConfig` and `setSubtitlesBatchQueueConfig` messages, allowing dynamic updates to `maxCharactersPerBatch`, `maxItemsPerBatch`, and processing delays at runtime. Similarly, `setTranslateRequestQueueConfig` instantly updates rate limits and burst capacity without requiring a service worker restart.

### How does Read Frog handle different content types like web pages versus video subtitles?

While both use the same underlying queue infrastructure in [`translation-queues.ts`](https://github.com/mengxi-ream/read-frog/blob/main/translation-queues.ts), the worker distinguishes content via separate message types: `enqueueTranslateRequest` for web content and `enqueueSubtitlesTranslateRequest` for video subtitles. Each handler applies appropriate preprocessing—including optional AI summary generation for articles—but funnels jobs through identical caching and queuing logic to ensure consistent performance.