> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fusioncore.us/llms.txt
> Use this file to discover all available pages before exploring further.

# Async Job Coordinator Overview

> Run long, multi-step Apex automation as an ordered group of batch jobs with per-record error tracking and one automatic retry.

The Async Job Coordinator runs long, multi-step Apex automation for you. You define an ordered set of steps called a **Job Group**. Each time the group runs, the coordinator starts every step as its own batch job, tracks progress, records failures, and retries failed records once.

## What the Coordinator Stores

The coordinator uses five objects. You manage Job Groups and their Job Definitions, and fusionCore creates the rest each time a group runs.

| **Object** | **What it represents** | **Who creates it** |
| - | - | - |
| **Job Group** (`Job_Group__c`) | An ordered set of steps, with a schedule and an active flag. | You |
| **Job Definition** (`Job_Definition__c`) | One step in a Job Group: its Apex class, batch size, and ordering options. | You |
| **Job Run** (`Job_Run__c`) | One execution of a Job Group, with an overall status and error count. | fusionCore |
| **Job Run Stage** (`Job_Run_Stage__c`) | One step's execution within a run. Each stage is its own batch job. | fusionCore |
| **Job Error** (`Job_Error__c`) | One failure: the message, the record involved, and the details. | fusionCore |

## What You Can Use It For

Use the coordinator when automation is too large or too interdependent for a single batch job. Typical patterns:

* Multi-step, high-volume processing that must stay within Salesforce limits.
* Chains where a later step depends on the output of an earlier step.
* Fan-out work spread across several concurrent batches.
* Scheduled data maintenance that needs per-record error tracking and an automatic retry.

For a complete walkthrough, see [Async Job Coordinator Example](https://docs.fusioncore.us/end-user-guides/platform-setup/async-job-coordinator/example.md).

## Where to Find It

From the **App Launcher**: search for **Job Groups**, **Job Definitions**, **Job Runs**, **Job Run Stages**, or **Job Errors**.

You create and edit Job Groups in the **Job Group Manager**, which opens when you click **New** or **Edit** on the Job Groups tab. See [Managing Job Groups](https://docs.fusioncore.us/end-user-guides/platform-setup/async-job-coordinator/managing-job-groups.md).

## Permissions

The **FC Platform - Manage Async Jobs** permission set grants full access to the five objects and their tabs, and access to the Job Group Manager.

## How a Run Works

A run starts from the Job Group's schedule, or from code (see [For Developers](#for-developers)).

When a run starts, fusionCore creates one Job Run in **Pending** status and one Pending Job Run Stage for each Job Definition. Each stage then runs as its own batch job.

### Ordering Options

Each Job Definition has these settings:

| **Setting** | **What it does** |
| - | - |
| **Sequence** | The order of the step. The lowest Sequence starts first. Sequence alone does **not** make later steps wait. They start as batch capacity allows. |
| **Batch Size** | The number of records per batch, from 1 to 2000. The default is 200. |
| **Await Stage Completion** | Makes every later step wait until this step, including any substages, finishes. Turn it on whenever a later step depends on this step's output. |
| **Parallel Substage Processing** | Turns the step into a container for substages that run as concurrent batches when slots are free. The previous step's code creates the substages, or fusionCore creates them automatically from a previous parallel step's successful records. |

### Batch Capacity

The coordinator starts a stage only when a batch slot is free. It counts every Batch Apex job in the org that is Processing, Preparing, or Queued, not only its own.

* The ceiling is the lower of the **FC: Async Coordinator Max Jobs** constant and 4. The shipped value is 3.
* Salesforce keeps one slot in reserve, so the effective maximum is 4.
* Stages that cannot start stay **Pending**. The coordinator checks again only when another stage of the same run finishes.

To change the limit, open **Setup**, go to **Custom Metadata Types**, open **Constant**, click **Manage Records**, and edit **FC: Async Coordinator Max Jobs**. The coordinator never uses more than 4 batch slots, so values above 4 have no effect.

### Errors and the Automatic Retry

Two kinds of failure can occur, and they behave differently:

| **Failure** | **What you see** | **Retried?** |
| - | - | - |
| A record the step reports as failed | One Job Error with the record's Id and a message. | Yes, once. |
| An unhandled exception in a batch chunk | One Job Error with the message, a stack trace, and the failing chunk's data. No record Id. | No. |

A stage with errors ends **Completed with Errors**, and the run continues with the other stages. After all regular stages finish, fusionCore retries once:

* It creates retry stages for the failed step and for every later step.
* The failed record Ids go to the first retry stage.
* Records that succeed on retry have their Job Errors deleted and move on to the next retry stage.
* A retry that fails again does not trigger another retry.

### Job Run Statuses

A Job Run moves through **Pending**, **In Progress**, and then **Completed Successfully** or **Completed with Errors**. It ends **Completed with Errors** when **Number Of Errors** is greater than 0.

Stages use the same four values. A stage's **Completed with Errors** means that stage logged errors. See [Monitoring Job Runs](https://docs.fusioncore.us/end-user-guides/platform-setup/async-job-coordinator/monitoring-job-runs.md) for detail.

## For Developers

Each Job Definition points to an Apex class that implements the global interface `FCORE_BASE.JobExecutor`. Until a developer deploys at least one such class, the **Apex Class** dropdown in the Job Group Manager is empty.

### Class Requirements

* Declare the class `global` and concrete.
* Implement all six interface methods. Return `null` from the ones you do not use.

### Interface Methods

| **Method** | **Purpose** |
| - | - |
| `getQueryLocator(context)` | Returns the records for a regular stage as a `Database.QueryLocator`. |
| `getIterable(context)` | Returns the records as an `Iterable<Object>`. Return one of the two methods and `null` from the other. If both return `null`, the stage has no records. |
| `execute(scope, context)` | Processes one batch. Returns a `FCORE_BASE.JobRunStageResult`, or `null` if there is nothing to report. |
| `getRetryQueryLocator(context)` | Returns the records for a retry stage. The retry stage's Context 1 (`FCORE_BASE__Context_1__c`) holds the record Ids to retry as a JSON list. |
| `getRetryIterable(context)` | The `Iterable<Object>` counterpart for retry stages. |
| `executeRetry(scope, context)` | Processes one retry batch. Returns a `FCORE_BASE.JobRunStageResult` that lists the records that succeeded. |

### Context and Result Objects

`FCORE_BASE.JobRunStageContext` has one member: `stage`, the current Job Run Stage record. It includes the stage's **Context 1** and **Context 2** and the Job Run's **Global Context 1** and **Global Context 2**.

Create a result with `new FCORE_BASE.JobRunStageResult(context)`. Its members:

| **Member** | **Purpose** |
| - | - |
| `recordErrors` | A list of `JobRunStageResult.RecordError` items, each with `recordId` and `errorMessage`. Each item becomes one Job Error. |
| `successfullyRetriedRecordIds` | Used in `executeRetry`. Resolves those records' Job Errors and forwards the Ids to the next retry stage. |
| `updateGlobalContext`, `globalContext1`, `globalContext2` | Writes values to the Job Run's Global Context fields for later steps to read. |
| `createNextStageSubsequence`, `nextStageSubsequenceContext1`, `nextStageSubsequenceContext2` | Creates a substage for a following Parallel Substage Processing step. |

### Start a Run from Code

Call `FCORE_BASE.JobRunService.createAndRunJob` with the Job Group's Id:

```java theme={null}
// jobGroupId: Id of a Job Group; recordIds: Set<Id>
FCORE_BASE.JobRunService.createAndRunJob(jobGroupId);

// Optionally seed Global Context 1 with a set of record Ids (stored as JSON)
FCORE_BASE.JobRunService.createAndRunJob(jobGroupId, recordIds);
```

If the group is inactive, the call fails with `Cannot start job. Job Group is inactive.` If the group has no Job Definitions, no run is created and fusionCore logs `Failed to run job. Job Group is missing Job Definitions.`

For complete, working classes, see [Async Job Coordinator Example](https://docs.fusioncore.us/end-user-guides/platform-setup/async-job-coordinator/example.md).

## Related Features

> [card] [Managing Job Groups](https://docs.fusioncore.us/end-user-guides/platform-setup/async-job-coordinator/managing-job-groups.md)
>
> Create, schedule, change, and delete Job Groups.

> [card] [Monitoring Job Runs](https://docs.fusioncore.us/end-user-guides/platform-setup/async-job-coordinator/monitoring-job-runs.md)
>
> Read run statuses, stages, and errors.

> [card] [Async Job Coordinator Example](https://docs.fusioncore.us/end-user-guides/platform-setup/async-job-coordinator/example.md)
>
> Follow a complete three-step example.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.