API reference › @evolu/common › Resource › SharedResourceByKeyWithClaims
Defined in: packages/common/src/Resource.ts:979
Shared keyed Resources retained through claims.
A claim identifies an application-level owner such as an account, tenant, or open document. Resource keys identify the shared resources that owner needs, such as relay URLs, database names, or worker IDs.
Use this abstraction when each owner needs a set of keyed resources and those sets can overlap. Calling SharedResourceByKeyWithClaims.claim | claim retains every resource in one owner's set. Overlapping owners share one resource instance per key, and the resource remains alive until every ClaimLease retaining that key is released.
Relation queries reflect active claims, not physical resource liveness. With
idleDisposeAfter, a resource can outlive its last claim.
Use SharedResourceByKey instead when callers only need independent leases by key and the application does not need to associate those leases with logical owners.
Two accounts can share a relay connection while one also uses a local-network transport:
import {
assertEqual,
createRun,
createSharedResourceByKeyWithClaims,
ok,
type Brand,
type Task,
} from "@evolu/common";
type AccountId = string & Brand<"AccountId">;
type TransportUrl = string & Brand<"TransportUrl">;
interface Connection extends Disposable {
readonly url: TransportUrl;
}
const createConnection =
(url: TransportUrl): Task<Connection> =>
() =>
ok({
url,
[Symbol.dispose]: () => {},
});
// These literals stand in for values validated at application boundaries.
const accountA = "account-a" as AccountId;
const accountB = "account-b" as AccountId;
const relay = "wss://relay.example.com" as TransportUrl;
const localNetwork = "ws://local-network" as TransportUrl;
await using run = createRun();
await using transports = await run.ok(
createSharedResourceByKeyWithClaims<TransportUrl, AccountId, Connection>(
createConnection,
),
);
{
// Account A retains both transports.
using _accountATransports = await run.ok(
transports.claim(accountA, [relay, localNetwork]),
);
{
// Account B reuses the relay already retained by account A.
using _accountBRelay = await run.ok(transports.claim(accountB, [relay]));
assertEqual(
transports.getClaimsForResource(relay),
new Set([accountA, accountB]),
);
assertEqual(
transports.getResourceKeysForClaim(accountA),
new Set([relay, localNetwork]),
);
}
// Releasing account B leaves account A's relay retain intact.
assertEqual(transports.getClaimsForResource(relay), new Set([accountA]));
}
// Releasing the final claim removes the relation for both transports.
assertEqual(transports.getClaimsForResource(relay), new Set<AccountId>());
assertEqual(
transports.getClaimsForResource(localNetwork),
new Set<AccountId>(),
);
Extends
Methods
[asyncDispose]()
asyncDispose: PromiseLike<void>;
Defined in: node_modules/@typescript/old/lib/lib.esnext.disposable.d.ts:38
Inherited from
AsyncDisposable.[asyncDispose]
Properties
claim
readonly claim: (claim: C, resourceKeys: readonly [K, K]) => Task<ClaimLease>;
Defined in: packages/common/src/Resource.ts:997
Retains every resource key for claim, creating absent resources lazily.
Keys are snapshotted when this Task starts and acquired sequentially in input order.
resourceKeys must not contain logical duplicates according to
SharedResourceByKeyWithClaimsOptions.resourceLookup. A duplicate is
a programmer defect that panics the owning Run.
The returned ClaimLease releases all retains added by this call. Resource creation must succeed, so this Task has no recoverable error.
forEachResourceForClaim
readonly forEachResourceForClaim: (claim: C, callback: (resource: DistributiveOmit<T>, resourceKey: K) => void) => void;
Defined in: packages/common/src/Resource.ts:1046
Calls callback for each current resource retained by claim.
The keys and resources are snapshotted before the first callback runs. Resources remain valid until this synchronous iteration returns, even if a callback releases the final retaining ClaimLease. Callbacks must not retain or asynchronously use borrowed resources afterward. Does nothing when the claim retains no resources, including after this registry is disposed.
getClaimsForResource
readonly getClaimsForResource: (resourceKey: K) => ReadonlySet<C>;
Defined in: packages/common/src/Resource.ts:1027
Returns the current unique claims retaining resourceKey.
Returns an empty snapshot when no claim retains the key, including after this registry is disposed.
getResourceKeysForClaim
readonly getResourceKeysForClaim: (claim: C) => ReadonlySet<K>;
Defined in: packages/common/src/Resource.ts:1035
Returns the current unique resource keys retained by claim.
Returns an empty snapshot when the claim retains no keys, including after this registry is disposed.
snapshot
readonly snapshot: () => SharedResourceByKeyWithClaimsSnapshot<K, C>;
Defined in: packages/common/src/Resource.ts:1058
Returns current claim-retain and keyed-resource states.
While a claim is acquiring keys, resourcesByKey can include inner leases
not yet reflected by claimLeaseCount or
retainCountsByResourceKeyByClaim.
use
readonly use: <R, E, D>(claim: C, resourceKeys: readonly [K, K], callback: (resources: readonly [readonly [DistributiveOmit<T, typeof dispose | typeof asyncDispose>, K], readonly [DistributiveOmit<T, typeof dispose | typeof asyncDispose>, K]]) => Task<R, E, D>) => Task<R, E, D>;
Defined in: packages/common/src/Resource.ts:1013
Retains every resource key for claim, runs a Task with those resources,
and releases the resulting ClaimLease after the Task settles.
The callback receives only the resources retained by this call, in input order. Other active ClaimLeases for the same logical claim are excluded. While this registry remains running, every borrowed resource remains valid until the callback Task settles. Disposing this registry is forceful: it drains the ClaimLease and may dispose resources before or while the callback Task runs.