# How ACE-Step UI Polls for Generation Job Status Updates

> Learn how ACE-Step UI polls for generation job status updates. Discover its interval polling, API calls, and status tracking for efficient job management and cleanup.

- Repository: [fspecii/ace-step-ui](https://github.com/fspecii/ace-step-ui)
- Tags: internals
- Published: 2026-04-29

---

**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`](https://github.com/fspecii/ace-step-ui/blob/main/src/App.tsx) (lines 39-45), the UI initializes a Map structure:

```typescript
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`](https://github.com/fspecii/ace-step-ui/blob/main/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`](https://github.com/fspecii/ace-step-ui/blob/main/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 authenticated `GET /api/generate/status/:jobId` endpoint ([`services/api.ts`](https://github.com/fspecii/ace-step-ui/blob/main/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`, and `queuePosition` values.
- **Terminal State Handling**:
  - **Success**: When status equals `succeeded`, the interval clears via `clearInterval`, 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.

## Resilience Mechanisms

### Timeout Protection

To prevent infinite polling of stalled jobs, the implementation enforces a 10-minute timeout ([`App.tsx`](https://github.com/fspecii/ace-step-ui/blob/main/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`](https://github.com/fspecii/ace-step-ui/blob/main/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`](https://github.com/fspecii/ace-step-ui/blob/main/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:

```typescript
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 server `jobId` values with temporary UI IDs and interval handles.
- The `beginPollingJob` function in [`src/App.tsx`](https://github.com/fspecii/ace-step-ui/blob/main/src/App.tsx) creates a 2-second `setInterval` that queries `GET /api/generate/status/:jobId` via the `generateApi.getStatus` wrapper.
- Progress updates normalize server responses to update placeholder songs with real-time `progress`, `stage`, and `queuePosition` data.
- Terminal states (`succeeded` or `failed`) 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`](https://github.com/fspecii/ace-step-ui/blob/main/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`](https://github.com/fspecii/ace-step-ui/blob/main/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`](https://github.com/fspecii/ace-step-ui/blob/main/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`](https://github.com/fspecii/ace-step-ui/blob/main/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.