API reference@evolu/commonResource › SharedResourceByKey

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

Shared Resources keyed by logical identity.

A map-like registry of SharedResources. Each key owns at most one current resource instance. The first acquire for a key lazily creates that key's resource; releasing the key's last Lease disposes it and removes the key from the registry.

Different keys are independent and may progress concurrently. Operations for the same key are serialized.

By default, keys use reference identity, matching native Map. Callers may instead provide a lookup so logical equality is based on a derived stable key.

Example

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

interface Connection extends Disposable {
  readonly ownerId: string;
  readonly send: (message: string) => void;
  readonly flush: () => ReadonlyArray<string>;
}

const createConnection =
  (ownerId: string): Task<Connection> =>
  () => {
    const pendingMessages: Array<string> = [];
    return ok({
      ownerId,
      send: (message) => {
        pendingMessages.push(message);
      },
      flush: () => pendingMessages.splice(0),
      [Symbol.dispose]: () => {},
    });
  };

await using run = createRun();
await using connections = await run.ok(
  createSharedResourceByKey(createConnection, {
    idleDisposeAfter: "30s",
  }),
);
const send = (ownerId: string, message: string): Task<void> =>
  connections.use(ownerId, (connection) => () => {
    connection.send(message);
    return ok();
  });

// Same-key calls share one connection. Work for different keys remains
// independent, so all three operations can run concurrently.
await run.ok(
  all(
    [
      send("owner-1", "first"),
      send("owner-1", "second"),
      send("owner-2", "hello"),
    ],
    { concurrency: 3 },
  ),
);

// `acquireCurrent` does not create absent keys. The idle delay keeps the two
// existing connections available to enumerate and flush.
using missingLease = await run.ok(connections.acquireCurrent("owner-3"));
const messagesByOwnerId = new Map<string, ReadonlyArray<string>>();
await run.ok(
  connections.forEachCurrent((connection) => {
    messagesByOwnerId.set(connection.ownerId, connection.flush());
  }),
);

assertSame(missingLease, undefined);
assertEqual(
  messagesByOwnerId,
  new Map([
    ["owner-1", ["first", "second"]],
    ["owner-2", ["hello"]],
  ]),
);

Extends

Methods

[asyncDispose]()

asyncDispose: PromiseLike<void>;

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

Inherited from

AsyncDisposable.[asyncDispose]

Properties

acquire

readonly acquire: (key: K) => Task<Lease<T>>;

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

Acquires a Lease on the shared resource for key, creating the resource on first use.

The same contract as SharedResource.acquire: once started, acquire runs to completion even when the caller aborts its Fiber, and the returned lease still counts as held. Registry disposal before lease transfer aborts the acquisition. Always await the result and release the lease.

acquireCurrent

readonly acquireCurrent: (key: K) => Task<
  | Lease<T>
| undefined>;

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

Acquires a Lease on the current resource for key without creating one.

Waits for preceding creation or disposal for the same key to finish. Returns undefined if no current resource remains. Registry disposal while waiting aborts the acquisition before a lease is transferred. Registry disposal after transfer can drain the lease before the caller resumes, matching SharedResource.acquireCurrent.

forEachCurrent

readonly forEachCurrent: (callback: (resource: DistributiveOmit<T>, key: K) => void) => Task<void>;

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

Calls callback for each current resource it can lease from keys registered when this Task starts.

Never creates resources. A resource whose creation is in progress may be included after creation finishes; one disposed before its temporary lease is acquired is skipped. Each acquired lease stays held while later keys are awaited, and every callback runs while all acquired resources remain leased. Caller abort is observed between keys; already-collected leases are released and no callbacks run.

snapshot

readonly snapshot: () => SharedResourceByKeySnapshot<K>;

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

Returns current per-key shared-resource states for monitoring/debugging.

use

readonly use: <R, E, D>(key: K, callback: (resource: DistributiveOmit<T>, created: boolean) => Task<R, E, D>) => Task<R, E, D>;

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

Acquires a Lease, runs a Task with the shared resource for key, and releases the lease after the Task settles.

Creates the resource when absent. The callback receives whether this use created the resource generation. While the registry remains running, the lease prevents ordinary idle disposal. Disposing this registry is forceful: it drains the lease and may dispose the resource before or while the callback Task runs.