@clickup/ent-framework
Version:
A PostgreSQL graph-database-alike library with microsharding and row-level security
84 lines • 4.24 kB
TypeScript
import type { Client } from "../abstract/Client";
import type { Cluster } from "../abstract/Cluster";
import type { Shard } from "../abstract/Shard";
import type { Table } from "../types";
import type { Inverse } from "./Inverse";
import type { ShardAffinity } from "./ShardAffinity";
import type { VC } from "./VC";
/**
* Knows how to locate Shard(s) based on various inputs. In some contexts, we
* expect exactly one Shard returned, and in other contexts, multiple Shards are
* okay.
*/
export declare class ShardLocator<TClient extends Client, TTable extends Table, TField extends string> {
private cluster;
private entName;
private shardAffinity;
private uniqueKey;
private inverses;
private globalShard;
private idAndShardAffinity;
constructor({ cluster, entName, shardAffinity, uniqueKey, inverses, }: {
cluster: Cluster<TClient>;
entName: string;
shardAffinity: ShardAffinity<TField>;
uniqueKey: readonly string[] | undefined;
inverses: ReadonlyArray<Inverse<TClient, TTable>>;
});
/**
* Called in a context when we must know exactly 1 Shard to work with (e.g.
* INSERT, UPSERT etc.). If op === "insert" (fallback to random Shard), then
* returns a random Shard in case when it can't infer the Shard number from
* the input (used in e.g. INSERT operations); otherwise throws ShardError
* (happens in e.g. UPSERT).
*
* The "randomness" of the "random Shard" is deterministic by the Ent's unique
* key (if it's defined), so Ents with the same unique key will map to the
* same "random" Shard (considering the total number of discovered Shards is
* unchanged). Notice that this logic applies at INSERT time: since we often
* times add Shards to the Cluster, we can't rely on it consistently at SELECT
* time (but relying at INSERT time is more or less fine: it protects against
* most of "unique key violation" problems, although still doesn't prevent all
* of them for a fraction of the second when the number of Shards has just
* been changed).
*/
singleShardForInsert(input: Record<string, unknown>, op: "insert" | "upsert"): Promise<Shard<TClient>>;
/**
* Called in a context when multiple Shards may be involved, e.g. when
* selecting Ents referred by some Inverses. May also return the empty list of
* Shards when, although there are fields with Inverses in input (i.e. the
* filtering is correct), there are no Inverse rows existing in the database.
*/
multiShardsFromInput(vc: VC, input: Record<string, unknown>, op: string): Promise<Array<Shard<TClient>>>;
/**
* A wrapper for Cluster#shard() which injects Ent name to the exception (in
* case of e.g. "Cannot locate Shard" exception). This is just a convenience
* for debugging.
*
* If this method returns null, that means the caller should give up trying to
* load the Ent with this ID, because it won't find it anyways (e.g. when we
* try to load a sharded Ent using an ID from the global Shard). This is
* identical to the case of an Ent not existing in the database.
*/
singleShardFromID(field: string, id: string | null | undefined, op: string): Promise<Shard<TClient> | null>;
/**
* All shards for this particular Ent depending on its affinity.
*/
allShards(): Promise<ReadonlyArray<Shard<TClient>>>;
/**
* Infers Shard number from shardAffinity info and the input record.
* - Returns null if it can't do this; the caller should likely throw in this
* case (although not always).
* - If a field's value is an array of IDs from multiple Shards, then returns
* the 1st inferred Shard still. This is the current limitation: we don't
* even try to infer multiple Shards if we have some affinity fields in the
* request, which e.g. simplifies Ent creation logic. Cross-Shard logic is
* only enabled when using Inverses; see multiShardsFromInput().
*/
private singleShardFromAffinity;
/**
* A helper to build uniform ShardError error messages.
*/
private buildShardErrorMessage;
}
//# sourceMappingURL=ShardLocator.d.ts.map