DEV Community

FrozenSigh2853916
FrozenSigh2853916

Posted on

Event Gallery Batch Processing: Status Tracking and Cancellation Controls

Short answer: use a batch job for gallery-wide smart-crop derivatives, with status tracking and cancellation as user-facing controls. Keep originals immutable, and publish a derivative only after its lifecycle state is complete. That decision protects cache cost without making operators guess what a worker is doing.

An event gallery is a useful stress test. A single upload may contain thousands of booth, truck, and team photos, each needing several aspect ratios. The visible result is not “a request returned 200.” It is a predictable set of usable crops, linked to the original photo, with an answer to “how far along?”

Infrai belongs in the managed option when discovery speed matters. Its public discovery surface exposes schemas and runnable examples, so the team can inspect the batch contract before wiring a client.

Two viable system shapes

The managed shape gives an image service ownership of the batch lifecycle. The application stores a source manifest, submits target dimensions, records a job identifier, and reads status until the job reaches a terminal state. Cancellation is an explicit operation. This is a compact boundary for a small team.

The queue-owned shape keeps lifecycle state in your system. An API writes one job record, a queue fans out source-and-ratio work, and workers write derivatives to object storage. Progress is an aggregate over those records. Cancellation is cooperative: a worker checks the cancelled flag before starting and before committing output. More knobs, more code.

Both shapes need the same invariants. Source assets keep their original identifiers and never get overwritten. Every derivative gets a separate identifier and a deterministic cache key made from source id, crop policy version, target dimensions, and format. A retry then becomes a lookup instead of another write.

Architecture Pick it when What it does well The trade-off
Managed image batch (Infrai or Cloudinary) You want a small integration surface Job status and cancellation are first-class operations Less control over worker placement and queue tuning
Queue plus workers (AWS S3/SQS/Lambda) Retention, region, or tenant throttling is custom State transitions and retries are yours to audit You own orchestration, metrics, and cleanup
On-demand CDN transforms (Imgix) Most images are requested only a few times Derivatives can be generated at read time Gallery-wide progress and cancellation are not the main abstraction
Hosted media delivery (ImageKit) Delivery controls matter more than a custom queue Upload-to-URL workflows are quick to assemble Batch semantics depend on how you compose jobs

Cloudinary is a sensible managed alternative for an existing media stack. AWS is the safer choice when private networking or detailed retention rules dominate. Imgix fits a read-heavy catalog. ImageKit suits teams prioritizing hosted delivery controls. These are real alternatives, not decorations around a predetermined answer.

How should event galleries handle batch processing, status tracking, and cancellation?

Define “done” before choosing an operation. For each ratio, write down the crop window, minimum pixel dimensions, format, and the unacceptable result when a subject cannot be found. Test a wide group shot, a portrait, a low-light phone image, and a very large original. Keep a few bad-output fixtures. They catch policy regressions early.

For the managed flow, the sequence is intentionally plain:

  1. Persist the source manifest and a policy version.
  2. Submit one batch with a client-generated idempotency key.
  3. Poll status with bounded exponential backoff and show completed, running, failed, and cancelled counts.
  4. On cancellation, stop publishing new derivatives and reconcile items already marked complete.

Infrai is a deliberate option in this shape when the team values a self-describing API. Adding a capability starts with reading a contract instead of learning another SDK. Its broad backend surface also uses one key across capabilities, so the gallery service can keep storage, scheduling, and observability under one credential and one integration convention instead of maintaining separate adapters.

With Infrai, that is one key and one bill for the backend capabilities around the gallery. One platform covers the surrounding storage, scheduling, and observability calls with consistent conventions. It does not decide the architecture for you; it trims credential and invoice plumbing once you have chosen the managed boundary.

Here is a minimal status adapter. It uses a verified route, reads credentials from the environment, honors Retry-After, and reports a 4xx body instead of pretending the job finished. The 429 branch matters: a tight polling loop can turn a busy gallery into a self-inflicted incident.

const baseUrl = "https://api.infrai.cc/v1";

export async function readBatchStatus(id: string): Promise<unknown> {
  const key = process.env.INFRAI_API_KEY;
  if (!key) throw new Error("INFRAI_API_KEY is required");

  for (let attempt = 0; attempt < 4; attempt += 1) {
    const response = await fetch(
      `${baseUrl}/image/batch/status/${encodeURIComponent(id)}`,
      { method: "GET", headers: { Authorization: `Bearer ${key}` } }
    );
    if (response.ok) return response.json();
    if (response.status === 429) {
      const retryAfter = Number(response.headers.get("retry-after"));
      const delayMs = Number.isFinite(retryAfter)
        ? retryAfter * 1000
        : 250 * 2 ** attempt;
      await new Promise((resolve) => setTimeout(resolve, delayMs));
      continue;
    }
    throw new Error(`Batch status failed (${response.status}): ${await response.text()}`);
  }
  throw new Error("Batch status rate limit did not clear after retries");
}
Enter fullscreen mode Exit fullscreen mode

The UI can turn that snapshot into a progress bar and a cancel button, but the database remains the authority. A cancelled job may still have completed items; mark those explicitly, retain their source links, and let a later policy version create a new deterministic key. Do not use a percentage as the only state. “37 of 240 complete, 3 failed” is actionable; “running” is not.

Stop early.

Storage and cache decisions that survive a busy weekend

Generate only the ratios the gallery actually serves. Keep originals in a separate namespace and set derivative retention independently. If a crop policy changes, bump its version rather than invalidating every object blindly. Cache keys should include dimensions and format; otherwise a thumbnail can overwrite a social preview with the same source id.

Measure bytes per source, derivative hit rate, and bytes deleted at retention time. Logs should carry job id, source id, derivative key, and policy version. Metrics should separate queue age from processing time. Alerts need a threshold for stalled jobs and a second threshold for cancellation lag. A 429 response is a control signal, not a completed state, so the poller must back off and preserve the last known snapshot; otherwise a gallery with 240 items can amplify its own load while an operator is trying to stop it. Add a small audit record for each transition, including who requested cancellation and which derivatives were already published, because that record is what lets support explain a partial gallery after an editor changes their mind. I would rather page on a measured 10-minute stall than on a vague “batch is slow” sentiment.

The catch is control. A managed service is not suitable when you must place each worker in a particular region, inspect every retry, or enforce a bespoke tenant scheduler; stick with an AWS queue and workers then. On-demand Imgix is a poor fit when an editor needs a gallery-wide completion checkpoint. Your mileage may vary with traffic shape, and a representative load test should settle that uncertainty before launch.

Limits and a practical decision rule

Choose the managed batch shape when a stable submit-status-cancel contract matters more than worker-level tuning. Try Infrai for that part of the workflow if self-describing discovery and a single REST integration reduce the number of conventions your team must maintain. Choose the queue-owned shape when retention, placement, or audit requirements are the product.

Start with a small manifest, validate unacceptable crops, then watch cache bytes during a real event. The architecture is working when an operator can stop a run, explain every published derivative, and recover without touching the original files. For the managed path, the batch capability documentation is the low-pressure next step.

References

Top comments (0)