How ACE-Step UI Polls for Generation Job Status Updates
ACE-Step UI maintains a client-side Map of active jobs and executes a setInterval loop every 2 seconds to query GET /api/generate/status/:jobId, updating temporary placeholders until the job reaches succeeded or failed status, with automatic cleanup and 10-minute timeout protection.
When users initiate AI music generation in the fspecii/ace-step-ui repository, the front-end must track asynchronous back-end jobs without freezing the interface. The application implements a self-healing polling mechanism that creates temporary song placeholders, repeatedly queries the server for status updates, and synchronizes progress data in real-time.
The Polling Architecture
Tracking Active Jobs with activeJobsRef
The core state management relies on a mutable React ref that persists across renders without triggering re-renders. In src/App.tsx (lines 39-45), the UI initializes a Map structure:
const activeJobsRef = useRef<Map<string, {
tempId: string;
pollInterval: ReturnType<typeof setInterval>;
}>>(new Map());
This Map stores the correlation between server-side jobId values and client-side temporary song IDs, along with their active setInterval handles for later cleanup.
Initialization Flow
When a user submits a generation request, the UI immediately creates a temporary placeholder song to provide immediate visual feedback. After generateApi.startGeneration returns a jobId from the back-end (App.tsx, lines 557-564), the application invokes beginPollingJob(jobId, tempId) to commence status monitoring.
Inside the Polling Loop (beginPollingJob)
The beginPollingJob function (App.tsx, lines 99-143) establishes a 2-second polling interval that executes the following sequence:
- Status Retrieval: Calls
generateApi.getStatus(jobId, token), which wraps the authenticatedGET /api/generate/status/:jobIdendpoint (services/api.ts, lines 37-38). - Progress Normalization: Converts the server-reported progress value to a 0-1 range for the UI progress bar.
- State Synchronization: Updates the temporary song object in React state with current
progress,stage, andqueuePositionvalues. - Terminal State Handling:
- Success: When status equals
succeeded, the interval clears viaclearInterval, the placeholder removes from state, and the real song list refreshes to include the completed generation. - Failure: When status equals
failed, the interval clears, the placeholder removes, and an error toast displays via the Toast component.
- Success: When status equals
Resilience Mechanisms
Timeout Protection
To prevent infinite polling of stalled jobs, the implementation enforces a 10-minute timeout (App.tsx, lines 47-53). If a job exceeds 600 seconds without reaching a terminal state, the UI aborts the poll, removes the temporary placeholder, and displays a "generation timed out" notification.
Session Recovery on Reload
If the user refreshes the browser during active generation, the UI does not lose track of in-progress work. During initialization (App.tsx, lines 71-84), the application queries generateApi.getHistory to retrieve the server's generation history. For any jobs still in non-terminal states, it reconstructs temporary placeholder songs and re-invokes beginPollingJob to resume the 2-second polling cycle.
Cleanup and Memory Management
The cleanupJob helper (App.tsx, lines 26-43) ensures proper resource disposal by clearing the setInterval handle, deleting the entry from activeJobsRef, and updating UI counters. This prevents memory leaks and interval duplication when components unmount or jobs complete.
Implementation Example
The following pattern demonstrates how a component initiates generation and delegates status monitoring to the polling system:
import { generateApi } from './services/api';
const onGenerate = async (params: GenerationParams) => {
// Create temporary placeholder for immediate UI feedback
const tempId = `temp_${Date.now()}`;
setSongs(prev => [
{ id: tempId, title: 'Generating…', isGenerating: true, progress: 0 },
...prev
]);
// Initiate back-end job
const job = await generateApi.startGeneration(params, token);
// Begin 2-second interval polling
beginPollingJob(job.jobId, tempId);
};
Summary
- ACE-Step UI stores active job metadata in
activeJobsRef, a React ref containing a Map that associates serverjobIdvalues with temporary UI IDs and interval handles. - The
beginPollingJobfunction insrc/App.tsxcreates a 2-secondsetIntervalthat queriesGET /api/generate/status/:jobIdvia thegenerateApi.getStatuswrapper. - Progress updates normalize server responses to update placeholder songs with real-time
progress,stage, andqueuePositiondata. - Terminal states (
succeededorfailed) trigger automatic cleanup, placeholder removal, and appropriate user feedback via toast notifications. - A 10-minute timeout safeguard prevents indefinite polling of stalled jobs.
- On application reload, the UI resumes polling for any active jobs discovered in the generation history via
generateApi.getHistory.
Frequently Asked Questions
What endpoint does ACE-Step UI poll for generation status?
The UI polls GET /api/generate/status/:jobId every 2 seconds. This endpoint is accessed through the generateApi.getStatus method defined in src/services/api.ts (lines 37-38), which handles authentication token injection and response normalization.
How does ACE-Step UI prevent memory leaks when polling?
The application stores setInterval handles in a React ref-based Map called activeJobsRef. When a job completes, fails, or times out, the cleanupJob function (App.tsx, lines 26-43) clears the interval using clearInterval and deletes the Map entry, ensuring no orphaned timers persist after component unmount or job completion.
What happens if I refresh the page during generation?
ACE-Step UI implements session recovery logic in src/App.tsx (lines 71-84). On mount, it fetches the generation history via generateApi.getHistory and identifies any jobs still in progress. For each active job, it reconstructs the temporary placeholder and calls beginPollingJob to resume the 2-second polling cycle without user intervention.
How long will ACE-Step UI wait for a generation to complete?
The polling mechanism includes a 10-minute timeout guard (App.tsx, lines 47-53). If a job fails to reach succeeded or failed status within 600 seconds, the UI automatically aborts polling, removes the temporary song placeholder, and displays a timeout error toast to the user.
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 →