How to Poll for Generation Task Status in GPT-Image2: A Complete Implementation Guide
Poll for generation task status in GPT-Image2 by using the pollApimartTask helper in src/apimartClient.js, which repeatedly queries the server-side endpoint until the APIMart task reaches a terminal state of completed or failed.
The freestylefly/awesome-gpt-image-2 repository implements a robust polling mechanism for monitoring asynchronous image generation jobs. When you submit a generation request, the APIMart service returns a taskId that represents a long-running operation requiring active status checks until the image is ready or fails.
Architecture of the GPT-Image2 Polling System
The polling implementation splits responsibilities between server-side API routes and a reusable client-side utility.
Server-Side Status Endpoint (api/generation/status.js)
The backend exposes a GET endpoint that validates the taskId parameter and retrieves the current state from APIMart. According to the source code in api/generation/status.js, this route:
- Validates the incoming
taskId - Calls
getApimartTask(fromapi/_lib/apimart.js) to fetch the live status - Returns the raw task object if pending, or stores and returns the final result if completed
When the task is still processing, the endpoint returns intermediate metadata; when finished, it persists the result locally before responding.
Client-Side Polling Engine (src/apimartClient.js)
The client library provides pollApimartTask, a generic poller implemented in src/apimartClient.js (lines 15-42). This function:
- Accepts a
fetchTaskcallback that retrieves the latest status - Checks
isTerminalApimartStatus(task.status)to detect completion (returnstruefor"completed"or"failed") - Respects APIMart rate limits by reading the
Retry-Afterheader orerror.retryAfterMs - Supports cancellation via
AbortSignal - Enforces default limits of 120 attempts or 10 minutes (
maxElapsedMs)
Step-by-Step Polling Workflow
Follow this sequence to monitor generation tasks from submission to completion:
- Submit the generation request to
/api/generate-image, which creates an APIMart task and returns ataskId - Initialize the poller by invoking
pollApimartTaskwith afetchTaskwrapper that calls/api/generation/status?taskId=${taskId} - Handle progress updates through the
onProgresscallback, which receives the task object on every poll interval - Detect terminal states automatically—the poller stops when
statusequals"completed"or"failed"and returns the final task object - Abort if necessary by passing an
AbortSignalfromAbortControllerto cancel polling during component unmount or user cancellation
Code Implementation Examples
React Component Implementation
Use the useGenerationStatus hook pattern to integrate polling into your frontend:
import { pollApimartTask } from '../apimartClient';
function useGenerationStatus(taskId) {
const [status, setStatus] = React.useState(null);
const [error, setError] = React.useState(null);
const controller = React.useRef(new AbortController());
React.useEffect(() => {
async function startPolling() {
try {
const finalTask = await pollApimartTask(
async () => {
const res = await fetch(`/api/generation/status?taskId=${taskId}`);
if (!res.ok) throw new Error('STATUS_FETCH_FAILED');
return res.json();
},
{
signal: controller.current.signal,
onProgress: (task) => setStatus(task),
maxAttempts: 200,
maxElapsedMs: 15 * 60 * 1000,
intervalMs: 3000
}
);
setStatus(finalTask);
} catch (e) {
if (e.code !== 'APIMART_POLL_ABORTED') setError(e);
}
}
startPolling();
return () => controller.current.abort();
}, [taskId]);
return { status, error };
}
The AbortController ensures polling stops automatically when the component unmounts, preventing memory leaks and unnecessary network requests.
Node.js CLI Implementation
For server-side scripts or command-line interfaces, import the client directly:
import { pollApimartTask } from './src/apimartClient.js';
import fetch from 'node-fetch';
const taskId = process.argv[2];
(async () => {
const final = await pollApimartTask(
async () => {
const res = await fetch(`http://localhost:3000/api/generation/status?taskId=${taskId}`);
return res.json();
},
{
onProgress: (t) => console.log('progress →', t.status),
intervalMs: 2000
}
);
console.log('final task:', final);
})();
Manual Polling Alternative
If you cannot use the helper, implement basic polling with setInterval, though this lacks rate-limit handling:
function pollStatusManually(taskId, onUpdate) {
const interval = setInterval(async () => {
const { ok, status } = await fetch(`/api/generation/status?taskId=${taskId}`)
.then(r => r.json());
if (!ok) {
clearInterval(interval);
throw new Error('Failed to get status');
}
onUpdate({ status });
if (['completed', 'failed'].includes(status)) {
clearInterval(interval);
}
}, 2000);
}
Warning: This manual approach does not respect Retry-After headers or handle APIMART_RATE_LIMITED errors, making pollApimartTask the recommended solution for production use.
Handling Rate Limits and Timeouts
The pollApimartTask function implements sophisticated error handling for APIMart's rate limiting:
- Rate-limit detection: When the API returns
APIMART_RATE_LIMITED, the poller extracts the delay fromerror.retryAfterMsor falls back to the configuredintervalMs - Timeout protection: Set
maxElapsedMsto prevent infinite polling (default: 600,000ms or 10 minutes) - Attempt limits: Configure
maxAttemptsto cap total requests (default: 120) - Cancellation: Pass an
AbortSignalto immediately terminate the polling loop; the function throwsAPIMART_POLL_ABORTEDwhen aborted
Summary
pollApimartTaskinsrc/apimartClient.jsis the core utility for polling generation status in GPT-Image2- The server-side endpoint
api/generation/status.jsvalidates task IDs and retrieves live status from APIMart - Terminal states are
completedandfailed, detected viaisTerminalApimartStatus - Always use
AbortSignalin React components to cancel polling on unmount - Default polling limits are 120 attempts or 10 minutes, configurable via the
optionsparameter - The poller automatically handles
Retry-Afterheaders when APIMart rate limits are encountered
Frequently Asked Questions
How do I cancel an active polling operation in GPT-Image2?
Create an AbortController and pass its signal property to the pollApimartTask options. When you call controller.abort(), the poller immediately stops and throws an error with code APIMART_POLL_ABORTED. In React, invoke abort() inside the useEffect cleanup function to prevent state updates after unmounting.
What are the default polling limits in pollApimartTask?
By default, pollApimartTask stops after 120 attempts or 10 minutes (600,000ms), whichever comes first. You can override these constraints by passing maxAttempts and maxElapsedMs in the options object. Exceeding either limit causes the function to throw a timeout error.
How does the system handle APIMart rate limiting?
When APIMart returns a rate-limit response, pollApimartTask checks for the Retry-After header or the retryAfterMs property in the error object. The poller waits for the specified duration before retrying, preventing request throttling or account suspension. If no retry delay is specified, it falls back to the standard intervalMs.
What is the difference between the server-side and client-side polling components?
The server-side component (api/generation/status.js) acts as a proxy that validates the taskId and fetches the current state from APIMart using getApimartTask. The client-side component (src/apimartClient.js) provides the pollApimartTask orchestration logic, managing the retry loop, terminal state detection, rate-limit handling, and cancellation signals that govern how frequently the frontend checks the server endpoint.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →