---
title: Jobs
description: Inspect and control long-running Chronicle Kernel operations such as replays and rebuilds.
---

import { Tabs, TabItem } from '@astrojs/starlight/components';


Jobs represent long-running operations the Chronicle Kernel performs in the background — replaying a projection, rebuilding a read model, and similar work that runs in steps over time rather than completing instantly. Use the jobs API to see what's running, check progress, and stop, resume, or delete a job.

## List all jobs

<Tabs syncKey="chronicle-client">
<TabItem label="C#">

```csharp
using Cratis.Chronicle;
using Cratis.Chronicle.Jobs;

public class JobsIndexListAll(IEventStore eventStore)
{
    public async Task<IEnumerable<Job>> GetAllJobs() => await eventStore.Jobs.GetJobs();
}
```

</TabItem>
<TabItem label="Kotlin">

```text
Kotlin does not support this workflow yet.
```

</TabItem>
<TabItem label="Java">

```text
Java does not support this workflow yet.
```

</TabItem>
<TabItem label="Elixir">

```elixir
defmodule MyApp.JobsIndexListAll do
  def get_all_jobs do
    Chronicle.Jobs.all()
  end
end
```

</TabItem>
<TabItem label="TypeScript">

```typescript
import { IEventStore } from '@cratis/chronicle';
import { Job } from '@cratis/chronicle.contracts';

class JobsIndexListAll {
    constructor(private readonly store: IEventStore) {}

    async getAllJobs(): Promise<Job[]> {
        return this.store.jobs.getJobs();
    }
}
```

</TabItem>
</Tabs>

## Get a single job

<Tabs syncKey="chronicle-client">
<TabItem label="C#">

```csharp
using Cratis.Chronicle;
using Cratis.Chronicle.Jobs;

public class JobsIndexGetOne(IEventStore eventStore)
{
    public async Task<Job?> GetJob(JobId jobId) => await eventStore.Jobs.GetJob(jobId);
}
```

</TabItem>
<TabItem label="Kotlin">

```text
Kotlin does not support this workflow yet.
```

</TabItem>
<TabItem label="Java">

```text
Java does not support this workflow yet.
```

</TabItem>
<TabItem label="Elixir">

```elixir
defmodule MyApp.JobsIndexGetOne do
  def get_job(job_id) do
    Chronicle.Jobs.get(job_id)
  end
end
```

</TabItem>
<TabItem label="TypeScript">

```typescript
import { IEventStore } from '@cratis/chronicle';
import { Job } from '@cratis/chronicle.contracts';

class JobsIndexGetOne {
    constructor(private readonly store: IEventStore) {}

    async getJob(jobId: string): Promise<Job | undefined> {
        return this.store.jobs.getJob(jobId);
    }
}
```

</TabItem>
</Tabs>

A missing job resolves to nothing rather than an error — check for that before using the result.

## Get the steps for a job

A job is made up of one or more steps. Get them to see fine-grained progress:

<Tabs syncKey="chronicle-client">
<TabItem label="C#">

```csharp
using Cratis.Chronicle;
using Cratis.Chronicle.Jobs;

public class JobsIndexGetSteps(IEventStore eventStore)
{
    public async Task<IEnumerable<JobStep>?> GetSteps(JobId jobId)
    {
        var job = await eventStore.Jobs.GetJob(jobId);
        return job is null ? null : await job.GetJobSteps();
    }
}
```

</TabItem>
<TabItem label="Kotlin">

```text
Kotlin does not support this workflow yet.
```

</TabItem>
<TabItem label="Java">

```text
Java does not support this workflow yet.
```

</TabItem>
<TabItem label="Elixir">

```elixir
defmodule MyApp.JobsIndexGetSteps do
  def get_steps(job_id) do
    Chronicle.Jobs.steps(job_id)
  end
end
```

</TabItem>
<TabItem label="TypeScript">

```typescript
import { IEventStore } from '@cratis/chronicle';
import { JobStep } from '@cratis/chronicle.contracts';

class JobsIndexGetSteps {
    constructor(private readonly store: IEventStore) {}

    async getSteps(jobId: string): Promise<JobStep[]> {
        return this.store.jobs.getJobSteps(jobId);
    }
}
```

</TabItem>
</Tabs>

## Stop, resume, and delete

<Tabs syncKey="chronicle-client">
<TabItem label="C#">

```csharp
using Cratis.Chronicle;
using Cratis.Chronicle.Jobs;

public class JobsIndexStopResumeDelete(IEventStore eventStore)
{
    public async Task StopJob(JobId jobId) => await eventStore.Jobs.Stop(jobId);

    public async Task ResumeJob(JobId jobId) => await eventStore.Jobs.Resume(jobId);

    public async Task DeleteJob(JobId jobId) => await eventStore.Jobs.Delete(jobId);
}
```

</TabItem>
<TabItem label="Kotlin">

```text
Kotlin does not support this workflow yet.
```

</TabItem>
<TabItem label="Java">

```text
Java does not support this workflow yet.
```

</TabItem>
<TabItem label="Elixir">

```elixir
defmodule MyApp.JobsIndexStopResumeDelete do
  def stop_job(job_id), do: Chronicle.Jobs.stop(job_id)
  def resume_job(job_id), do: Chronicle.Jobs.resume(job_id)
  def delete_job(job_id), do: Chronicle.Jobs.delete(job_id)
end
```

</TabItem>
<TabItem label="TypeScript">

```typescript
import { IEventStore } from '@cratis/chronicle';

class JobsIndexStopResumeDelete {
    constructor(private readonly store: IEventStore) {}

    async stopJob(jobId: string): Promise<void> {
        await this.store.jobs.stop(jobId);
    }

    async resumeJob(jobId: string): Promise<void> {
        await this.store.jobs.resume(jobId);
    }

    async deleteJob(jobId: string): Promise<void> {
        await this.store.jobs.delete(jobId);
    }
}
```

</TabItem>
</Tabs>

Kotlin and Java don't currently have a jobs API — there's no equivalent anywhere in the Kotlin client SDK yet.

## Related topics

- [Webhooks](/chronicle/webhooks/) — pushing observed events to external HTTP endpoints, the other kernel-managed background concern.
