API reference › @evolu/common › Resource › ResettableResource

Defined in: packages/common/src/Resource.ts:577

A Resource reset in place.

Holds one current resource and resets it on request: the current resource is disposed first, then create runs again. At most one resource exists, and there is an observable gap with none. Consumers keep the ResettableResource and read the current resource through get, so a reset needs no re-registration. A resource that cannot reset itself is the case for it. One that can, as WebSocket.reconnect does, keeps a stable identity and needs no wrapper.

The ResettableResource keeps a stable identity while its current resource changes. SharedResourceByKeyWithClaims can retain it directly; consumers read the current resource through get.

Repeated async disposal calls await the same cleanup and preserve any disposal failure.

Example

import {
  assertEqual,
  assertSame,
  createRun,
  createResettableResource,
  ok,
  type Task,
} from "@evolu/common";

interface Connection extends Disposable {
  readonly id: number;
  readonly isClosed: () => boolean;
}

let nextId = 1;
const createConnection: Task<Connection> = () => {
  const id = nextId++;
  let isClosed = false;
  return ok({
    id,
    isClosed: () => isClosed,
    [Symbol.dispose]: () => {
      isClosed = true;
    },
  });
};

await using run = createRun();
await using connection = await run.ok(
  createResettableResource(createConnection),
);
const first = connection.get();
assertEqual(first?.id, 1);

await run.ok(connection.reset(first));
assertSame(first?.isClosed(), true);
assertEqual(connection.get()?.id, 2);

Extends

Methods

[asyncDispose]()

[asyncDispose](): PromiseLike<void>;

Defined in: node_modules/@typescript/old/lib/lib.esnext.disposable.d.ts:38

Inherited from

AsyncDisposable.[asyncDispose]

Properties

get

readonly get: () =>
  | DistributiveOmit<T, typeof dispose | typeof asyncDispose>
  | undefined;

Defined in: packages/common/src/Resource.ts:586

Returns the current resource, or undefined when there is none: while a reset is in progress, after a reset whose creation aborted, and after disposal. Callers treat every absence alike, as the resource's own not-ready state.


reset

readonly reset: (observed:
  | DistributiveOmit<T, typeof dispose | typeof asyncDispose>
| undefined) => Task<void>;

Defined in: packages/common/src/Resource.ts:609

Resets the current resource: disposes it, then creates the next one.

A reset is requested because observed misbehaved, and it runs only while observed is still current or there is no current resource. A request that finds a different resource current returns without resetting, so every observer of one dead resource shares one reset, however late its request arrives. An observed of undefined is an observation of absence, as get returns during a reset: the request runs only while nothing is current, so it retries an aborted creation and skips once a replacement exists.

Resets are serialized. Owner disposal aborts a pending reset with runDisposedAbortReason, and a resource that create returns after disposal started is disposed and never becomes current.

Resets follow the resource-owned Run's lifecycle: an abort request can cancel them, and calling reset after that Run starts disposal is a programmer error. Aborting the caller's Fiber does not cancel a started reset; dependencies remain those captured at creation.