API reference@evolu/commonTask › firstNSettled

function firstNSettled<TTasks>(
  tasks: TTasks,
  count: Int1To100OrPositiveInt,
  options?: TaskCollectionOptions,
): Task<
  readonly InferTasksResult<TTasks>[],
  never,
  ParameterIntersection<
    TTasks[number] extends TTask
      ? TTask extends AnyTask
        ? (deps: InferTaskDeps<TTask>) => void
        : never
      : never
  >
>;

Defined in: packages/common/src/Task.ts:4527

Runs Tasks until count Tasks settle or all Tasks settle.

Returns Ok with Task Results in settlement order, not input order. When count Results have settled, queued Tasks are not started and remaining running Tasks are aborted. If fewer than count Tasks settle, returns the Results that did settle.

Sequential by default; pass a concurrency option to run more than one Task at a time. The count uses Int1To100OrPositiveInt: pass 1 to 100 as a literal, or a validated PositiveInt for larger values.

Example

import {
  assertFalse,
  assertOk,
  createRun,
  err,
  firstNSettled,
  ok,
  sleep,
  type Task,
  type Typed,
} from "@evolu/common";

let slowCompleted = false;
const slow: Task<string> = async (run) => {
  await run.ok(sleep("10ms"));
  slowCompleted = true;
  return ok("slow");
};
const unavailable: Task<never, ServiceUnavailableError> = () =>
  err({ type: "ServiceUnavailable" });

interface ServiceUnavailableError extends Typed<"ServiceUnavailable"> {}

const tasks = [slow, unavailable, () => ok("fast")] as const;
await using run = createRun();

// Err and Ok both count, and Results use settlement order.
const result = await run(firstNSettled(tasks, 2, { concurrency: 3 }));
assertOk(result, [
  { ok: false, error: { type: "ServiceUnavailable" } },
  { ok: true, value: "fast" },
]);
assertFalse(slowCompleted);