[API reference](https://evolu.dev/docs/api-reference) › [@evolu/common](https://evolu.dev/docs/api-reference/common) › [Task](https://evolu.dev/docs/api-reference/common/Task) › Run

Defined in: [packages/common/src/Task.ts:578](https://github.com/evoluhq/evolu/blob/e7144e2bbe9069362b62dec1b64a8aa922b8f1b0/packages/common/src/Task.ts#L578)

Runs a [Task](https://evolu.dev/docs/api-reference/common/Task/type-aliases/Task) with
[structured concurrency](https://en.wikipedia.org/wiki/Structured_concurrency)
semantics.

Each `Run` forms a Task tree: child Tasks are bound to it, abort propagates
through that tree, and state is observable via snapshots and events.

`Run` is a callable object — callable because it's convenient to run Tasks as
`run(task)`, and an object because it holds state.

Calling `run(task)` creates a child `Run`, passes it to the Task, and returns
a [Fiber](https://evolu.dev/docs/api-reference/common/Task/interfaces/Fiber). The child is tracked in `getChildren()`/events while running,
then disposed and removed when settled.

Before Task execution, `run(task)` applies two short-circuit checks:

- If this Run is not `Running`, the child is aborted with
  [runStoppedError](https://evolu.dev/docs/api-reference/common/Task/variables/runStoppedError) and the Task is replaced with `err(AbortError)`.
- If this Run's signal is already aborted and the child is abortable
  (`abortMask === 0`), the child is aborted with the same reason and the Task
  is replaced with `err(AbortError)`.

After execution, the child stores both values: `outcome` (what the Task
returned) and `result` (what callers observe). If the child signal is aborted
at settlement time, `result` is forced to `err(AbortError)` even when
`outcome` is `ok(...)`.

That's the whole mechanism: [Task](https://evolu.dev/docs/api-reference/common/Task/type-aliases/Task) is a function that takes a `Run` and
returns an [Awaitable](https://evolu.dev/docs/api-reference/common/Types/type-aliases/Awaitable) [Result](https://evolu.dev/docs/api-reference/common/Result/type-aliases/Result). `run(task)` runs the Task via
`Promise.try(task, run)` with aforementioned logic.

## See

- [createRun](https://evolu.dev/docs/api-reference/common/Task/variables/createRun)
- [Task](https://evolu.dev/docs/api-reference/common/Task/type-aliases/Task)

## Extends

- [`AsyncDisposable`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html#using-declarations-and-explicit-resource-management)

## Methods

<a id="asyncdispose"></a>

### \[asyncDispose\]()

```ts
asyncDispose: PromiseLike<void>;
```

Defined in: node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.disposable.d.ts:40

#### Inherited from

```ts
AsyncDisposable.[asyncDispose]
```

## Properties

<a id="abortmask"></a>

### abortMask

```ts
readonly abortMask: number & Brand<"Int"> & Brand<"NonNegative"> & Brand<"AbortMask">;
```

Defined in: [packages/common/src/Task.ts:617](https://github.com/evoluhq/evolu/blob/e7144e2bbe9069362b62dec1b64a8aa922b8f1b0/packages/common/src/Task.ts#L617)

The abort mask depth. `0` means abortable, `>= 1` means unabortable.

---

<a id="adddeps"></a>

### addDeps

```ts
readonly addDeps: <E>(extraDeps: E) => Run<D & E>;
```

Defined in: [packages/common/src/Task.ts:801](https://github.com/evoluhq/evolu/blob/e7144e2bbe9069362b62dec1b64a8aa922b8f1b0/packages/common/src/Task.ts#L801)

Adds additional dependencies to this Run and returns it.

Use for runtime-created dependencies — dependencies that cannot be created
in the composition root (e.g., app start).

### Example

```ts
// One-shot
await run.addDeps({ db })(getUser(123));

// Multiple deps at once
await run.addDeps({ db, cache })(task);

// Reusable — config comes from outside (message, file, etc.)
type DbWorkerDeps = DbDep; // or DbDep & CacheDep & ...

const init =
  (config: Config): Task<void, InitError, CreateDbDep> =>
  async (run) => {
    const { createDb } = run.deps;
    await using stack = new AsyncDisposableStack();

    const db = stack.use(await run.orThrow(startApp()));
    if (!db.ok) return db;

    const runWithDb = run.addDeps({ db: db.value });

    await runWithDb(getUser(123));
    await runWithDb(insertUser(user));
    return ok();
  };
```

## FAQ

### How does it work?

This is the whole implementation:

```ts
run.addDeps = <E extends NewKeys<E, D>>(newDeps: E): Run<D & E> => {
  depsRef.modify((currentDeps) => {
    const duplicate = Object.keys(newDeps).find((k) => k in currentDeps);
    assert(!duplicate, `Dependency '${duplicate}' already added.`);
    return [undefined, { ...currentDeps, ...newDeps }];
  });
  return self as unknown as Run<D & E>;
};
```

Dependencies are stored in a shared [Ref](https://evolu.dev/docs/api-reference/common/Ref/interfaces/Ref), so `addDeps` propagates to
all runs. The runtime assertion ensures dependencies are created once —
automatic deduplication would mask poor design (dependencies should have a
single, clear point of creation).

### concurrency

```ts
readonly concurrency: Concurrency;
```

Defined in: [packages/common/src/Task.ts:740](https://github.com/evoluhq/evolu/blob/e7144e2bbe9069362b62dec1b64a8aa922b8f1b0/packages/common/src/Task.ts#L740)

#### See

- [Concurrency](https://evolu.dev/docs/api-reference/common/Task/type-aliases/Concurrency)
- [concurrently](https://evolu.dev/docs/api-reference/common/Task/functions/concurrently)

---

<a id="create"></a>

### create

```ts
readonly create: () => Run<D>;
```

Defined in: [packages/common/src/Task.ts:731](https://github.com/evoluhq/evolu/blob/e7144e2bbe9069362b62dec1b64a8aa922b8f1b0/packages/common/src/Task.ts#L731)

Creates a [Run](https://evolu.dev/docs/api-reference/common/Task/interfaces/Run) from this Run.

Like [createRun](https://evolu.dev/docs/api-reference/common/Task/variables/createRun), the returned Run is daemon: it stays running until
disposed. Unlike [createRun](https://evolu.dev/docs/api-reference/common/Task/variables/createRun), it shares the same Deps as this Run.

Use this for long-lived disposable resources that need to own async work.
The resource creates one internal Run with `run.create()` and uses that Run
for all of its work. Disposing the resource then disposes that internal
Run, which aborts in-flight child Tasks, waits for them to settle, and
rejects later calls through it.

Typical examples are database clients, connection pools, workers, or other
reusable resources with async methods and an async dispose operation.

To run a single Task as daemon, use [Run.daemon](https://evolu.dev/docs/api-reference/common/Task/interfaces/Run#daemon).

### daemon

```ts
readonly daemon: Run<D>;
```

Defined in: [packages/common/src/Task.ts:712](https://github.com/evoluhq/evolu/blob/e7144e2bbe9069362b62dec1b64a8aa922b8f1b0/packages/common/src/Task.ts#L712)

The root [Run](https://evolu.dev/docs/api-reference/common/Task/interfaces/Run) of this Task tree.

It is called `daemon` because that is how it should be used: for
long-running work that must not be disposed when the current Task settles.
Normal child Runs are disposed by their parent when they settle. The root
Run has no parent, so work started with `run.daemon(task)` is attached to
that root Run instead of the current Run and keeps running until the root
Run is disposed manually.

In application code, that usually means disposing the root Run on process
shutdown in Node.js or when another platform-specific lifecycle hook is
available. Browsers do not provide a fully reliable app termination hook.

### Example

```ts
const myTask: Task<void, never> = async (run) => {
  // Aborted when myTask ends
  run(helperTask);

  // Outlives myTask, aborted when the root Run is disposed
  const backgroundFiber = run.daemon(backgroundSync);

  // Can still be aborted manually if needed
  backgroundFiber.abort();

  return ok();
};
```

For a long-lived reusable [Run](https://evolu.dev/docs/api-reference/common/Task/interfaces/Run), use [Run.create](https://evolu.dev/docs/api-reference/common/Task/interfaces/Run#create).

---

<a id="deps"></a>

### deps

```ts
readonly deps: ConsoleDep & RandomBytesDep & RandomDep & TimeDep & Partial<RunConfigDep> & D;
```

Defined in: [packages/common/src/Task.ts:734](https://github.com/evoluhq/evolu/blob/e7144e2bbe9069362b62dec1b64a8aa922b8f1b0/packages/common/src/Task.ts#L734)

Returns the dependencies passed to [createRun](https://evolu.dev/docs/api-reference/common/Task/variables/createRun).

---

<a id="getchildren"></a>

### getChildren

```ts
readonly getChildren: () => ReadonlySet<Fiber<any, any, D>>;
```

Defined in: [packages/common/src/Task.ts:645](https://github.com/evoluhq/evolu/blob/e7144e2bbe9069362b62dec1b64a8aa922b8f1b0/packages/common/src/Task.ts#L645)

Returns the current child [Fiber](https://evolu.dev/docs/api-reference/common/Task/interfaces/Fiber)s.

### getState

```ts
readonly getState: () => RunState;
```

Defined in: [packages/common/src/Task.ts:642](https://github.com/evoluhq/evolu/blob/e7144e2bbe9069362b62dec1b64a8aa922b8f1b0/packages/common/src/Task.ts#L642)

Returns the current [RunState](https://evolu.dev/docs/api-reference/common/Task/type-aliases/RunState).

### id

```ts
readonly id: string & Brand<"Id">;
```

Defined in: [packages/common/src/Task.ts:608](https://github.com/evoluhq/evolu/blob/e7144e2bbe9069362b62dec1b64a8aa922b8f1b0/packages/common/src/Task.ts#L608)

Unique [Id](https://evolu.dev/docs/api-reference/common/Type/variables/Id) for this Run.

---

<a id="onabort"></a>

### onAbort

```ts
readonly onAbort: (callback: Callback<unknown>) => void;
```

Defined in: [packages/common/src/Task.ts:639](https://github.com/evoluhq/evolu/blob/e7144e2bbe9069362b62dec1b64a8aa922b8f1b0/packages/common/src/Task.ts#L639)

Registers a callback to run when abort is requested.

This is a convenience wrapper around subscribing to this Run's abort
signal. The callback receives the abort reason extracted from
[AbortError.reason](https://evolu.dev/docs/api-reference/common/Task/interfaces/AbortError#reason) rather than the whole [AbortError](https://evolu.dev/docs/api-reference/common/Task/variables/AbortError).

If already aborted, the callback is invoked immediately. For
[unabortable](https://evolu.dev/docs/api-reference/common/Task/variables/unabortable) Tasks, the callback is never invoked because their
signal never aborts.

Intentionally synchronous and not awaited. The callback runs in the abort
request path, which may already be transitioning this Run to `Disposing` or
`Settled`, so it is too late to start normal Tasks from there.

Use for immediate abort-time reactions such as removing listeners, clearing
timers, removing waiters from queues, or resolving pending promises. Do not
use it for awaited cleanup or resource ownership. For that, use standard
JavaScript resource management with `AsyncDisposableStack`.

### onEvent

```ts
onEvent:
  | ((event: RunEvent) => void)
  | undefined;
```

Defined in: [packages/common/src/Task.ts:677](https://github.com/evoluhq/evolu/blob/e7144e2bbe9069362b62dec1b64a8aa922b8f1b0/packages/common/src/Task.ts#L677)

Callback for monitoring Run events.

Called when this Run or any descendant emits a [RunEvent](https://evolu.dev/docs/api-reference/common/Task/variables/RunEvent). Events
bubble up through parent runs, enabling centralized monitoring. Only
emitted when [RunConfig.eventsEnabled](https://evolu.dev/docs/api-reference/common/Task/interfaces/RunConfig#eventsenabled) is `true`.

---

<a id="orthrow"></a>

### orThrow

```ts
readonly orThrow: <T, E>(task: Task<T, E, D>) => Promise<T>;
```

Defined in: [packages/common/src/Task.ts:605](https://github.com/evoluhq/evolu/blob/e7144e2bbe9069362b62dec1b64a8aa922b8f1b0/packages/common/src/Task.ts#L605)

Runs a [Task](https://evolu.dev/docs/api-reference/common/Task/type-aliases/Task) and throws if the returned [Result](https://evolu.dev/docs/api-reference/common/Result/type-aliases/Result) is an error.

Use this where failure should crash the current flow instead of being
handled locally.

This is the async equivalent of [getOrThrow](https://evolu.dev/docs/api-reference/common/Result/functions/getOrThrow). It runs the Task, awaits
its [Result](https://evolu.dev/docs/api-reference/common/Result/type-aliases/Result), and returns the value on success.

**When to use:**

- Application startup or composition-root setup where errors must stop the
  program immediately. In Evolu apps, errors are handled by
  platform-specific `createRun` adapters at the app boundary.
- Module-level constants
- Test setup with values that are expected to be valid

Prefer `await run(task)` with an explicit `if (!result.ok)` check in
ordinary application logic where the caller can recover, retry, or choose a
different flow.

Throws: `Error` with the original Task error attached as `cause`.

### parent

```ts
readonly parent: Run<D> | null;
```

Defined in: [packages/common/src/Task.ts:611](https://github.com/evoluhq/evolu/blob/e7144e2bbe9069362b62dec1b64a8aa922b8f1b0/packages/common/src/Task.ts#L611)

The parent [Run](https://evolu.dev/docs/api-reference/common/Task/interfaces/Run), if this Run was created as a child.

---

<a id="signal"></a>

### signal

```ts
readonly signal: AbortSignal;
```

Defined in: [packages/common/src/Task.ts:614](https://github.com/evoluhq/evolu/blob/e7144e2bbe9069362b62dec1b64a8aa922b8f1b0/packages/common/src/Task.ts#L614)

#### See

https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal

---

<a id="snapshot"></a>

### snapshot

```ts
readonly snapshot: () => RunSnapshot;
```

Defined in: [packages/common/src/Task.ts:668](https://github.com/evoluhq/evolu/blob/e7144e2bbe9069362b62dec1b64a8aa922b8f1b0/packages/common/src/Task.ts#L668)

Creates a memoized [RunSnapshot](https://evolu.dev/docs/api-reference/common/Task/interfaces/RunSnapshot) of this Run.

Use for monitoring, debugging, or building UI that visualizes Task trees.

### Example

```ts
// React integration with useSyncExternalStore
const useRunSnapshot = (run: Run) =>
  useSyncExternalStore(
    (callback) => {
      run.onEvent = callback;
      return () => {
        run.onEvent = undefined;
      };
    },
    () => run.snapshot(),
  );
```