import type { Pool } from "pg"; import type { JSONWithUndefined } from "type-party"; import type { CacheSpec } from "../../types/00_CacheSpec.js"; import type { AnyValidators } from "../../types/02_Validators.js"; import type { NormalizedParams } from "../../types/06_Normalization.js"; import type { StoreGetManyResult } from "../../types/06_Store.js"; import type { EntryForId, Logger, Store, StoreEntryInput, StoreGetManyRequest } from "../../types/index.js"; /** * When we match `vary` values when retrieving entries, we currently query: * `vary <@ $params`, which means: "is the `vary` JSON value fully contained in * the params". This gives the correct result when the param and vary values are * _primitives_ (i.e., it asks: "does the request contain a superset of the * params, with matching values, that the response varied on"). But, it would * not work if the param or vary values are objects/arrays. For example: * * {"a": {"b": {"c": "c"}}} is contained in {"a": {"b": {"c": "c", "d": "d"}}} * according to this operator. * * But, the rules of `vary` say that the value of param `b` has to match exactly * the value of `vary.b`. I.e., we want containment only at the top level and * then check for equality at deeper levels. To do that, we could use ? and = * operators while iterating over the vary keys, but, since we're not * implementing that for now, we restrict this store to a set of param values * that are safe. */ export type PostgresStoreSupportedParams = { [paramName: string]: string | number | boolean | undefined; }; /** * The constraint that PostgresStore places on a `Spec`'s `content`: must be * JSON-serializable (potentially with undefined values present, since those * are stripped on serialization). */ export type PostgresStoreCompatibleSpec = CacheSpec; /** * This class implements a store for cache entries, backed by Postgres. For * details on each method, see the Store interface. * * Each row in the table is a separate cache entry, uniquely identified by * (resourceId, vary) pair. Each of these rows stores the id (string), vary * (jsonb), and a full entry (jsonb). * * We do not use any mechanisms to speed up the entry lookup aside from an index * on the vary column. We rely on Postgres to be fast enough for our needs. */ export default class PostgresStore implements Store { /** Object containing info about the schema and table name */ private readonly tableNameData; private readonly db; /** Promise that resolves when the required tables are initialized */ private ensureInitializedPromise; private readonly logInfo; private readonly logTrace; private readonly logError; private readonly logWarn; /** * @param pool - The postgres pool to use * @param opts.schemaName - The name of the schema to use * @param opts.tableName - The name of the table to use * @param opts.logger - Optional custom logger to use. Defaults to using * the debug module with the @zingage/cache:postgres-store namespace */ constructor(pool: Pool, opts: { schemaName: string; tableName: string; logger?: Logger; assumeIsInitialized?: boolean; }); get(id: Id, params: Readonly>, options?: { signal?: AbortSignal; }): Promise[]>; getMany[]>(requests: Reqs, options?: { signal?: AbortSignal; }): Promise>; store(entries: readonly StoreEntryInput[]): Promise; delete(id: Spec["id"]): Promise; [Symbol.asyncDispose](): Promise; private getTableNameData; private get tableName(); /** * Initialize the database schema and table if they don't exist. * This is called automatically in the constructor. */ private ensureInitialized; private serializeEntry; private serializeVary; private deserializeEntry; } //# sourceMappingURL=PostgresStore.d.ts.map