Classify browser upload outcomes
This browser helper sends one bounded Arrow IPC upload and classifies the response without clearing input or silently retrying. Supply encoded bytes and their expected row count. Preserve input after partial or unknown outcomes; even a fully admitted batch has not necessarily reached your application’s required durability boundary.
Browser upload example
Section titled “Browser upload example”Encode data with an Arrow library using the target schema, then pass the resulting
Uint8Array and its row count to this function. It sends one request, retains the caller’s
bytes, and reports the outcome. It does not clear a queue or silently retry.
async function uploadArrow(endpoint, bytes, expectedRows, maxBytes = 128 * 1024) { if (!Number.isSafeInteger(maxBytes) || maxBytes <= 0 || !(bytes instanceof Uint8Array) || bytes.byteLength === 0 || bytes.byteLength > maxBytes || !Number.isSafeInteger(expectedRows) || expectedRows <= 0) { throw new Error('Provide a nonempty, bounded Arrow batch and its row count'); }
let response; let body; try { response = await fetch(endpoint, { method: 'POST', headers: { 'Content-Type': 'application/vnd.apache.arrow.stream' }, body: bytes }); body = await response.json(); } catch { return { outcome: 'unknown' }; }
if (response.status === 200 && body?.status === 'success' && Number.isSafeInteger(body.rows) && body.rows >= 0 && body.rows <= expectedRows) { return { outcome: body.rows === expectedRows ? 'admitted' : 'partial', admittedRows: body.rows }; } if (response.status === 429 || response.status === 503) { const delay = body?.retry_after_ms; return { outcome: 'retry-later', status: response.status, retryAfterMs: Number.isSafeInteger(delay) && delay > 0 ? delay : null }; } if ([400, 401, 403, 404, 405].includes(response.status)) { return { outcome: 'rejected', status: response.status }; } return { outcome: 'unknown', status: response.status };}The 128 KiB value is a client-side example bound, not a promise about server request-size limits. Use bounded batches and one upload at a time. Keep a bounded pending queue or a durable application outbox if data must survive a browser close.
Only remove input from the pending queue after the outcome required by your application.
admitted establishes memory admission only. For retry-later, preserve the same bytes;
retry a confirmed pre-admission rejection after the indicated delay, with a retry limit.
For partial or unknown, retain the input and reconcile it instead of retrying blindly.
Application event IDs help reconciliation but do not automatically enable server deduplication.
The current server admits a validated request as one group. The helper retains its
partial outcome defensively for an unexpected count mismatch. retry-later is a
signal to inspect the refusal, not permission to replay: confirm the server’s
pre-admission contract first. A 503 status alone can also mean an uncertain outcome.