Display Media Request Handling with Timeout and Caching in Fluxer

Fluxer processes display-media requests through a layered pipeline that combines in-memory request coalescing, network timeouts, and FFmpeg-level execution guards to serve transformed images and videos reliably.

The fluxerapp/fluxer repository implements a robust media-proxy service designed to handle external display-media requests—such as signed URLs pointing to images or videos—while preventing redundant processing and ensuring strict timeout enforcement at every I/O boundary. This architecture guarantees that concurrent identical requests are deduplicated, upstream fetches are bounded by network timeouts, and CPU-intensive media operations are guarded by process-level timeouts.

Architecture Overview

The request flow follows a deterministic pipeline orchestrated by ExternalMediaController. When a client requests a proxied media asset, the system first verifies the cryptographic signature, generates a cache key from the URL and transformation parameters, and checks the InMemoryCoalescer for an existing in-flight promise. On cache miss, the controller fetches the asset via HttpClient, validates the MIME type, optionally transforms it through MediaTransformService, and streams the response back with proper HTTP Range support.


Client → ExternalMediaController
      → verifySignature / parse query
      → cacheKey = `${proxyUrl}_${signature}_…`
      → InMemoryCoalescer.coalesce(cacheKey, async () => {
            fetchAndValidate(url)          ← HttpClient (network timeout)
            → getMimeType / validateMedia
            → if transforms → MediaTransformService
                 → FFmpegUtils (probe / thumbnail / frame extraction)
                    → execFile(..., {timeout})
                    → throws FFmpegTimeoutError on timeout
            → return {data, contentType}
         })
      → Range handling (parseRange)
      → setHeaders + ctx.body(toBodyData)

Core Components

ExternalMediaController

Located at packages/media_proxy/src/controllers/ExternalMediaController.tsx (lines 16-33), this controller serves as the entry point and orchestrator. It handles signature verification, query parameter parsing, and coordinates the interaction between the caching layer and transformation services. The controller also manages response headers and range-request parsing for efficient streaming.

InMemoryCoalescer

The InMemoryCoalescer class (packages/media_proxy/src/lib/InMemoryCoalescer.tsx, lines 33-63) provides request deduplication by maintaining a map of in-flight promises keyed by deterministic cache keys. When multiple concurrent requests arrive for the same resource and transformation parameters, only one upstream fetch is initiated; subsequent requests receive the same promise. This component emits metrics for media_proxy.cache.hit and media_proxy.cache.miss to track coalescing efficiency.

HttpClient with Timeout Protection

The HttpClient.sendRequest method (packages/media_proxy/src/controllers/ExternalMediaController.tsx, lines 76-90) executes the upstream HTTP fetch. Non-200 responses are captured and converted into metric-tagged errors (media_proxy.external.upstream_error), allowing the system to distinguish between network failures and application-level errors.

MediaTransformService

When transformation parameters (width, height, format, quality) are present, MediaTransformService (packages/media_proxy/src/controllers/ExternalMediaController.tsx, lines 43-55) coordinates the conversion pipeline. It delegates CPU-intensive operations to FFmpegUtils while maintaining timeout context throughout the transformation chain.

FFmpegUtils and Timeout Enforcement

The FFmpegUtils module (packages/media_proxy/src/lib/FFmpegUtils.tsx, lines 35-45 and 78-90) wraps FFmpeg and ffprobe calls using execFile with explicit timeout options. When an operation exceeds its allocated time, the utility throws a custom FFmpegTimeoutError. This error propagates to calling services like FrameService, which converts it into either a graceful fallback or a structured HTTP 400 response.

Request Coalescing and Caching Strategy

Fluxer employs an in-memory request coalescing strategy rather than long-term caching. The cache key is constructed from:

  • The original media URL
  • The cryptographic signature
  • Transformation parameters (width, height, format, quality, animation flag)

This deterministic key ensures that identical requests receive identical processing. The InMemoryCoalescer stores only the promise for the duration of processing; once resolved, the entry is immediately removed. This approach prevents stale data while eliminating redundant work for concurrent requests, significantly reducing load on upstream resources and improving latency under high concurrency.

Timeout Management at Every Layer

Network Fetch Timeouts

The HttpClient enforces network-level timeouts during the initial upstream fetch. If the external server fails to respond within the configured window, the promise rejects and the controller records a media_proxy.external.upstream_error metric. This prevents worker threads from hanging on slow external resources.

FFmpeg Operation Timeouts

All FFmpeg operations—probing, thumbnail generation, and frame extraction—execute via execFile with per-operation timeout configurations (packages/media_proxy/src/lib/FFmpegUtils.tsx). When the OS-level timeout is exceeded, the utility throws FFmpegTimeoutError. The FrameService catches this specifically (packages/media_proxy/src/services/FrameService.tsx, lines 38-44):

} catch (error) {
    logger.error({error, source: filename}, 'Failed to extract media frames');
    if (error instanceof FFmpegTimeoutError) {
        throw new Error(`Frame extraction timed out: ${error.operation}`);
    }
    return {frames: []};
}

This layered timeout approach ensures that neither network I/O nor CPU-intensive media processing can indefinitely block the request pipeline.

Error Handling and Observability

The architecture emits structured metrics and tracing spans throughout the request lifecycle. Key metrics include:

  • media_proxy.cache.hit and media_proxy.cache.miss for coalescing performance
  • media_proxy.external.upstream_error for external fetch failures
  • Custom counters for FFmpegTimeoutError occurrences

Tracing spans cover the signature verification, cache lookup, external fetch, and transformation phases, providing end-to-end visibility into latency bottlenecks. When timeouts occur, the system returns clear error messages to clients while logging detailed context for operators.

Summary

  • In-memory request coalescing via InMemoryCoalescer eliminates duplicate processing for concurrent identical requests, improving throughput and reducing upstream load.
  • Deterministic cache keys incorporate the URL, signature, and all transformation parameters to ensure consistent behavior.
  • Network timeouts enforced by HttpClient prevent hanging on slow external servers.
  • FFmpeg timeouts using execFile with custom FFmpegTimeoutError handling guard against runaway media processing.
  • Comprehensive metrics for cache hit rates, upstream errors, and timeout events enable operational monitoring and debugging.

Frequently Asked Questions

How does Fluxer prevent duplicate requests for the same media asset?

Fluxer uses the InMemoryCoalescer class to deduplicate concurrent requests. When a request arrives, the system generates a deterministic cache key and checks if an identical request is already being processed. If found, the new request receives the existing promise rather than initiating a separate fetch or transformation workflow.

What happens when an FFmpeg operation times out?

When an FFmpeg operation exceeds its configured timeout, FFmpegUtils throws a custom FFmpegTimeoutError. This error propagates to the calling service—such as FrameService or ExternalMediaController—which either returns a graceful fallback (such as the original unmodified media) or an HTTP 400 error with a clear timeout message, depending on the operation context.

Does Fluxer cache the actual media files in memory?

No, Fluxer does not cache the final media bytes in memory. The InMemoryCoalescer caches only the promise representing the in-flight work for a specific cache key. Once the promise resolves, the entry is removed from the coalescer. This design prevents memory bloat from large media files while still eliminating redundant processing for concurrent requests.

How are cache keys constructed for display-media requests?

Cache keys are constructed deterministically from the original URL, the cryptographic signature, and all transformation parameters including width, height, format, quality settings, and animation flags. This ensures that requests with different transformations receive separate processing pipelines while identical requests benefit from coalescing.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →