@workglow/storage 0.2.26 → 0.2.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.js +218 -12
- package/dist/browser.js.map +13 -13
- package/dist/bun.js +703 -24
- package/dist/bun.js.map +18 -17
- package/dist/common-server.d.ts +1 -0
- package/dist/common-server.d.ts.map +1 -1
- package/dist/node.js +703 -24
- package/dist/node.js.map +18 -17
- package/dist/queue/IQueueStorage.d.ts +25 -2
- package/dist/queue/IQueueStorage.d.ts.map +1 -1
- package/dist/queue/InMemoryQueueStorage.d.ts +1 -0
- package/dist/queue/InMemoryQueueStorage.d.ts.map +1 -1
- package/dist/queue/IndexedDbQueueStorage.d.ts +1 -0
- package/dist/queue/IndexedDbQueueStorage.d.ts.map +1 -1
- package/dist/queue/PostgresQueueStorage.d.ts +24 -3
- package/dist/queue/PostgresQueueStorage.d.ts.map +1 -1
- package/dist/queue/SqliteQueueStorage.d.ts +8 -0
- package/dist/queue/SqliteQueueStorage.d.ts.map +1 -1
- package/dist/queue/SupabaseQueueStorage.d.ts +1 -0
- package/dist/queue/SupabaseQueueStorage.d.ts.map +1 -1
- package/dist/queue/TelemetryQueueStorage.d.ts +2 -1
- package/dist/queue/TelemetryQueueStorage.d.ts.map +1 -1
- package/dist/queue-limiter/IRateLimiterStorage.d.ts +46 -0
- package/dist/queue-limiter/IRateLimiterStorage.d.ts.map +1 -1
- package/dist/queue-limiter/InMemoryRateLimiterStorage.d.ts +12 -1
- package/dist/queue-limiter/InMemoryRateLimiterStorage.d.ts.map +1 -1
- package/dist/queue-limiter/IndexedDbRateLimiterStorage.d.ts +28 -1
- package/dist/queue-limiter/IndexedDbRateLimiterStorage.d.ts.map +1 -1
- package/dist/queue-limiter/PostgresRateLimiterStorage.d.ts +4 -1
- package/dist/queue-limiter/PostgresRateLimiterStorage.d.ts.map +1 -1
- package/dist/queue-limiter/SqliteRateLimiterStorage.d.ts +10 -1
- package/dist/queue-limiter/SqliteRateLimiterStorage.d.ts.map +1 -1
- package/dist/queue-limiter/SupabaseRateLimiterStorage.d.ts +6 -1
- package/dist/queue-limiter/SupabaseRateLimiterStorage.d.ts.map +1 -1
- package/dist/tabular/IndexedDbTabularStorage.d.ts.map +1 -1
- package/dist/tabular/SharedInMemoryTabularStorage.d.ts +2 -1
- package/dist/tabular/SharedInMemoryTabularStorage.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/bun.js.map
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/tabular/BaseTabularStorage.ts", "../src/tabular/ITabularStorage.ts", "../src/tabular/StorageError.ts", "../src/tabular/CoveringIndexMissingError.ts", "../src/tabular/CachedTabularStorage.ts", "../src/tabular/InMemoryTabularStorage.ts", "../src/tabular/coveringIndexPicker.ts", "../src/tabular/HuggingFaceTabularStorage.ts", "../src/tabular/TabularStorageRegistry.ts", "../src/util/traced.ts", "../src/tabular/TelemetryTabularStorage.ts", "../src/kv/IKvStorage.ts", "../src/kv/InMemoryKvStorage.ts", "../src/kv/KvStorage.ts", "../src/kv/KvViaTabularStorage.ts", "../src/kv/TelemetryKvStorage.ts", "../src/queue/InMemoryQueueStorage.ts", "../src/queue/IQueueStorage.ts", "../src/queue/TelemetryQueueStorage.ts", "../src/queue-limiter/InMemoryRateLimiterStorage.ts", "../src/queue-limiter/IRateLimiterStorage.ts", "../src/util/HybridSubscriptionManager.ts", "../src/util/PollingSubscriptionManager.ts", "../src/vector/InMemoryVectorStorage.ts", "../src/vector/IVectorStorage.ts", "../src/vector/TelemetryVectorStorage.ts", "../src/credentials/EncryptedKvCredentialStore.ts", "../src/credentials/LazyEncryptedCredentialStore.ts", "../src/tabular/FsFolderTabularStorage.ts", "../src/tabular/PostgresTabularStorage.ts", "../src/tabular/BaseSqlTabularStorage.ts", "../src/tabular/SqliteTabularStorage.ts", "../src/tabular/SupabaseTabularStorage.ts", "../src/kv/FsFolderJsonKvStorage.ts", "../src/kv/FsFolderKvStorage.ts", "../src/kv/PostgresKvStorage.ts", "../src/kv/SqliteKvStorage.ts", "../src/kv/SupabaseKvStorage.ts", "../src/queue/PostgresQueueStorage.ts", "../src/queue/SqliteQueueStorage.ts", "../src/queue/SupabaseQueueStorage.ts", "../src/queue-limiter/PostgresRateLimiterStorage.ts", "../src/queue-limiter/SqliteRateLimiterStorage.ts", "../src/queue-limiter/SupabaseRateLimiterStorage.ts", "../src/vector/PostgresVectorStorage.ts", "../src/vector/SqliteVectorStorage.ts", "../src/vector/SqliteAiVectorStorage.ts", "../src/kv/IndexedDbKvStorage.ts", "../src/tabular/IndexedDbTabularStorage.ts", "../src/util/IndexedDbTable.ts", "../src/queue-limiter/IndexedDbRateLimiterStorage.ts", "../src/queue/IndexedDbQueueStorage.ts", "../src/vector/IndexedDbVectorStorage.ts"],
|
|
3
|
+
"sources": ["../src/tabular/BaseTabularStorage.ts", "../src/tabular/ITabularStorage.ts", "../src/tabular/StorageError.ts", "../src/tabular/CoveringIndexMissingError.ts", "../src/tabular/CachedTabularStorage.ts", "../src/tabular/InMemoryTabularStorage.ts", "../src/tabular/coveringIndexPicker.ts", "../src/tabular/HuggingFaceTabularStorage.ts", "../src/tabular/TabularStorageRegistry.ts", "../src/util/traced.ts", "../src/tabular/TelemetryTabularStorage.ts", "../src/kv/IKvStorage.ts", "../src/kv/InMemoryKvStorage.ts", "../src/kv/KvStorage.ts", "../src/kv/KvViaTabularStorage.ts", "../src/kv/TelemetryKvStorage.ts", "../src/queue/InMemoryQueueStorage.ts", "../src/queue/IQueueStorage.ts", "../src/queue/TelemetryQueueStorage.ts", "../src/queue-limiter/InMemoryRateLimiterStorage.ts", "../src/queue-limiter/IRateLimiterStorage.ts", "../src/util/HybridSubscriptionManager.ts", "../src/util/PollingSubscriptionManager.ts", "../src/vector/InMemoryVectorStorage.ts", "../src/vector/IVectorStorage.ts", "../src/vector/TelemetryVectorStorage.ts", "../src/credentials/EncryptedKvCredentialStore.ts", "../src/credentials/LazyEncryptedCredentialStore.ts", "../src/tabular/FsFolderTabularStorage.ts", "../src/tabular/PostgresTabularStorage.ts", "../src/tabular/BaseSqlTabularStorage.ts", "../src/tabular/SqliteTabularStorage.ts", "../src/tabular/SupabaseTabularStorage.ts", "../src/kv/FsFolderJsonKvStorage.ts", "../src/kv/FsFolderKvStorage.ts", "../src/kv/PostgresKvStorage.ts", "../src/kv/SqliteKvStorage.ts", "../src/kv/SupabaseKvStorage.ts", "../src/queue/PostgresQueueStorage.ts", "../src/queue/SqliteQueueStorage.ts", "../src/queue/SupabaseQueueStorage.ts", "../src/queue-limiter/PostgresRateLimiterStorage.ts", "../src/queue-limiter/SqliteRateLimiterStorage.ts", "../src/queue-limiter/SupabaseRateLimiterStorage.ts", "../src/vector/PostgresVectorStorage.ts", "../src/vector/SqliteVectorStorage.ts", "../src/vector/SqliteAiVectorStorage.ts", "../src/kv/IndexedDbKvStorage.ts", "../src/tabular/IndexedDbTabularStorage.ts", "../src/util/IndexedDbTable.ts", "../src/queue-limiter/IndexedDbRateLimiterStorage.ts", "../src/queue/IndexedDbQueueStorage.ts", "../src/tabular/SharedInMemoryTabularStorage.ts", "../src/vector/IndexedDbVectorStorage.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { createServiceToken, EventEmitter, makeFingerprint } from \"@workglow/util\";\nimport { DataPortSchemaObject, FromSchema, TypedArraySchemaOptions } from \"@workglow/util/schema\";\nimport {\n AnyTabularStorage,\n AutoGeneratedKeys,\n CoveringIndexQueryOptions,\n DeleteSearchCriteria,\n InsertEntity,\n isSearchCondition,\n ITabularStorage,\n QueryOptions,\n SearchCriteria,\n SimplifyPrimaryKey,\n TabularChangePayload,\n TabularEventListener,\n TabularEventListeners,\n TabularEventName,\n TabularEventParameters,\n TabularSubscribeOptions,\n ValueOptionType,\n} from \"./ITabularStorage\";\nimport { CoveringIndexMissingError } from \"./CoveringIndexMissingError\";\nimport {\n StorageEmptyCriteriaError,\n StorageInvalidColumnError,\n StorageInvalidLimitError,\n StorageValidationError,\n} from \"./StorageError\";\n\nexport const TABULAR_REPOSITORY = createServiceToken<AnyTabularStorage>(\n \"storage.tabularRepository\"\n);\n\n/**\n * Options for controlling how client-provided values for auto-generated keys are handled\n */\nexport type ClientProvidedKeysOption = \"never\" | \"if-missing\" | \"always\";\n\n/**\n * Generation strategy for auto-generated keys\n */\nexport type KeyGenerationStrategy = \"autoincrement\" | \"uuid\";\n\n/**\n * Abstract base class for tabular storage repositories.\n * Provides functionality for storing and retrieving data with typed\n * primary keys and values, and supports compound keys and partial key lookup.\n * Has a basic event emitter for listening to repository events.\n *\n * @template Schema - The schema definition for the entity using JSON Schema\n * @template PrimaryKeyNames - Array of property names that form the primary key\n */\nexport abstract class BaseTabularStorage<\n Schema extends DataPortSchemaObject,\n PrimaryKeyNames extends ReadonlyArray<keyof Schema[\"properties\"]>,\n // computed types\n Entity = FromSchema<Schema, TypedArraySchemaOptions>,\n PrimaryKey = SimplifyPrimaryKey<Entity, PrimaryKeyNames>,\n Value = Omit<Entity, PrimaryKeyNames[number] & keyof Entity>,\n InsertType = InsertEntity<Entity, AutoGeneratedKeys<Schema>>,\n> implements ITabularStorage<Schema, PrimaryKeyNames, Entity, PrimaryKey, InsertType> {\n /** Event emitter for repository events */\n protected events = new EventEmitter<TabularEventListeners<PrimaryKey, Entity>>();\n\n protected indexes: Array<keyof Entity>[];\n protected primaryKeySchema: DataPortSchemaObject;\n protected valueSchema: DataPortSchemaObject;\n\n /** Name of the auto-generated key column (at most one primary key column may be auto-generated) */\n protected autoGeneratedKeyName: keyof Entity | null = null;\n /** Strategy for generating the auto-generated key */\n protected autoGeneratedKeyStrategy: KeyGenerationStrategy | null = null;\n /** How to handle client-provided values for auto-generated keys */\n protected clientProvidedKeys: ClientProvidedKeysOption;\n\n /**\n * Creates a new BaseTabularStorage instance\n * @param schema - Schema defining the structure of the entity\n * @param primaryKeyNames - Array of property names that form the primary key\n * @param indexes - Array of columns or column arrays to make searchable. Each string or single column creates a single-column index,\n * while each array creates a compound index with columns in the specified order.\n * @param clientProvidedKeys - How to handle client-provided values for auto-generated keys\n */\n constructor(\n protected schema: Schema,\n protected primaryKeyNames: PrimaryKeyNames,\n indexes: readonly (keyof NoInfer<Entity> | readonly (keyof NoInfer<Entity>)[])[] = [],\n clientProvidedKeys: ClientProvidedKeysOption = \"if-missing\"\n ) {\n this.clientProvidedKeys = clientProvidedKeys;\n const primaryKeyProps: Record<string, any> = {};\n const valueProps: Record<string, any> = {};\n const primaryKeySet = new Set(primaryKeyNames);\n\n // Split the schema properties into primary key and value properties\n for (const [key, typeDef] of Object.entries(schema.properties)) {\n if (primaryKeySet.has(key as keyof Schema[\"properties\"])) {\n primaryKeyProps[key] = Object.assign({}, typeDef);\n } else {\n valueProps[key] = Object.assign({}, typeDef);\n }\n }\n\n // Filter required array to only include primary key fields\n const primaryKeyRequired =\n schema.required?.filter((key) => primaryKeySet.has(key as keyof Schema[\"properties\"])) ?? [];\n // Filter required array to only include value fields\n const valueRequired =\n schema.required?.filter((key) => !primaryKeySet.has(key as keyof Schema[\"properties\"])) ?? [];\n\n this.primaryKeySchema = {\n type: \"object\",\n properties: primaryKeyProps,\n required: primaryKeyRequired,\n additionalProperties: false,\n } as DataPortSchemaObject;\n this.valueSchema = {\n type: \"object\",\n properties: valueProps,\n required: valueRequired,\n additionalProperties: false,\n } as DataPortSchemaObject;\n\n // validate all combined columns names are \"identifier\" names\n const combinedColumns = [...this.primaryKeyColumns(), ...this.valueColumns()];\n for (const column of combinedColumns) {\n if (typeof column !== \"string\") {\n throw new Error(\"Column names must be strings\");\n }\n if (!/^[a-zA-Z][a-zA-Z0-9_]*$/.test(column)) {\n throw new Error(\n \"Column names must start with a letter and contain only letters, digits, and underscores\"\n );\n }\n }\n\n // Normalize searchable into array of arrays\n this.indexes = indexes.map((spec) => (Array.isArray(spec) ? spec : [spec])) as Array<\n Array<keyof Entity>\n >;\n\n // searchable is an array of compound keys, which are arrays of columns\n // clean up searchable array by removing any compoundkeys that are a prefix of another compoundkey\n // or a prefix of the primary key\n this.indexes = this.filterCompoundKeys(\n this.primaryKeyColumns() as unknown as Array<keyof Entity>,\n this.indexes\n );\n\n // Validate searchable columns\n for (const compoundIndex of this.indexes) {\n for (const column of compoundIndex) {\n if (\n !(column in this.primaryKeySchema.properties) &&\n !(column in this.valueSchema.properties)\n ) {\n throw new Error(\n `Searchable column ${String(column)} is not in the primary key schema or value schema`\n );\n }\n }\n }\n\n // Detect and validate auto-generated keys (at most one PK column; any PK position is allowed).\n // Composite keys often put a scope column first (e.g. kb_id) and auto-generate a second id.\n const autoGeneratedKeys: string[] = [];\n for (const key of primaryKeyNames) {\n const keyStr = String(key);\n const propDef = (schema.properties as any)[keyStr];\n if (propDef && typeof propDef === \"object\" && \"x-auto-generated\" in propDef) {\n if (propDef[\"x-auto-generated\"] === true) {\n autoGeneratedKeys.push(keyStr);\n }\n }\n }\n\n if (autoGeneratedKeys.length > 1) {\n throw new Error(\n `Multiple auto-generated keys detected: ${autoGeneratedKeys.join(\", \")}. ` +\n `At most one primary key column can be auto-generated.`\n );\n }\n\n if (autoGeneratedKeys.length > 0) {\n const autoGenKeyName = autoGeneratedKeys[0];\n\n this.autoGeneratedKeyName = autoGenKeyName as keyof Entity;\n this.autoGeneratedKeyStrategy = this.determineGenerationStrategy(\n autoGenKeyName,\n schema.properties[autoGenKeyName as keyof Schema[\"properties\"]]\n );\n }\n }\n\n protected filterCompoundKeys(\n primaryKey: Array<keyof Entity>,\n potentialKeys: Array<keyof Entity>[]\n ): Array<keyof Entity>[] {\n // Function to check if one array is a prefix of another\n const isPrefix = (prefix: Array<keyof Entity>, arr: Array<keyof Entity>): boolean => {\n if (prefix.length > arr.length) return false;\n return prefix.every((val, index) => val === arr[index]);\n };\n\n // Sort potential keys by length\n potentialKeys.sort((a, b) => a.length - b.length);\n\n let filteredKeys: Array<keyof Entity>[] = [];\n\n for (let i = 0; i < potentialKeys.length; i++) {\n let key = potentialKeys[i];\n\n if (isPrefix(key, primaryKey)) continue;\n\n // Keep single-column indexes regardless of being a prefix\n if (key.length === 1) {\n filteredKeys.push(key);\n continue;\n }\n\n // Skip if the key is a prefix of a later key in the list\n let isRedundant = potentialKeys.some((otherKey, j) => j > i && isPrefix(key, otherKey));\n\n if (!isRedundant) {\n filteredKeys.push(key);\n }\n }\n\n return filteredKeys;\n }\n\n /**\n * Adds an event listener for a specific event\n * @param name The name of the event to listen for\n * @param fn The callback function to execute when the event occurs\n */\n on<Event extends TabularEventName>(\n name: Event,\n fn: TabularEventListener<Event, PrimaryKey, Entity>\n ) {\n this.events.on(name, fn);\n }\n\n /**\n * Removes an event listener for a specific event\n * @param name The name of the event to remove the listener from\n * @param fn The callback function to remove\n */\n off<Event extends TabularEventName>(\n name: Event,\n fn: TabularEventListener<Event, PrimaryKey, Entity>\n ) {\n this.events.off(name, fn);\n }\n\n /**\n * Adds an event listener that will only be called once\n * @param name The name of the event to listen for\n * @param fn The callback function to execute when the event occurs\n */\n once<Event extends TabularEventName>(\n name: Event,\n fn: TabularEventListener<Event, PrimaryKey, Entity>\n ) {\n this.events.once(name, fn);\n }\n\n /**\n * Emits an event with the specified name and arguments\n * @param name The name of the event to emit\n * @param args The arguments to pass to the event listeners\n */\n emit<Event extends TabularEventName>(\n name: Event,\n ...args: TabularEventParameters<Event, PrimaryKey, Entity>\n ) {\n this.events.emit(name, ...args);\n }\n\n /**\n * Returns when the event was emitted (promise form of once)\n * @param name The name of the event to check\n * @returns true if the event has listeners, false otherwise\n */\n waitOn<Event extends TabularEventName>(\n name: Event\n ): Promise<TabularEventParameters<Event, PrimaryKey, Entity>> {\n return this.events.waitOn(name) as Promise<TabularEventParameters<Event, PrimaryKey, Entity>>;\n }\n\n /**\n * Core abstract methods that must be implemented by concrete repositories\n */\n abstract put(value: InsertType): Promise<Entity>;\n abstract putBulk(values: InsertType[]): Promise<Entity[]>;\n abstract get(key: PrimaryKey): Promise<Entity | undefined>;\n abstract delete(key: PrimaryKey | Entity): Promise<void>;\n abstract getAll(options?: QueryOptions<Entity>): Promise<Entity[] | undefined>;\n abstract deleteAll(): Promise<void>;\n abstract size(): Promise<number>;\n\n /**\n * Counts entries matching the specified search criteria.\n * Concrete storage implementations can override this with native count APIs.\n */\n async count(criteria?: SearchCriteria<Entity>): Promise<number> {\n if (!criteria || Object.keys(criteria).length === 0) {\n return await this.size();\n }\n const entities = await this.query(criteria);\n return entities?.length ?? 0;\n }\n\n /**\n * Deletes all entries matching the specified search criteria.\n * Supports multiple columns with optional comparison operators.\n *\n * @param criteria - Object with column names as keys and values or SearchConditions\n */\n abstract deleteSearch(criteria: DeleteSearchCriteria<Entity>): Promise<void>;\n\n /**\n * Queries entries matching the specified search criteria with optional ordering and limit.\n * Unlike `search`, this method does not require an index and supports comparison operators,\n * ORDER BY, and LIMIT.\n *\n * @param criteria - Object with column names as keys and values or SearchConditions\n * @param options - Optional ordering and limit options\n * @returns Array of matching entities or undefined if no matches found\n */\n abstract query(\n criteria: SearchCriteria<Entity>,\n options?: QueryOptions<Entity>\n ): Promise<Entity[] | undefined>;\n\n /**\n * Strict, projected query served entirely by a covering compound index.\n * Subclasses that support index-only reads (e.g. IndexedDB, InMemory) should\n * override this with an efficient implementation. The default throws\n * {@link CoveringIndexMissingError} so callers get a consistent error when\n * the storage backend has not implemented index-only projection.\n */\n queryIndex<K extends keyof Entity & string>(\n criteria: SearchCriteria<Entity>,\n options: CoveringIndexQueryOptions<Entity, K>\n ): Promise<Pick<Entity, K>[]> {\n this.validateSelect(options);\n const requiredColumns = [\n ...Object.keys(criteria),\n ...(options.orderBy ?? []).map((o) => String(o.column)),\n ...options.select.map(String),\n ];\n throw new CoveringIndexMissingError(this.constructor.name, requiredColumns, []);\n }\n\n /**\n * Abstract method to fetch a page of records.\n * @param offset - Number of records to skip\n * @param limit - Maximum number of records to return\n * @returns Promise resolving to an array of entities or undefined if no records found\n */\n abstract getBulk(offset: number, limit: number): Promise<Entity[] | undefined>;\n\n /**\n * Async generator that yields records one at a time.\n * Uses getBulk internally to fetch pages of data.\n * @param pageSize - Number of records to fetch per page (default: 100)\n * @yields Individual entity records\n */\n async *records(pageSize: number = 100): AsyncGenerator<Entity, void, undefined> {\n if (pageSize <= 0) {\n throw new RangeError(`pageSize must be greater than 0, got ${pageSize}`);\n }\n let offset = 0;\n while (true) {\n const page = await this.getBulk(offset, pageSize);\n if (!page || page.length === 0) {\n break;\n }\n for (const entity of page) {\n yield entity;\n }\n if (page.length < pageSize) {\n break;\n }\n offset += pageSize;\n }\n }\n\n /**\n * Async generator that yields pages of records.\n * Uses getBulk internally to fetch pages of data.\n * @param pageSize - Number of records per page (default: 100)\n * @yields Arrays of entities\n */\n async *pages(pageSize: number = 100): AsyncGenerator<Entity[], void, undefined> {\n if (pageSize <= 0) {\n throw new RangeError(`pageSize must be greater than 0, got ${pageSize}`);\n }\n let offset = 0;\n while (true) {\n const page = await this.getBulk(offset, pageSize);\n if (!page || page.length === 0) {\n break;\n }\n yield page;\n if (page.length < pageSize) {\n break;\n }\n offset += pageSize;\n }\n }\n\n /**\n * Subscribes to changes in the repository (including remote changes).\n * Default implementation throws an error - override in subclasses that support subscriptions.\n *\n * @param callback - Function called when a change occurs\n * @param options - Optional subscription options (e.g., polling interval)\n * @returns Unsubscribe function\n * @throws Error if not implemented by the concrete repository\n */\n public subscribeToChanges(\n _callback: (change: TabularChangePayload<Entity>) => void,\n _options?: TabularSubscribeOptions\n ): () => void {\n throw new Error(\n `subscribeToChanges is not implemented for ${this.constructor.name}. ` +\n `All concrete repository implementations should override this method.`\n );\n }\n\n /**\n * Validates query parameters: criteria columns, options, and operator values.\n * @throws StorageEmptyCriteriaError if criteria is empty\n * @throws StorageInvalidLimitError if limit <= 0\n * @throws StorageValidationError if offset < 0\n * @throws StorageInvalidColumnError if any column name is not in the schema\n */\n protected validateQueryParams(\n criteria: SearchCriteria<Entity>,\n options?: QueryOptions<Entity>\n ): void {\n const criteriaKeys = Object.keys(criteria) as Array<keyof Entity>;\n\n if (criteriaKeys.length === 0) {\n throw new StorageEmptyCriteriaError();\n }\n\n if (options?.limit !== undefined && options.limit <= 0) {\n throw new StorageInvalidLimitError(options.limit);\n }\n\n if (options?.offset !== undefined && options.offset < 0) {\n throw new StorageValidationError(`Query offset must be non-negative, got ${options.offset}`);\n }\n\n // Validate criteria column names exist in schema\n for (const column of criteriaKeys) {\n if (!(column in this.schema.properties)) {\n throw new StorageInvalidColumnError(String(column));\n }\n // Validate operator values at runtime\n const criterion = criteria[column];\n if (isSearchCondition(criterion)) {\n const validOperators = [\"=\", \"<\", \"<=\", \">\", \">=\"];\n if (!validOperators.includes(criterion.operator)) {\n throw new StorageValidationError(\n `Invalid operator \"${criterion.operator}\". Must be one of: ${validOperators.join(\", \")}`\n );\n }\n }\n }\n\n // Validate orderBy column names\n if (options?.orderBy) {\n const validDirections = [\"ASC\", \"DESC\"];\n for (const { column, direction } of options.orderBy) {\n if (!(column in this.schema.properties)) {\n throw new StorageInvalidColumnError(String(column));\n }\n if (!validDirections.includes(direction)) {\n throw new StorageValidationError(\n `Invalid sort direction \"${direction}\". Must be \"ASC\" or \"DESC\"`\n );\n }\n }\n }\n }\n\n /**\n * Validates getAll options (orderBy, limit, offset) without criteria.\n */\n protected validateGetAllOptions(options?: QueryOptions<Entity>): void {\n if (!options) return;\n\n if (options.limit !== undefined && options.limit <= 0) {\n throw new StorageInvalidLimitError(options.limit);\n }\n\n if (options.offset !== undefined && options.offset < 0) {\n throw new StorageValidationError(`Query offset must be non-negative, got ${options.offset}`);\n }\n\n if (options.orderBy) {\n const validDirections = [\"ASC\", \"DESC\"];\n for (const { column, direction } of options.orderBy) {\n if (!(column in this.schema.properties)) {\n throw new StorageInvalidColumnError(String(column));\n }\n if (!validDirections.includes(direction)) {\n throw new StorageValidationError(\n `Invalid sort direction \"${direction}\". Must be \"ASC\" or \"DESC\"`\n );\n }\n }\n }\n }\n\n /**\n * Validates the `select` array in a {@link CoveringIndexQueryOptions}.\n * Throws {@link StorageValidationError} when `select` is empty or contains\n * a column that is not in the schema's `properties`.\n */\n protected validateSelect<K extends keyof Entity & string>(\n options: CoveringIndexQueryOptions<Entity, K>\n ): void {\n if (!options.select || options.select.length === 0) {\n throw new StorageValidationError(\"queryIndex requires a non-empty select array\");\n }\n const schemaProps = Object.keys(this.schema.properties);\n for (const col of options.select) {\n const colStr = String(col);\n if (!schemaProps.includes(colStr)) {\n throw new StorageValidationError(`queryIndex select column \"${colStr}\" is not in schema`);\n }\n }\n }\n\n protected primaryKeyColumns(): Array<keyof PrimaryKey> {\n const columns: Array<keyof PrimaryKey> = [];\n for (const key of Object.keys(this.primaryKeySchema.properties)) {\n columns.push(key as keyof PrimaryKey);\n }\n return columns;\n }\n\n protected valueColumns(): Array<keyof Value> {\n const columns: Array<keyof Value> = [];\n for (const key of Object.keys(this.valueSchema.properties)) {\n columns.push(key as keyof Value);\n }\n return columns;\n }\n\n /**\n * Utility method to separate a combined object into its key and value components\n * for storage.\n * @param obj - Entity row object\n * @returns Separated key and value objects\n */\n protected separateKeyValueFromCombined(obj: Entity): { value: Value; key: PrimaryKey } {\n if (obj === null) {\n console.warn(\"Key is null\");\n return { value: {} as Value, key: {} as PrimaryKey };\n }\n if (typeof obj !== \"object\") {\n console.warn(\"Object is not an object\");\n return { value: {} as Value, key: {} as PrimaryKey };\n }\n const primaryKeyNames = this.primaryKeyColumns();\n const valueNames = this.valueColumns();\n const value: Partial<Value> = {};\n const key: Partial<PrimaryKey> = {};\n const objRecord = obj as Record<string, unknown>;\n for (const k of primaryKeyNames) {\n (key as Record<string, unknown>)[k as string] = objRecord[k as string];\n }\n for (const k of valueNames) {\n (value as Record<string, unknown>)[k as string] = objRecord[k as string];\n }\n\n return { value: value as Value, key: key as PrimaryKey };\n }\n\n /**\n * Generates a consistent string identifier for a given key.\n *\n * @param key - Primary key to convert\n * @returns Promise resolving to a string fingerprint of the key\n */\n protected async getKeyAsIdString(key: PrimaryKey): Promise<string> {\n return await makeFingerprint(key);\n }\n\n /**\n * Converts a primary key object into an ordered array based on the schema\n * This ensures consistent parameter ordering for storage operations\n * @param key - The primary key object to convert\n * @returns Array of key values ordered according to the schema\n */\n protected getPrimaryKeyAsOrderedArray(key: PrimaryKey): ValueOptionType[] {\n const orderedParams: ValueOptionType[] = [];\n const keyObj = key as Record<string, ValueOptionType>;\n for (const k in this.primaryKeySchema.properties) {\n if (k in keyObj) {\n orderedParams.push(keyObj[k]);\n } else {\n throw new Error(`Missing required primary key field: ${k}`);\n }\n }\n return orderedParams;\n }\n\n /**\n * Finds the best matching index for a set of search keys.\n * @param unorderedSearchKey - Unordered array of keys being searched, can be reordered\n * @returns Array of column names representing the best matching index, or undefined if no suitable index is found\n */\n public findBestMatchingIndex(\n unorderedSearchKey: Array<keyof Entity>\n ): Array<keyof Entity> | undefined {\n if (!unorderedSearchKey.length) return undefined;\n\n const allKeys: Array<keyof Entity>[] = [\n this.primaryKeyColumns() as unknown as Array<keyof Entity>,\n ...(this.indexes as Array<keyof Entity>[]),\n ];\n\n const searchKeySet = new Set(unorderedSearchKey);\n\n const hasMatchingPrefix = (index: Array<keyof Entity>): boolean => {\n // Check if the first column of the index is in our search keys\n return index.length > 0 && searchKeySet.has(index[0]);\n };\n\n let bestMatch: Array<keyof Entity> | undefined;\n let bestMatchScore = 0;\n\n for (const index of allKeys) {\n if (hasMatchingPrefix(index)) {\n // Calculate how many consecutive search keys we can use from this index\n let score = 0;\n for (const col of index) {\n if (!searchKeySet.has(col)) break;\n score++;\n }\n\n if (score > bestMatchScore) {\n bestMatch = index;\n bestMatchScore = score;\n }\n }\n }\n\n return bestMatch;\n }\n\n /**\n * Checks if this storage has an auto-generated key configured\n * @returns true if an auto-generated key is configured\n */\n protected hasAutoGeneratedKey(): boolean {\n return this.autoGeneratedKeyName !== null;\n }\n\n /**\n * Checks if a given column name is the auto-generated key\n * @param name - Column name to check\n * @returns true if the column is the auto-generated key\n */\n protected isAutoGeneratedKey(name: string): boolean {\n return this.autoGeneratedKeyName !== null && String(this.autoGeneratedKeyName) === name;\n }\n\n /**\n * Determines the generation strategy for an auto-generated key based on its type\n * @param columnName - Name of the column\n * @param typeDef - JSON Schema type definition for the column\n * @returns The generation strategy to use\n */\n protected determineGenerationStrategy(columnName: string, typeDef: any): KeyGenerationStrategy {\n // Extract the actual type if it's a union with null\n let actualType = typeDef;\n if (typeDef && typeof typeDef === \"object\") {\n if (typeDef.anyOf && Array.isArray(typeDef.anyOf)) {\n actualType = typeDef.anyOf.find((t: any) => t.type !== \"null\") || typeDef;\n } else if (typeDef.oneOf && Array.isArray(typeDef.oneOf)) {\n actualType = typeDef.oneOf.find((t: any) => t.type !== \"null\") || typeDef;\n }\n }\n\n if (typeof actualType !== \"object\") {\n return \"uuid\";\n }\n\n // Integer types use autoincrement\n if (actualType.type === \"integer\") {\n return \"autoincrement\";\n }\n\n // Default to UUID for strings and other types\n return \"uuid\";\n }\n\n /**\n * Generates a key value for client-side key generation\n * Override in storage classes that generate keys client-side (InMemory, IndexedDB for UUIDs)\n * SQL-based storages typically generate keys server-side\n * @param columnName - Name of the column to generate a key for\n * @param strategy - The generation strategy to use\n * @returns The generated key value\n */\n protected generateKeyValue(\n columnName: string,\n strategy: KeyGenerationStrategy\n ): Promise<string | number> | string | number {\n throw new Error(\n `generateKeyValue not implemented for ${this.constructor.name}. ` +\n `Column: ${columnName}, Strategy: ${strategy}`\n );\n }\n\n /**\n * Sets up the database/storage for the repository.\n * Must be called before using any other methods (except for in-memory implementations).\n * Default implementation is a no-op - override in subclasses that need setup.\n */\n async setupDatabase(): Promise<void> {\n // no op by default\n }\n\n /**\n * Destroys the repository and frees up resources.\n */\n destroy(): void {\n // no op by default\n }\n\n async [Symbol.asyncDispose](): Promise<void> {\n this.destroy();\n }\n\n [Symbol.dispose](): void {\n this.destroy();\n }\n}\n",
|
|
6
6
|
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { EventParameters } from \"@workglow/util\";\nimport { DataPortSchemaObject, FromSchema, TypedArraySchemaOptions } from \"@workglow/util/schema\";\n\n// Generic type for possible value types in the repository\nexport type ValueOptionType = string | number | bigint | boolean | null | Uint8Array;\n\n/**\n * Type definitions for tabular repository events\n */\nexport type TabularEventListeners<PrimaryKey, Entity> = {\n put: (entity: Entity) => void;\n get: (key: PrimaryKey, entity: Entity | undefined) => void;\n query: (key: Partial<Entity>, entities: Entity[] | undefined) => void;\n delete: (key: keyof Entity) => void;\n clearall: () => void;\n};\n\nexport type TabularEventName = keyof TabularEventListeners<any, any>;\nexport type TabularEventListener<\n Event extends TabularEventName,\n PrimaryKey,\n Entity,\n> = TabularEventListeners<PrimaryKey, Entity>[Event];\n\nexport type TabularEventParameters<\n Event extends TabularEventName,\n PrimaryKey,\n Entity,\n> = EventParameters<TabularEventListeners<PrimaryKey, Entity>, Event>;\n\n/**\n * Type of change that occurred in the repository\n */\nexport type TabularChangeType = \"INSERT\" | \"UPDATE\" | \"DELETE\";\n\n/**\n * Payload describing a change to an entity\n */\nexport interface TabularChangePayload<Entity> {\n readonly type: TabularChangeType;\n readonly old?: Entity;\n readonly new?: Entity;\n}\n\n/**\n * Options for subscribing to changes in a tabular repository\n */\nexport interface TabularSubscribeOptions {\n /** Polling interval in milliseconds (used by implementations that rely on polling) */\n readonly pollingIntervalMs?: number;\n}\n\nexport type JSONValue =\n | string\n | number\n | boolean\n | null\n | JSONValue[]\n | { [key: string]: JSONValue };\n\n/**\n * Comparison operators for search and deleteSearch operations\n */\nexport type SearchOperator = \"=\" | \"<\" | \"<=\" | \">\" | \">=\";\n\n/**\n * A search condition with a value and comparison operator\n */\nexport interface SearchCondition<T> {\n readonly value: T;\n readonly operator: SearchOperator;\n}\n\n/**\n * Criteria for deleteSearch operations supporting multiple columns.\n * Each column can have either a direct value (equality) or a SearchCondition with an operator.\n *\n * @example\n * // Equality match\n * { category: \"electronics\" }\n *\n * // With operator\n * { createdAt: { value: date, operator: \"<\" } }\n *\n * // Multiple columns\n * { category: \"electronics\", createdAt: { value: date, operator: \"<\" } }\n */\nexport type DeleteSearchCriteria<Entity> = {\n readonly [K in keyof Entity]?: Entity[K] | SearchCondition<Entity[K]>;\n};\n\nexport type SearchCriteria<Entity> = DeleteSearchCriteria<Entity>;\n\nexport type SortDirection = \"ASC\" | \"DESC\";\n\nexport interface OrderBy<Entity> {\n readonly column: keyof Entity;\n readonly direction: SortDirection;\n}\n\nexport interface QueryOptions<Entity> {\n readonly orderBy?: ReadonlyArray<OrderBy<Entity>>;\n readonly limit?: number;\n readonly offset?: number;\n}\n\nexport interface CoveringIndexQueryOptions<Entity, K extends keyof Entity & string> {\n readonly select: readonly K[];\n readonly orderBy?: ReadonlyArray<OrderBy<Entity>>;\n readonly limit?: number;\n readonly offset?: number;\n}\n\n/**\n * Type guard to check if a value is a SearchCondition\n */\nexport function isSearchCondition<T>(value: unknown): value is SearchCondition<T> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"value\" in value &&\n \"operator\" in value &&\n typeof (value as SearchCondition<T>).operator === \"string\"\n );\n}\n\n/**\n * Helper type to compute PrimaryKey while deferring Entity resolution.\n * Uses a conditional type to avoid forcing full Entity resolution at class definition time.\n *\n */\nexport type SimplifyPrimaryKey<\n Entity,\n KeyName extends ReadonlyArray<keyof any>,\n> = Entity extends any ? Pick<Entity, Extract<KeyName[number], keyof Entity>> : never;\n\n/**\n * Extracts property names marked as auto-generated from the schema.\n * Properties with `x-auto-generated: true` are considered auto-generated.\n */\nexport type AutoGeneratedKeys<Schema extends DataPortSchemaObject> = {\n [K in keyof Schema[\"properties\"]]: Schema[\"properties\"][K] extends { \"x-auto-generated\": true }\n ? K\n : never;\n}[keyof Schema[\"properties\"]];\n\n/**\n * Entity type for insertion - auto-generated keys are optional.\n * This allows clients to omit auto-generated keys when inserting entities.\n */\nexport type InsertEntity<Entity, AutoGenKeys> = Omit<Entity, AutoGenKeys & keyof Entity> &\n Partial<Pick<Entity, AutoGenKeys & keyof Entity>>;\n\n/**\n * Interface defining the contract for tabular storage repositories.\n * Provides a flexible interface for storing and retrieving data with typed\n * primary keys and values, and supports compound keys and partial key lookup.\n *\n * @typeParam Schema - The schema definition for the entity using JSON Schema\n * @typeParam PrimaryKeyNames - Array of property names that form the primary key\n */\nexport interface ITabularStorage<\n Schema extends DataPortSchemaObject,\n PrimaryKeyNames extends ReadonlyArray<keyof Schema[\"properties\"]>,\n // computed types\n Entity = FromSchema<Schema, TypedArraySchemaOptions>,\n PrimaryKey = SimplifyPrimaryKey<Entity, PrimaryKeyNames>,\n InsertType = InsertEntity<Entity, AutoGeneratedKeys<Schema>>,\n> {\n // Core methods\n put(value: InsertType): Promise<Entity>;\n putBulk(values: InsertType[]): Promise<Entity[]>;\n get(key: PrimaryKey): Promise<Entity | undefined>;\n delete(key: PrimaryKey | Entity): Promise<void>;\n getAll(options?: QueryOptions<Entity>): Promise<Entity[] | undefined>;\n deleteAll(): Promise<void>;\n size(): Promise<number>;\n /**\n * Counts rows matching the specified search criteria without requiring\n * callers to load the matching entities.\n *\n * @param criteria - Optional object with column names as keys and values or SearchConditions\n * @returns Count of matching rows\n */\n count(criteria?: SearchCriteria<Entity>): Promise<number>;\n /**\n * Deletes all entries matching the specified search criteria.\n * Supports multiple columns with optional comparison operators.\n *\n * @param criteria - Object with column names as keys and values or SearchConditions\n * @example\n * // Delete by equality\n * await repo.deleteSearch({ category: \"electronics\" });\n *\n * // Delete with operator\n * await repo.deleteSearch({ createdAt: { value: date, operator: \"<\" } });\n *\n * // Delete with multiple criteria (AND)\n * await repo.deleteSearch({ category: \"electronics\", value: { value: 100, operator: \"<\" } });\n */\n deleteSearch(criteria: DeleteSearchCriteria<Entity>): Promise<void>;\n\n /**\n * Fetches a page of records from the repository.\n * @param offset - Number of records to skip\n * @param limit - Maximum number of records to return\n * @returns Array of entities or undefined if no records found\n */\n getBulk(offset: number, limit: number): Promise<Entity[] | undefined>;\n\n /**\n * Async generator that yields records one at a time.\n * @param pageSize - Number of records to fetch per page (default: 100)\n * @yields Individual entity records\n */\n records(pageSize?: number): AsyncGenerator<Entity, void, undefined>;\n\n /**\n * Async generator that yields pages of records.\n * @param pageSize - Number of records per page (default: 100)\n * @yields Arrays of entities\n */\n pages(pageSize?: number): AsyncGenerator<Entity[], void, undefined>;\n\n // Event handling methods\n on<Event extends TabularEventName>(\n name: Event,\n fn: TabularEventListener<Event, PrimaryKey, Entity>\n ): void;\n off<Event extends TabularEventName>(\n name: Event,\n fn: TabularEventListener<Event, PrimaryKey, Entity>\n ): void;\n emit<Event extends TabularEventName>(\n name: Event,\n ...args: TabularEventParameters<Event, PrimaryKey, Entity>\n ): void;\n once<Event extends TabularEventName>(\n name: Event,\n fn: TabularEventListener<Event, PrimaryKey, Entity>\n ): void;\n waitOn<Event extends TabularEventName>(\n name: Event\n ): Promise<TabularEventParameters<Event, PrimaryKey, Entity>>;\n\n /**\n * Queries entries matching the specified search criteria with optional ordering, limit, and offset.\n * Uses optimized index paths when possible, falls back to full scan otherwise.\n *\n * @param criteria - Object with column names as keys and values or SearchConditions\n * @param options - Optional ordering, limit, and offset options\n * @returns Array of matching entities or undefined if no matches found\n */\n query(\n criteria: SearchCriteria<Entity>,\n options?: QueryOptions<Entity>\n ): Promise<Entity[] | undefined>;\n\n /**\n * Strict, projected query served entirely by a covering compound index.\n * Throws CoveringIndexMissingError when no registered index can serve\n * (criteria + orderBy + select). Returns Pick<Entity, K>[] — never the heavy fields.\n *\n * @param criteria - equality (and optionally non-equality) filters\n * @param options - select (required), orderBy, limit, offset\n * @returns array of projected rows (empty array, not undefined, when no matches)\n */\n queryIndex<K extends keyof Entity & string>(\n criteria: SearchCriteria<Entity>,\n options: CoveringIndexQueryOptions<Entity, K>\n ): Promise<Pick<Entity, K>[]>;\n\n /**\n * Subscribes to changes in the repository (including remote changes).\n * @param callback - Function called when a change occurs\n * @param options - Optional subscription options (e.g., polling interval)\n * @returns Unsubscribe function\n */\n subscribeToChanges(\n callback: (change: TabularChangePayload<Entity>) => void,\n options?: TabularSubscribeOptions\n ): () => void;\n\n /**\n * Sets up the database/storage for the repository.\n * Must be called before using any other methods (except for in-memory implementations).\n * @returns Promise that resolves when setup is complete\n */\n setupDatabase(): Promise<void>;\n\n // Destroy the repository and frees up resources.\n destroy(): void;\n [Symbol.dispose](): void;\n [Symbol.asyncDispose](): Promise<void>;\n}\n\nexport type AnyTabularStorage = Omit<ITabularStorage<any, any, any, any, any>, \"queryIndex\"> & {\n queryIndex(criteria: any, options: any): Promise<any[]>;\n};\n",
|
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { JsonSchema } from \"@workglow/util/schema\";\nimport { createServiceToken, EventEmitter, makeFingerprint } from \"@workglow/util\";\nimport { JSONValue } from \"../tabular/ITabularStorage\";\nimport {\n IKvStorage,\n KvEventListener,\n KvEventListeners,\n KvEventName,\n KvEventParameters,\n} from \"./IKvStorage\";\n\nexport const KV_REPOSITORY = createServiceToken<IKvStorage<any, any, any>>(\"storage.kvRepository\");\n\n/**\n * Abstract base class for key-value storage repositories.\n * Has a basic event emitter for listening to repository events.\n *\n * @template Key - The type of the primary key\n * @template Value - The type of the value being stored\n * @template Combined - Combined type of Key & Value\n */\nexport abstract class KvStorage<\n Key extends string = string,\n Value extends any = any,\n Combined = { key: Key; value: Value },\n> implements IKvStorage<Key, Value, Combined> {\n /** Event emitter for repository events */\n protected events = new EventEmitter<KvEventListeners<Key, Value, Combined>>();\n\n /**\n * Creates a new KvStorage instance\n */\n constructor(\n public keySchema: JsonSchema = { type: \"string\" },\n public valueSchema: JsonSchema = {}\n ) {}\n\n /**\n * Stores a row in the repository.\n * @param key - The primary key\n * @param value - The value to store\n */\n abstract put(key: Key, value: Value): Promise<void>;\n\n /**\n * Stores multiple rows in the repository in a bulk operation.\n * @param items - Array of key-value pairs to store\n */\n abstract putBulk(items: Array<{ key: Key; value: Value }>): Promise<void>;\n\n /**\n * Retrieves a value by its key.\n * This is a convenience method that automatically converts simple types to structured format if using default schema.\n *\n * @param key - Primary key to look up (basic key like default schema)\n * @returns The stored value or undefined if not found\n */\n abstract get(key: Key): Promise<Value | undefined>;\n\n /**\n * Deletes a row from the repository.\n * @param key - The primary key of the row to delete\n */\n abstract delete(key: Key): Promise<void>;\n\n /**\n * Retrieves all rows from the repository.\n * @returns An array of all rows in the repository or undefined if empty\n */\n abstract getAll(): Promise<Combined[] | undefined>;\n\n /**\n * Deletes all rows from the repository.\n */\n abstract deleteAll(): Promise<void>;\n\n /**\n * Retrieves the number of rows in the repository.\n * @returns The number of rows in the repository\n */\n abstract size(): Promise<number>;\n\n /**\n * Generates a consistent string identifier for a given key.\n *\n * @param object - Object to convert\n * @returns Promise resolving to a string fingerprint of the object for use as an id\n */\n public async getObjectAsIdString(object: JSONValue): Promise<string> {\n return await makeFingerprint(object);\n }\n\n /**\n * Adds an event listener for a specific event\n * @param name The name of the event to listen for\n * @param fn The callback function to execute when the event occurs\n */\n on<Event extends KvEventName>(name: Event, fn: KvEventListener<Event, Key, Value, Combined>) {\n this.events.on(name, fn);\n }\n\n /**\n * Removes an event listener for a specific event\n * @param name The name of the event to remove the listener from\n * @param fn The callback function to remove\n */\n off<Event extends KvEventName>(name: Event, fn: KvEventListener<Event, Key, Value, Combined>) {\n this.events.off(name, fn);\n }\n\n /**\n * Adds an event listener that will only be called once\n * @param name The name of the event to listen for\n * @param fn The callback function to execute when the event occurs\n */\n once<Event extends KvEventName>(name: Event, fn: KvEventListener<Event, Key, Value, Combined>) {\n this.events.once(name, fn);\n }\n\n /**\n * Emits an event with the specified name and arguments\n * @param name The name of the event to emit\n * @param args The arguments to pass to the event listeners\n */\n emit<Event extends KvEventName>(\n name: Event,\n ...args: KvEventParameters<Event, Key, Value, Combined>\n ) {\n this.events.emit(name, ...args);\n }\n\n /**\n * Returns when the event was emitted (promise form of once)\n * @param name The name of the event to check\n * @returns true if the event has listeners, false otherwise\n */\n waitOn<Event extends KvEventName>(\n name: Event\n ): Promise<KvEventParameters<Event, Key, Value, Combined>> {\n return this.events.waitOn(name) as Promise<KvEventParameters<Event, Key, Value, Combined>>;\n }\n}\n",
|
|
19
19
|
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { BaseTabularStorage } from \"../tabular/BaseTabularStorage\";\nimport { DefaultKeyValueKey, DefaultKeyValueSchema } from \"./IKvStorage\";\nimport { KvStorage } from \"./KvStorage\";\n\n/**\n * Abstract base class for key-value storage repositories that uses a tabular repository for storage.\n * Has a basic event emitter for listening to repository events.\n *\n * @template Key - The type of the primary key\n * @template Value - The type of the value being stored\n * @template Combined - Combined type of Key & Value\n */\n/** Schema types that are stored as-is without JSON serialization */\nconst PRIMITIVE_SCHEMA_TYPES = new Set([\"number\", \"boolean\", \"string\", \"blob\"]);\n\nexport abstract class KvViaTabularStorage<\n Key extends string = string,\n Value extends any = any,\n Combined = { key: Key; value: Value },\n> extends KvStorage<Key, Value, Combined> {\n public abstract tabularRepository: BaseTabularStorage<\n typeof DefaultKeyValueSchema,\n typeof DefaultKeyValueKey\n >;\n\n /** Whether values need JSON serialization (cached from schema) */\n private get needsJsonSerialization(): boolean {\n if (this._needsJsonSerialization === undefined) {\n const schemaType =\n typeof this.valueSchema === \"object\" &&\n this.valueSchema !== null &&\n \"type\" in this.valueSchema\n ? this.valueSchema.type\n : undefined;\n this._needsJsonSerialization = !PRIMITIVE_SCHEMA_TYPES.has(schemaType as string);\n }\n return this._needsJsonSerialization;\n }\n private _needsJsonSerialization: boolean | undefined;\n\n /**\n * Sets up the database for the repository.\n * Must be called before using any other methods.\n */\n public async setupDatabase(): Promise<void> {\n await this.tabularRepository.setupDatabase?.();\n }\n\n /**\n * Stores a row in the repository.\n * @param key - The primary key\n * @param value - The value to store\n */\n public async put(key: Key, value: Value): Promise<void> {\n if (this.needsJsonSerialization) {\n value = JSON.stringify(value) as Value;\n }\n await this.tabularRepository.put({ key, value });\n }\n\n /**\n * Stores multiple rows in the repository in a bulk operation.\n * @param items - Array of key-value pairs to store\n */\n public async putBulk(items: Array<{ key: Key; value: Value }>): Promise<void> {\n const entities = this.needsJsonSerialization\n ? items.map(({ key, value }) => ({ key, value: JSON.stringify(value) as Value }))\n : items;\n\n await this.tabularRepository.putBulk(entities);\n }\n\n /**\n * Retrieves a value by its key.\n * This is a convenience method that automatically converts simple types to structured format if using default schema.\n *\n * @param key - Primary key to look up (basic key like default schema)\n * @returns The stored value or undefined if not found\n */\n public async get(key: Key): Promise<Value | undefined> {\n const result = await this.tabularRepository.get({ key });\n if (!result) return undefined;\n\n if (this.needsJsonSerialization) {\n try {\n return JSON.parse(result.value as unknown as string) as Value;\n } catch (e) {\n return result.value as unknown as Value;\n }\n }\n return result.value as unknown as Value;\n }\n\n /**\n * Deletes a row from the repository.\n * @param key - The primary key of the row to delete\n */\n public async delete(key: Key): Promise<void> {\n return await this.tabularRepository.delete({ key });\n }\n\n /**\n * Retrieves all rows from the repository.\n * @returns An array of all rows in the repository or undefined if empty\n */\n public async getAll(): Promise<Combined[] | undefined> {\n const values = await this.tabularRepository.getAll();\n if (values) {\n return values.map(\n (value) =>\n ({\n key: value.key,\n value: (() => {\n if (this.needsJsonSerialization && typeof value.value === \"string\") {\n try {\n return JSON.parse(value.value);\n } catch (e) {\n return value.value;\n }\n }\n return value.value;\n })(),\n }) as Combined\n );\n }\n }\n\n /**\n * Deletes all rows from the repository.\n */\n public async deleteAll(): Promise<void> {\n return await this.tabularRepository.deleteAll();\n }\n\n /**\n * Retrieves the number of rows in the repository.\n * @returns The number of rows in the repository\n */\n public async size(): Promise<number> {\n return await this.tabularRepository.size();\n }\n\n /**\n * Destroys the repository and frees up resources.\n */\n destroy(): void {\n this.tabularRepository.destroy();\n }\n}\n",
|
|
20
20
|
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { JSONValue } from \"../tabular/ITabularStorage\";\nimport { traced } from \"../util/traced\";\nimport type { IKvStorage, KvEventListener, KvEventName, KvEventParameters } from \"./IKvStorage\";\n\n/**\n * Telemetry wrapper for any IKvStorage implementation.\n * Creates spans for all storage operations.\n */\nexport class TelemetryKvStorage<\n Key extends string | number = string,\n Value extends any = any,\n Combined = { key: Key; value: Value },\n> implements IKvStorage<Key, Value, Combined> {\n constructor(\n private readonly storageName: string,\n private readonly inner: IKvStorage<Key, Value, Combined>\n ) {}\n\n put(key: Key, value: Value): Promise<void> {\n return traced(\"workglow.storage.kv.put\", this.storageName, () => this.inner.put(key, value));\n }\n putBulk(items: Array<{ key: Key; value: Value }>): Promise<void> {\n return traced(\"workglow.storage.kv.putBulk\", this.storageName, () => this.inner.putBulk(items));\n }\n get(key: Key): Promise<Value | undefined> {\n return traced(\"workglow.storage.kv.get\", this.storageName, () => this.inner.get(key));\n }\n delete(key: Key): Promise<void> {\n return traced(\"workglow.storage.kv.delete\", this.storageName, () => this.inner.delete(key));\n }\n getAll(): Promise<Combined[] | undefined> {\n return traced(\"workglow.storage.kv.getAll\", this.storageName, () => this.inner.getAll());\n }\n deleteAll(): Promise<void> {\n return traced(\"workglow.storage.kv.deleteAll\", this.storageName, () => this.inner.deleteAll());\n }\n size(): Promise<number> {\n return traced(\"workglow.storage.kv.size\", this.storageName, () => this.inner.size());\n }\n getObjectAsIdString(object: JSONValue): Promise<string> {\n return this.inner.getObjectAsIdString(object);\n }\n\n // Event delegation — no telemetry needed\n on<Event extends KvEventName>(name: Event, fn: KvEventListener<Event, Key, Value, Combined>) {\n this.inner.on(name, fn);\n }\n off<Event extends KvEventName>(name: Event, fn: KvEventListener<Event, Key, Value, Combined>) {\n this.inner.off(name, fn);\n }\n emit<Event extends KvEventName>(\n name: Event,\n ...args: KvEventParameters<Event, Key, Value, Combined>\n ) {\n this.inner.emit(name, ...args);\n }\n once<Event extends KvEventName>(name: Event, fn: KvEventListener<Event, Key, Value, Combined>) {\n this.inner.once(name, fn);\n }\n waitOn<Event extends KvEventName>(\n name: Event\n ): Promise<KvEventParameters<Event, Key, Value, Combined>> {\n return this.inner.waitOn(name);\n }\n}\n",
|
|
21
|
-
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {\n createServiceToken,\n EventEmitter,\n getLogger,\n makeFingerprint,\n sleep,\n uuid4,\n} from \"@workglow/util\";\nimport {\n IQueueStorage,\n JobStatus,\n JobStorageFormat,\n QueueChangePayload,\n QueueStorageOptions,\n QueueSubscribeOptions,\n} from \"./IQueueStorage\";\n\n/**\n * Event listeners for queue storage events\n */\ntype QueueEventListeners<Input, Output> = {\n change: (payload: QueueChangePayload<Input, Output>) => void;\n};\n\nexport const IN_MEMORY_QUEUE_STORAGE = createServiceToken<IQueueStorage<any, any>>(\n \"jobqueue.storage.inMemory\"\n);\n\n/**\n * In-memory implementation of a job queue that manages asynchronous tasks.\n * Supports job scheduling, status tracking, result caching, and prefix-based filtering.\n */\nexport class InMemoryQueueStorage<Input, Output> implements IQueueStorage<Input, Output> {\n /** The prefix values for filtering jobs */\n protected readonly prefixValues: Readonly<Record<string, string | number>>;\n /** Event emitter for change notifications */\n protected readonly events = new EventEmitter<QueueEventListeners<Input, Output>>();\n\n /**\n * Creates a new in-memory job queue\n * @param queueName - Name of the queue\n * @param options - Optional configuration including prefix filters\n */\n constructor(\n public readonly queueName: string,\n options?: QueueStorageOptions\n ) {\n this.jobQueue = [];\n this.prefixValues = options?.prefixValues ?? {};\n }\n\n /** Internal array storing all jobs */\n public jobQueue: Array<JobStorageFormat<Input, Output> & Record<string, unknown>>;\n\n /**\n * Checks if a job matches the current prefix values\n */\n private matchesPrefixes(job: JobStorageFormat<Input, Output> & Record<string, unknown>): boolean {\n for (const [key, value] of Object.entries(this.prefixValues)) {\n if (job[key] !== value) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Returns a filtered and sorted list of pending jobs that are ready to run\n * Sorts by creation time to maintain FIFO order\n */\n private pendingQueue(): Array<JobStorageFormat<Input, Output> & Record<string, unknown>> {\n const now = new Date().toISOString();\n return this.jobQueue\n .filter((job) => this.matchesPrefixes(job))\n .filter((job) => job.status === JobStatus.PENDING)\n .filter((job) => !job.run_after || job.run_after <= now)\n .sort((a, b) => (a.run_after || \"\").localeCompare(b.run_after || \"\"));\n }\n\n /**\n * Adds a new job to the queue\n * Generates an ID and fingerprint if not provided\n */\n public async add(job: JobStorageFormat<Input, Output>): Promise<unknown> {\n await sleep(0);\n const now = new Date().toISOString();\n const jobWithPrefixes = job as JobStorageFormat<Input, Output> & Record<string, unknown>;\n jobWithPrefixes.id = jobWithPrefixes.id ?? uuid4();\n jobWithPrefixes.job_run_id = jobWithPrefixes.job_run_id ?? uuid4();\n jobWithPrefixes.queue = this.queueName;\n jobWithPrefixes.fingerprint = await makeFingerprint(jobWithPrefixes.input);\n jobWithPrefixes.status = JobStatus.PENDING;\n jobWithPrefixes.progress = 0;\n jobWithPrefixes.progress_message = \"\";\n jobWithPrefixes.progress_details = null;\n jobWithPrefixes.created_at = now;\n jobWithPrefixes.run_after = now;\n\n // Add prefix values to the job\n for (const [key, value] of Object.entries(this.prefixValues)) {\n jobWithPrefixes[key] = value;\n }\n\n this.jobQueue.push(jobWithPrefixes);\n this.events.emit(\"change\", { type: \"INSERT\", new: jobWithPrefixes });\n return jobWithPrefixes.id;\n }\n\n /**\n * Retrieves a job from the queue by its id.\n * @param id - The id of the job to retrieve.\n * @returns A promise that resolves to the job or undefined if the job is not found.\n */\n public async get(id: unknown): Promise<JobStorageFormat<Input, Output> | undefined> {\n await sleep(0);\n const job = this.jobQueue.find((j) => j.id === id);\n if (job && this.matchesPrefixes(job)) {\n return job;\n }\n return undefined;\n }\n\n /**\n * Retrieves a slice of jobs from the queue.\n * @param status - The status of the jobs to retrieve.\n * @param num - The number of jobs to retrieve.\n * @returns A promise that resolves to an array of jobs.\n */\n public async peek(\n status: JobStatus = JobStatus.PENDING,\n num: number = 100\n ): Promise<Array<JobStorageFormat<Input, Output>>> {\n await sleep(0);\n num = Number(num) || 100;\n return this.jobQueue\n .filter((j) => this.matchesPrefixes(j))\n .sort((a, b) => (a.run_after || \"\").localeCompare(b.run_after || \"\"))\n .filter((j) => j.status === status)\n .slice(0, num);\n }\n\n /**\n * Retrieves the next available job that is ready to be processed\n * Updates the job status to PROCESSING before returning\n * @param workerId - Worker ID to associate with the job\n * @returns The next job or undefined if no job is available\n */\n public async next(workerId: string): Promise<JobStorageFormat<Input, Output> | undefined> {\n await sleep(0);\n const top = this.pendingQueue();\n\n const job = top[0];\n if (job) {\n const oldJob = { ...job };\n job.status = JobStatus.PROCESSING;\n job.last_ran_at = new Date().toISOString();\n job.worker_id = workerId;\n this.events.emit(\"change\", { type: \"UPDATE\", old: oldJob, new: job });\n return job;\n }\n }\n\n /**\n * Retrieves the size of the queue for a given status\n * @param status - The status of the jobs to retrieve.\n * @returns A promise that resolves to the number of jobs.\n */\n public async size(status = JobStatus.PENDING): Promise<number> {\n await sleep(0);\n return this.jobQueue.filter((j) => this.matchesPrefixes(j) && j.status === status).length;\n }\n\n /**\n * Saves the progress of a job\n * @param jobId - The id of the job to save the progress for.\n * @param progress - The progress of the job.\n * @param message - The message of the job.\n * @param details - The details of the job.\n */\n public async saveProgress(\n id: unknown,\n progress: number,\n message: string,\n details: Record<string, any> | null\n ): Promise<void> {\n await sleep(0);\n const job = this.jobQueue.find((j) => j.id === id && this.matchesPrefixes(j));\n if (!job) {\n // Job not found - this can happen if the job was already completed/removed\n // or if there's a race condition. Silently ignore progress updates for missing jobs.\n const jobWithAnyPrefix = this.jobQueue.find((j) => j.id === id);\n getLogger().warn(\"Job not found for progress update\", {\n id,\n reason: jobWithAnyPrefix ? \"prefix_mismatch\" : \"missing\",\n existingStatus: jobWithAnyPrefix?.status,\n queueName: this.queueName,\n prefixValues: this.prefixValues,\n });\n return;\n }\n\n // Skip progress updates for jobs that are already completed or failed\n // to avoid unnecessary updates and potential race conditions\n if (job.status === JobStatus.COMPLETED || job.status === JobStatus.FAILED) {\n getLogger().warn(\"Job already completed or failed for progress update\", {\n id,\n status: job.status,\n completedAt: job.completed_at,\n error: job.error,\n });\n return;\n }\n\n const oldJob = { ...job };\n job.progress = progress;\n job.progress_message = message;\n job.progress_details = details;\n this.events.emit(\"change\", { type: \"UPDATE\", old: oldJob, new: job });\n }\n\n /**\n * Marks a job as complete with its output or error\n * Handles run_attempts for failed jobs and triggers completion callbacks\n * @param id - ID of the job to complete\n * @param output - Result of the job execution\n * @param error - Optional error message if job failed\n */\n public async complete(job: JobStorageFormat<Input, Output>) {\n await sleep(0);\n const jobWithPrefixes = job as JobStorageFormat<Input, Output> & Record<string, unknown>;\n const index = this.jobQueue.findIndex((j) => j.id === job.id && this.matchesPrefixes(j));\n if (index !== -1) {\n const existing = this.jobQueue[index];\n const currentAttempts = existing?.run_attempts ?? 0;\n jobWithPrefixes.run_attempts = currentAttempts + 1;\n // Preserve prefix values from the existing job\n for (const [key, value] of Object.entries(this.prefixValues)) {\n jobWithPrefixes[key] = value;\n }\n this.jobQueue[index] = jobWithPrefixes;\n this.events.emit(\"change\", { type: \"UPDATE\", old: existing, new: jobWithPrefixes });\n }\n }\n\n /**\n * Releases a claimed job back to PENDING without incrementing run_attempts.\n * @param id - The id of the claimed job to release.\n */\n public async release(id: unknown): Promise<void> {\n await sleep(0);\n const job = this.jobQueue.find((j) => j.id === id && this.matchesPrefixes(j));\n if (job) {\n const oldJob = { ...job };\n job.status = JobStatus.PENDING;\n job.worker_id = null;\n job.progress = 0;\n job.progress_message = \"\";\n job.progress_details = null;\n this.events.emit(\"change\", { type: \"UPDATE\", old: oldJob, new: job });\n }\n }\n\n /**\n * Aborts a job\n * @param id - The id of the job to abort.\n */\n public async abort(id: unknown): Promise<void> {\n await sleep(0);\n const job = this.jobQueue.find((j) => j.id === id && this.matchesPrefixes(j));\n if (job) {\n const oldJob = { ...job };\n job.status = JobStatus.ABORTING;\n this.events.emit(\"change\", { type: \"UPDATE\", old: oldJob, new: job });\n }\n }\n\n /**\n * Retrieves all jobs by their job_run_id.\n * @param job_run_id - The job_run_id of the jobs to retrieve.\n * @returns A promise that resolves to an array of jobs.\n */\n public async getByRunId(runId: string): Promise<Array<JobStorageFormat<Input, Output>>> {\n await sleep(0);\n return this.jobQueue.filter((job) => this.matchesPrefixes(job) && job.job_run_id === runId);\n }\n\n /**\n * Deletes all jobs from the queue that match the current prefix values.\n */\n public async deleteAll(): Promise<void> {\n await sleep(0);\n const deletedJobs = this.jobQueue.filter((job) => this.matchesPrefixes(job));\n this.jobQueue = this.jobQueue.filter((job) => !this.matchesPrefixes(job));\n for (const job of deletedJobs) {\n this.events.emit(\"change\", { type: \"DELETE\", old: job });\n }\n }\n\n /**\n * Looks up cached output for a given input\n * Uses input fingerprinting for efficient matching\n * @param input - The input to look up the cached output for.\n * @returns The cached output or null if not found\n */\n public async outputForInput(input: Input): Promise<Output | null> {\n await sleep(0);\n const fingerprint = await makeFingerprint(input);\n return (\n this.jobQueue.find(\n (j) =>\n this.matchesPrefixes(j) &&\n j.fingerprint === fingerprint &&\n j.status === JobStatus.COMPLETED\n )?.output ?? null\n );\n }\n\n /**\n * Deletes a job by its ID\n */\n public async delete(id: unknown): Promise<void> {\n await sleep(0);\n const deletedJob = this.jobQueue.find((job) => job.id === id && this.matchesPrefixes(job));\n this.jobQueue = this.jobQueue.filter((job) => !(job.id === id && this.matchesPrefixes(job)));\n if (deletedJob) {\n this.events.emit(\"change\", { type: \"DELETE\", old: deletedJob });\n }\n }\n\n /**\n * Delete jobs with a specific status older than a cutoff date\n * @param status - Status of jobs to delete\n * @param olderThanMs - Delete jobs completed more than this many milliseconds ago\n */\n public async deleteJobsByStatusAndAge(status: JobStatus, olderThanMs: number): Promise<void> {\n await sleep(0);\n const cutoffDate = new Date(Date.now() - olderThanMs).toISOString();\n const deletedJobs = this.jobQueue.filter(\n (job) =>\n this.matchesPrefixes(job) &&\n job.status === status &&\n job.completed_at &&\n job.completed_at <= cutoffDate\n );\n this.jobQueue = this.jobQueue.filter(\n (job) =>\n !this.matchesPrefixes(job) ||\n job.status !== status ||\n !job.completed_at ||\n job.completed_at > cutoffDate\n );\n for (const job of deletedJobs) {\n this.events.emit(\"change\", { type: \"DELETE\", old: job });\n }\n }\n\n /**\n * Sets up the database schema and tables.\n * No-op for in-memory storage as it doesn't require database setup.\n */\n public async setupDatabase(): Promise<void> {\n // No-op for in-memory storage\n }\n\n /**\n * Checks if a job matches the specified prefix filter\n * @param job - The job to check\n * @param prefixFilter - The prefix filter (undefined = use instance prefixes, {} = no filter)\n */\n private matchesPrefixFilter(\n job: JobStorageFormat<Input, Output>,\n prefixFilter?: Readonly<Record<string, string | number>>\n ): boolean {\n // If prefixFilter is explicitly an empty object, no prefix filtering\n if (prefixFilter && Object.keys(prefixFilter).length === 0) {\n return true;\n }\n\n // Use provided prefixFilter or fall back to instance's prefixValues\n const filterValues = prefixFilter ?? this.prefixValues;\n\n // If no filter values, match all\n if (Object.keys(filterValues).length === 0) {\n return true;\n }\n\n // Check each filter value\n const jobWithPrefixes = job as JobStorageFormat<Input, Output> & Record<string, unknown>;\n for (const [key, value] of Object.entries(filterValues)) {\n if (jobWithPrefixes[key] !== value) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Subscribes to changes in the queue.\n * Since InMemory is both client and server, changes are detected via local events.\n *\n * @param callback - Function called when a change occurs\n * @param options - Subscription options including prefix filter\n * @returns Unsubscribe function\n */\n public subscribeToChanges(\n callback: (change: QueueChangePayload<Input, Output>) => void,\n options?: QueueSubscribeOptions\n ): () => void {\n const prefixFilter = options?.prefixFilter;\n\n // Create a filtered callback wrapper\n const filteredCallback = (change: QueueChangePayload<Input, Output>) => {\n // Check if either old or new job matches the filter\n const newMatches = change.new ? this.matchesPrefixFilter(change.new, prefixFilter) : false;\n const oldMatches = change.old ? this.matchesPrefixFilter(change.old, prefixFilter) : false;\n\n if (!newMatches && !oldMatches) {\n return;\n }\n\n callback(change);\n };\n\n return this.events.subscribe(\"change\", filteredCallback);\n }\n}\n",
|
|
22
|
-
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { createServiceToken } from \"@workglow/util\";\n\nexport const QUEUE_STORAGE = createServiceToken<IQueueStorage<any, any>>(\"jobqueue.storage\");\n\n/**\n * The type of a prefix column.\n * - \"uuid\" maps to UUID in PostgreSQL/Supabase, TEXT in SQLite/IndexedDB/InMemory\n * - \"number\" maps to INTEGER in PostgreSQL/Supabase/SQLite, number in IndexedDB/InMemory\n */\nexport type PrefixColumnType = \"uuid\" | \"number\";\n\n/**\n * Defines a prefix column for queue storage filtering.\n */\nexport interface PrefixColumn {\n readonly name: string;\n readonly type: PrefixColumnType;\n}\n\n/**\n * Options for configuring queue storage with prefix filters.\n */\nexport interface QueueStorageOptions {\n /** The prefix column definitions for this storage */\n readonly prefixes?: readonly PrefixColumn[];\n /** The values for each prefix column */\n readonly prefixValues?: Readonly<Record<string, string | number>>;\n}\n\nexport type JobStatus = \"PENDING\" | \"PROCESSING\" | \"COMPLETED\" | \"ABORTING\" | \"FAILED\" | \"DISABLED\";\nexport const JobStatus = {\n PENDING: \"PENDING\",\n PROCESSING: \"PROCESSING\",\n COMPLETED: \"COMPLETED\",\n ABORTING: \"ABORTING\",\n FAILED: \"FAILED\",\n DISABLED: \"DISABLED\",\n} as const satisfies Record<JobStatus, JobStatus>;\n\n/**\n * Type of change that occurred in the queue\n */\nexport type QueueChangeType = \"INSERT\" | \"UPDATE\" | \"DELETE\";\n\n/**\n * Payload describing a change to a job\n */\nexport interface QueueChangePayload<Input, Output> {\n readonly type: QueueChangeType;\n readonly old?: JobStorageFormat<Input, Output>;\n readonly new?: JobStorageFormat<Input, Output>;\n}\n\n/**\n * Options for subscribing to queue changes\n */\nexport interface QueueSubscribeOptions {\n /** Polling interval in milliseconds (used by implementations that rely on polling) */\n readonly pollingIntervalMs?: number;\n /**\n * Custom prefix filter for this subscription.\n *\n * - If not provided (undefined): Uses the storage instance's configured prefixValues\n * - If empty object ({}): Receives ALL changes across all prefix combinations\n * - If partial object: Receives changes matching the specified subset of prefixes\n *\n * @example\n * // Storage configured with prefixes: [{name: \"user_id\"}, {name: \"project_id\"}]\n * // and prefixValues: {user_id: \"abc\", project_id: \"123\"}\n *\n * // Subscribe to only this user+project (default behavior)\n * storage.subscribeToChanges(callback);\n *\n * // Subscribe to all projects for this user\n * storage.subscribeToChanges(callback, { prefixFilter: { user_id: \"abc\" } });\n *\n * // Subscribe to ALL jobs in this queue (admin/supervisor view)\n * storage.subscribeToChanges(callback, { prefixFilter: {} });\n */\n readonly prefixFilter?: Readonly<Record<string, string | number>>;\n}\n\n/**\n * Details about a job that reflect the structure in the database.\n */\nexport type JobStorageFormat<Input, Output> = {\n id?: unknown;\n job_run_id?: string;\n queue?: string;\n input: Input;\n output?: Output | null;\n error?: string | null;\n error_code?: string | null;\n fingerprint?: string;\n max_retries?: number;\n status?: JobStatus;\n created_at?: string;\n deadline_at?: string | null;\n last_ran_at?: string | null;\n run_after: string | null;\n completed_at: string | null;\n run_attempts?: number;\n progress?: number;\n progress_message?: string;\n progress_details?: Record<string, any> | null;\n worker_id?: string | null;\n};\n\n/**\n * Interface defining the storage operations for a job queue\n */\nexport interface IQueueStorage<Input, Output> {\n /**\n * Adds a job to the queue storage\n * @param job - The job to add to the queue storage\n * @returns The ID of the job\n */\n add(job: JobStorageFormat<Input, Output>): Promise<unknown>;\n\n /**\n * Gets a job from the queue storage by ID\n * @param id - The ID of the job to get\n * @returns The job with the given ID\n */\n get(id: unknown): Promise<JobStorageFormat<Input, Output> | undefined>;\n\n /**\n * Gets the next job from the queue storage\n * @param workerId - Worker ID to associate with the job (required)\n * @returns The next job from the queue storage\n */\n next(workerId: string): Promise<JobStorageFormat<Input, Output> | undefined>;\n\n /**\n * Releases a job that was just claimed by {@link next} but won't be\n * processed (e.g. the worker was stopped mid-claim). Resets status to\n * PENDING and clears worker_id WITHOUT incrementing run_attempts —\n * the worker never actually attempted execution, so the retry budget\n * must be preserved.\n * @param id - The id of the claimed job to release.\n */\n release(id: unknown): Promise<void>;\n\n /**\n * Peeks at the next job(s) from the queue storage without removing them\n * @param status - The status of the jobs to peek at\n * @param num - The number of jobs to peek at\n * @returns The jobs with the given status\n */\n peek(status?: JobStatus, num?: number): Promise<Array<JobStorageFormat<Input, Output>>>;\n\n /**\n * Gets the size of the queue storage\n * @param status - The status of the jobs to get the size for\n * @returns The size of the queue storage\n */\n size(status?: JobStatus): Promise<number>;\n\n /**\n * Completes a job in the queue storage\n * @param job - The job to complete\n */\n complete(job: JobStorageFormat<Input, Output>): Promise<void>;\n\n /**\n * Deletes all jobs from the queue storage\n */\n deleteAll(): Promise<void>;\n\n /**\n * Gets the output for a given input from the queue storage\n * @param input - The input to get the output for\n * @returns The output of the job\n */\n outputForInput(input: Input): Promise<Output | null>;\n\n /**\n * Aborts a job in the queue storage\n * @param id - The ID of the job to abort\n */\n abort(id: unknown): Promise<void>;\n\n /**\n * Gets the jobs by job run ID from the queue storage\n * @param runId - The job run ID of the jobs to get\n * @returns The jobs with the given job run ID\n */\n getByRunId(runId: string): Promise<Array<JobStorageFormat<Input, Output>>>;\n\n /**\n * Saves progress updates for a job in the queue storage\n * @param id - The ID of the job to save the progress for\n * @param progress - The progress of the job\n * @param message - The message of the job\n * @param details - The details of the job\n */\n saveProgress(\n id: unknown,\n progress: number,\n message: string,\n details: Record<string, any> | null\n ): Promise<void>;\n\n /**\n * Deletes a job by its ID from the queue storage\n * @param id - The ID of the job to delete\n */\n delete(id: unknown): Promise<void>;\n\n /**\n * Deletes jobs from the queue storage that are of a specific status and older than the specified time\n * @param status - The status of the jobs to delete\n * @param olderThanMs - The time in milliseconds that the jobs must be older than to be deleted\n */\n deleteJobsByStatusAndAge(status: JobStatus, olderThanMs: number): Promise<void>;\n\n /**\n * Sets up the database schema and tables.\n * This method should be called before using the storage in tests.\n * For production use, database setup should be done via migrations.\n */\n setupDatabase(): Promise<void>;\n\n /**\n * Subscribes to changes in the queue (including remote changes).\n * @param callback - Function called when a change occurs\n * @param options - Optional subscription options (e.g., polling interval)\n * @returns Unsubscribe function\n */\n subscribeToChanges(\n callback: (change: QueueChangePayload<Input, Output>) => void,\n options?: QueueSubscribeOptions\n ): () => void;\n}\n",
|
|
23
|
-
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { traced } from \"../util/traced\";\nimport type {\n IQueueStorage,\n JobStatus,\n JobStorageFormat,\n QueueChangePayload,\n QueueSubscribeOptions,\n} from \"./IQueueStorage\";\n\n/**\n * Telemetry wrapper for any IQueueStorage implementation.\n * Creates spans for all queue storage operations.\n */\nexport class TelemetryQueueStorage<Input, Output> implements IQueueStorage<Input, Output> {\n constructor(\n private readonly storageName: string,\n private readonly inner: IQueueStorage<Input, Output>\n ) {}\n\n add(job: JobStorageFormat<Input, Output>): Promise<unknown> {\n return traced(\"workglow.storage.queue.add\", this.storageName, () => this.inner.add(job));\n }\n get(id: unknown): Promise<JobStorageFormat<Input, Output> | undefined> {\n return traced(\"workglow.storage.queue.get\", this.storageName, () => this.inner.get(id));\n }\n next(workerId: string): Promise<JobStorageFormat<Input, Output> | undefined> {\n return traced(\"workglow.storage.queue.next\", this.storageName, () => this.inner.next(workerId));\n }\n peek(status?: JobStatus, num?: number): Promise<Array<JobStorageFormat<Input, Output>>> {\n return traced(\"workglow.storage.queue.peek\", this.storageName, () =>\n this.inner.peek(status, num)\n );\n }\n size(status?: JobStatus): Promise<number> {\n return traced(\"workglow.storage.queue.size\", this.storageName, () => this.inner.size(status));\n }\n complete(job: JobStorageFormat<Input, Output>): Promise<void> {\n return traced(\"workglow.storage.queue.complete\", this.storageName, () =>\n this.inner.complete(job)\n );\n }\n release(id: unknown): Promise<void> {\n return traced(\"workglow.storage.queue.release\", this.storageName, () => this.inner.release(id));\n }\n deleteAll(): Promise<void> {\n return traced(\"workglow.storage.queue.deleteAll\", this.storageName, () =>\n this.inner.deleteAll()\n );\n }\n outputForInput(input: Input): Promise<Output | null> {\n return traced(\"workglow.storage.queue.outputForInput\", this.storageName, () =>\n this.inner.outputForInput(input)\n );\n }\n abort(id: unknown): Promise<void> {\n return traced(\"workglow.storage.queue.abort\", this.storageName, () => this.inner.abort(id));\n }\n getByRunId(runId: string): Promise<Array<JobStorageFormat<Input, Output>>> {\n return traced(\"workglow.storage.queue.getByRunId\", this.storageName, () =>\n this.inner.getByRunId(runId)\n );\n }\n saveProgress(\n id: unknown,\n progress: number,\n message: string,\n details: Record<string, any> | null\n ): Promise<void> {\n return traced(\"workglow.storage.queue.saveProgress\", this.storageName, () =>\n this.inner.saveProgress(id, progress, message, details)\n );\n }\n delete(id: unknown): Promise<void> {\n return traced(\"workglow.storage.queue.delete\", this.storageName, () => this.inner.delete(id));\n }\n deleteJobsByStatusAndAge(status: JobStatus, olderThanMs: number): Promise<void> {\n return traced(\"workglow.storage.queue.deleteJobsByStatusAndAge\", this.storageName, () =>\n this.inner.deleteJobsByStatusAndAge(status, olderThanMs)\n );\n }\n setupDatabase(): Promise<void> {\n return this.inner.setupDatabase();\n }\n subscribeToChanges(\n callback: (change: QueueChangePayload<Input, Output>) => void,\n options?: QueueSubscribeOptions\n ): () => void {\n return this.inner.subscribeToChanges(callback, options);\n }\n}\n",
|
|
24
|
-
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { createServiceToken, sleep } from \"@workglow/util\";\nimport {
|
|
25
|
-
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { createServiceToken } from \"@workglow/util\";\nimport type { PrefixColumn } from \"../queue/IQueueStorage\";\n\nexport const RATE_LIMITER_STORAGE = createServiceToken<IRateLimiterStorage>(\"ratelimiter.storage\");\n\n/**\n * Options for configuring rate limiter storage with prefix filters.\n */\nexport interface RateLimiterStorageOptions {\n /** The prefix column definitions for this storage */\n readonly prefixes?: readonly PrefixColumn[];\n /** The values for each prefix column */\n readonly prefixValues?: Readonly<Record<string, string | number>>;\n}\n\n/**\n * Record of a job execution for rate limiting tracking.\n */\nexport interface ExecutionRecord {\n readonly id?: unknown;\n readonly queue_name: string;\n readonly executed_at: string;\n}\n\n/**\n * Record of the next available time for a queue.\n */\nexport interface NextAvailableRecord {\n readonly queue_name: string;\n readonly next_available_at: string;\n}\n\n/**\n * Interface defining the storage operations for a rate limiter.\n * This separates the storage concerns from the rate limiting logic.\n */\nexport interface IRateLimiterStorage {\n /**\n * Sets up the database schema and tables.\n * This method should be called before using the storage.\n * For production use, database setup should be done via migrations.\n */\n setupDatabase(): Promise<void>;\n\n /**\n * Records a job execution for rate limiting tracking.\n * @param queueName - The name of the queue\n */\n recordExecution(queueName: string): Promise<void>;\n\n /**\n * Gets the count of executions within a time window.\n * @param queueName - The name of the queue\n * @param windowStartTime - The start of the time window (ISO string)\n * @returns The count of executions within the window\n */\n getExecutionCount(queueName: string, windowStartTime: string): Promise<number>;\n\n /**\n * Gets the oldest execution time within the window, offset by a count.\n * Used to calculate when the rate limit will allow the next execution.\n * @param queueName - The name of the queue\n * @param offset - The offset (typically maxExecutions - 1)\n * @returns The execution time or undefined if not enough executions\n */\n getOldestExecutionAtOffset(queueName: string, offset: number): Promise<string | undefined>;\n\n /**\n * Gets the next available time for a queue.\n * @param queueName - The name of the queue\n * @returns The next available time or undefined if not set\n */\n getNextAvailableTime(queueName: string): Promise<string | undefined>;\n\n /**\n * Sets the next available time for a queue.\n * @param queueName - The name of the queue\n * @param nextAvailableAt - The next available time (ISO string)\n */\n setNextAvailableTime(queueName: string, nextAvailableAt: string): Promise<void>;\n\n /**\n * Clears all rate limit entries for a queue.\n * @param queueName - The name of the queue\n */\n clear(queueName: string): Promise<void>;\n}\n",
|
|
21
|
+
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {\n createServiceToken,\n EventEmitter,\n getLogger,\n makeFingerprint,\n sleep,\n uuid4,\n} from \"@workglow/util\";\nimport {\n IQueueStorage,\n JobStatus,\n JobStorageFormat,\n QueueChangePayload,\n QueueStorageOptions,\n QueueSubscribeOptions,\n} from \"./IQueueStorage\";\n\n/**\n * Event listeners for queue storage events\n */\ntype QueueEventListeners<Input, Output> = {\n change: (payload: QueueChangePayload<Input, Output>) => void;\n};\n\nexport const IN_MEMORY_QUEUE_STORAGE = createServiceToken<IQueueStorage<any, any>>(\n \"jobqueue.storage.inMemory\"\n);\n\n/**\n * In-memory implementation of a job queue that manages asynchronous tasks.\n * Supports job scheduling, status tracking, result caching, and prefix-based filtering.\n */\nexport class InMemoryQueueStorage<Input, Output> implements IQueueStorage<Input, Output> {\n public readonly scope = \"process\" as const;\n /** The prefix values for filtering jobs */\n protected readonly prefixValues: Readonly<Record<string, string | number>>;\n /** Event emitter for change notifications */\n protected readonly events = new EventEmitter<QueueEventListeners<Input, Output>>();\n\n /**\n * Creates a new in-memory job queue\n * @param queueName - Name of the queue\n * @param options - Optional configuration including prefix filters\n */\n constructor(\n public readonly queueName: string,\n options?: QueueStorageOptions\n ) {\n this.jobQueue = [];\n this.prefixValues = options?.prefixValues ?? {};\n }\n\n /** Internal array storing all jobs */\n public jobQueue: Array<JobStorageFormat<Input, Output> & Record<string, unknown>>;\n\n /**\n * Checks if a job matches the current prefix values\n */\n private matchesPrefixes(job: JobStorageFormat<Input, Output> & Record<string, unknown>): boolean {\n for (const [key, value] of Object.entries(this.prefixValues)) {\n if (job[key] !== value) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Returns a filtered and sorted list of pending jobs that are ready to run\n * Sorts by creation time to maintain FIFO order\n */\n private pendingQueue(): Array<JobStorageFormat<Input, Output> & Record<string, unknown>> {\n const now = new Date().toISOString();\n return this.jobQueue\n .filter((job) => this.matchesPrefixes(job))\n .filter((job) => job.status === JobStatus.PENDING)\n .filter((job) => !job.run_after || job.run_after <= now)\n .sort((a, b) => (a.run_after || \"\").localeCompare(b.run_after || \"\"));\n }\n\n /**\n * Adds a new job to the queue\n * Generates an ID and fingerprint if not provided\n */\n public async add(job: JobStorageFormat<Input, Output>): Promise<unknown> {\n await sleep(0);\n const now = new Date().toISOString();\n const jobWithPrefixes = job as JobStorageFormat<Input, Output> & Record<string, unknown>;\n jobWithPrefixes.id = jobWithPrefixes.id ?? uuid4();\n jobWithPrefixes.job_run_id = jobWithPrefixes.job_run_id ?? uuid4();\n jobWithPrefixes.queue = this.queueName;\n jobWithPrefixes.fingerprint = await makeFingerprint(jobWithPrefixes.input);\n jobWithPrefixes.status = JobStatus.PENDING;\n jobWithPrefixes.progress = 0;\n jobWithPrefixes.progress_message = \"\";\n jobWithPrefixes.progress_details = null;\n jobWithPrefixes.created_at = now;\n jobWithPrefixes.run_after = now;\n\n // Add prefix values to the job\n for (const [key, value] of Object.entries(this.prefixValues)) {\n jobWithPrefixes[key] = value;\n }\n\n this.jobQueue.push(jobWithPrefixes);\n this.events.emit(\"change\", { type: \"INSERT\", new: jobWithPrefixes });\n return jobWithPrefixes.id;\n }\n\n /**\n * Retrieves a job from the queue by its id.\n * @param id - The id of the job to retrieve.\n * @returns A promise that resolves to the job or undefined if the job is not found.\n */\n public async get(id: unknown): Promise<JobStorageFormat<Input, Output> | undefined> {\n await sleep(0);\n const job = this.jobQueue.find((j) => j.id === id);\n if (job && this.matchesPrefixes(job)) {\n return job;\n }\n return undefined;\n }\n\n /**\n * Retrieves a slice of jobs from the queue.\n * @param status - The status of the jobs to retrieve.\n * @param num - The number of jobs to retrieve.\n * @returns A promise that resolves to an array of jobs.\n */\n public async peek(\n status: JobStatus = JobStatus.PENDING,\n num: number = 100\n ): Promise<Array<JobStorageFormat<Input, Output>>> {\n await sleep(0);\n num = Number(num) || 100;\n return this.jobQueue\n .filter((j) => this.matchesPrefixes(j))\n .sort((a, b) => (a.run_after || \"\").localeCompare(b.run_after || \"\"))\n .filter((j) => j.status === status)\n .slice(0, num);\n }\n\n /**\n * Retrieves the next available job that is ready to be processed\n * Updates the job status to PROCESSING before returning\n * @param workerId - Worker ID to associate with the job\n * @returns The next job or undefined if no job is available\n */\n public async next(workerId: string): Promise<JobStorageFormat<Input, Output> | undefined> {\n await sleep(0);\n const top = this.pendingQueue();\n\n const job = top[0];\n if (job) {\n const oldJob = { ...job };\n job.status = JobStatus.PROCESSING;\n job.last_ran_at = new Date().toISOString();\n job.worker_id = workerId;\n this.events.emit(\"change\", { type: \"UPDATE\", old: oldJob, new: job });\n return job;\n }\n }\n\n /**\n * Retrieves the size of the queue for a given status\n * @param status - The status of the jobs to retrieve.\n * @returns A promise that resolves to the number of jobs.\n */\n public async size(status = JobStatus.PENDING): Promise<number> {\n await sleep(0);\n return this.jobQueue.filter((j) => this.matchesPrefixes(j) && j.status === status).length;\n }\n\n /**\n * Saves the progress of a job\n * @param jobId - The id of the job to save the progress for.\n * @param progress - The progress of the job.\n * @param message - The message of the job.\n * @param details - The details of the job.\n */\n public async saveProgress(\n id: unknown,\n progress: number,\n message: string,\n details: Record<string, any> | null\n ): Promise<void> {\n await sleep(0);\n const job = this.jobQueue.find((j) => j.id === id && this.matchesPrefixes(j));\n if (!job) {\n // Job not found - this can happen if the job was already completed/removed\n // or if there's a race condition. Silently ignore progress updates for missing jobs.\n const jobWithAnyPrefix = this.jobQueue.find((j) => j.id === id);\n getLogger().warn(\"Job not found for progress update\", {\n id,\n reason: jobWithAnyPrefix ? \"prefix_mismatch\" : \"missing\",\n existingStatus: jobWithAnyPrefix?.status,\n queueName: this.queueName,\n prefixValues: this.prefixValues,\n });\n return;\n }\n\n // Skip progress updates for jobs that are already completed or failed\n // to avoid unnecessary updates and potential race conditions\n if (job.status === JobStatus.COMPLETED || job.status === JobStatus.FAILED) {\n getLogger().warn(\"Job already completed or failed for progress update\", {\n id,\n status: job.status,\n completedAt: job.completed_at,\n error: job.error,\n });\n return;\n }\n\n const oldJob = { ...job };\n job.progress = progress;\n job.progress_message = message;\n job.progress_details = details;\n this.events.emit(\"change\", { type: \"UPDATE\", old: oldJob, new: job });\n }\n\n /**\n * Marks a job as complete with its output or error\n * Handles run_attempts for failed jobs and triggers completion callbacks\n * @param id - ID of the job to complete\n * @param output - Result of the job execution\n * @param error - Optional error message if job failed\n */\n public async complete(job: JobStorageFormat<Input, Output>) {\n await sleep(0);\n const jobWithPrefixes = job as JobStorageFormat<Input, Output> & Record<string, unknown>;\n const index = this.jobQueue.findIndex((j) => j.id === job.id && this.matchesPrefixes(j));\n if (index !== -1) {\n const existing = this.jobQueue[index];\n const currentAttempts = existing?.run_attempts ?? 0;\n jobWithPrefixes.run_attempts = currentAttempts + 1;\n // Preserve prefix values from the existing job\n for (const [key, value] of Object.entries(this.prefixValues)) {\n jobWithPrefixes[key] = value;\n }\n this.jobQueue[index] = jobWithPrefixes;\n this.events.emit(\"change\", { type: \"UPDATE\", old: existing, new: jobWithPrefixes });\n }\n }\n\n /**\n * Releases a claimed job back to PENDING without incrementing run_attempts.\n * @param id - The id of the claimed job to release.\n */\n public async release(id: unknown): Promise<void> {\n await sleep(0);\n const job = this.jobQueue.find((j) => j.id === id && this.matchesPrefixes(j));\n if (job) {\n const oldJob = { ...job };\n job.status = JobStatus.PENDING;\n job.worker_id = null;\n job.progress = 0;\n job.progress_message = \"\";\n job.progress_details = null;\n this.events.emit(\"change\", { type: \"UPDATE\", old: oldJob, new: job });\n }\n }\n\n /**\n * Aborts a job\n * @param id - The id of the job to abort.\n */\n public async abort(id: unknown): Promise<void> {\n await sleep(0);\n const job = this.jobQueue.find((j) => j.id === id && this.matchesPrefixes(j));\n if (job) {\n const oldJob = { ...job };\n job.status = JobStatus.ABORTING;\n this.events.emit(\"change\", { type: \"UPDATE\", old: oldJob, new: job });\n }\n }\n\n /**\n * Retrieves all jobs by their job_run_id.\n * @param job_run_id - The job_run_id of the jobs to retrieve.\n * @returns A promise that resolves to an array of jobs.\n */\n public async getByRunId(runId: string): Promise<Array<JobStorageFormat<Input, Output>>> {\n await sleep(0);\n return this.jobQueue.filter((job) => this.matchesPrefixes(job) && job.job_run_id === runId);\n }\n\n /**\n * Deletes all jobs from the queue that match the current prefix values.\n */\n public async deleteAll(): Promise<void> {\n await sleep(0);\n const deletedJobs = this.jobQueue.filter((job) => this.matchesPrefixes(job));\n this.jobQueue = this.jobQueue.filter((job) => !this.matchesPrefixes(job));\n for (const job of deletedJobs) {\n this.events.emit(\"change\", { type: \"DELETE\", old: job });\n }\n }\n\n /**\n * Looks up cached output for a given input\n * Uses input fingerprinting for efficient matching\n * @param input - The input to look up the cached output for.\n * @returns The cached output or null if not found\n */\n public async outputForInput(input: Input): Promise<Output | null> {\n await sleep(0);\n const fingerprint = await makeFingerprint(input);\n return (\n this.jobQueue.find(\n (j) =>\n this.matchesPrefixes(j) &&\n j.fingerprint === fingerprint &&\n j.status === JobStatus.COMPLETED\n )?.output ?? null\n );\n }\n\n /**\n * Deletes a job by its ID\n */\n public async delete(id: unknown): Promise<void> {\n await sleep(0);\n const deletedJob = this.jobQueue.find((job) => job.id === id && this.matchesPrefixes(job));\n this.jobQueue = this.jobQueue.filter((job) => !(job.id === id && this.matchesPrefixes(job)));\n if (deletedJob) {\n this.events.emit(\"change\", { type: \"DELETE\", old: deletedJob });\n }\n }\n\n /**\n * Delete jobs with a specific status older than a cutoff date\n * @param status - Status of jobs to delete\n * @param olderThanMs - Delete jobs completed more than this many milliseconds ago\n */\n public async deleteJobsByStatusAndAge(status: JobStatus, olderThanMs: number): Promise<void> {\n await sleep(0);\n const cutoffDate = new Date(Date.now() - olderThanMs).toISOString();\n const deletedJobs = this.jobQueue.filter(\n (job) =>\n this.matchesPrefixes(job) &&\n job.status === status &&\n job.completed_at &&\n job.completed_at <= cutoffDate\n );\n this.jobQueue = this.jobQueue.filter(\n (job) =>\n !this.matchesPrefixes(job) ||\n job.status !== status ||\n !job.completed_at ||\n job.completed_at > cutoffDate\n );\n for (const job of deletedJobs) {\n this.events.emit(\"change\", { type: \"DELETE\", old: job });\n }\n }\n\n /**\n * Sets up the database schema and tables.\n * No-op for in-memory storage as it doesn't require database setup.\n */\n public async setupDatabase(): Promise<void> {\n // No-op for in-memory storage\n }\n\n /**\n * Checks if a job matches the specified prefix filter\n * @param job - The job to check\n * @param prefixFilter - The prefix filter (undefined = use instance prefixes, {} = no filter)\n */\n private matchesPrefixFilter(\n job: JobStorageFormat<Input, Output>,\n prefixFilter?: Readonly<Record<string, string | number>>\n ): boolean {\n // If prefixFilter is explicitly an empty object, no prefix filtering\n if (prefixFilter && Object.keys(prefixFilter).length === 0) {\n return true;\n }\n\n // Use provided prefixFilter or fall back to instance's prefixValues\n const filterValues = prefixFilter ?? this.prefixValues;\n\n // If no filter values, match all\n if (Object.keys(filterValues).length === 0) {\n return true;\n }\n\n // Check each filter value\n const jobWithPrefixes = job as JobStorageFormat<Input, Output> & Record<string, unknown>;\n for (const [key, value] of Object.entries(filterValues)) {\n if (jobWithPrefixes[key] !== value) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Subscribes to changes in the queue.\n * Since InMemory is both client and server, changes are detected via local events.\n *\n * @param callback - Function called when a change occurs\n * @param options - Subscription options including prefix filter\n * @returns Unsubscribe function\n */\n public subscribeToChanges(\n callback: (change: QueueChangePayload<Input, Output>) => void,\n options?: QueueSubscribeOptions\n ): () => void {\n const prefixFilter = options?.prefixFilter;\n\n // Create a filtered callback wrapper\n const filteredCallback = (change: QueueChangePayload<Input, Output>) => {\n // Check if either old or new job matches the filter\n const newMatches = change.new ? this.matchesPrefixFilter(change.new, prefixFilter) : false;\n const oldMatches = change.old ? this.matchesPrefixFilter(change.old, prefixFilter) : false;\n\n if (!newMatches && !oldMatches) {\n return;\n }\n\n callback(change);\n };\n\n return this.events.subscribe(\"change\", filteredCallback);\n }\n}\n",
|
|
22
|
+
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { createServiceToken } from \"@workglow/util\";\n\nexport const QUEUE_STORAGE = createServiceToken<IQueueStorage<any, any>>(\"jobqueue.storage\");\n\n/**\n * The type of a prefix column.\n * - \"uuid\" maps to UUID in PostgreSQL/Supabase, TEXT in SQLite/IndexedDB/InMemory\n * - \"number\" maps to INTEGER in PostgreSQL/Supabase/SQLite, number in IndexedDB/InMemory\n */\nexport type PrefixColumnType = \"uuid\" | \"number\";\n\n/**\n * Defines a prefix column for queue storage filtering.\n */\nexport interface PrefixColumn {\n readonly name: string;\n readonly type: PrefixColumnType;\n}\n\n/**\n * Options for configuring queue storage with prefix filters.\n */\nexport interface QueueStorageOptions {\n /** The prefix column definitions for this storage */\n readonly prefixes?: readonly PrefixColumn[];\n /** The values for each prefix column */\n readonly prefixValues?: Readonly<Record<string, string | number>>;\n}\n\nexport type JobStatus = \"PENDING\" | \"PROCESSING\" | \"COMPLETED\" | \"ABORTING\" | \"FAILED\" | \"DISABLED\";\nexport const JobStatus = {\n PENDING: \"PENDING\",\n PROCESSING: \"PROCESSING\",\n COMPLETED: \"COMPLETED\",\n ABORTING: \"ABORTING\",\n FAILED: \"FAILED\",\n DISABLED: \"DISABLED\",\n} as const satisfies Record<JobStatus, JobStatus>;\n\n/**\n * Type of change that occurred in the queue.\n *\n * `RESYNC` is a synthetic event emitted by some backends (e.g. Postgres\n * LISTEN/NOTIFY) after a (re)connect to indicate that arbitrary changes may\n * have happened during a disconnect window. Subscribers should treat it as a\n * \"kick the workers, re-poll state\" signal — `old` and `new` are both\n * undefined.\n */\nexport type QueueChangeType = \"INSERT\" | \"UPDATE\" | \"DELETE\" | \"RESYNC\";\n\n/**\n * Payload describing a change to a job\n */\nexport interface QueueChangePayload<Input, Output> {\n readonly type: QueueChangeType;\n readonly old?: JobStorageFormat<Input, Output>;\n readonly new?: JobStorageFormat<Input, Output>;\n}\n\n/**\n * Options for subscribing to queue changes\n */\nexport interface QueueSubscribeOptions {\n /** Polling interval in milliseconds (used by implementations that rely on polling) */\n readonly pollingIntervalMs?: number;\n /**\n * Custom prefix filter for this subscription.\n *\n * - If not provided (undefined): Uses the storage instance's configured prefixValues\n * - If empty object ({}): Receives ALL changes across all prefix combinations\n * - If partial object: Receives changes matching the specified subset of prefixes\n *\n * @example\n * // Storage configured with prefixes: [{name: \"user_id\"}, {name: \"project_id\"}]\n * // and prefixValues: {user_id: \"abc\", project_id: \"123\"}\n *\n * // Subscribe to only this user+project (default behavior)\n * storage.subscribeToChanges(callback);\n *\n * // Subscribe to all projects for this user\n * storage.subscribeToChanges(callback, { prefixFilter: { user_id: \"abc\" } });\n *\n * // Subscribe to ALL jobs in this queue (admin/supervisor view)\n * storage.subscribeToChanges(callback, { prefixFilter: {} });\n */\n readonly prefixFilter?: Readonly<Record<string, string | number>>;\n}\n\n/**\n * Details about a job that reflect the structure in the database.\n */\nexport type JobStorageFormat<Input, Output> = {\n id?: unknown;\n job_run_id?: string;\n queue?: string;\n input: Input;\n output?: Output | null;\n error?: string | null;\n error_code?: string | null;\n fingerprint?: string;\n max_retries?: number;\n status?: JobStatus;\n created_at?: string;\n deadline_at?: string | null;\n last_ran_at?: string | null;\n run_after: string | null;\n completed_at: string | null;\n run_attempts?: number;\n progress?: number;\n progress_message?: string;\n progress_details?: Record<string, any> | null;\n worker_id?: string | null;\n};\n\n/**\n * Whether a queue storage's state is shared across processes.\n *\n * - `\"process\"` — in-memory / per-process state. Workers in the same process\n * share it, but separate processes do not.\n * - `\"cluster\"` — state lives in shared external storage (Postgres, Supabase,\n * etc.) visible to every process. Pairing a `\"process\"`-scoped limiter with\n * a `\"cluster\"`-scoped queue almost always indicates a misconfiguration.\n */\nexport type QueueStorageScope = \"process\" | \"cluster\";\n\n/**\n * Interface defining the storage operations for a job queue\n */\nexport interface IQueueStorage<Input, Output> {\n /**\n * Whether this storage is shared across processes. In-memory / browser\n * backends MUST report `\"process\"`. Shared databases (Postgres, Supabase)\n * report `\"cluster\"`. Used by JobQueueServer to detect process-scoped\n * limiters paired with cluster-scoped queues.\n */\n readonly scope: QueueStorageScope;\n\n /**\n * Adds a job to the queue storage\n * @param job - The job to add to the queue storage\n * @returns The ID of the job\n */\n add(job: JobStorageFormat<Input, Output>): Promise<unknown>;\n\n /**\n * Gets a job from the queue storage by ID\n * @param id - The ID of the job to get\n * @returns The job with the given ID\n */\n get(id: unknown): Promise<JobStorageFormat<Input, Output> | undefined>;\n\n /**\n * Gets the next job from the queue storage\n * @param workerId - Worker ID to associate with the job (required)\n * @returns The next job from the queue storage\n */\n next(workerId: string): Promise<JobStorageFormat<Input, Output> | undefined>;\n\n /**\n * Releases a job that was just claimed by {@link next} but won't be\n * processed (e.g. the worker was stopped mid-claim). Resets status to\n * PENDING and clears worker_id WITHOUT incrementing run_attempts —\n * the worker never actually attempted execution, so the retry budget\n * must be preserved.\n * @param id - The id of the claimed job to release.\n */\n release(id: unknown): Promise<void>;\n\n /**\n * Peeks at the next job(s) from the queue storage without removing them\n * @param status - The status of the jobs to peek at\n * @param num - The number of jobs to peek at\n * @returns The jobs with the given status\n */\n peek(status?: JobStatus, num?: number): Promise<Array<JobStorageFormat<Input, Output>>>;\n\n /**\n * Gets the size of the queue storage\n * @param status - The status of the jobs to get the size for\n * @returns The size of the queue storage\n */\n size(status?: JobStatus): Promise<number>;\n\n /**\n * Completes a job in the queue storage\n * @param job - The job to complete\n */\n complete(job: JobStorageFormat<Input, Output>): Promise<void>;\n\n /**\n * Deletes all jobs from the queue storage\n */\n deleteAll(): Promise<void>;\n\n /**\n * Gets the output for a given input from the queue storage\n * @param input - The input to get the output for\n * @returns The output of the job\n */\n outputForInput(input: Input): Promise<Output | null>;\n\n /**\n * Aborts a job in the queue storage\n * @param id - The ID of the job to abort\n */\n abort(id: unknown): Promise<void>;\n\n /**\n * Gets the jobs by job run ID from the queue storage\n * @param runId - The job run ID of the jobs to get\n * @returns The jobs with the given job run ID\n */\n getByRunId(runId: string): Promise<Array<JobStorageFormat<Input, Output>>>;\n\n /**\n * Saves progress updates for a job in the queue storage\n * @param id - The ID of the job to save the progress for\n * @param progress - The progress of the job\n * @param message - The message of the job\n * @param details - The details of the job\n */\n saveProgress(\n id: unknown,\n progress: number,\n message: string,\n details: Record<string, any> | null\n ): Promise<void>;\n\n /**\n * Deletes a job by its ID from the queue storage\n * @param id - The ID of the job to delete\n */\n delete(id: unknown): Promise<void>;\n\n /**\n * Deletes jobs from the queue storage that are of a specific status and older than the specified time\n * @param status - The status of the jobs to delete\n * @param olderThanMs - The time in milliseconds that the jobs must be older than to be deleted\n */\n deleteJobsByStatusAndAge(status: JobStatus, olderThanMs: number): Promise<void>;\n\n /**\n * Sets up the database schema and tables.\n * This method should be called before using the storage in tests.\n * For production use, database setup should be done via migrations.\n */\n setupDatabase(): Promise<void>;\n\n /**\n * Subscribes to changes in the queue (including remote changes).\n * @param callback - Function called when a change occurs\n * @param options - Optional subscription options (e.g., polling interval)\n * @returns Unsubscribe function\n */\n subscribeToChanges(\n callback: (change: QueueChangePayload<Input, Output>) => void,\n options?: QueueSubscribeOptions\n ): () => void;\n}\n",
|
|
23
|
+
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { traced } from \"../util/traced\";\nimport type {\n IQueueStorage,\n JobStatus,\n JobStorageFormat,\n QueueChangePayload,\n QueueStorageScope,\n QueueSubscribeOptions,\n} from \"./IQueueStorage\";\n\n/**\n * Telemetry wrapper for any IQueueStorage implementation.\n * Creates spans for all queue storage operations.\n */\nexport class TelemetryQueueStorage<Input, Output> implements IQueueStorage<Input, Output> {\n constructor(\n private readonly storageName: string,\n private readonly inner: IQueueStorage<Input, Output>\n ) {}\n\n public get scope(): QueueStorageScope {\n return this.inner.scope;\n }\n\n add(job: JobStorageFormat<Input, Output>): Promise<unknown> {\n return traced(\"workglow.storage.queue.add\", this.storageName, () => this.inner.add(job));\n }\n get(id: unknown): Promise<JobStorageFormat<Input, Output> | undefined> {\n return traced(\"workglow.storage.queue.get\", this.storageName, () => this.inner.get(id));\n }\n next(workerId: string): Promise<JobStorageFormat<Input, Output> | undefined> {\n return traced(\"workglow.storage.queue.next\", this.storageName, () => this.inner.next(workerId));\n }\n peek(status?: JobStatus, num?: number): Promise<Array<JobStorageFormat<Input, Output>>> {\n return traced(\"workglow.storage.queue.peek\", this.storageName, () =>\n this.inner.peek(status, num)\n );\n }\n size(status?: JobStatus): Promise<number> {\n return traced(\"workglow.storage.queue.size\", this.storageName, () => this.inner.size(status));\n }\n complete(job: JobStorageFormat<Input, Output>): Promise<void> {\n return traced(\"workglow.storage.queue.complete\", this.storageName, () =>\n this.inner.complete(job)\n );\n }\n release(id: unknown): Promise<void> {\n return traced(\"workglow.storage.queue.release\", this.storageName, () => this.inner.release(id));\n }\n deleteAll(): Promise<void> {\n return traced(\"workglow.storage.queue.deleteAll\", this.storageName, () =>\n this.inner.deleteAll()\n );\n }\n outputForInput(input: Input): Promise<Output | null> {\n return traced(\"workglow.storage.queue.outputForInput\", this.storageName, () =>\n this.inner.outputForInput(input)\n );\n }\n abort(id: unknown): Promise<void> {\n return traced(\"workglow.storage.queue.abort\", this.storageName, () => this.inner.abort(id));\n }\n getByRunId(runId: string): Promise<Array<JobStorageFormat<Input, Output>>> {\n return traced(\"workglow.storage.queue.getByRunId\", this.storageName, () =>\n this.inner.getByRunId(runId)\n );\n }\n saveProgress(\n id: unknown,\n progress: number,\n message: string,\n details: Record<string, any> | null\n ): Promise<void> {\n return traced(\"workglow.storage.queue.saveProgress\", this.storageName, () =>\n this.inner.saveProgress(id, progress, message, details)\n );\n }\n delete(id: unknown): Promise<void> {\n return traced(\"workglow.storage.queue.delete\", this.storageName, () => this.inner.delete(id));\n }\n deleteJobsByStatusAndAge(status: JobStatus, olderThanMs: number): Promise<void> {\n return traced(\"workglow.storage.queue.deleteJobsByStatusAndAge\", this.storageName, () =>\n this.inner.deleteJobsByStatusAndAge(status, olderThanMs)\n );\n }\n setupDatabase(): Promise<void> {\n return this.inner.setupDatabase();\n }\n subscribeToChanges(\n callback: (change: QueueChangePayload<Input, Output>) => void,\n options?: QueueSubscribeOptions\n ): () => void {\n return this.inner.subscribeToChanges(callback, options);\n }\n}\n",
|
|
24
|
+
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { createServiceToken, sleep, uuid4 } from \"@workglow/util\";\nimport {\n IRateLimiterStorage,\n RateLimiterStorageOptions,\n RateLimiterStorageScope,\n} from \"./IRateLimiterStorage\";\n\nexport const IN_MEMORY_RATE_LIMITER_STORAGE = createServiceToken<IRateLimiterStorage>(\n \"ratelimiter.storage.inMemory\"\n);\n\n/**\n * Record of a job execution stored in memory.\n */\ninterface ExecutionEntry {\n /** Per-row id; serves as the opaque token returned by tryReserveExecution. */\n readonly id: string;\n readonly queueName: string;\n readonly executedAt: Date;\n}\n\n/**\n * In-memory implementation of rate limiter storage.\n * Manages execution records and next available times for rate limiting.\n */\nexport class InMemoryRateLimiterStorage implements IRateLimiterStorage {\n public readonly scope: RateLimiterStorageScope = \"process\";\n\n /** The prefix values for filtering */\n protected readonly prefixValues: Readonly<Record<string, string | number>>;\n\n /** Execution records keyed by a composite of prefix values and queue name */\n private readonly executions: Map<string, ExecutionEntry[]> = new Map();\n\n /** Next available times keyed by a composite of prefix values and queue name */\n private readonly nextAvailableTimes: Map<string, Date> = new Map();\n\n /**\n * Per-key promise chain used to serialize {@link tryReserveExecution} so\n * concurrent callers cannot both observe `count < max` before either\n * inserts. Each key's chain is replaced with the next pending operation\n * before the current one returns, giving FIFO mutex semantics.\n */\n private readonly reserveChains: Map<string, Promise<unknown>> = new Map();\n\n constructor(options?: RateLimiterStorageOptions) {\n this.prefixValues = options?.prefixValues ?? {};\n }\n\n /**\n * Creates a storage key from the queue name and prefix values.\n */\n private makeKey(queueName: string): string {\n const prefixPart = Object.entries(this.prefixValues)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([k, v]) => `${k}:${v}`)\n .join(\"|\");\n return prefixPart ? `${prefixPart}|${queueName}` : queueName;\n }\n\n public async setupDatabase(): Promise<void> {\n // No-op for in-memory storage\n }\n\n /**\n * Run `fn` under a per-key mutex. Without this, two concurrent\n * `tryReserveExecution` calls would both `await sleep(0)`, both observe the\n * same execution count, and both insert — overshooting the configured limit.\n */\n private async withKeyLock<T>(key: string, fn: () => T | Promise<T>): Promise<T> {\n const previous = this.reserveChains.get(key) ?? Promise.resolve();\n let release!: (value: unknown) => void;\n const next = new Promise((resolve) => {\n release = resolve;\n });\n this.reserveChains.set(key, next);\n try {\n await previous;\n return await fn();\n } finally {\n release(undefined);\n if (this.reserveChains.get(key) === next) {\n this.reserveChains.delete(key);\n }\n }\n }\n\n public async tryReserveExecution(\n queueName: string,\n maxExecutions: number,\n windowMs: number\n ): Promise<unknown | null> {\n const key = this.makeKey(queueName);\n return this.withKeyLock(key, () => {\n const now = Date.now();\n const windowStart = new Date(now - windowMs);\n const executions = this.executions.get(key) ?? [];\n const live = executions.filter((e) => e.executedAt > windowStart);\n if (live.length >= maxExecutions) {\n // Compact while we're here.\n if (live.length !== executions.length) {\n this.executions.set(key, live);\n }\n return null;\n }\n const next = this.nextAvailableTimes.get(key);\n if (next && next.getTime() > now) {\n return null;\n }\n const id = uuid4();\n live.push({ id, queueName, executedAt: new Date(now) });\n this.executions.set(key, live);\n return id;\n });\n }\n\n public async releaseExecution(queueName: string, token: unknown): Promise<void> {\n if (token === null || token === undefined) return;\n const key = this.makeKey(queueName);\n await this.withKeyLock(key, () => {\n const executions = this.executions.get(key);\n if (!executions || executions.length === 0) return;\n // Delete by id — NEVER by recency. Two concurrent acquirers can hold\n // tokens for different rows; popping the most recent would release the\n // other worker's slot.\n const idx = executions.findIndex((e) => e.id === token);\n if (idx === -1) return;\n executions.splice(idx, 1);\n this.executions.set(key, executions);\n });\n }\n\n public async recordExecution(queueName: string): Promise<void> {\n await sleep(0);\n const key = this.makeKey(queueName);\n const executions = this.executions.get(key) ?? [];\n executions.push({\n id: uuid4(),\n queueName,\n executedAt: new Date(),\n });\n this.executions.set(key, executions);\n }\n\n public async getExecutionCount(queueName: string, windowStartTime: string): Promise<number> {\n await sleep(0);\n const key = this.makeKey(queueName);\n const executions = this.executions.get(key) ?? [];\n const windowStart = new Date(windowStartTime);\n return executions.filter((e) => e.executedAt > windowStart).length;\n }\n\n public async getOldestExecutionAtOffset(\n queueName: string,\n offset: number\n ): Promise<string | undefined> {\n await sleep(0);\n const key = this.makeKey(queueName);\n const executions = this.executions.get(key) ?? [];\n const sorted = [...executions].sort((a, b) => a.executedAt.getTime() - b.executedAt.getTime());\n const execution = sorted[offset];\n return execution?.executedAt.toISOString();\n }\n\n public async getNextAvailableTime(queueName: string): Promise<string | undefined> {\n await sleep(0);\n const key = this.makeKey(queueName);\n const time = this.nextAvailableTimes.get(key);\n return time?.toISOString();\n }\n\n public async setNextAvailableTime(queueName: string, nextAvailableAt: string): Promise<void> {\n await sleep(0);\n const key = this.makeKey(queueName);\n this.nextAvailableTimes.set(key, new Date(nextAvailableAt));\n }\n\n public async clear(queueName: string): Promise<void> {\n await sleep(0);\n const key = this.makeKey(queueName);\n this.executions.delete(key);\n this.nextAvailableTimes.delete(key);\n }\n}\n",
|
|
25
|
+
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { createServiceToken } from \"@workglow/util\";\nimport type { PrefixColumn } from \"../queue/IQueueStorage\";\n\nexport const RATE_LIMITER_STORAGE = createServiceToken<IRateLimiterStorage>(\"ratelimiter.storage\");\n\n/**\n * Whether a rate-limiter storage's state is shared across processes.\n *\n * - `\"process\"` — in-memory / per-process state. Multiple workers in the same\n * process share it, but separate processes do not.\n * - `\"cluster\"` — state lives in shared external storage (Postgres, Supabase,\n * etc.) visible to every process.\n */\nexport type RateLimiterStorageScope = \"process\" | \"cluster\";\n\n/**\n * Options for configuring rate limiter storage with prefix filters.\n */\nexport interface RateLimiterStorageOptions {\n /** The prefix column definitions for this storage */\n readonly prefixes?: readonly PrefixColumn[];\n /** The values for each prefix column */\n readonly prefixValues?: Readonly<Record<string, string | number>>;\n}\n\n/**\n * Record of a job execution for rate limiting tracking.\n */\nexport interface ExecutionRecord {\n readonly id?: unknown;\n readonly queue_name: string;\n readonly executed_at: string;\n}\n\n/**\n * Record of the next available time for a queue.\n */\nexport interface NextAvailableRecord {\n readonly queue_name: string;\n readonly next_available_at: string;\n}\n\n/**\n * Interface defining the storage operations for a rate limiter.\n * This separates the storage concerns from the rate limiting logic.\n */\nexport interface IRateLimiterStorage {\n /**\n * Whether this storage is shared across processes. In-memory backends MUST\n * report `\"process\"`. Shared databases (Postgres, Supabase) report\n * `\"cluster\"`.\n */\n readonly scope: RateLimiterStorageScope;\n\n /**\n * Sets up the database schema and tables.\n * This method should be called before using the storage.\n * For production use, database setup should be done via migrations.\n */\n setupDatabase(): Promise<void>;\n\n /**\n * Atomic check-and-record. Inserts an execution row and returns the\n * inserted row's id iff BOTH (a) fewer than `maxExecutions` rows have\n * `executed_at > (now - windowMs)` AND (b) any persisted `nextAvailableAt`\n * is in the past or absent. Returns `null` without writing anything\n * otherwise.\n *\n * The returned id MUST be passed to {@link releaseExecution} to free the\n * slot — otherwise concurrent acquirers would race to delete the wrong\n * worker's row when one of them rolls back.\n *\n * Implementations MUST serialize concurrent callers (advisory locks,\n * `BEGIN IMMEDIATE`, per-key mutex, etc.) so the count-then-insert window\n * is uninterruptible.\n *\n * @param queueName - The name of the queue\n * @param maxExecutions - Max allowed executions in the window\n * @param windowMs - Window size in milliseconds\n * @returns the inserted row's id on success, or `null` on failure\n */\n tryReserveExecution(\n queueName: string,\n maxExecutions: number,\n windowMs: number\n ): Promise<unknown | null>;\n\n /**\n * Release the execution row identified by `token` (the value previously\n * returned from {@link tryReserveExecution}). No-op if the row no longer\n * exists.\n *\n * Critical: implementations MUST delete by id, NOT by recency or position.\n * Two concurrent workers can hold tokens for different rows; deleting the\n * \"most recent\" row would release another worker's reservation.\n */\n releaseExecution(queueName: string, token: unknown): Promise<void>;\n\n /**\n * Records a job execution for rate limiting tracking.\n * @param queueName - The name of the queue\n */\n recordExecution(queueName: string): Promise<void>;\n\n /**\n * Gets the count of executions within a time window.\n * @param queueName - The name of the queue\n * @param windowStartTime - The start of the time window (ISO string)\n * @returns The count of executions within the window\n */\n getExecutionCount(queueName: string, windowStartTime: string): Promise<number>;\n\n /**\n * Gets the oldest execution time within the window, offset by a count.\n * Used to calculate when the rate limit will allow the next execution.\n * @param queueName - The name of the queue\n * @param offset - The offset (typically maxExecutions - 1)\n * @returns The execution time or undefined if not enough executions\n */\n getOldestExecutionAtOffset(queueName: string, offset: number): Promise<string | undefined>;\n\n /**\n * Gets the next available time for a queue.\n * @param queueName - The name of the queue\n * @returns The next available time or undefined if not set\n */\n getNextAvailableTime(queueName: string): Promise<string | undefined>;\n\n /**\n * Sets the next available time for a queue.\n * @param queueName - The name of the queue\n * @param nextAvailableAt - The next available time (ISO string)\n */\n setNextAvailableTime(queueName: string, nextAvailableAt: string): Promise<void>;\n\n /**\n * Clears all rate limit entries for a queue.\n * @param queueName - The name of the queue\n */\n clear(queueName: string): Promise<void>;\n}\n",
|
|
26
26
|
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Configuration options for the hybrid subscription manager\n */\nexport interface HybridManagerOptions {\n /** Default polling interval in milliseconds for backup polling */\n readonly defaultIntervalMs?: number;\n /** Backup polling interval in milliseconds (0 to disable, default: 5000) */\n readonly backupPollingIntervalMs?: number;\n /** Enable BroadcastChannel notifications (default: true) */\n readonly useBroadcastChannel?: boolean;\n /** BroadcastChannel name for cross-tab communication */\n readonly broadcastChannelName?: string;\n}\n\n// Re-use types from PollingSubscriptionManager to avoid duplication\nimport type {\n ChangeCallback,\n ChangePayloadFactory,\n ItemComparator,\n StateFetcher,\n} from \"./PollingSubscriptionManager\";\n\n/**\n * Options for subscribing to changes\n */\nexport interface HybridSubscriptionOptions {\n /** Polling interval in milliseconds (not used if BroadcastChannel is active) */\n readonly intervalMs?: number;\n}\n\n/**\n * Internal subscription record\n */\ninterface Subscription<ChangePayload> {\n readonly callback: ChangeCallback<ChangePayload>;\n readonly intervalMs: number;\n}\n\n/**\n * BroadcastChannel message types\n */\ntype BroadcastMessage =\n | { readonly type: \"CHANGE\" }\n | { readonly type: \"HEARTBEAT\"; readonly tabId: string; readonly timestamp: number };\n\n/**\n * Manages hybrid event + polling subscriptions efficiently by using BroadcastChannel\n * for instant cross-tab change notifications with optional backup polling for reliability.\n *\n * This manager combines three notification mechanisms:\n * 1. Local event notifications for same-tab changes (instant)\n * 2. BroadcastChannel for cross-tab change notifications (near-instant)\n * 3. Optional backup polling for reliability (infrequent, 5-10s)\n *\n * When BroadcastChannel is not available, falls back to local events only (assumes single tab).\n *\n * @template Item - The type of items being tracked\n * @template Key - The type of key used to identify items\n * @template ChangePayload - The type of change payload sent to subscribers\n */\nexport class HybridSubscriptionManager<Item, Key, ChangePayload> {\n /** Map of interval (ms) to interval ID and subscriber list */\n private readonly subscribers = new Set<Subscription<ChangePayload>>();\n\n /** Current known state from last fetch */\n private lastKnownState = new Map<Key, Item>();\n\n /** Whether the manager has been initialized with a state fetch */\n private initialized = false;\n\n /** BroadcastChannel for cross-tab communication */\n private channel: BroadcastChannel | null = null;\n\n /** Backup polling interval ID */\n private backupPollingIntervalId: ReturnType<typeof setInterval> | null = null;\n\n /** Function to fetch current state */\n private readonly fetchState: StateFetcher<Item, Key>;\n\n /** Function to compare items for equality */\n private readonly compareItems: ItemComparator<Item>;\n\n /** Factory for creating change payloads */\n private readonly payloadFactory: ChangePayloadFactory<Item, ChangePayload>;\n\n /** Configuration options */\n private readonly options: Required<HybridManagerOptions>;\n\n /** Whether BroadcastChannel is available */\n private readonly hasBroadcastChannel: boolean;\n\n /**\n * Creates a new HybridSubscriptionManager\n *\n * @param channelName - Name for the BroadcastChannel (should be unique per storage instance)\n * @param fetchState - Function that returns the current state as a Map\n * @param compareItems - Function that compares two items for equality\n * @param payloadFactory - Factory for creating INSERT/UPDATE/DELETE payloads\n * @param options - Configuration options\n */\n constructor(\n channelName: string,\n fetchState: StateFetcher<Item, Key>,\n compareItems: ItemComparator<Item>,\n payloadFactory: ChangePayloadFactory<Item, ChangePayload>,\n options?: HybridManagerOptions\n ) {\n this.fetchState = fetchState;\n this.compareItems = compareItems;\n this.payloadFactory = payloadFactory;\n\n this.options = {\n defaultIntervalMs: options?.defaultIntervalMs ?? 1000,\n backupPollingIntervalMs: options?.backupPollingIntervalMs ?? 5000,\n useBroadcastChannel: options?.useBroadcastChannel ?? true,\n broadcastChannelName: options?.broadcastChannelName ?? channelName,\n };\n\n this.hasBroadcastChannel =\n this.options.useBroadcastChannel && typeof BroadcastChannel !== \"undefined\";\n\n if (this.hasBroadcastChannel) {\n this.initializeBroadcastChannel();\n }\n }\n\n /**\n * Initializes the BroadcastChannel and sets up message handlers\n */\n private initializeBroadcastChannel(): void {\n try {\n this.channel = new BroadcastChannel(this.options.broadcastChannelName);\n this.channel.onmessage = (event: MessageEvent<BroadcastMessage>) => {\n this.handleBroadcastMessage(event.data);\n };\n } catch (error) {\n console.error(\"Failed to initialize BroadcastChannel:\", error);\n this.channel = null;\n }\n }\n\n /**\n * Handles incoming BroadcastChannel messages\n */\n private async handleBroadcastMessage(message: BroadcastMessage): Promise<void> {\n if (message.type === \"CHANGE\") {\n // Another tab made a change - poll for updates\n await this.pollAndNotify();\n }\n // HEARTBEAT messages could be used for tab detection in future\n }\n\n /**\n * Notifies other tabs that a local change occurred\n * Should be called after any local mutation\n */\n notifyLocalChange(): void {\n // Immediately poll and notify local subscribers\n this.pollAndNotify();\n\n // Broadcast change notification to other tabs\n if (this.channel) {\n try {\n this.channel.postMessage({ type: \"CHANGE\" } as BroadcastMessage);\n } catch (error) {\n // Ignore broadcast errors\n }\n }\n }\n\n /**\n * Subscribe to changes\n *\n * @param callback - Function called when changes are detected\n * @param options - Subscription options\n * @returns Unsubscribe function\n */\n subscribe(\n callback: ChangeCallback<ChangePayload>,\n options?: HybridSubscriptionOptions\n ): () => void {\n const interval = options?.intervalMs ?? this.options.defaultIntervalMs;\n const subscription: Subscription<ChangePayload> = {\n callback,\n intervalMs: interval,\n };\n\n const isFirstSubscriber = this.subscribers.size === 0;\n this.subscribers.add(subscription);\n\n if (isFirstSubscriber) {\n // First subscriber - initialize and set up backup polling\n if (!this.initialized) {\n this.initialized = true;\n // Don't await - let it run async to avoid blocking\n void this.initAndNotify(subscription);\n } else {\n // Send current state to new subscriber\n this.notifySubscriberOfCurrentState(subscription);\n }\n\n // Start backup polling if configured\n // When BroadcastChannel is active, use backup polling for reliability\n // When BroadcastChannel is not available/disabled, use polling as the primary mechanism\n if (this.options.backupPollingIntervalMs > 0) {\n this.startBackupPolling();\n }\n } else {\n this.notifySubscriberOfCurrentState(subscription);\n }\n\n return () => {\n this.subscribers.delete(subscription);\n\n // If no more subscribers, stop backup polling\n if (this.subscribers.size === 0) {\n this.stopBackupPolling();\n }\n };\n }\n\n /**\n * Initialize state and notify first subscriber\n */\n private async initAndNotify(subscription: Subscription<ChangePayload>): Promise<void> {\n try {\n this.lastKnownState = await this.fetchState();\n // Notify the new subscriber of initial state as INSERTs\n for (const [, item] of this.lastKnownState) {\n const payload = this.payloadFactory.insert(item);\n try {\n subscription.callback(payload);\n } catch {\n // Ignore callback errors\n }\n }\n } catch {\n // Ignore fetch errors during initialization\n }\n }\n\n /**\n * Send current state to a subscriber\n */\n private notifySubscriberOfCurrentState(subscription: Subscription<ChangePayload>): void {\n // Send current state as INSERTs to the new subscriber\n for (const [, item] of this.lastKnownState) {\n const payload = this.payloadFactory.insert(item);\n try {\n subscription.callback(payload);\n } catch {\n // Ignore callback errors\n }\n }\n }\n\n /**\n * Poll for changes and notify all subscribers\n */\n private async pollAndNotify(): Promise<void> {\n if (this.subscribers.size === 0) return;\n\n try {\n const currentState = await this.fetchState();\n const changes: ChangePayload[] = [];\n\n // Detect new and updated items\n for (const [key, item] of currentState) {\n const oldItem = this.lastKnownState.get(key);\n if (!oldItem) {\n changes.push(this.payloadFactory.insert(item));\n } else if (!this.compareItems(oldItem, item)) {\n changes.push(this.payloadFactory.update(oldItem, item));\n }\n }\n\n // Detect deleted items\n for (const [key, item] of this.lastKnownState) {\n if (!currentState.has(key)) {\n changes.push(this.payloadFactory.delete(item));\n }\n }\n\n // Update state\n this.lastKnownState = currentState;\n\n // Broadcast changes to all subscribers\n for (const change of changes) {\n for (const sub of this.subscribers) {\n try {\n sub.callback(change);\n } catch {\n // Ignore callback errors\n }\n }\n }\n } catch {\n // Ignore polling errors\n }\n }\n\n /**\n * Start backup polling\n */\n private startBackupPolling(): void {\n if (this.backupPollingIntervalId) return;\n\n this.backupPollingIntervalId = setInterval(\n () => this.pollAndNotify(),\n this.options.backupPollingIntervalMs\n );\n }\n\n /**\n * Stop backup polling\n */\n private stopBackupPolling(): void {\n if (this.backupPollingIntervalId) {\n clearInterval(this.backupPollingIntervalId);\n this.backupPollingIntervalId = null;\n }\n }\n\n /**\n * Get the number of active subscriptions\n */\n get subscriptionCount(): number {\n return this.subscribers.size;\n }\n\n /**\n * Check if there are any active subscriptions\n */\n get hasSubscriptions(): boolean {\n return this.subscribers.size > 0;\n }\n\n /**\n * Check if BroadcastChannel is available and active\n */\n get isBroadcastChannelActive(): boolean {\n return this.channel !== null;\n }\n\n /**\n * Destroy the manager and clean up all resources\n */\n destroy(): void {\n this.stopBackupPolling();\n if (this.channel) {\n this.channel.close();\n this.channel = null;\n }\n this.subscribers.clear();\n this.lastKnownState.clear();\n this.initialized = false;\n }\n}\n",
|
|
27
27
|
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Configuration options for the polling subscription manager\n */\nexport interface PollingManagerOptions {\n /** Default polling interval in milliseconds */\n readonly defaultIntervalMs?: number;\n}\n\n/**\n * A callback function that is called when changes are detected\n */\nexport type ChangeCallback<T> = (change: T) => void;\n\n/**\n * A function that fetches the current state for comparison\n */\nexport type StateFetcher<Item, Key> = () => Promise<Map<Key, Item>>;\n\n/**\n * A function that compares two items for equality\n */\nexport type ItemComparator<Item> = (a: Item, b: Item) => boolean;\n\n/**\n * A factory function that creates change payloads\n */\nexport interface ChangePayloadFactory<Item, ChangePayload> {\n /** Create an INSERT change payload */\n readonly insert: (item: Item) => ChangePayload;\n /** Create an UPDATE change payload */\n readonly update: (oldItem: Item, newItem: Item) => ChangePayload;\n /** Create a DELETE change payload */\n readonly delete: (item: Item) => ChangePayload;\n}\n\n/**\n * Options for subscribing to changes\n */\nexport interface PollingSubscriptionOptions {\n /** Polling interval in milliseconds */\n readonly intervalMs?: number;\n}\n\n/**\n * Internal subscription record\n */\ninterface Subscription<ChangePayload> {\n readonly callback: ChangeCallback<ChangePayload>;\n readonly intervalMs: number;\n}\n\n/**\n * Manages polling-based subscriptions efficiently by consolidating multiple\n * subscribers into a single polling loop per interval tier.\n *\n * Instead of each subscription creating its own polling interval, this manager\n * groups subscriptions by their requested polling interval and runs a single\n * poll for each group, broadcasting changes to all subscribers in that group.\n *\n * @template Item - The type of items being tracked\n * @template Key - The type of key used to identify items\n * @template ChangePayload - The type of change payload sent to subscribers\n */\nexport class PollingSubscriptionManager<Item, Key, ChangePayload> {\n /** Map of interval (ms) to interval ID and subscriber list */\n private readonly intervals = new Map<\n number,\n {\n intervalId: ReturnType<typeof setInterval>;\n subscribers: Set<Subscription<ChangePayload>>;\n }\n >();\n\n /** Current known state from last poll */\n private lastKnownState = new Map<Key, Item>();\n\n /** Whether the manager has been initialized with a state fetch */\n private initialized = false;\n\n /** Whether initialization is currently in progress (guards against poll/init race) */\n private initializing = false;\n\n /** Function to fetch current state */\n private readonly fetchState: StateFetcher<Item, Key>;\n\n /** Function to compare items for equality */\n private readonly compareItems: ItemComparator<Item>;\n\n /** Factory for creating change payloads */\n private readonly payloadFactory: ChangePayloadFactory<Item, ChangePayload>;\n\n /** Default polling interval */\n private readonly defaultIntervalMs: number;\n\n /**\n * Creates a new PollingSubscriptionManager\n *\n * @param fetchState - Function that returns the current state as a Map\n * @param compareItems - Function that compares two items for equality\n * @param payloadFactory - Factory for creating INSERT/UPDATE/DELETE payloads\n * @param options - Configuration options\n */\n constructor(\n fetchState: StateFetcher<Item, Key>,\n compareItems: ItemComparator<Item>,\n payloadFactory: ChangePayloadFactory<Item, ChangePayload>,\n options?: PollingManagerOptions\n ) {\n this.fetchState = fetchState;\n this.compareItems = compareItems;\n this.payloadFactory = payloadFactory;\n this.defaultIntervalMs = options?.defaultIntervalMs ?? 1000;\n }\n\n /**\n * Subscribe to changes with a specific polling interval\n *\n * @param callback - Function called when changes are detected\n * @param options - Subscription options including interval\n * @returns Unsubscribe function\n */\n subscribe(\n callback: ChangeCallback<ChangePayload>,\n options?: PollingSubscriptionOptions\n ): () => void {\n const interval = options?.intervalMs ?? this.defaultIntervalMs;\n const subscription: Subscription<ChangePayload> = {\n callback,\n intervalMs: interval,\n };\n\n let intervalGroup = this.intervals.get(interval);\n if (!intervalGroup) {\n // First subscriber for this interval - create the polling loop\n const subscribers = new Set<Subscription<ChangePayload>>();\n const intervalId = setInterval(() => this.poll(subscribers), interval);\n\n intervalGroup = { intervalId, subscribers };\n this.intervals.set(interval, intervalGroup);\n\n // Run initial poll if this is the first subscriber ever\n if (!this.initialized) {\n this.initialized = true;\n this.initializing = true;\n this.initAndPoll(subscription);\n } else {\n // Run immediate poll for new subscriber\n this.pollForNewSubscriber(subscription);\n }\n } else {\n // New subscriber joining existing interval - send them current state\n this.pollForNewSubscriber(subscription);\n }\n\n intervalGroup.subscribers.add(subscription);\n\n return () => {\n const group = this.intervals.get(interval);\n if (group) {\n group.subscribers.delete(subscription);\n\n // If no more subscribers for this interval, clean up\n if (group.subscribers.size === 0) {\n clearInterval(group.intervalId);\n this.intervals.delete(interval);\n }\n }\n };\n }\n\n /**\n * Initialize state and run first poll\n */\n private async initAndPoll(newSubscription: Subscription<ChangePayload>): Promise<void> {\n try {\n this.lastKnownState = await this.fetchState();\n // Notify the new subscriber of initial state as INSERTs\n for (const [, item] of this.lastKnownState) {\n const payload = this.payloadFactory.insert(item);\n try {\n newSubscription.callback(payload);\n } catch {\n // Ignore callback errors\n }\n }\n } catch {\n // Ignore fetch errors during initialization\n } finally {\n this.initializing = false;\n }\n }\n\n /**\n * Send current state to a new subscriber\n */\n private pollForNewSubscriber(subscription: Subscription<ChangePayload>): void {\n // Send current state as INSERTs to the new subscriber\n for (const [, item] of this.lastKnownState) {\n const payload = this.payloadFactory.insert(item);\n try {\n subscription.callback(payload);\n } catch {\n // Ignore callback errors\n }\n }\n }\n\n /**\n * Poll for changes and notify all subscribers in the given set\n */\n private async poll(subscribers: Set<Subscription<ChangePayload>>): Promise<void> {\n if (subscribers.size === 0) return;\n // Skip polling while initAndPoll is still running to avoid racing on lastKnownState\n if (this.initializing) return;\n\n try {\n const currentState = await this.fetchState();\n const changes: ChangePayload[] = [];\n\n // Detect new and updated items\n for (const [key, item] of currentState) {\n const oldItem = this.lastKnownState.get(key);\n if (!oldItem) {\n changes.push(this.payloadFactory.insert(item));\n } else if (!this.compareItems(oldItem, item)) {\n changes.push(this.payloadFactory.update(oldItem, item));\n }\n }\n\n // Detect deleted items\n for (const [key, item] of this.lastKnownState) {\n if (!currentState.has(key)) {\n changes.push(this.payloadFactory.delete(item));\n }\n }\n\n // Update state\n this.lastKnownState = currentState;\n\n // Broadcast changes to all subscribers\n for (const change of changes) {\n for (const sub of subscribers) {\n try {\n sub.callback(change);\n } catch {\n // Ignore callback errors\n }\n }\n }\n } catch {\n // Ignore polling errors\n }\n }\n\n /**\n * Get the number of active subscriptions across all intervals\n */\n get subscriptionCount(): number {\n let count = 0;\n for (const group of this.intervals.values()) {\n count += group.subscribers.size;\n }\n return count;\n }\n\n /**\n * Check if there are any active subscriptions\n */\n get hasSubscriptions(): boolean {\n return this.intervals.size > 0;\n }\n\n /**\n * Destroy the manager and clean up all intervals\n */\n destroy(): void {\n for (const group of this.intervals.values()) {\n clearInterval(group.intervalId);\n }\n this.intervals.clear();\n this.lastKnownState.clear();\n this.initialized = false;\n this.initializing = false;\n }\n}\n",
|
|
28
28
|
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type {\n DataPortSchemaObject,\n FromSchema,\n TypedArray,\n TypedArrayConstructor,\n TypedArraySchemaOptions,\n} from \"@workglow/util/schema\";\nimport { cosineSimilarity } from \"@workglow/util/schema\";\nimport { InMemoryTabularStorage } from \"../tabular/InMemoryTabularStorage\";\nimport type { HybridSearchOptions, IVectorStorage, VectorSearchOptions } from \"./IVectorStorage\";\nimport { getMetadataProperty, getVectorProperty } from \"./IVectorStorage\";\n\n/**\n * Check if metadata matches filter\n */\nfunction matchesFilter<Metadata>(metadata: Metadata, filter: Partial<Metadata>): boolean {\n for (const [key, value] of Object.entries(filter)) {\n if (metadata[key as keyof Metadata] !== value) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Simple full-text search scoring (keyword matching)\n */\nfunction textRelevance(text: string, query: string): number {\n const textLower = text.toLowerCase();\n const queryLower = query.toLowerCase();\n const queryWords = queryLower.split(/\\s+/).filter((w) => w.length > 0);\n if (queryWords.length === 0) {\n return 0;\n }\n let matches = 0;\n for (const word of queryWords) {\n if (textLower.includes(word)) {\n matches++;\n }\n }\n return matches / queryWords.length;\n}\n\n/**\n * In-memory document chunk vector repository implementation.\n * Extends InMemoryTabularStorage for storage.\n * Suitable for testing and small-scale browser applications.\n * Supports all vector types including quantized formats.\n *\n * @template Metadata - The metadata type for the document chunk\n * @template VectorCtor - Constructor for stored vectors (default {@link typeof Float32Array})\n */\nexport class InMemoryVectorStorage<\n Schema extends DataPortSchemaObject,\n PrimaryKeyNames extends ReadonlyArray<keyof Schema[\"properties\"]>,\n Metadata extends Record<string, unknown> = Record<string, unknown>,\n Entity = FromSchema<Schema, TypedArraySchemaOptions>,\n>\n extends InMemoryTabularStorage<Schema, PrimaryKeyNames, Entity>\n implements IVectorStorage<Metadata, Schema, Entity, PrimaryKeyNames>\n{\n private vectorDimensions: number;\n private vectorPropertyName: keyof Entity;\n private metadataPropertyName: keyof Entity | undefined;\n\n /**\n * Creates a new in-memory document chunk vector repository\n * @param schema - The schema definition for the entity\n * @param primaryKeyNames - Array of property names that form the primary key\n * @param indexes - Array of columns or column arrays to make searchable\n * @param dimensions - The number of dimensions of the vector\n * @param _vectorCtor - TypedArray constructor (unused, for API compatibility)\n */\n constructor(\n schema: Schema,\n primaryKeyNames: PrimaryKeyNames,\n indexes: readonly (keyof NoInfer<Entity> | readonly (keyof NoInfer<Entity>)[])[] = [],\n dimensions: number,\n _vectorCtor: TypedArrayConstructor = Float32Array\n ) {\n super(schema, primaryKeyNames, indexes);\n\n this.vectorDimensions = dimensions;\n\n // Cache vector and metadata property names from schema\n const vectorProp = getVectorProperty(schema);\n if (!vectorProp) {\n throw new Error(\"Schema must have a property with type array and format TypedArray\");\n }\n this.vectorPropertyName = vectorProp as keyof Entity;\n this.metadataPropertyName = getMetadataProperty(schema) as keyof Entity | undefined;\n }\n\n /**\n * Get the vector dimensions\n * @returns The vector dimensions\n */\n getVectorDimensions(): number {\n return this.vectorDimensions;\n }\n\n async similaritySearch(\n query: TypedArray,\n options: VectorSearchOptions<Record<string, unknown>> = {}\n ) {\n const { topK = 10, filter, scoreThreshold = 0 } = options;\n const results: Array<Entity & { score: number }> = [];\n\n const allEntities = (await this.getAll()) || [];\n\n for (const entity of allEntities) {\n const vector = entity[this.vectorPropertyName] as TypedArray;\n const metadata = this.metadataPropertyName\n ? (entity[this.metadataPropertyName] as Metadata)\n : ({} as Metadata);\n\n // Apply filter if provided\n if (filter && !matchesFilter(metadata, filter)) {\n continue;\n }\n\n // Calculate similarity\n const score = cosineSimilarity(query, vector);\n\n // Apply threshold\n if (score < scoreThreshold) {\n continue;\n }\n\n results.push({\n ...entity,\n score,\n } as Entity & { score: number });\n }\n\n // Sort by score descending and take top K\n results.sort((a, b) => b.score - a.score);\n const topResults = results.slice(0, topK);\n\n return topResults;\n }\n\n async hybridSearch(query: TypedArray, options: HybridSearchOptions<Record<string, unknown>>) {\n const { topK = 10, filter, scoreThreshold = 0, textQuery, vectorWeight = 0.7 } = options;\n\n if (!textQuery || textQuery.trim().length === 0) {\n // Fall back to regular vector search if no text query\n return this.similaritySearch(query, { topK, filter, scoreThreshold });\n }\n\n const results: Array<Entity & { score: number }> = [];\n const allEntities = (await this.getAll()) || [];\n\n for (const entity of allEntities) {\n // In memory, vectors are stored as TypedArrays directly (not serialized)\n const vector = entity[this.vectorPropertyName] as TypedArray;\n const metadata = this.metadataPropertyName\n ? (entity[this.metadataPropertyName] as Metadata)\n : ({} as Metadata);\n\n // Apply filter if provided\n if (filter && !matchesFilter(metadata, filter)) {\n continue;\n }\n\n // Calculate vector similarity\n const vectorScore = cosineSimilarity(query, vector);\n\n // Calculate text relevance (simple keyword matching)\n const metadataText = Object.values(metadata ?? {})\n .join(\" \")\n .toLowerCase();\n const textScore = textRelevance(metadataText, textQuery);\n\n // Combine scores\n const combinedScore = vectorWeight * vectorScore + (1 - vectorWeight) * textScore;\n\n // Apply threshold\n if (combinedScore < scoreThreshold) {\n continue;\n }\n\n results.push({\n ...entity,\n score: combinedScore,\n } as Entity & { score: number });\n }\n\n // Sort by combined score descending and take top K\n results.sort((a, b) => b.score - a.score);\n const topResults = results.slice(0, topK);\n\n return topResults;\n }\n}\n",
|
|
@@ -40,23 +40,24 @@
|
|
|
40
40
|
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { JsonSchema } from \"@workglow/util/schema\";\nimport { createServiceToken } from \"@workglow/util\";\nimport { PostgresTabularStorage } from \"../tabular/PostgresTabularStorage\";\nimport { DefaultKeyValueKey, DefaultKeyValueSchema, IKvStorage } from \"./IKvStorage\";\nimport { KvViaTabularStorage } from \"./KvViaTabularStorage\";\n\nexport const POSTGRES_KV_REPOSITORY = createServiceToken<IKvStorage<string, any, any>>(\n \"storage.kvRepository.postgres\"\n);\n\n/**\n * A key-value repository implementation that uses PostgreSQL for persistent storage.\n * Leverages a tabular repository abstraction for PostgreSQL operations.\n *\n * @template Key - The type of the primary key\n * @template Value - The type of the value being stored\n * @template Combined - Combined type of Key & Value\n */\nexport class PostgresKvStorage extends KvViaTabularStorage {\n public tabularRepository: PostgresTabularStorage<\n typeof DefaultKeyValueSchema,\n typeof DefaultKeyValueKey\n >;\n\n /**\n * Creates a new KvStorage instance\n */\n constructor(\n public db: any,\n public dbName: string,\n keySchema: JsonSchema = { type: \"string\" },\n valueSchema: JsonSchema = {}\n ) {\n super(keySchema, valueSchema);\n this.tabularRepository = new PostgresTabularStorage(\n db,\n dbName,\n DefaultKeyValueSchema,\n DefaultKeyValueKey\n );\n }\n}\n",
|
|
41
41
|
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { JsonSchema } from \"@workglow/util/schema\";\nimport { createServiceToken } from \"@workglow/util\";\nimport { SqliteTabularStorage } from \"../tabular/SqliteTabularStorage\";\nimport { DefaultKeyValueKey, DefaultKeyValueSchema, IKvStorage } from \"./IKvStorage\";\nimport { KvViaTabularStorage } from \"./KvViaTabularStorage\";\n\nexport const SQLITE_KV_REPOSITORY = createServiceToken<IKvStorage<string, any, any>>(\n \"storage.kvRepository.sqlite\"\n);\n\n/**\n * A key-value repository implementation that uses SQLite for persistent storage.\n * Leverages a tabular repository abstraction for SQLite operations.\n *\n * @template Key - The type of the primary key\n * @template Value - The type of the value being stored\n * @template Combined - Combined type of Key & Value\n */\nexport class SqliteKvStorage extends KvViaTabularStorage {\n public tabularRepository: SqliteTabularStorage<\n typeof DefaultKeyValueSchema,\n typeof DefaultKeyValueKey\n >;\n\n /**\n * Creates a new KvStorage instance\n */\n constructor(\n public db: any,\n public dbName: string,\n keySchema: JsonSchema = { type: \"string\" },\n valueSchema: JsonSchema = {}\n ) {\n super(keySchema, valueSchema);\n this.tabularRepository = new SqliteTabularStorage(\n db,\n dbName,\n DefaultKeyValueSchema,\n DefaultKeyValueKey\n );\n }\n}\n",
|
|
42
42
|
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { createServiceToken } from \"@workglow/util\";\nimport { JsonSchema } from \"@workglow/util/schema\";\nimport { SupabaseTabularStorage } from \"../tabular/SupabaseTabularStorage\";\nimport { DefaultKeyValueKey, DefaultKeyValueSchema, IKvStorage } from \"./IKvStorage\";\nimport { KvViaTabularStorage } from \"./KvViaTabularStorage\";\n\nexport const SUPABASE_KV_REPOSITORY = createServiceToken<IKvStorage<string, any, any>>(\n \"storage.kvRepository.supabase\"\n);\n\n/**\n * A key-value repository implementation that uses Supabase for persistent storage.\n * Leverages a tabular repository abstraction for Supabase operations.\n *\n * @template Key - The type of the primary key\n * @template Value - The type of the value being stored\n * @template Combined - Combined type of Key & Value\n */\nexport class SupabaseKvStorage extends KvViaTabularStorage {\n public tabularRepository: SupabaseTabularStorage<\n typeof DefaultKeyValueSchema,\n typeof DefaultKeyValueKey\n >;\n\n /**\n * Creates a new SupabaseKvStorage instance\n *\n * @param client - Supabase client instance\n * @param tableName - Name of the table to store data\n * @param keySchema - Schema for the key type (defaults to string)\n * @param valueSchema - Schema for the value type (defaults to any)\n */\n constructor(\n public client: unknown,\n public tableName: string,\n keySchema: JsonSchema = { type: \"string\" },\n valueSchema: JsonSchema = {},\n tabularRepository?: SupabaseTabularStorage<\n typeof DefaultKeyValueSchema,\n typeof DefaultKeyValueKey\n >\n ) {\n super(keySchema, valueSchema);\n this.tabularRepository =\n tabularRepository ??\n new SupabaseTabularStorage(client, tableName, DefaultKeyValueSchema, DefaultKeyValueKey);\n }\n}\n",
|
|
43
|
-
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Pool } from \"@workglow/storage/postgres\";\nimport { createServiceToken, makeFingerprint, uuid4 } from \"@workglow/util\";\nimport {\n IQueueStorage,\n JobStatus,\n JobStorageFormat,\n PrefixColumn,\n QueueChangePayload,\n QueueStorageOptions,\n QueueSubscribeOptions,\n} from \"./IQueueStorage\";\n\nexport const POSTGRES_QUEUE_STORAGE = createServiceToken<IQueueStorage<any, any>>(\n \"jobqueue.storage.postgres\"\n);\n\n/** Regex for safe SQL identifiers: starts with a letter, then alphanumeric/underscores */\nconst SAFE_IDENTIFIER = /^[a-zA-Z][a-zA-Z0-9_]*$/;\n\n/**\n * PostgreSQL implementation of a job queue.\n * Provides storage and retrieval for job execution states using PostgreSQL.\n */\nexport class PostgresQueueStorage<Input, Output> implements IQueueStorage<Input, Output> {\n /** The prefix column definitions */\n protected readonly prefixes: readonly PrefixColumn[];\n /** The prefix values for filtering */\n protected readonly prefixValues: Readonly<Record<string, string | number>>;\n /** The table name for the job queue */\n protected readonly tableName: string;\n\n constructor(\n protected readonly db: Pool,\n protected readonly queueName: string,\n options?: QueueStorageOptions\n ) {\n this.prefixes = options?.prefixes ?? [];\n this.prefixValues = options?.prefixValues ?? {};\n\n // Validate prefix column names to prevent SQL injection in DDL statements\n for (const prefix of this.prefixes) {\n if (!SAFE_IDENTIFIER.test(prefix.name)) {\n throw new Error(\n `Prefix column name must start with a letter and contain only letters, digits, and underscores, got: ${prefix.name}`\n );\n }\n }\n\n // Generate table name based on prefix configuration to avoid column conflicts\n if (this.prefixes.length > 0) {\n const prefixNames = this.prefixes.map((p) => p.name).join(\"_\");\n this.tableName = `job_queue_${prefixNames}`;\n } else {\n this.tableName = \"job_queue\";\n }\n }\n\n /**\n * Gets the SQL column type for a prefix column\n */\n private getPrefixColumnType(type: PrefixColumn[\"type\"]): string {\n return type === \"uuid\" ? \"UUID\" : \"INTEGER\";\n }\n\n /**\n * Builds the prefix columns SQL for CREATE TABLE\n */\n private buildPrefixColumnsSql(): string {\n if (this.prefixes.length === 0) return \"\";\n return (\n this.prefixes\n .map((p) => `${p.name} ${this.getPrefixColumnType(p.type)} NOT NULL`)\n .join(\",\\n \") + \",\\n \"\n );\n }\n\n /**\n * Builds prefix column names for use in queries\n */\n private getPrefixColumnNames(): string[] {\n return this.prefixes.map((p) => p.name);\n }\n\n /**\n * Builds WHERE clause conditions for prefix filtering\n * @param startParam - The starting parameter number for parameterized queries\n * @returns Object with conditions string and parameter values\n */\n private buildPrefixWhereClause(startParam: number): {\n conditions: string;\n params: Array<string | number>;\n } {\n if (this.prefixes.length === 0) {\n return { conditions: \"\", params: [] };\n }\n const conditions = this.prefixes.map((p, i) => `${p.name} = $${startParam + i}`).join(\" AND \");\n const params = this.prefixes.map((p) => this.prefixValues[p.name]);\n return { conditions: \" AND \" + conditions, params };\n }\n\n /**\n * Gets prefix values as an array in column order\n */\n private getPrefixParamValues(): Array<string | number> {\n return this.prefixes.map((p) => this.prefixValues[p.name]);\n }\n\n public async setupDatabase(): Promise<void> {\n let sql: string;\n try {\n const enumValues = Object.values(JobStatus);\n for (const v of enumValues) {\n if (!SAFE_IDENTIFIER.test(v)) {\n throw new Error(`Invalid JobStatus enum value: ${v}`);\n }\n }\n sql = `CREATE TYPE job_status AS ENUM (${enumValues.map((v) => `'${v}'`).join(\",\")})`;\n await this.db.query(sql);\n } catch (e: any) {\n // Ignore error if type already exists (code 42710)\n if (e.code !== \"42710\") throw e;\n }\n\n const prefixColumnsSql = this.buildPrefixColumnsSql();\n const prefixColumnNames = this.getPrefixColumnNames();\n const prefixIndexPrefix =\n prefixColumnNames.length > 0 ? prefixColumnNames.join(\", \") + \", \" : \"\";\n\n sql = `\n CREATE TABLE IF NOT EXISTS ${this.tableName} (\n id SERIAL NOT NULL,\n ${prefixColumnsSql}fingerprint text NOT NULL,\n queue text NOT NULL,\n job_run_id text NOT NULL,\n status job_status NOT NULL default 'PENDING',\n input jsonb NOT NULL,\n output jsonb,\n run_attempts integer default 0,\n max_retries integer default 20,\n run_after timestamp with time zone DEFAULT now(),\n last_ran_at timestamp with time zone,\n created_at timestamp with time zone DEFAULT now(),\n deadline_at timestamp with time zone,\n completed_at timestamp with time zone,\n error text,\n error_code text,\n progress real DEFAULT 0,\n progress_message text DEFAULT '',\n progress_details jsonb,\n worker_id text\n )`;\n\n await this.db.query(sql);\n\n // Create indexes with prefix columns prepended\n const indexSuffix = prefixColumnNames.length > 0 ? \"_\" + prefixColumnNames.join(\"_\") : \"\";\n\n sql = `\n CREATE INDEX IF NOT EXISTS job_fetcher${indexSuffix}_idx \n ON ${this.tableName} (${prefixIndexPrefix}id, status, run_after)`;\n await this.db.query(sql);\n\n sql = `\n CREATE INDEX IF NOT EXISTS job_queue_fetcher${indexSuffix}_idx \n ON ${this.tableName} (${prefixIndexPrefix}queue, status, run_after)`;\n await this.db.query(sql);\n\n sql = `\n CREATE INDEX IF NOT EXISTS jobs_fingerprint${indexSuffix}_unique_idx \n ON ${this.tableName} (${prefixIndexPrefix}queue, fingerprint, status)`;\n await this.db.query(sql);\n }\n\n /**\n * Adds a new job to the queue.\n * @param job - The job to add\n * @returns The ID of the added job\n */\n public async add(job: JobStorageFormat<Input, Output>): Promise<unknown> {\n const now = new Date().toISOString();\n job.queue = this.queueName;\n job.job_run_id = job.job_run_id ?? uuid4();\n job.fingerprint = await makeFingerprint(job.input);\n job.status = JobStatus.PENDING;\n job.progress = 0;\n job.progress_message = \"\";\n job.progress_details = null;\n job.created_at = now;\n job.run_after = now;\n\n const prefixColumnNames = this.getPrefixColumnNames();\n const prefixColumnsInsert =\n prefixColumnNames.length > 0 ? prefixColumnNames.join(\", \") + \", \" : \"\";\n const prefixParamValues = this.getPrefixParamValues();\n const prefixParamPlaceholders =\n prefixColumnNames.length > 0\n ? prefixColumnNames.map((_, i) => `$${i + 1}`).join(\",\") + \",\"\n : \"\";\n const baseParamStart = prefixColumnNames.length + 1;\n\n const sql = `\n INSERT INTO ${this.tableName}(\n ${prefixColumnsInsert}queue, \n fingerprint, \n input, \n run_after,\n created_at,\n deadline_at,\n max_retries, \n job_run_id, \n progress, \n progress_message, \n progress_details\n )\n VALUES \n (${prefixParamPlaceholders}$${baseParamStart},$${baseParamStart + 1},$${baseParamStart + 2},$${baseParamStart + 3},$${baseParamStart + 4},$${baseParamStart + 5},$${baseParamStart + 6},$${baseParamStart + 7},$${baseParamStart + 8},$${baseParamStart + 9},$${baseParamStart + 10})\n RETURNING id`;\n const params = [\n ...prefixParamValues,\n job.queue,\n job.fingerprint,\n JSON.stringify(job.input),\n job.run_after,\n job.created_at,\n job.deadline_at,\n job.max_retries,\n job.job_run_id,\n job.progress,\n job.progress_message,\n job.progress_details ? JSON.stringify(job.progress_details) : null,\n ];\n const result = await this.db.query(sql, params);\n\n if (!result) throw new Error(\"Failed to add to queue\");\n job.id = result.rows[0].id;\n return job.id;\n }\n\n /**\n * Retrieves a job by its ID.\n * @param id - The ID of the job to retrieve\n * @returns The job if found, undefined otherwise\n */\n public async get(id: unknown): Promise<JobStorageFormat<Input, Output> | undefined> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(3);\n const result = await this.db.query(\n `SELECT *\n FROM ${this.tableName}\n WHERE id = $1 AND queue = $2${prefixConditions}\n FOR UPDATE SKIP LOCKED\n LIMIT 1`,\n [id, this.queueName, ...prefixParams]\n );\n\n if (!result || result.rows.length === 0) return undefined;\n return result.rows[0];\n }\n\n /**\n * Retrieves a slice of jobs from the queue.\n * @param num - Maximum number of jobs to return\n * @returns An array of jobs\n */\n public async peek(\n status: JobStatus = JobStatus.PENDING,\n num: number = 100\n ): Promise<Array<JobStorageFormat<Input, Output>>> {\n num = Number(num) || 100; // TS does not validate, so ensure it is a number\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(4);\n const result = await this.db.query<\n JobStorageFormat<Input, Output>,\n Array<string | number | JobStatus>\n >(\n `\n SELECT *\n FROM ${this.tableName}\n WHERE queue = $1\n AND status = $2${prefixConditions}\n ORDER BY run_after ASC\n LIMIT $3\n FOR UPDATE SKIP LOCKED`,\n [this.queueName, status, num, ...prefixParams]\n );\n if (!result) return [];\n return result.rows;\n }\n\n /**\n * Retrieves the next available job that is ready to be processed.\n * @param workerId - Worker ID to associate with the job (required)\n * @returns The next job or undefined if no job is available\n */\n public async next(workerId: string): Promise<JobStorageFormat<Input, Output> | undefined> {\n // Parameters: $1=status, $2=queue, $3=status, $4=worker_id, $5+=prefix params\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(5);\n const result = await this.db.query<\n JobStorageFormat<Input, Output>,\n Array<string | number | JobStatus | null>\n >(\n `\n UPDATE ${this.tableName} \n SET status = $1, last_ran_at = NOW() AT TIME ZONE 'UTC', worker_id = $4\n WHERE id = (\n SELECT id \n FROM ${this.tableName} \n WHERE queue = $2 \n AND status = $3\n ${prefixConditions}\n AND run_after <= NOW() AT TIME ZONE 'UTC'\n ORDER BY run_after ASC \n FOR UPDATE SKIP LOCKED \n LIMIT 1\n )\n RETURNING *`,\n [JobStatus.PROCESSING, this.queueName, JobStatus.PENDING, workerId, ...prefixParams]\n );\n\n return result?.rows?.[0] ?? undefined;\n }\n\n /**\n * Retrieves the number of jobs in the queue with a specific status.\n * @param status - The status of the jobs to count\n * @returns The count of jobs with the specified status\n */\n public async size(status = JobStatus.PENDING): Promise<number> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(3);\n const result = await this.db.query<{ count: string }, Array<string | number | JobStatus>>(\n `\n SELECT COUNT(*) as count\n FROM ${this.tableName}\n WHERE queue = $1\n AND status = $2${prefixConditions}`,\n [this.queueName, status, ...prefixParams]\n );\n if (!result) return 0;\n return parseInt(result.rows[0].count, 10);\n }\n\n /**\n * Marks a job as complete with its output or error.\n * Enhanced error handling:\n * - For a retryable error, increments run_attempts and updates run_after.\n * - Marks a job as FAILED immediately for permanent or generic errors.\n */\n public async complete(jobDetails: JobStorageFormat<Input, Output>): Promise<void> {\n const prefixParams = this.getPrefixParamValues();\n\n if (jobDetails.status === JobStatus.DISABLED) {\n const { conditions: prefixConditions } = this.buildPrefixWhereClause(4);\n await this.db.query(\n `UPDATE ${this.tableName} \n SET \n status = $1, \n progress = 100,\n progress_message = '',\n progress_details = NULL,\n completed_at = NOW() AT TIME ZONE 'UTC'\n WHERE id = $2 AND queue = $3${prefixConditions}`,\n [jobDetails.status, jobDetails.id, this.queueName, ...prefixParams]\n );\n } else if (jobDetails.status === JobStatus.PENDING) {\n const { conditions: prefixConditions } = this.buildPrefixWhereClause(7);\n await this.db.query(\n `UPDATE ${this.tableName} \n SET \n error = $1, \n error_code = $2,\n status = $3, \n run_after = $4, \n progress = 0,\n progress_message = '',\n progress_details = NULL,\n run_attempts = run_attempts + 1, \n last_ran_at = NOW() AT TIME ZONE 'UTC'\n WHERE id = $5 AND queue = $6${prefixConditions}`,\n [\n jobDetails.error,\n jobDetails.error_code,\n jobDetails.status,\n jobDetails.run_after,\n jobDetails.id,\n this.queueName,\n ...prefixParams,\n ]\n );\n } else {\n const { conditions: prefixConditions } = this.buildPrefixWhereClause(7);\n await this.db.query(\n `\n UPDATE ${this.tableName} \n SET \n output = $1, \n error = $2, \n error_code = $3,\n status = $4, \n progress = 100,\n progress_message = '',\n progress_details = NULL,\n run_attempts = run_attempts + 1, \n completed_at = NOW() AT TIME ZONE 'UTC',\n last_ran_at = NOW() AT TIME ZONE 'UTC'\n WHERE id = $5 AND queue = $6${prefixConditions}`,\n [\n jobDetails.output ? JSON.stringify(jobDetails.output) : null,\n jobDetails.error ?? null,\n jobDetails.error_code ?? null,\n jobDetails.status,\n jobDetails.id,\n this.queueName,\n ...prefixParams,\n ]\n );\n }\n }\n\n /**\n * Clears all jobs from the queue.\n */\n public async deleteAll(): Promise<void> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(2);\n await this.db.query(\n `\n DELETE FROM ${this.tableName}\n WHERE queue = $1${prefixConditions}`,\n [this.queueName, ...prefixParams]\n );\n }\n\n /**\n * Looks up cached output for a given input\n * Uses input fingerprinting for efficient matching\n * @returns The cached output or null if not found\n */\n public async outputForInput(input: Input): Promise<Output | null> {\n const fingerprint = await makeFingerprint(input);\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(3);\n const result = await this.db.query(\n `\n SELECT output\n FROM ${this.tableName}\n WHERE fingerprint = $1 AND queue = $2 AND status = 'COMPLETED'${prefixConditions}`,\n [fingerprint, this.queueName, ...prefixParams]\n );\n if (!result || result.rows.length === 0) return null;\n return result.rows[0].output;\n }\n\n /**\n * Aborts a job by setting its status to \"ABORTING\".\n * This method will signal the corresponding AbortController so that\n * the job's execute() method (if it supports an AbortSignal parameter)\n * can clean up and exit.\n */\n public async abort(jobId: unknown): Promise<void> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(3);\n await this.db.query(\n `\n UPDATE ${this.tableName} \n SET status = 'ABORTING' \n WHERE id = $1 AND queue = $2${prefixConditions}`,\n [jobId, this.queueName, ...prefixParams]\n );\n }\n\n /**\n * Releases a claimed job back to PENDING without incrementing run_attempts.\n * @param jobId - The id of the claimed job to release.\n */\n public async release(jobId: unknown): Promise<void> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(3);\n await this.db.query(\n `\n UPDATE ${this.tableName}\n SET status = 'PENDING',\n worker_id = NULL,\n progress = 0,\n progress_message = '',\n progress_details = NULL\n WHERE id = $1 AND queue = $2${prefixConditions}`,\n [jobId, this.queueName, ...prefixParams]\n );\n }\n\n /**\n * Retrieves all jobs for a given job run ID.\n * @param job_run_id - The ID of the job run to retrieve\n * @returns An array of jobs\n */\n public async getByRunId(job_run_id: string): Promise<Array<JobStorageFormat<Input, Output>>> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(3);\n const result = await this.db.query(\n `\n SELECT * FROM ${this.tableName} WHERE job_run_id = $1 AND queue = $2${prefixConditions}`,\n [job_run_id, this.queueName, ...prefixParams]\n );\n if (!result) return [];\n return result.rows;\n }\n\n /**\n * Implements the abstract saveProgress method from JobQueue\n */\n public async saveProgress(\n jobId: unknown,\n progress: number,\n message: string,\n details: Record<string, any>\n ): Promise<void> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(6);\n await this.db.query(\n `\n UPDATE ${this.tableName} \n SET progress = $1,\n progress_message = $2,\n progress_details = $3\n WHERE id = $4 AND queue = $5${prefixConditions}`,\n [\n progress,\n message,\n details ? JSON.stringify(details) : null,\n jobId,\n this.queueName,\n ...prefixParams,\n ]\n );\n }\n\n /**\n * Deletes a job by its ID\n */\n public async delete(jobId: unknown): Promise<void> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(3);\n await this.db.query(\n `DELETE FROM ${this.tableName} WHERE id = $1 AND queue = $2${prefixConditions}`,\n [jobId, this.queueName, ...prefixParams]\n );\n }\n\n /**\n * Delete jobs with a specific status older than a cutoff date\n * @param status - Status of jobs to delete\n * @param olderThanMs - Delete jobs completed more than this many milliseconds ago\n */\n public async deleteJobsByStatusAndAge(status: JobStatus, olderThanMs: number): Promise<void> {\n const cutoffDate = new Date(Date.now() - olderThanMs).toISOString();\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(4);\n await this.db.query(\n `DELETE FROM ${this.tableName} \n WHERE queue = $1 \n AND status = $2 \n AND completed_at IS NOT NULL \n AND completed_at <= $3${prefixConditions}`,\n [this.queueName, status, cutoffDate, ...prefixParams]\n );\n }\n\n /**\n * Subscribes to changes in the queue.\n * NOT IMPLEMENTED for PostgreSQL storage.\n *\n * @throws Error always - subscribeToChanges is not supported for PostgreSQL storage\n */\n public subscribeToChanges(\n callback: (change: QueueChangePayload<Input, Output>) => void,\n options?: QueueSubscribeOptions\n ): () => void {\n throw new Error(\"subscribeToChanges is not supported for PostgresQueueStorage\");\n }\n}\n",
|
|
44
|
-
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Sqlite } from \"@workglow/storage/sqlite\";\nimport { createServiceToken, makeFingerprint, sleep, uuid4 } from \"@workglow/util\";\nimport {\n IQueueStorage,\n JobStatus,\n JobStorageFormat,\n PrefixColumn,\n QueueChangePayload,\n QueueStorageOptions,\n QueueSubscribeOptions,\n} from \"./IQueueStorage\";\n\nexport const SQLITE_QUEUE_STORAGE =\n createServiceToken<IQueueStorage<any, any>>(\"jobqueue.storage.sqlite\");\n\ntype JobRowWithJsonStrings<Input, Output> = JobStorageFormat<Input, Output> & {\n input: string;\n output: string | null;\n progress_details: string | null;\n};\n\n/**\n * Extended options for SQLite queue storage including prefix support\n */\nexport interface SqliteQueueStorageOptions extends QueueStorageOptions {\n readonly deleteAfterCompletionMs?: number;\n readonly deleteAfterFailureMs?: number;\n}\n\n/**\n * SQLite implementation of a job queue.\n * Provides storage and retrieval for job execution states using SQLite.\n */\nexport class SqliteQueueStorage<Input, Output> implements IQueueStorage<Input, Output> {\n /** The prefix column definitions */\n protected readonly prefixes: readonly PrefixColumn[];\n /** The prefix values for filtering */\n protected readonly prefixValues: Readonly<Record<string, string | number>>;\n /** The table name for the job queue */\n protected readonly tableName: string;\n\n constructor(\n protected db: Sqlite.Database,\n protected queueName: string,\n protected options?: SqliteQueueStorageOptions\n ) {\n this.prefixes = options?.prefixes ?? [];\n this.prefixValues = options?.prefixValues ?? {};\n // Generate table name based on prefix configuration to avoid column conflicts\n if (this.prefixes.length > 0) {\n const prefixNames = this.prefixes.map((p) => p.name).join(\"_\");\n this.tableName = `job_queue_${prefixNames}`;\n } else {\n this.tableName = \"job_queue\";\n }\n }\n\n /**\n * Gets the SQL column type for a prefix column (SQLite uses TEXT for uuid)\n */\n private getPrefixColumnType(type: PrefixColumn[\"type\"]): string {\n return type === \"uuid\" ? \"TEXT\" : \"INTEGER\";\n }\n\n /**\n * Builds the prefix columns SQL for CREATE TABLE\n */\n private buildPrefixColumnsSql(): string {\n if (this.prefixes.length === 0) return \"\";\n return (\n this.prefixes\n .map((p) => `${p.name} ${this.getPrefixColumnType(p.type)} NOT NULL`)\n .join(\",\\n \") + \",\\n \"\n );\n }\n\n /**\n * Builds prefix column names for use in queries\n */\n private getPrefixColumnNames(): string[] {\n return this.prefixes.map((p) => p.name);\n }\n\n /**\n * Builds WHERE clause conditions for prefix filtering\n * @returns The conditions string with placeholders\n */\n private buildPrefixWhereClause(): string {\n if (this.prefixes.length === 0) {\n return \"\";\n }\n const conditions = this.prefixes.map((p) => `${p.name} = ?`).join(\" AND \");\n return \" AND \" + conditions;\n }\n\n /**\n * Gets prefix values as an array in column order\n */\n private getPrefixParamValues(): Array<string | number> {\n return this.prefixes.map((p) => this.prefixValues[p.name]);\n }\n\n public async setupDatabase(): Promise<void> {\n await sleep(0);\n const prefixColumnsSql = this.buildPrefixColumnsSql();\n const prefixColumnNames = this.getPrefixColumnNames();\n const prefixIndexPrefix =\n prefixColumnNames.length > 0 ? prefixColumnNames.join(\", \") + \", \" : \"\";\n const indexSuffix = prefixColumnNames.length > 0 ? \"_\" + prefixColumnNames.join(\"_\") : \"\";\n\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS ${this.tableName} (\n id INTEGER PRIMARY KEY,\n ${prefixColumnsSql}fingerprint text NOT NULL,\n queue text NOT NULL,\n job_run_id text NOT NULL,\n status TEXT NOT NULL default 'PENDING',\n input TEXT NOT NULL,\n output TEXT,\n run_attempts INTEGER default 0,\n max_retries INTEGER default 23,\n run_after TEXT NOT NULL,\n last_ran_at TEXT,\n created_at TEXT NOT NULL,\n completed_at TEXT,\n deadline_at TEXT,\n error TEXT,\n error_code TEXT,\n progress REAL DEFAULT 0,\n progress_message TEXT DEFAULT '',\n progress_details TEXT NULL,\n worker_id TEXT\n );\n \n CREATE INDEX IF NOT EXISTS job_queue_fetcher${indexSuffix}_idx ON ${this.tableName} (${prefixIndexPrefix}queue, status, run_after);\n CREATE INDEX IF NOT EXISTS job_queue_fingerprint${indexSuffix}_idx ON ${this.tableName} (${prefixIndexPrefix}queue, fingerprint, status);\n CREATE INDEX IF NOT EXISTS job_queue_job_run_id${indexSuffix}_idx ON ${this.tableName} (${prefixIndexPrefix}queue, job_run_id);\n `);\n }\n\n /**\n * Adds a new job to the queue.\n * @param job - The job to add\n * @returns The ID of the added job\n */\n public async add(job: JobStorageFormat<Input, Output>): Promise<unknown> {\n const now = new Date().toISOString();\n job.job_run_id = job.job_run_id ?? uuid4();\n job.queue = this.queueName;\n job.fingerprint = await makeFingerprint(job.input);\n job.status = JobStatus.PENDING;\n job.progress = 0;\n job.progress_message = \"\";\n job.progress_details = null;\n job.created_at = now;\n job.run_after = now;\n\n const prefixColumnNames = this.getPrefixColumnNames();\n const prefixColumnsInsert =\n prefixColumnNames.length > 0 ? prefixColumnNames.join(\", \") + \", \" : \"\";\n const prefixPlaceholders =\n prefixColumnNames.length > 0 ? prefixColumnNames.map(() => \"?\").join(\", \") + \", \" : \"\";\n const prefixParamValues = this.getPrefixParamValues();\n\n const AddQuery = `\n INSERT INTO ${this.tableName}(\n ${prefixColumnsInsert}queue, \n fingerprint, \n input, \n run_after, \n deadline_at, \n max_retries, \n job_run_id, \n progress, \n progress_message, \n progress_details,\n created_at\n )\n VALUES (${prefixPlaceholders}?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n RETURNING id`;\n\n const stmt = this.db.prepare<unknown[], { id: string }>(AddQuery);\n\n const result = stmt.get(\n ...prefixParamValues,\n job.queue,\n job.fingerprint,\n JSON.stringify(job.input),\n job.run_after,\n job.deadline_at ?? null,\n job.max_retries!,\n job.job_run_id,\n job.progress,\n job.progress_message,\n job.progress_details ? JSON.stringify(job.progress_details) : null,\n job.created_at\n ) as { id: string } | undefined;\n\n job.id = result?.id;\n return result?.id;\n }\n\n /**\n * Retrieves a job by its ID.\n * @param id - The ID of the job to retrieve\n * @returns The job if found, undefined otherwise\n */\n public async get(id: unknown): Promise<JobStorageFormat<Input, Output> | undefined> {\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n const JobQuery = `\n SELECT *\n FROM ${this.tableName}\n WHERE id = ? AND queue = ?${prefixConditions}\n LIMIT 1`;\n const stmt = this.db.prepare<\n unknown[],\n JobStorageFormat<Input, Output> & {\n input: string;\n output: string | null;\n progress_details: string | null;\n }\n >(JobQuery);\n const result = stmt.get(String(id), this.queueName, ...prefixParams);\n if (!result) return undefined;\n\n // Parse JSON fields\n if (result.input) result.input = JSON.parse(result.input);\n if (result.output) result.output = JSON.parse(result.output);\n if (result.progress_details) result.progress_details = JSON.parse(result.progress_details);\n return result;\n }\n\n /**\n * Retrieves a slice of jobs from the queue.\n * @param num - Maximum number of jobs to return\n * @returns An array of jobs\n */\n public async peek(\n status: JobStatus = JobStatus.PENDING,\n num: number = 100\n ): Promise<Array<JobStorageFormat<Input, Output>>> {\n num = Math.max(1, Math.min(10000, Math.floor(Number(num) || 100))); // Validate and clamp to safe range\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n const FutureJobQuery = `\n SELECT * \n FROM ${this.tableName}\n WHERE queue = ?\n AND status = ?${prefixConditions}\n ORDER BY run_after ASC\n LIMIT ${num}`;\n const stmt = this.db.prepare<\n unknown[],\n JobStorageFormat<Input, Output> & {\n input: string;\n output: string | null;\n progress_details: string | null;\n }\n >(FutureJobQuery);\n const result = stmt.all(this.queueName, status, ...prefixParams);\n return (result || []).map((details: JobRowWithJsonStrings<Input, Output>) => {\n // Parse JSON fields\n if (details.input) details.input = JSON.parse(details.input);\n if (details.output) details.output = JSON.parse(details.output);\n if (details.progress_details) details.progress_details = JSON.parse(details.progress_details);\n\n return details;\n });\n }\n\n /**\n * Aborts a job by setting its status to \"ABORTING\".\n * This method will signal the corresponding AbortController so that\n * the job's execute() method (if it supports an AbortSignal parameter)\n * can clean up and exit.\n */\n public async abort(jobId: unknown): Promise<void> {\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n const AbortQuery = `\n UPDATE ${this.tableName}\n SET status = ? \n WHERE id = ? AND queue = ?${prefixConditions}`;\n const stmt = this.db.prepare(AbortQuery);\n stmt.run(JobStatus.ABORTING, String(jobId), this.queueName, ...prefixParams);\n }\n\n /**\n * Releases a claimed job back to PENDING without incrementing run_attempts.\n * @param jobId - The id of the claimed job to release.\n */\n public async release(jobId: unknown): Promise<void> {\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n const ReleaseQuery = `\n UPDATE ${this.tableName}\n SET status = ?,\n worker_id = NULL,\n progress = 0,\n progress_message = '',\n progress_details = NULL\n WHERE id = ? AND queue = ?${prefixConditions}`;\n const stmt = this.db.prepare(ReleaseQuery);\n stmt.run(JobStatus.PENDING, String(jobId), this.queueName, ...prefixParams);\n }\n\n /**\n * Retrieves all jobs for a given job run ID.\n * @param job_run_id - The ID of the job run to retrieve\n * @returns An array of jobs\n */\n public async getByRunId(job_run_id: string): Promise<Array<JobStorageFormat<Input, Output>>> {\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n const JobsByRunIdQuery = `\n SELECT *\n FROM ${this.tableName}\n WHERE job_run_id = ? AND queue = ?${prefixConditions}`;\n const stmt = this.db.prepare<\n unknown[],\n JobStorageFormat<Input, Output> & {\n input: string;\n output: string | null;\n progress_details: string | null;\n }\n >(JobsByRunIdQuery);\n const result = stmt.all(job_run_id, this.queueName, ...prefixParams);\n return (result || []).map((details: JobRowWithJsonStrings<Input, Output>) => {\n // Parse JSON fields\n if (details.input) details.input = JSON.parse(details.input);\n if (details.output) details.output = JSON.parse(details.output);\n if (details.progress_details) details.progress_details = JSON.parse(details.progress_details);\n\n return details;\n });\n }\n\n /**\n * Retrieves the next available job that is ready to be processed,\n * and updates its status to PROCESSING.\n *\n * @param workerId - Worker ID to associate with the job\n * @returns The next job or undefined if no job is available\n */\n public async next(workerId: string): Promise<JobStorageFormat<Input, Output> | undefined> {\n const now = new Date().toISOString();\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n // Then, get the next job to process\n const stmt = this.db.prepare<\n unknown[],\n JobStorageFormat<Input, Output> & {\n input: string;\n output: string | null;\n progress_details: string | null;\n }\n >(\n `\n UPDATE ${this.tableName} \n SET status = ?, last_ran_at = ?, worker_id = ?\n WHERE id = (\n SELECT id \n FROM ${this.tableName} \n WHERE queue = ? \n AND status = ?${prefixConditions}\n AND run_after <= ? \n ORDER BY run_after ASC \n LIMIT 1\n )\n RETURNING *`\n );\n const result = stmt.get(\n JobStatus.PROCESSING,\n now,\n workerId,\n this.queueName,\n JobStatus.PENDING,\n ...prefixParams,\n now\n );\n if (!result) return undefined;\n\n // Parse JSON fields\n if (result.input) result.input = JSON.parse(result.input);\n if (result.output) result.output = JSON.parse(result.output);\n if (result.progress_details) result.progress_details = JSON.parse(result.progress_details);\n\n return result;\n }\n\n /**\n * Retrieves the number of jobs in the queue with a specific status.\n * @param status - The status of the jobs to count\n * @returns The count of jobs with the specified status\n */\n public async size(status = JobStatus.PENDING): Promise<number> {\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n const sizeQuery = `\n SELECT COUNT(*) as count\n FROM ${this.tableName}\n WHERE queue = ?\n AND status = ?${prefixConditions}`;\n const stmt = this.db.prepare<unknown[], { count: number }>(sizeQuery);\n const result = stmt.get(this.queueName, status, ...prefixParams) as any;\n return result.count;\n }\n\n /**\n * Marks a job as complete with its output or error.\n * Enhanced error handling:\n * - Increments the retry count.\n * - For a retryable error, updates run_after with the retry date.\n * - Marks the job as FAILED for permanent or generic errors.\n * - Marks the job as DISABLED for disabled jobs.\n */\n public async complete(job: JobStorageFormat<Input, Output>): Promise<void> {\n const now = new Date().toISOString();\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n let updateQuery: string;\n let params: Array<string | number | null>;\n if (job.status === JobStatus.DISABLED) {\n updateQuery = `\n UPDATE ${this.tableName} \n SET \n status = ?, \n progress = 100, \n progress_message = '', \n progress_details = NULL, \n completed_at = ? \n WHERE id = ? AND queue = ?${prefixConditions}`;\n params = [job.status, now, job.id as string, this.queueName, ...prefixParams];\n } else {\n updateQuery = `\n UPDATE ${this.tableName} \n SET \n output = ?, \n error = ?, \n error_code = ?, \n status = ?, \n progress = 100, \n progress_message = '', \n progress_details = NULL, \n last_ran_at = ?,\n completed_at = ?,\n run_attempts = run_attempts + 1\n WHERE id = ? AND queue = ?${prefixConditions}`;\n params = [\n job.output ? JSON.stringify(job.output) : null,\n job.error ?? null,\n job.error_code ?? null,\n job.status!,\n now,\n now,\n job.id as string,\n this.queueName,\n ...prefixParams,\n ];\n }\n const stmt = this.db.prepare(updateQuery);\n stmt.run(...params);\n }\n\n public async deleteAll(): Promise<void> {\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n const ClearQuery = `\n DELETE FROM ${this.tableName}\n WHERE queue = ?${prefixConditions}`;\n const stmt = this.db.prepare(ClearQuery);\n stmt.run(this.queueName, ...prefixParams);\n }\n\n /**\n * Looks up cached output for a given input\n * Uses input fingerprinting for efficient matching\n * @returns The cached output or null if not found\n */\n public async outputForInput(input: Input): Promise<Output | null> {\n const fingerprint = await makeFingerprint(input);\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n const OutputQuery = `\n SELECT output\n FROM ${this.tableName}\n WHERE queue = ? AND fingerprint = ? AND status = ?${prefixConditions}`;\n const stmt = this.db.prepare<unknown[], { output: string }>(OutputQuery);\n const result = stmt.get(this.queueName, fingerprint, JobStatus.COMPLETED, ...prefixParams);\n return result?.output ? JSON.parse(result.output) : null;\n }\n\n /**\n * Implements the abstract saveProgress method from JobQueue\n */\n public async saveProgress(\n jobId: unknown,\n progress: number,\n message: string,\n details: Record<string, any>\n ): Promise<void> {\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n const UpdateProgressQuery = `\n UPDATE ${this.tableName}\n SET progress = ?,\n progress_message = ?,\n progress_details = ?\n WHERE id = ? AND queue = ?${prefixConditions}`;\n\n const stmt = this.db.prepare(UpdateProgressQuery);\n stmt.run(\n progress,\n message,\n JSON.stringify(details),\n String(jobId),\n this.queueName,\n ...prefixParams\n );\n }\n\n /**\n * Deletes a job by its ID\n */\n public async delete(jobId: unknown): Promise<void> {\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n const DeleteQuery = `\n DELETE FROM ${this.tableName}\n WHERE id = ? AND queue = ?${prefixConditions}`;\n const stmt = this.db.prepare(DeleteQuery);\n stmt.run(String(jobId), this.queueName, ...prefixParams);\n }\n\n /**\n * Delete jobs with a specific status older than a cutoff date\n * @param status - Status of jobs to delete\n * @param olderThanMs - Delete jobs completed more than this many milliseconds ago\n */\n public async deleteJobsByStatusAndAge(status: JobStatus, olderThanMs: number): Promise<void> {\n const cutoffDate = new Date(Date.now() - olderThanMs).toISOString();\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n const DeleteQuery = `\n DELETE FROM ${this.tableName}\n WHERE queue = ?\n AND status = ?\n AND completed_at IS NOT NULL\n AND completed_at <= ?${prefixConditions}`;\n const stmt = this.db.prepare(DeleteQuery);\n stmt.run(this.queueName, status, cutoffDate, ...prefixParams);\n }\n\n /**\n * Subscribes to changes in the queue.\n * NOT IMPLEMENTED for SQLite storage.\n *\n * @throws Error always - subscribeToChanges is not supported for SQLite storage\n */\n public subscribeToChanges(\n callback: (change: QueueChangePayload<Input, Output>) => void,\n options?: QueueSubscribeOptions\n ): () => void {\n throw new Error(\"subscribeToChanges is not supported for SqliteQueueStorage\");\n }\n}\n",
|
|
45
|
-
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { RealtimeChannel, SupabaseClient } from \"@supabase/supabase-js\";\nimport { createServiceToken, deepEqual, makeFingerprint, uuid4 } from \"@workglow/util\";\nimport { PollingSubscriptionManager } from \"../util/PollingSubscriptionManager\";\nimport {\n IQueueStorage,\n JobStatus,\n JobStorageFormat,\n PrefixColumn,\n QueueChangePayload,\n QueueChangeType,\n QueueStorageOptions,\n QueueSubscribeOptions,\n} from \"./IQueueStorage\";\n\nexport const SUPABASE_QUEUE_STORAGE = createServiceToken<IQueueStorage<any, any>>(\n \"jobqueue.storage.supabase\"\n);\n\n/**\n * Supabase implementation of a job queue.\n * Provides storage and retrieval for job execution states using Supabase.\n */\nexport class SupabaseQueueStorage<Input, Output> implements IQueueStorage<Input, Output> {\n protected readonly client: SupabaseClient;\n protected readonly prefixes: readonly PrefixColumn[];\n protected readonly prefixValues: Readonly<Record<string, string | number>>;\n protected readonly tableName: string;\n private realtimeChannel: RealtimeChannel | null = null;\n private pollingManager: PollingSubscriptionManager<\n JobStorageFormat<Input, Output>,\n unknown,\n QueueChangePayload<Input, Output>\n > | null = null;\n\n constructor(\n client: SupabaseClient,\n protected readonly queueName: string,\n options?: QueueStorageOptions\n ) {\n this.client = client as SupabaseClient;\n this.prefixes = options?.prefixes ?? [];\n this.prefixValues = options?.prefixValues ?? {};\n // Generate table name based on prefix configuration to avoid column conflicts\n if (this.prefixes.length > 0) {\n const prefixNames = this.prefixes.map((p) => p.name).join(\"_\");\n this.tableName = `job_queue_${prefixNames}`;\n } else {\n this.tableName = \"job_queue\";\n }\n }\n\n /**\n * Gets the SQL column type for a prefix column (Supabase supports UUID natively)\n */\n private getPrefixColumnType(type: PrefixColumn[\"type\"]): string {\n return type === \"uuid\" ? \"UUID\" : \"INTEGER\";\n }\n\n /**\n * Builds the prefix columns SQL for CREATE TABLE\n */\n private buildPrefixColumnsSql(): string {\n if (this.prefixes.length === 0) return \"\";\n return (\n this.prefixes\n .map((p) => `${p.name} ${this.getPrefixColumnType(p.type)} NOT NULL`)\n .join(\",\\n \") + \",\\n \"\n );\n }\n\n /**\n * Builds prefix column names for use in queries\n */\n private getPrefixColumnNames(): string[] {\n return this.prefixes.map((p) => p.name);\n }\n\n /**\n * Applies prefix filters to a Supabase query builder\n */\n private applyPrefixFilters<T>(query: T): T {\n let result = query as any;\n for (const prefix of this.prefixes) {\n result = result.eq(prefix.name, this.prefixValues[prefix.name]);\n }\n return result as T;\n }\n\n /**\n * Gets prefix values as an object for inserts\n */\n private getPrefixInsertValues(): Record<string, string | number> {\n const values: Record<string, string | number> = {};\n for (const prefix of this.prefixes) {\n values[prefix.name] = this.prefixValues[prefix.name];\n }\n return values;\n }\n\n /**\n * Builds WHERE clause conditions for prefix filtering with inline values (for raw SQL)\n * @returns SQL conditions string with values inlined\n */\n private buildPrefixWhereSql(): string {\n if (this.prefixes.length === 0) {\n return \"\";\n }\n const conditions = this.prefixes\n .map((p) => {\n const value = this.prefixValues[p.name];\n if (p.type === \"uuid\") {\n const validated = this.validateSqlValue(String(value), `prefix \"${p.name}\"`);\n return `${p.name} = '${this.escapeSqlString(validated)}'`;\n }\n const numValue = Number(value ?? 0);\n if (!Number.isFinite(numValue)) {\n throw new Error(`Invalid numeric prefix value for \"${p.name}\": ${value}`);\n }\n return `${p.name} = ${numValue}`;\n })\n .join(\" AND \");\n return \" AND \" + conditions;\n }\n\n /**\n * Regex for validating SQL literal-safe strings.\n * Used for quoted values (e.g. queue names/IDs) and only allows alphanumeric\n * characters, underscores, hyphens, colons, and periods.\n */\n private static readonly SAFE_SQL_VALUE_RE = /^[a-zA-Z0-9_\\-.:]+$/;\n\n /**\n * Validates that a string value is safe for use as a quoted SQL literal.\n * Throws an error if the value contains characters outside SAFE_SQL_VALUE_RE.\n */\n private validateSqlValue(value: string, context: string): string {\n if (!SupabaseQueueStorage.SAFE_SQL_VALUE_RE.test(value)) {\n throw new Error(\n `Unsafe value for ${context}: \"${value}\". Values must match /^[a-zA-Z0-9_\\\\-.:]+$/.`\n );\n }\n return value;\n }\n\n /**\n * Escapes a string value for use in SQL\n */\n private escapeSqlString(value: string): string {\n return value.replace(/'/g, \"''\");\n }\n\n public async setupDatabase(): Promise<void> {\n // Note: For Supabase, table creation should typically be done through migrations\n // This setup assumes the table already exists or uses exec_sql RPC function\n const createTypeSql = `CREATE TYPE job_status AS ENUM (${Object.values(JobStatus)\n .map((v) => `'${v}'`)\n .join(\",\")})`;\n\n const { error: typeError } = await this.client.rpc(\"exec_sql\", { query: createTypeSql });\n // Ignore error if type already exists (code 42710)\n if (typeError && typeError.code !== \"42710\") {\n throw typeError;\n }\n\n const prefixColumnsSql = this.buildPrefixColumnsSql();\n const prefixColumnNames = this.getPrefixColumnNames();\n const prefixIndexPrefix =\n prefixColumnNames.length > 0 ? prefixColumnNames.join(\", \") + \", \" : \"\";\n const indexSuffix = prefixColumnNames.length > 0 ? \"_\" + prefixColumnNames.join(\"_\") : \"\";\n\n const createTableSql = `\n CREATE TABLE IF NOT EXISTS ${this.tableName} (\n id SERIAL NOT NULL,\n ${prefixColumnsSql}fingerprint text NOT NULL,\n queue text NOT NULL,\n job_run_id text NOT NULL,\n status job_status NOT NULL default 'PENDING',\n input jsonb NOT NULL,\n output jsonb,\n run_attempts integer default 0,\n max_retries integer default 20,\n run_after timestamp with time zone DEFAULT now(),\n last_ran_at timestamp with time zone,\n created_at timestamp with time zone DEFAULT now(),\n deadline_at timestamp with time zone,\n completed_at timestamp with time zone,\n error text,\n error_code text,\n progress real DEFAULT 0,\n progress_message text DEFAULT '',\n progress_details jsonb,\n worker_id text\n )`;\n\n const { error: tableError } = await this.client.rpc(\"exec_sql\", { query: createTableSql });\n if (tableError) {\n // Ignore error if table already exists (code 42P07)\n if (tableError.code !== \"42P07\") {\n throw tableError;\n }\n }\n\n // Create indexes with prefix columns prepended\n const indexes = [\n `CREATE INDEX IF NOT EXISTS job_fetcher${indexSuffix}_idx ON ${this.tableName} (${prefixIndexPrefix}id, status, run_after)`,\n `CREATE INDEX IF NOT EXISTS job_queue_fetcher${indexSuffix}_idx ON ${this.tableName} (${prefixIndexPrefix}queue, status, run_after)`,\n `CREATE INDEX IF NOT EXISTS jobs_fingerprint${indexSuffix}_unique_idx ON ${this.tableName} (${prefixIndexPrefix}queue, fingerprint, status)`,\n ];\n\n for (const indexSql of indexes) {\n await this.client.rpc(\"exec_sql\", { query: indexSql });\n // Ignore index creation errors\n }\n }\n\n /**\n * Adds a new job to the queue.\n * @param job - The job to add\n * @returns The ID of the added job\n */\n public async add(job: JobStorageFormat<Input, Output>): Promise<unknown> {\n const now = new Date().toISOString();\n job.queue = this.queueName;\n job.job_run_id = job.job_run_id ?? uuid4();\n job.fingerprint = await makeFingerprint(job.input);\n job.status = JobStatus.PENDING;\n job.progress = 0;\n job.progress_message = \"\";\n job.progress_details = null;\n job.created_at = now;\n job.run_after = now;\n\n const prefixInsertValues = this.getPrefixInsertValues();\n\n const { data, error } = await this.client\n .from(this.tableName)\n .insert({\n ...prefixInsertValues,\n queue: job.queue,\n fingerprint: job.fingerprint,\n input: job.input,\n run_after: job.run_after,\n created_at: job.created_at,\n deadline_at: job.deadline_at,\n max_retries: job.max_retries,\n job_run_id: job.job_run_id,\n progress: job.progress,\n progress_message: job.progress_message,\n progress_details: job.progress_details,\n })\n .select(\"id\")\n .single();\n\n if (error) throw error;\n if (!data) throw new Error(\"Failed to add to queue\");\n\n job.id = data.id;\n return job.id;\n }\n\n /**\n * Retrieves a job by its ID.\n * @param id - The ID of the job to retrieve\n * @returns The job if found, undefined otherwise\n */\n public async get(id: unknown): Promise<JobStorageFormat<Input, Output> | undefined> {\n let query = this.client\n .from(this.tableName)\n .select(\"*\")\n .eq(\"id\", id)\n .eq(\"queue\", this.queueName);\n\n query = this.applyPrefixFilters(query);\n\n const { data, error } = await query.single();\n\n if (error) {\n if (error.code === \"PGRST116\") return undefined; // Not found\n throw error;\n }\n\n return data as JobStorageFormat<Input, Output> | undefined;\n }\n\n /**\n * Retrieves a slice of jobs from the queue.\n * @param status - The status to filter by\n * @param num - Maximum number of jobs to return\n * @returns An array of jobs\n */\n public async peek(\n status: JobStatus = JobStatus.PENDING,\n num: number = 100\n ): Promise<JobStorageFormat<Input, Output>[]> {\n num = Number(num) || 100;\n\n let query = this.client\n .from(this.tableName)\n .select(\"*\")\n .eq(\"queue\", this.queueName)\n .eq(\"status\", status);\n\n query = this.applyPrefixFilters(query);\n\n const { data, error } = await query.order(\"run_after\", { ascending: true }).limit(num);\n\n if (error) throw error;\n return (data as JobStorageFormat<Input, Output>[]) ?? [];\n }\n\n /**\n * Retrieves the next available job that is ready to be processed.\n * Uses atomic UPDATE with subquery SELECT FOR UPDATE SKIP LOCKED to prevent race conditions.\n * @param workerId - Worker ID to associate with the job (required)\n * @returns The next job or undefined if no job is available\n */\n public async next(workerId: string): Promise<JobStorageFormat<Input, Output> | undefined> {\n const prefixConditions = this.buildPrefixWhereSql();\n const validatedQueueName = this.validateSqlValue(this.queueName, \"queueName\");\n const validatedWorkerId = this.validateSqlValue(workerId, \"workerId\");\n const escapedQueueName = this.escapeSqlString(validatedQueueName);\n const escapedWorkerId = this.escapeSqlString(validatedWorkerId);\n\n // Use the same atomic UPDATE...WHERE id = (SELECT...FOR UPDATE SKIP LOCKED) pattern as PostgresQueueStorage\n const sql = `\n UPDATE ${this.tableName}\n SET status = '${JobStatus.PROCESSING}', last_ran_at = NOW() AT TIME ZONE 'UTC', worker_id = '${escapedWorkerId}'\n WHERE id = (\n SELECT id\n FROM ${this.tableName}\n WHERE queue = '${escapedQueueName}'\n AND status = '${JobStatus.PENDING}'\n ${prefixConditions}\n AND run_after <= NOW() AT TIME ZONE 'UTC'\n ORDER BY run_after ASC\n FOR UPDATE SKIP LOCKED\n LIMIT 1\n )\n RETURNING *`;\n\n const { data, error } = await this.client.rpc(\"exec_sql\", { query: sql });\n\n if (error) throw error;\n\n // exec_sql returns result rows as an array\n if (!data || !Array.isArray(data) || data.length === 0) {\n return undefined;\n }\n\n return data[0] as JobStorageFormat<Input, Output>;\n }\n\n /**\n * Retrieves the number of jobs in the queue with a specific status.\n * @param status - The status of the jobs to count\n * @returns The count of jobs with the specified status\n */\n public async size(status = JobStatus.PENDING): Promise<number> {\n let query = this.client\n .from(this.tableName)\n .select(\"*\", { count: \"exact\", head: true })\n .eq(\"queue\", this.queueName)\n .eq(\"status\", status);\n\n query = this.applyPrefixFilters(query);\n\n const { count, error } = await query;\n\n if (error) throw error;\n return count ?? 0;\n }\n\n /**\n * Gets all jobs from the queue that match the current prefix values.\n * Used internally for polling-based subscriptions.\n *\n * @returns An array of jobs\n */\n private async getAllJobs(): Promise<Array<JobStorageFormat<Input, Output>>> {\n let query = this.client.from(this.tableName).select(\"*\").eq(\"queue\", this.queueName);\n\n query = this.applyPrefixFilters(query);\n\n const { data, error } = await query;\n\n if (error) throw error;\n return (data ?? []) as Array<JobStorageFormat<Input, Output>>;\n }\n\n /**\n * Marks a job as complete with its output or error.\n * Enhanced error handling:\n * - For a retryable error, increments run_attempts and updates run_after.\n * - Marks a job as FAILED immediately for permanent or generic errors.\n */\n public async complete(jobDetails: JobStorageFormat<Input, Output>): Promise<void> {\n const now = new Date().toISOString();\n\n // Handle disabled without changing attempts\n if (jobDetails.status === JobStatus.DISABLED) {\n let query = this.client\n .from(this.tableName)\n .update({\n status: jobDetails.status,\n progress: 100,\n progress_message: \"\",\n progress_details: null,\n completed_at: now,\n last_ran_at: now,\n })\n .eq(\"id\", jobDetails.id)\n .eq(\"queue\", this.queueName);\n query = this.applyPrefixFilters(query);\n const { error } = await query;\n if (error) throw error;\n return;\n }\n\n // Read current attempts to compute next value deterministically\n let getQuery = this.client\n .from(this.tableName)\n .select(\"run_attempts, max_retries\")\n .eq(\"id\", jobDetails.id as number)\n .eq(\"queue\", this.queueName);\n getQuery = this.applyPrefixFilters(getQuery);\n const { data: current, error: getError } = await getQuery.single();\n if (getError) throw getError;\n const currentAttempts = (current?.run_attempts as number | undefined) ?? 0;\n const maxRetries = (current?.max_retries as number | undefined) ?? jobDetails.max_retries ?? 10;\n const nextAttempts = currentAttempts + 1;\n\n if (jobDetails.status === JobStatus.PENDING) {\n // Check if the next attempt would exceed max retries\n if (nextAttempts > maxRetries) {\n // Update to FAILED status instead of rescheduling\n let failQuery = this.client\n .from(this.tableName)\n .update({\n status: JobStatus.FAILED,\n error: \"Max retries reached\",\n error_code: \"MAX_RETRIES_REACHED\",\n progress: 100,\n progress_message: \"\",\n progress_details: null,\n completed_at: now,\n last_ran_at: now,\n })\n .eq(\"id\", jobDetails.id)\n .eq(\"queue\", this.queueName);\n failQuery = this.applyPrefixFilters(failQuery);\n const { error: failError } = await failQuery;\n if (failError) throw failError;\n return;\n }\n\n // Reschedule the job\n let query = this.client\n .from(this.tableName)\n .update({\n error: jobDetails.error ?? null,\n error_code: jobDetails.error_code ?? null,\n status: jobDetails.status,\n run_after: jobDetails.run_after!,\n progress: 0,\n progress_message: \"\",\n progress_details: null,\n run_attempts: nextAttempts,\n last_ran_at: now,\n })\n .eq(\"id\", jobDetails.id)\n .eq(\"queue\", this.queueName);\n query = this.applyPrefixFilters(query);\n const { error } = await query;\n if (error) throw error;\n return;\n }\n\n if (jobDetails.status === JobStatus.COMPLETED || jobDetails.status === JobStatus.FAILED) {\n let query = this.client\n .from(this.tableName)\n .update({\n output: jobDetails.output ?? null,\n error: jobDetails.error ?? null,\n error_code: jobDetails.error_code ?? null,\n status: jobDetails.status,\n progress: 100,\n progress_message: \"\",\n progress_details: null,\n run_attempts: nextAttempts,\n completed_at: now,\n last_ran_at: now,\n })\n .eq(\"id\", jobDetails.id)\n .eq(\"queue\", this.queueName);\n query = this.applyPrefixFilters(query);\n const { error } = await query;\n if (error) throw error;\n return;\n }\n\n // Transitional states: PROCESSING/ABORTING etc - increment attempts like other stores\n let query = this.client\n .from(this.tableName)\n .update({\n status: jobDetails.status,\n output: jobDetails.output ?? null,\n error: jobDetails.error ?? null,\n error_code: jobDetails.error_code ?? null,\n run_after: jobDetails.run_after ?? null,\n run_attempts: nextAttempts,\n last_ran_at: now,\n })\n .eq(\"id\", jobDetails.id)\n .eq(\"queue\", this.queueName);\n query = this.applyPrefixFilters(query);\n const { error } = await query;\n if (error) throw error;\n }\n\n /**\n * Releases a claimed job without consuming a retry attempt.\n */\n public async release(jobId: unknown): Promise<void> {\n let query = this.client\n .from(this.tableName)\n .update({\n status: JobStatus.PENDING,\n worker_id: null,\n progress: 0,\n progress_message: \"\",\n progress_details: null,\n })\n .eq(\"id\", jobId)\n .eq(\"queue\", this.queueName);\n\n query = this.applyPrefixFilters(query);\n const { error } = await query;\n if (error) throw error;\n }\n\n /**\n * Clears all jobs from the queue.\n */\n public async deleteAll(): Promise<void> {\n let query = this.client.from(this.tableName).delete().eq(\"queue\", this.queueName);\n query = this.applyPrefixFilters(query);\n const { error } = await query;\n\n if (error) throw error;\n }\n\n /**\n * Looks up cached output for a given input\n * Uses input fingerprinting for efficient matching\n * @returns The cached output or null if not found\n */\n public async outputForInput(input: Input): Promise<Output | null> {\n const fingerprint = await makeFingerprint(input);\n\n let query = this.client\n .from(this.tableName)\n .select(\"output\")\n .eq(\"fingerprint\", fingerprint)\n .eq(\"queue\", this.queueName)\n .eq(\"status\", JobStatus.COMPLETED);\n\n query = this.applyPrefixFilters(query);\n\n const { data, error } = await query.single();\n\n if (error) {\n if (error.code === \"PGRST116\") return null; // Not found\n throw error;\n }\n\n return data?.output ?? null;\n }\n\n /**\n * Aborts a job by setting its status to \"ABORTING\".\n * This method will signal the corresponding AbortController so that\n * the job's execute() method (if it supports an AbortSignal parameter)\n * can clean up and exit.\n */\n public async abort(jobId: unknown): Promise<void> {\n let query = this.client\n .from(this.tableName)\n .update({ status: JobStatus.ABORTING })\n .eq(\"id\", jobId)\n .eq(\"queue\", this.queueName);\n\n query = this.applyPrefixFilters(query);\n const { error } = await query;\n\n if (error) throw error;\n }\n\n /**\n * Retrieves all jobs for a given job run ID.\n * @param job_run_id - The ID of the job run to retrieve\n * @returns An array of jobs\n */\n public async getByRunId(job_run_id: string): Promise<Array<JobStorageFormat<Input, Output>>> {\n let query = this.client\n .from(this.tableName)\n .select(\"*\")\n .eq(\"job_run_id\", job_run_id)\n .eq(\"queue\", this.queueName);\n\n query = this.applyPrefixFilters(query);\n const { data, error } = await query;\n\n if (error) throw error;\n return (data as Array<JobStorageFormat<Input, Output>>) ?? [];\n }\n\n /**\n * Implements the saveProgress method\n */\n public async saveProgress(\n jobId: unknown,\n progress: number,\n message: string,\n details: Record<string, any>\n ): Promise<void> {\n let query = this.client\n .from(this.tableName)\n .update({\n progress,\n progress_message: message,\n progress_details: details,\n })\n .eq(\"id\", jobId)\n .eq(\"queue\", this.queueName);\n\n query = this.applyPrefixFilters(query);\n const { error } = await query;\n\n if (error) throw error;\n }\n\n /**\n * Deletes a job by its ID\n */\n public async delete(jobId: unknown): Promise<void> {\n let query = this.client\n .from(this.tableName)\n .delete()\n .eq(\"id\", jobId)\n .eq(\"queue\", this.queueName);\n\n query = this.applyPrefixFilters(query);\n const { error } = await query;\n\n if (error) throw error;\n }\n\n /**\n * Delete jobs with a specific status older than a cutoff date\n * @param status - Status of jobs to delete\n * @param olderThanMs - Delete jobs completed more than this many milliseconds ago\n */\n public async deleteJobsByStatusAndAge(status: JobStatus, olderThanMs: number): Promise<void> {\n const cutoffDate = new Date(Date.now() - olderThanMs).toISOString();\n\n let query = this.client\n .from(this.tableName)\n .delete()\n .eq(\"queue\", this.queueName)\n .eq(\"status\", status)\n .not(\"completed_at\", \"is\", null)\n .lte(\"completed_at\", cutoffDate);\n\n query = this.applyPrefixFilters(query);\n const { error } = await query;\n\n if (error) throw error;\n }\n\n /**\n * Checks if a job from a realtime payload matches the specified prefix filter\n * @param job - The job record from the realtime payload\n * @param prefixFilter - The prefix filter to match against (undefined = use instance prefixes, {} = no filter)\n */\n private matchesPrefixFilter(\n job: Record<string, unknown> | undefined,\n prefixFilter?: Readonly<Record<string, string | number>>\n ): boolean {\n if (!job) return false;\n\n // Check queue name first\n if (job.queue !== this.queueName) {\n return false;\n }\n\n // If prefixFilter is explicitly an empty object, no prefix filtering\n if (prefixFilter && Object.keys(prefixFilter).length === 0) {\n return true;\n }\n\n // Use provided prefixFilter or fall back to instance's prefixValues\n const filterValues = prefixFilter ?? this.prefixValues;\n\n // If no filter values, match all\n if (Object.keys(filterValues).length === 0) {\n return true;\n }\n\n // Check each filter value\n for (const [key, value] of Object.entries(filterValues)) {\n if (job[key] !== value) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Checks if a prefix filter is custom (different from instance's prefixes).\n */\n private isCustomPrefixFilter(prefixFilter?: Readonly<Record<string, string | number>>): boolean {\n // No filter specified - use instance prefixes (not custom)\n if (prefixFilter === undefined) {\n return false;\n }\n // Empty filter - receive all (custom)\n if (Object.keys(prefixFilter).length === 0) {\n return true;\n }\n // Check if filter matches instance prefixes exactly\n const instanceKeys = Object.keys(this.prefixValues);\n const filterKeys = Object.keys(prefixFilter);\n if (instanceKeys.length !== filterKeys.length) {\n return true; // Different number of keys = custom\n }\n for (const key of instanceKeys) {\n if (this.prefixValues[key] !== prefixFilter[key]) {\n return true; // Different value = custom\n }\n }\n return false; // Matches instance prefixes exactly\n }\n\n /**\n * Gets all jobs from the queue with a custom prefix filter.\n * Used for subscriptions with custom prefix filters (filters at DB level).\n *\n * @param prefixFilter - The prefix values to filter by (empty object = all jobs)\n * @returns A promise that resolves to an array of jobs\n */\n private async getAllJobsWithFilter(\n prefixFilter: Readonly<Record<string, string | number>>\n ): Promise<Array<JobStorageFormat<Input, Output>>> {\n let query = this.client.from(this.tableName).select(\"*\").eq(\"queue\", this.queueName);\n\n // Apply the custom prefix filter\n for (const [key, value] of Object.entries(prefixFilter)) {\n query = query.eq(key, value);\n }\n\n const { data, error } = await query;\n\n if (error) throw error;\n return (data ?? []) as Array<JobStorageFormat<Input, Output>>;\n }\n\n /**\n * Subscribes to changes in the queue.\n * Uses Supabase realtime by default.\n *\n * @param callback - Function called when a change occurs\n * @param options - Subscription options including prefix filter\n * @returns Unsubscribe function\n */\n public subscribeToChanges(\n callback: (change: QueueChangePayload<Input, Output>) => void,\n options?: QueueSubscribeOptions\n ): () => void {\n return this.subscribeToChangesWithRealtime(callback, options?.prefixFilter);\n }\n\n /**\n * Subscribe using Supabase realtime (protected).\n *\n * @param callback - Function called when a change occurs\n * @param prefixFilter - Optional prefix filter (undefined = use instance prefixes, {} = no filter)\n * @returns Unsubscribe function\n */\n protected subscribeToChangesWithRealtime(\n callback: (change: QueueChangePayload<Input, Output>) => void,\n prefixFilter?: Readonly<Record<string, string | number>>\n ): () => void {\n const channelName = `queue-${this.tableName}-${this.queueName}-${Date.now()}`;\n\n this.realtimeChannel = this.client\n .channel(channelName)\n .on(\n \"postgres_changes\",\n {\n event: \"*\",\n schema: \"public\",\n table: this.tableName,\n filter: `queue=eq.${this.queueName}`,\n },\n (payload) => {\n // Filter by prefix values\n const newJob = payload.new as Record<string, unknown> | undefined;\n const oldJob = payload.old as Record<string, unknown> | undefined;\n\n // Check if either old or new job matches the filter\n const newMatches = this.matchesPrefixFilter(newJob, prefixFilter);\n const oldMatches = this.matchesPrefixFilter(oldJob, prefixFilter);\n\n if (!newMatches && !oldMatches) {\n return;\n }\n\n callback({\n type: payload.eventType.toUpperCase() as QueueChangeType,\n old:\n oldJob && Object.keys(oldJob).length > 0\n ? (oldJob as JobStorageFormat<Input, Output>)\n : undefined,\n new:\n newJob && Object.keys(newJob).length > 0\n ? (newJob as JobStorageFormat<Input, Output>)\n : undefined,\n });\n }\n )\n .subscribe();\n\n return () => {\n if (this.realtimeChannel) {\n this.client.removeChannel(this.realtimeChannel);\n this.realtimeChannel = null;\n }\n };\n }\n\n /**\n * Gets or creates the shared polling subscription manager for normal subscriptions (fallback).\n * This ensures all normal subscriptions share a single polling loop per interval.\n */\n private getPollingManager(): PollingSubscriptionManager<\n JobStorageFormat<Input, Output>,\n unknown,\n QueueChangePayload<Input, Output>\n > {\n if (!this.pollingManager) {\n this.pollingManager = new PollingSubscriptionManager<\n JobStorageFormat<Input, Output>,\n unknown,\n QueueChangePayload<Input, Output>\n >(\n async () => {\n // Fetch jobs with instance's prefix filter (efficient DB-level filtering)\n const jobs = await this.getAllJobs();\n return new Map(jobs.map((j) => [j.id, j]));\n },\n (a, b) => deepEqual(a, b),\n {\n insert: (item) => ({ type: \"INSERT\" as const, new: item }),\n update: (oldItem, newItem) => ({ type: \"UPDATE\" as const, old: oldItem, new: newItem }),\n delete: (item) => ({ type: \"DELETE\" as const, old: item }),\n }\n );\n }\n return this.pollingManager;\n }\n\n /**\n * Creates a dedicated polling subscription for custom prefix filters (fallback).\n * This runs separately from the normal polling manager with DB-level filtering.\n */\n private subscribeWithCustomPrefixFilterPolling(\n callback: (change: QueueChangePayload<Input, Output>) => void,\n prefixFilter: Readonly<Record<string, string | number>>,\n intervalMs: number\n ): () => void {\n let lastKnownJobs = new Map<unknown, JobStorageFormat<Input, Output>>();\n let cancelled = false;\n\n const poll = async () => {\n if (cancelled) return;\n try {\n const currentJobs = await this.getAllJobsWithFilter(prefixFilter);\n if (cancelled) return;\n const currentMap = new Map(currentJobs.map((j) => [j.id, j]));\n\n // Detect changes\n for (const [id, job] of currentMap) {\n const old = lastKnownJobs.get(id);\n if (!old) {\n callback({ type: \"INSERT\", new: job });\n } else if (!deepEqual(old, job)) {\n callback({ type: \"UPDATE\", old, new: job });\n }\n }\n\n for (const [id, job] of lastKnownJobs) {\n if (!currentMap.has(id)) {\n callback({ type: \"DELETE\", old: job });\n }\n }\n\n lastKnownJobs = currentMap;\n } catch {\n // Ignore polling errors\n }\n };\n\n const intervalId = setInterval(poll, intervalMs);\n poll(); // Initial poll\n\n return () => {\n cancelled = true;\n clearInterval(intervalId);\n };\n }\n\n /**\n * Subscribe using polling (protected, available as fallback).\n *\n * Normal subscriptions (no custom prefix filter) share a single polling loop for efficiency.\n * Custom prefix filter subscriptions get their own dedicated polling loop with DB-level filtering.\n *\n * @param callback - Function called when a change occurs\n * @param options - Subscription options including interval and prefix filter\n * @returns Unsubscribe function\n */\n protected subscribeToChangesWithPolling(\n callback: (change: QueueChangePayload<Input, Output>) => void,\n options?: QueueSubscribeOptions\n ): () => void {\n const intervalMs = options?.pollingIntervalMs ?? 1000;\n\n // Check if this is a custom prefix filter subscription\n if (this.isCustomPrefixFilter(options?.prefixFilter)) {\n // Custom prefix filter - use dedicated polling with DB-level filtering\n return this.subscribeWithCustomPrefixFilterPolling(\n callback,\n options!.prefixFilter!,\n intervalMs\n );\n }\n\n // Normal subscription - use shared polling manager (efficient)\n const manager = this.getPollingManager();\n return manager.subscribe(callback, { intervalMs });\n }\n}\n",
|
|
46
|
-
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { createServiceToken } from \"@workglow/util\";\nimport type { Pool } from \"@workglow/storage/postgres\";\nimport type { PrefixColumn } from \"../queue/IQueueStorage\";\nimport { IRateLimiterStorage, RateLimiterStorageOptions } from \"./IRateLimiterStorage\";\n\nexport const POSTGRES_RATE_LIMITER_STORAGE = createServiceToken<IRateLimiterStorage>(\n \"ratelimiter.storage.postgres\"\n);\n\n/**\n * PostgreSQL implementation of rate limiter storage.\n * Manages execution records and next available times for rate limiting.\n */\nexport class PostgresRateLimiterStorage implements IRateLimiterStorage {\n /** The prefix column definitions */\n protected readonly prefixes: readonly PrefixColumn[];\n /** The prefix values for filtering */\n protected readonly prefixValues: Readonly<Record<string, string | number>>;\n /** The table name for execution tracking */\n protected readonly executionTableName: string;\n /** The table name for next available times */\n protected readonly nextAvailableTableName: string;\n\n constructor(\n protected readonly db: Pool,\n options?: RateLimiterStorageOptions\n ) {\n this.prefixes = options?.prefixes ?? [];\n this.prefixValues = options?.prefixValues ?? {};\n\n // Generate table names based on prefix configuration\n if (this.prefixes.length > 0) {\n const prefixNames = this.prefixes.map((p) => p.name).join(\"_\");\n this.executionTableName = `rate_limit_executions_${prefixNames}`;\n this.nextAvailableTableName = `rate_limit_next_available_${prefixNames}`;\n } else {\n this.executionTableName = \"rate_limit_executions\";\n this.nextAvailableTableName = \"rate_limit_next_available\";\n }\n }\n\n /**\n * Gets the SQL column type for a prefix column.\n */\n private getPrefixColumnType(type: PrefixColumn[\"type\"]): string {\n return type === \"uuid\" ? \"UUID\" : \"INTEGER\";\n }\n\n /**\n * Builds the prefix columns SQL for CREATE TABLE.\n */\n private buildPrefixColumnsSql(): string {\n if (this.prefixes.length === 0) return \"\";\n return (\n this.prefixes\n .map((p) => `${p.name} ${this.getPrefixColumnType(p.type)} NOT NULL`)\n .join(\",\\n \") + \",\\n \"\n );\n }\n\n /**\n * Builds prefix column names for use in queries.\n */\n private getPrefixColumnNames(): string[] {\n return this.prefixes.map((p) => p.name);\n }\n\n /**\n * Builds WHERE clause conditions for prefix filtering.\n * @param startParam - The starting parameter number for parameterized queries\n */\n private buildPrefixWhereClause(startParam: number): {\n conditions: string;\n params: Array<string | number>;\n } {\n if (this.prefixes.length === 0) {\n return { conditions: \"\", params: [] };\n }\n const conditions = this.prefixes.map((p, i) => `${p.name} = $${startParam + i}`).join(\" AND \");\n const params = this.prefixes.map((p) => this.prefixValues[p.name]);\n return { conditions: \" AND \" + conditions, params };\n }\n\n /**\n * Gets prefix values as an array in column order.\n */\n private getPrefixParamValues(): Array<string | number> {\n return this.prefixes.map((p) => this.prefixValues[p.name]);\n }\n\n public async setupDatabase(): Promise<void> {\n const prefixColumnsSql = this.buildPrefixColumnsSql();\n const prefixColumnNames = this.getPrefixColumnNames();\n const prefixIndexPrefix =\n prefixColumnNames.length > 0 ? prefixColumnNames.join(\", \") + \", \" : \"\";\n const indexSuffix = prefixColumnNames.length > 0 ? \"_\" + prefixColumnNames.join(\"_\") : \"\";\n\n await this.db.query(`\n CREATE TABLE IF NOT EXISTS ${this.executionTableName} (\n id SERIAL PRIMARY KEY,\n ${prefixColumnsSql}queue_name TEXT NOT NULL,\n executed_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()\n )\n `);\n\n await this.db.query(`\n CREATE INDEX IF NOT EXISTS rate_limit_exec_queue${indexSuffix}_idx \n ON ${this.executionTableName} (${prefixIndexPrefix}queue_name, executed_at)\n `);\n\n // For the next_available table, we need a composite primary key with prefixes\n const primaryKeyColumns =\n prefixColumnNames.length > 0 ? `${prefixColumnNames.join(\", \")}, queue_name` : \"queue_name\";\n\n await this.db.query(`\n CREATE TABLE IF NOT EXISTS ${this.nextAvailableTableName} (\n ${prefixColumnsSql}queue_name TEXT NOT NULL,\n next_available_at TIMESTAMP WITH TIME ZONE,\n PRIMARY KEY (${primaryKeyColumns})\n )\n `);\n }\n\n public async recordExecution(queueName: string): Promise<void> {\n const prefixColumnNames = this.getPrefixColumnNames();\n const prefixColumnsInsert =\n prefixColumnNames.length > 0 ? prefixColumnNames.join(\", \") + \", \" : \"\";\n const prefixParamValues = this.getPrefixParamValues();\n const prefixParamPlaceholders =\n prefixColumnNames.length > 0\n ? prefixColumnNames.map((_, i) => `$${i + 1}`).join(\", \") + \", \"\n : \"\";\n const queueParamNum = prefixColumnNames.length + 1;\n\n await this.db.query(\n `\n INSERT INTO ${this.executionTableName} (${prefixColumnsInsert}queue_name)\n VALUES (${prefixParamPlaceholders}$${queueParamNum})\n `,\n [...prefixParamValues, queueName]\n );\n }\n\n public async getExecutionCount(queueName: string, windowStartTime: string): Promise<number> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(3);\n\n const result = await this.db.query(\n `\n SELECT COUNT(*) AS count\n FROM ${this.executionTableName}\n WHERE queue_name = $1 AND executed_at > $2${prefixConditions}\n `,\n [queueName, windowStartTime, ...prefixParams]\n );\n\n return parseInt(result.rows[0]?.count ?? \"0\", 10);\n }\n\n public async getOldestExecutionAtOffset(\n queueName: string,\n offset: number\n ): Promise<string | undefined> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(3);\n\n const result = await this.db.query(\n `\n SELECT executed_at\n FROM ${this.executionTableName}\n WHERE queue_name = $1${prefixConditions}\n ORDER BY executed_at ASC\n LIMIT 1 OFFSET $2\n `,\n [queueName, offset, ...prefixParams]\n );\n\n const executedAt = result.rows[0]?.executed_at;\n if (!executedAt) return undefined;\n return new Date(executedAt).toISOString();\n }\n\n public async getNextAvailableTime(queueName: string): Promise<string | undefined> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(2);\n\n const result = await this.db.query(\n `\n SELECT next_available_at\n FROM ${this.nextAvailableTableName}\n WHERE queue_name = $1${prefixConditions}\n `,\n [queueName, ...prefixParams]\n );\n\n const nextAvailableAt = result.rows[0]?.next_available_at;\n if (!nextAvailableAt) return undefined;\n return new Date(nextAvailableAt).toISOString();\n }\n\n public async setNextAvailableTime(queueName: string, nextAvailableAt: string): Promise<void> {\n const prefixColumnNames = this.getPrefixColumnNames();\n const prefixColumnsInsert =\n prefixColumnNames.length > 0 ? prefixColumnNames.join(\", \") + \", \" : \"\";\n const prefixParamValues = this.getPrefixParamValues();\n const prefixParamPlaceholders =\n prefixColumnNames.length > 0\n ? prefixColumnNames.map((_, i) => `$${i + 1}`).join(\", \") + \", \"\n : \"\";\n const baseParamStart = prefixColumnNames.length + 1;\n\n // Build the conflict columns for upsert\n const conflictColumns =\n prefixColumnNames.length > 0 ? `${prefixColumnNames.join(\", \")}, queue_name` : \"queue_name\";\n\n await this.db.query(\n `\n INSERT INTO ${this.nextAvailableTableName} (${prefixColumnsInsert}queue_name, next_available_at)\n VALUES (${prefixParamPlaceholders}$${baseParamStart}, $${baseParamStart + 1})\n ON CONFLICT (${conflictColumns})\n DO UPDATE SET next_available_at = EXCLUDED.next_available_at\n `,\n [...prefixParamValues, queueName, nextAvailableAt]\n );\n }\n\n public async clear(queueName: string): Promise<void> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(2);\n\n await this.db.query(\n `DELETE FROM ${this.executionTableName} WHERE queue_name = $1${prefixConditions}`,\n [queueName, ...prefixParams]\n );\n await this.db.query(\n `DELETE FROM ${this.nextAvailableTableName} WHERE queue_name = $1${prefixConditions}`,\n [queueName, ...prefixParams]\n );\n }\n}\n",
|
|
47
|
-
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Sqlite } from \"@workglow/storage/sqlite\";\nimport { createServiceToken, sleep, toSQLiteTimestamp } from \"@workglow/util\";\nimport type { PrefixColumn } from \"../queue/IQueueStorage\";\nimport { IRateLimiterStorage, RateLimiterStorageOptions } from \"./IRateLimiterStorage\";\n\nexport const SQLITE_RATE_LIMITER_STORAGE = createServiceToken<IRateLimiterStorage>(\n \"ratelimiter.storage.sqlite\"\n);\n\n/**\n * SQLite implementation of rate limiter storage.\n * Manages execution records and next available times for rate limiting.\n */\nexport class SqliteRateLimiterStorage implements IRateLimiterStorage {\n /** The prefix column definitions */\n protected readonly prefixes: readonly PrefixColumn[];\n /** The prefix values for filtering */\n protected readonly prefixValues: Readonly<Record<string, string | number>>;\n /** The table name for execution tracking */\n protected readonly executionTableName: string;\n /** The table name for next available times */\n protected readonly nextAvailableTableName: string;\n\n constructor(\n protected readonly db: Sqlite.Database,\n options?: RateLimiterStorageOptions\n ) {\n this.prefixes = options?.prefixes ?? [];\n this.prefixValues = options?.prefixValues ?? {};\n\n // Generate table names based on prefix configuration\n if (this.prefixes.length > 0) {\n const prefixNames = this.prefixes.map((p) => p.name).join(\"_\");\n this.executionTableName = `rate_limit_executions_${prefixNames}`;\n this.nextAvailableTableName = `rate_limit_next_available_${prefixNames}`;\n } else {\n this.executionTableName = \"rate_limit_executions\";\n this.nextAvailableTableName = \"rate_limit_next_available\";\n }\n }\n\n /**\n * Gets the SQL column type for a prefix column (SQLite uses TEXT for uuid).\n */\n private getPrefixColumnType(type: PrefixColumn[\"type\"]): string {\n return type === \"uuid\" ? \"TEXT\" : \"INTEGER\";\n }\n\n /**\n * Builds the prefix columns SQL for CREATE TABLE.\n */\n private buildPrefixColumnsSql(): string {\n if (this.prefixes.length === 0) return \"\";\n return (\n this.prefixes\n .map((p) => `${p.name} ${this.getPrefixColumnType(p.type)} NOT NULL`)\n .join(\",\\n \") + \",\\n \"\n );\n }\n\n /**\n * Builds prefix column names for use in queries.\n */\n private getPrefixColumnNames(): string[] {\n return this.prefixes.map((p) => p.name);\n }\n\n /**\n * Builds WHERE clause conditions for prefix filtering.\n */\n private buildPrefixWhereClause(): string {\n if (this.prefixes.length === 0) {\n return \"\";\n }\n const conditions = this.prefixes.map((p) => `${p.name} = ?`).join(\" AND \");\n return \" AND \" + conditions;\n }\n\n /**\n * Gets prefix values as an array in column order.\n */\n private getPrefixParamValues(): Array<string | number> {\n return this.prefixes.map((p) => this.prefixValues[p.name]);\n }\n\n public async setupDatabase(): Promise<void> {\n await sleep(0);\n const prefixColumnsSql = this.buildPrefixColumnsSql();\n const prefixColumnNames = this.getPrefixColumnNames();\n const prefixIndexPrefix =\n prefixColumnNames.length > 0 ? prefixColumnNames.join(\", \") + \", \" : \"\";\n const indexSuffix = prefixColumnNames.length > 0 ? \"_\" + prefixColumnNames.join(\"_\") : \"\";\n\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS ${this.executionTableName} (\n id INTEGER PRIMARY KEY,\n ${prefixColumnsSql}queue_name TEXT NOT NULL,\n executed_at TEXT DEFAULT CURRENT_TIMESTAMP\n );\n \n CREATE INDEX IF NOT EXISTS rate_limit_exec_queue${indexSuffix}_idx \n ON ${this.executionTableName} (${prefixIndexPrefix}queue_name, executed_at);\n `);\n\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS ${this.nextAvailableTableName} (\n ${prefixColumnsSql}queue_name TEXT PRIMARY KEY,\n next_available_at TEXT\n );\n `);\n }\n\n public async recordExecution(queueName: string): Promise<void> {\n const prefixColumnNames = this.getPrefixColumnNames();\n const prefixColumnsInsert =\n prefixColumnNames.length > 0 ? prefixColumnNames.join(\", \") + \", \" : \"\";\n const prefixPlaceholders =\n prefixColumnNames.length > 0 ? prefixColumnNames.map(() => \"?\").join(\", \") + \", \" : \"\";\n const prefixParamValues = this.getPrefixParamValues();\n\n const stmt = this.db.prepare(`\n INSERT INTO ${this.executionTableName} (${prefixColumnsInsert}queue_name)\n VALUES (${prefixPlaceholders}?)\n `);\n stmt.run(...prefixParamValues, queueName);\n }\n\n public async getExecutionCount(queueName: string, windowStartTime: string): Promise<number> {\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n const thresholdTime = toSQLiteTimestamp(new Date(windowStartTime));\n\n const stmt = this.db.prepare<unknown[], { count: number }>(`\n SELECT COUNT(*) AS count\n FROM ${this.executionTableName}\n WHERE queue_name = ? AND executed_at > ?${prefixConditions}\n `);\n const result = stmt.get(queueName, thresholdTime!, ...prefixParams);\n return result?.count ?? 0;\n }\n\n public async getOldestExecutionAtOffset(\n queueName: string,\n offset: number\n ): Promise<string | undefined> {\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n const stmt = this.db.prepare<unknown[], { executed_at: string }>(`\n SELECT executed_at\n FROM ${this.executionTableName}\n WHERE queue_name = ?${prefixConditions}\n ORDER BY executed_at ASC\n LIMIT 1 OFFSET ?\n `);\n const result = stmt.get(queueName, ...prefixParams, offset);\n if (!result) return undefined;\n // SQLite stores times without timezone, add Z for UTC\n return result.executed_at + \"Z\";\n }\n\n public async getNextAvailableTime(queueName: string): Promise<string | undefined> {\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n const stmt = this.db.prepare<unknown[], { next_available_at: string }>(`\n SELECT next_available_at\n FROM ${this.nextAvailableTableName}\n WHERE queue_name = ?${prefixConditions}\n `);\n const result = stmt.get(queueName, ...prefixParams);\n if (!result?.next_available_at) return undefined;\n // SQLite stores times without timezone, add Z for UTC\n return result.next_available_at + \"Z\";\n }\n\n public async setNextAvailableTime(queueName: string, nextAvailableAt: string): Promise<void> {\n const prefixColumnNames = this.getPrefixColumnNames();\n const prefixColumnsInsert =\n prefixColumnNames.length > 0 ? prefixColumnNames.join(\", \") + \", \" : \"\";\n const prefixPlaceholders =\n prefixColumnNames.length > 0 ? prefixColumnNames.map(() => \"?\").join(\", \") + \", \" : \"\";\n const prefixParamValues = this.getPrefixParamValues();\n\n const stmt = this.db.prepare(`\n INSERT INTO ${this.nextAvailableTableName} (${prefixColumnsInsert}queue_name, next_available_at)\n VALUES (${prefixPlaceholders}?, ?)\n ON CONFLICT(queue_name) DO UPDATE SET next_available_at = excluded.next_available_at\n `);\n stmt.run(...prefixParamValues, queueName, nextAvailableAt);\n }\n\n public async clear(queueName: string): Promise<void> {\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n this.db\n .prepare(`DELETE FROM ${this.executionTableName} WHERE queue_name = ?${prefixConditions}`)\n .run(queueName, ...prefixParams);\n this.db\n .prepare(`DELETE FROM ${this.nextAvailableTableName} WHERE queue_name = ?${prefixConditions}`)\n .run(queueName, ...prefixParams);\n }\n}\n",
|
|
48
|
-
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { SupabaseClient } from \"@supabase/supabase-js\";\nimport { createServiceToken } from \"@workglow/util\";\nimport type { PrefixColumn } from \"../queue/IQueueStorage\";\nimport { IRateLimiterStorage, RateLimiterStorageOptions } from \"./IRateLimiterStorage\";\n\nexport const SUPABASE_RATE_LIMITER_STORAGE = createServiceToken<IRateLimiterStorage>(\n \"ratelimiter.storage.supabase\"\n);\n\n/**\n * Supabase implementation of rate limiter storage.\n * Manages execution records and next available times for rate limiting.\n */\nexport class SupabaseRateLimiterStorage implements IRateLimiterStorage {\n protected readonly client: SupabaseClient;\n protected readonly prefixes: readonly PrefixColumn[];\n protected readonly prefixValues: Readonly<Record<string, string | number>>;\n protected readonly executionTableName: string;\n protected readonly nextAvailableTableName: string;\n\n constructor(client: unknown, options?: RateLimiterStorageOptions) {\n this.client = client as SupabaseClient;\n this.prefixes = options?.prefixes ?? [];\n this.prefixValues = options?.prefixValues ?? {};\n\n // Generate table names based on prefix configuration\n if (this.prefixes.length > 0) {\n const prefixNames = this.prefixes.map((p) => p.name).join(\"_\");\n this.executionTableName = `rate_limit_executions_${prefixNames}`;\n this.nextAvailableTableName = `rate_limit_next_available_${prefixNames}`;\n } else {\n this.executionTableName = \"rate_limit_executions\";\n this.nextAvailableTableName = \"rate_limit_next_available\";\n }\n }\n\n /**\n * Gets the SQL column type for a prefix column (Supabase supports UUID natively).\n */\n private getPrefixColumnType(type: PrefixColumn[\"type\"]): string {\n return type === \"uuid\" ? \"UUID\" : \"INTEGER\";\n }\n\n /**\n * Builds the prefix columns SQL for CREATE TABLE.\n */\n private buildPrefixColumnsSql(): string {\n if (this.prefixes.length === 0) return \"\";\n return (\n this.prefixes\n .map((p) => `${p.name} ${this.getPrefixColumnType(p.type)} NOT NULL`)\n .join(\",\\n \") + \",\\n \"\n );\n }\n\n /**\n * Builds prefix column names for use in queries.\n */\n private getPrefixColumnNames(): string[] {\n return this.prefixes.map((p) => p.name);\n }\n\n /**\n * Applies prefix filters to a Supabase query builder.\n */\n private applyPrefixFilters<T>(query: T): T {\n let result = query as any;\n for (const prefix of this.prefixes) {\n result = result.eq(prefix.name, this.prefixValues[prefix.name]);\n }\n return result as T;\n }\n\n /**\n * Gets prefix values as an object for inserts.\n */\n private getPrefixInsertValues(): Record<string, string | number> {\n const values: Record<string, string | number> = {};\n for (const prefix of this.prefixes) {\n values[prefix.name] = this.prefixValues[prefix.name];\n }\n return values;\n }\n\n public async setupDatabase(): Promise<void> {\n const prefixColumnsSql = this.buildPrefixColumnsSql();\n const prefixColumnNames = this.getPrefixColumnNames();\n const prefixIndexPrefix =\n prefixColumnNames.length > 0 ? prefixColumnNames.join(\", \") + \", \" : \"\";\n const indexSuffix = prefixColumnNames.length > 0 ? \"_\" + prefixColumnNames.join(\"_\") : \"\";\n\n // Create execution tracking table\n const createExecTableSql = `\n CREATE TABLE IF NOT EXISTS ${this.executionTableName} (\n id SERIAL PRIMARY KEY,\n ${prefixColumnsSql}queue_name TEXT NOT NULL,\n executed_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()\n )\n `;\n\n const { error: execTableError } = await this.client.rpc(\"exec_sql\", {\n query: createExecTableSql,\n });\n if (execTableError && execTableError.code !== \"42P07\") {\n throw execTableError;\n }\n\n // Create index on execution table\n const createExecIndexSql = `\n CREATE INDEX IF NOT EXISTS rate_limit_exec_queue${indexSuffix}_idx \n ON ${this.executionTableName} (${prefixIndexPrefix}queue_name, executed_at)\n `;\n await this.client.rpc(\"exec_sql\", { query: createExecIndexSql });\n\n // Build primary key columns\n const primaryKeyColumns =\n prefixColumnNames.length > 0 ? `${prefixColumnNames.join(\", \")}, queue_name` : \"queue_name\";\n\n // Create next available table\n const createNextTableSql = `\n CREATE TABLE IF NOT EXISTS ${this.nextAvailableTableName} (\n ${prefixColumnsSql}queue_name TEXT NOT NULL,\n next_available_at TIMESTAMP WITH TIME ZONE,\n PRIMARY KEY (${primaryKeyColumns})\n )\n `;\n\n const { error: nextTableError } = await this.client.rpc(\"exec_sql\", {\n query: createNextTableSql,\n });\n if (nextTableError && nextTableError.code !== \"42P07\") {\n throw nextTableError;\n }\n }\n\n public async recordExecution(queueName: string): Promise<void> {\n const prefixInsertValues = this.getPrefixInsertValues();\n\n const { error } = await this.client.from(this.executionTableName).insert({\n ...prefixInsertValues,\n queue_name: queueName,\n });\n\n if (error) throw error;\n }\n\n public async getExecutionCount(queueName: string, windowStartTime: string): Promise<number> {\n let query = this.client\n .from(this.executionTableName)\n .select(\"*\", { count: \"exact\", head: true })\n .eq(\"queue_name\", queueName)\n .gt(\"executed_at\", windowStartTime);\n\n query = this.applyPrefixFilters(query);\n\n const { count, error } = await query;\n\n if (error) throw error;\n return count ?? 0;\n }\n\n public async getOldestExecutionAtOffset(\n queueName: string,\n offset: number\n ): Promise<string | undefined> {\n let query = this.client\n .from(this.executionTableName)\n .select(\"executed_at\")\n .eq(\"queue_name\", queueName);\n\n query = this.applyPrefixFilters(query);\n\n const { data, error } = await query\n .order(\"executed_at\", { ascending: true })\n .range(offset, offset);\n\n if (error) throw error;\n if (!data || data.length === 0) return undefined;\n return new Date(data[0].executed_at).toISOString();\n }\n\n public async getNextAvailableTime(queueName: string): Promise<string | undefined> {\n let query = this.client\n .from(this.nextAvailableTableName)\n .select(\"next_available_at\")\n .eq(\"queue_name\", queueName);\n\n query = this.applyPrefixFilters(query);\n\n const { data, error } = await query.single();\n\n if (error) {\n if (error.code === \"PGRST116\") return undefined; // Not found\n throw error;\n }\n\n if (!data?.next_available_at) return undefined;\n return new Date(data.next_available_at).toISOString();\n }\n\n public async setNextAvailableTime(queueName: string, nextAvailableAt: string): Promise<void> {\n const prefixInsertValues = this.getPrefixInsertValues();\n\n const { error } = await this.client.from(this.nextAvailableTableName).upsert(\n {\n ...prefixInsertValues,\n queue_name: queueName,\n next_available_at: nextAvailableAt,\n },\n {\n onConflict:\n this.prefixes.length > 0\n ? `${this.getPrefixColumnNames().join(\",\")},queue_name`\n : \"queue_name\",\n }\n );\n\n if (error) throw error;\n }\n\n public async clear(queueName: string): Promise<void> {\n let execQuery = this.client.from(this.executionTableName).delete().eq(\"queue_name\", queueName);\n execQuery = this.applyPrefixFilters(execQuery);\n const { error: execError } = await execQuery;\n if (execError) throw execError;\n\n let nextQuery = this.client\n .from(this.nextAvailableTableName)\n .delete()\n .eq(\"queue_name\", queueName);\n nextQuery = this.applyPrefixFilters(nextQuery);\n const { error: nextError } = await nextQuery;\n if (nextError) throw nextError;\n }\n}\n",
|
|
43
|
+
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { createHash } from \"node:crypto\";\nimport type { Pool } from \"@workglow/storage/postgres\";\nimport { createServiceToken, getLogger, makeFingerprint, uuid4 } from \"@workglow/util\";\nimport {\n IQueueStorage,\n JobStatus,\n JobStorageFormat,\n PrefixColumn,\n QueueChangePayload,\n QueueStorageOptions,\n QueueSubscribeOptions,\n} from \"./IQueueStorage\";\n\nexport const POSTGRES_QUEUE_STORAGE = createServiceToken<IQueueStorage<any, any>>(\n \"jobqueue.storage.postgres\"\n);\n\n/** Regex for safe SQL identifiers: starts with a letter, then alphanumeric/underscores */\nconst SAFE_IDENTIFIER = /^[a-zA-Z][a-zA-Z0-9_]*$/;\n\n/**\n * Subset of pg.PoolClient that {@link PostgresQueueStorage.subscribeToChanges}\n * needs. Typed locally so we don't require `pg` types at the storage layer.\n */\ninterface ListenClient {\n query: (sql: string) => Promise<unknown>;\n release: () => void;\n removeAllListeners?: (event: string) => void;\n on: (event: string, listener: (...args: any[]) => void) => void;\n}\n\n/**\n * PostgreSQL implementation of a job queue.\n * Provides storage and retrieval for job execution states using PostgreSQL.\n */\nexport class PostgresQueueStorage<Input, Output> implements IQueueStorage<Input, Output> {\n public readonly scope = \"cluster\" as const;\n /** The prefix column definitions */\n protected readonly prefixes: readonly PrefixColumn[];\n /** The prefix values for filtering */\n protected readonly prefixValues: Readonly<Record<string, string | number>>;\n /** The table name for the job queue */\n protected readonly tableName: string;\n\n constructor(\n protected readonly db: Pool,\n protected readonly queueName: string,\n options?: QueueStorageOptions\n ) {\n this.prefixes = options?.prefixes ?? [];\n this.prefixValues = options?.prefixValues ?? {};\n\n // Validate prefix column names to prevent SQL injection in DDL statements\n for (const prefix of this.prefixes) {\n if (!SAFE_IDENTIFIER.test(prefix.name)) {\n throw new Error(\n `Prefix column name must start with a letter and contain only letters, digits, and underscores, got: ${prefix.name}`\n );\n }\n }\n\n // Generate table name based on prefix configuration to avoid column conflicts\n if (this.prefixes.length > 0) {\n const prefixNames = this.prefixes.map((p) => p.name).join(\"_\");\n this.tableName = `job_queue_${prefixNames}`;\n } else {\n this.tableName = \"job_queue\";\n }\n }\n\n /**\n * Gets the SQL column type for a prefix column\n */\n private getPrefixColumnType(type: PrefixColumn[\"type\"]): string {\n return type === \"uuid\" ? \"UUID\" : \"INTEGER\";\n }\n\n /**\n * Builds the prefix columns SQL for CREATE TABLE\n */\n private buildPrefixColumnsSql(): string {\n if (this.prefixes.length === 0) return \"\";\n return (\n this.prefixes\n .map((p) => `${p.name} ${this.getPrefixColumnType(p.type)} NOT NULL`)\n .join(\",\\n \") + \",\\n \"\n );\n }\n\n /**\n * Builds prefix column names for use in queries\n */\n private getPrefixColumnNames(): string[] {\n return this.prefixes.map((p) => p.name);\n }\n\n /**\n * Builds WHERE clause conditions for prefix filtering\n * @param startParam - The starting parameter number for parameterized queries\n * @returns Object with conditions string and parameter values\n */\n private buildPrefixWhereClause(startParam: number): {\n conditions: string;\n params: Array<string | number>;\n } {\n if (this.prefixes.length === 0) {\n return { conditions: \"\", params: [] };\n }\n const conditions = this.prefixes.map((p, i) => `${p.name} = $${startParam + i}`).join(\" AND \");\n const params = this.prefixes.map((p) => this.prefixValues[p.name]);\n return { conditions: \" AND \" + conditions, params };\n }\n\n /**\n * Gets prefix values as an array in column order\n */\n private getPrefixParamValues(): Array<string | number> {\n return this.prefixes.map((p) => this.prefixValues[p.name]);\n }\n\n public async setupDatabase(): Promise<void> {\n let sql: string;\n try {\n const enumValues = Object.values(JobStatus);\n for (const v of enumValues) {\n if (!SAFE_IDENTIFIER.test(v)) {\n throw new Error(`Invalid JobStatus enum value: ${v}`);\n }\n }\n sql = `CREATE TYPE job_status AS ENUM (${enumValues.map((v) => `'${v}'`).join(\",\")})`;\n await this.db.query(sql);\n } catch (e: any) {\n // Ignore error if type already exists (code 42710)\n if (e.code !== \"42710\") throw e;\n }\n\n const prefixColumnsSql = this.buildPrefixColumnsSql();\n const prefixColumnNames = this.getPrefixColumnNames();\n const prefixIndexPrefix =\n prefixColumnNames.length > 0 ? prefixColumnNames.join(\", \") + \", \" : \"\";\n\n sql = `\n CREATE TABLE IF NOT EXISTS ${this.tableName} (\n id SERIAL NOT NULL,\n ${prefixColumnsSql}fingerprint text NOT NULL,\n queue text NOT NULL,\n job_run_id text NOT NULL,\n status job_status NOT NULL default 'PENDING',\n input jsonb NOT NULL,\n output jsonb,\n run_attempts integer default 0,\n max_retries integer default 20,\n run_after timestamp with time zone DEFAULT now(),\n last_ran_at timestamp with time zone,\n created_at timestamp with time zone DEFAULT now(),\n deadline_at timestamp with time zone,\n completed_at timestamp with time zone,\n error text,\n error_code text,\n progress real DEFAULT 0,\n progress_message text DEFAULT '',\n progress_details jsonb,\n worker_id text\n )`;\n\n await this.db.query(sql);\n\n // Create indexes with prefix columns prepended\n const indexSuffix = prefixColumnNames.length > 0 ? \"_\" + prefixColumnNames.join(\"_\") : \"\";\n\n sql = `\n CREATE INDEX IF NOT EXISTS job_fetcher${indexSuffix}_idx \n ON ${this.tableName} (${prefixIndexPrefix}id, status, run_after)`;\n await this.db.query(sql);\n\n sql = `\n CREATE INDEX IF NOT EXISTS job_queue_fetcher${indexSuffix}_idx \n ON ${this.tableName} (${prefixIndexPrefix}queue, status, run_after)`;\n await this.db.query(sql);\n\n sql = `\n CREATE INDEX IF NOT EXISTS jobs_fingerprint${indexSuffix}_unique_idx\n ON ${this.tableName} (${prefixIndexPrefix}queue, fingerprint, status)`;\n await this.db.query(sql);\n\n // Install LISTEN/NOTIFY plumbing so subscribers can wake on INSERT/UPDATE\n // without polling. The channel name is derived from md5(table || queue) so\n // (a) it fits Postgres's 63-char identifier limit even with long queue\n // names, and (b) different queues on the same table don't share a channel.\n //\n // Best-effort: in-process Postgres-compatible engines like PGLite may not\n // implement pg_notify or plpgsql. Skip trigger installation in that case\n // — subscribeToChanges will throw synchronously for those engines anyway,\n // so callers fall back to polling.\n const fnName = `${this.tableName}_notify`;\n const trgName = `${this.tableName}_notify_trg`;\n try {\n await this.db.query(`\n CREATE OR REPLACE FUNCTION ${fnName}() RETURNS trigger AS $fn$\n DECLARE\n channel TEXT := 'wglw_q_' || md5('${this.tableName}' || COALESCE(NEW.queue, OLD.queue));\n payload TEXT;\n BEGIN\n payload := json_build_object(\n 'op', TG_OP,\n 'id', COALESCE(NEW.id, OLD.id),\n 'queue', COALESCE(NEW.queue, OLD.queue),\n 'status', COALESCE(NEW.status::text, OLD.status::text)\n )::text;\n PERFORM pg_notify(channel, payload);\n RETURN NULL;\n END;\n $fn$ LANGUAGE plpgsql;\n `);\n await this.db.query(`DROP TRIGGER IF EXISTS ${trgName} ON ${this.tableName}`);\n await this.db.query(`\n CREATE TRIGGER ${trgName}\n AFTER INSERT OR UPDATE ON ${this.tableName}\n FOR EACH ROW EXECUTE FUNCTION ${fnName}();\n `);\n } catch {\n // best-effort — the engine doesn't support LISTEN/NOTIFY; subscribers\n // will get a synchronous throw and fall back to polling.\n }\n }\n\n /**\n * Channel name for this storage's LISTEN/NOTIFY. Mirrors the trigger's\n * computation so subscriber and notifier agree.\n */\n private notifyChannelName(): string {\n // md5() returns 32 hex chars; combined with the 7-char prefix this is well\n // under Postgres's 63-byte identifier limit.\n const tableAndQueue = `${this.tableName}${this.queueName}`;\n const hash = createHash(\"md5\").update(tableAndQueue).digest(\"hex\");\n return `wglw_q_${hash}`;\n }\n\n /**\n * Adds a new job to the queue.\n * @param job - The job to add\n * @returns The ID of the added job\n */\n public async add(job: JobStorageFormat<Input, Output>): Promise<unknown> {\n const now = new Date().toISOString();\n job.queue = this.queueName;\n job.job_run_id = job.job_run_id ?? uuid4();\n job.fingerprint = await makeFingerprint(job.input);\n job.status = JobStatus.PENDING;\n job.progress = 0;\n job.progress_message = \"\";\n job.progress_details = null;\n job.created_at = now;\n job.run_after = now;\n\n const prefixColumnNames = this.getPrefixColumnNames();\n const prefixColumnsInsert =\n prefixColumnNames.length > 0 ? prefixColumnNames.join(\", \") + \", \" : \"\";\n const prefixParamValues = this.getPrefixParamValues();\n const prefixParamPlaceholders =\n prefixColumnNames.length > 0\n ? prefixColumnNames.map((_, i) => `$${i + 1}`).join(\",\") + \",\"\n : \"\";\n const baseParamStart = prefixColumnNames.length + 1;\n\n const sql = `\n INSERT INTO ${this.tableName}(\n ${prefixColumnsInsert}queue, \n fingerprint, \n input, \n run_after,\n created_at,\n deadline_at,\n max_retries, \n job_run_id, \n progress, \n progress_message, \n progress_details\n )\n VALUES \n (${prefixParamPlaceholders}$${baseParamStart},$${baseParamStart + 1},$${baseParamStart + 2},$${baseParamStart + 3},$${baseParamStart + 4},$${baseParamStart + 5},$${baseParamStart + 6},$${baseParamStart + 7},$${baseParamStart + 8},$${baseParamStart + 9},$${baseParamStart + 10})\n RETURNING id`;\n const params = [\n ...prefixParamValues,\n job.queue,\n job.fingerprint,\n JSON.stringify(job.input),\n job.run_after,\n job.created_at,\n job.deadline_at,\n job.max_retries,\n job.job_run_id,\n job.progress,\n job.progress_message,\n job.progress_details ? JSON.stringify(job.progress_details) : null,\n ];\n const result = await this.db.query(sql, params);\n\n if (!result) throw new Error(\"Failed to add to queue\");\n job.id = result.rows[0].id;\n return job.id;\n }\n\n /**\n * Retrieves a job by its ID.\n * @param id - The ID of the job to retrieve\n * @returns The job if found, undefined otherwise\n */\n public async get(id: unknown): Promise<JobStorageFormat<Input, Output> | undefined> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(3);\n const result = await this.db.query(\n `SELECT *\n FROM ${this.tableName}\n WHERE id = $1 AND queue = $2${prefixConditions}\n FOR UPDATE SKIP LOCKED\n LIMIT 1`,\n [id, this.queueName, ...prefixParams]\n );\n\n if (!result || result.rows.length === 0) return undefined;\n return result.rows[0];\n }\n\n /**\n * Retrieves a slice of jobs from the queue.\n * @param num - Maximum number of jobs to return\n * @returns An array of jobs\n */\n public async peek(\n status: JobStatus = JobStatus.PENDING,\n num: number = 100\n ): Promise<Array<JobStorageFormat<Input, Output>>> {\n num = Number(num) || 100; // TS does not validate, so ensure it is a number\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(4);\n const result = await this.db.query<\n JobStorageFormat<Input, Output>,\n Array<string | number | JobStatus>\n >(\n `\n SELECT *\n FROM ${this.tableName}\n WHERE queue = $1\n AND status = $2${prefixConditions}\n ORDER BY run_after ASC\n LIMIT $3\n FOR UPDATE SKIP LOCKED`,\n [this.queueName, status, num, ...prefixParams]\n );\n if (!result) return [];\n return result.rows;\n }\n\n /**\n * Retrieves the next available job that is ready to be processed.\n * @param workerId - Worker ID to associate with the job (required)\n * @returns The next job or undefined if no job is available\n */\n public async next(workerId: string): Promise<JobStorageFormat<Input, Output> | undefined> {\n // Parameters: $1=status, $2=queue, $3=status, $4=worker_id, $5+=prefix params\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(5);\n const result = await this.db.query<\n JobStorageFormat<Input, Output>,\n Array<string | number | JobStatus | null>\n >(\n `\n UPDATE ${this.tableName} \n SET status = $1, last_ran_at = NOW() AT TIME ZONE 'UTC', worker_id = $4\n WHERE id = (\n SELECT id \n FROM ${this.tableName} \n WHERE queue = $2 \n AND status = $3\n ${prefixConditions}\n AND run_after <= NOW() AT TIME ZONE 'UTC'\n ORDER BY run_after ASC \n FOR UPDATE SKIP LOCKED \n LIMIT 1\n )\n RETURNING *`,\n [JobStatus.PROCESSING, this.queueName, JobStatus.PENDING, workerId, ...prefixParams]\n );\n\n return result?.rows?.[0] ?? undefined;\n }\n\n /**\n * Retrieves the number of jobs in the queue with a specific status.\n * @param status - The status of the jobs to count\n * @returns The count of jobs with the specified status\n */\n public async size(status = JobStatus.PENDING): Promise<number> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(3);\n const result = await this.db.query<{ count: string }, Array<string | number | JobStatus>>(\n `\n SELECT COUNT(*) as count\n FROM ${this.tableName}\n WHERE queue = $1\n AND status = $2${prefixConditions}`,\n [this.queueName, status, ...prefixParams]\n );\n if (!result) return 0;\n return parseInt(result.rows[0].count, 10);\n }\n\n /**\n * Marks a job as complete with its output or error.\n * Enhanced error handling:\n * - For a retryable error, increments run_attempts and updates run_after.\n * - Marks a job as FAILED immediately for permanent or generic errors.\n */\n public async complete(jobDetails: JobStorageFormat<Input, Output>): Promise<void> {\n const prefixParams = this.getPrefixParamValues();\n\n if (jobDetails.status === JobStatus.DISABLED) {\n const { conditions: prefixConditions } = this.buildPrefixWhereClause(4);\n await this.db.query(\n `UPDATE ${this.tableName} \n SET \n status = $1, \n progress = 100,\n progress_message = '',\n progress_details = NULL,\n completed_at = NOW() AT TIME ZONE 'UTC'\n WHERE id = $2 AND queue = $3${prefixConditions}`,\n [jobDetails.status, jobDetails.id, this.queueName, ...prefixParams]\n );\n } else if (jobDetails.status === JobStatus.PENDING) {\n const { conditions: prefixConditions } = this.buildPrefixWhereClause(7);\n await this.db.query(\n `UPDATE ${this.tableName} \n SET \n error = $1, \n error_code = $2,\n status = $3, \n run_after = $4, \n progress = 0,\n progress_message = '',\n progress_details = NULL,\n run_attempts = run_attempts + 1, \n last_ran_at = NOW() AT TIME ZONE 'UTC'\n WHERE id = $5 AND queue = $6${prefixConditions}`,\n [\n jobDetails.error,\n jobDetails.error_code,\n jobDetails.status,\n jobDetails.run_after,\n jobDetails.id,\n this.queueName,\n ...prefixParams,\n ]\n );\n } else {\n const { conditions: prefixConditions } = this.buildPrefixWhereClause(7);\n await this.db.query(\n `\n UPDATE ${this.tableName} \n SET \n output = $1, \n error = $2, \n error_code = $3,\n status = $4, \n progress = 100,\n progress_message = '',\n progress_details = NULL,\n run_attempts = run_attempts + 1, \n completed_at = NOW() AT TIME ZONE 'UTC',\n last_ran_at = NOW() AT TIME ZONE 'UTC'\n WHERE id = $5 AND queue = $6${prefixConditions}`,\n [\n jobDetails.output ? JSON.stringify(jobDetails.output) : null,\n jobDetails.error ?? null,\n jobDetails.error_code ?? null,\n jobDetails.status,\n jobDetails.id,\n this.queueName,\n ...prefixParams,\n ]\n );\n }\n }\n\n /**\n * Clears all jobs from the queue.\n */\n public async deleteAll(): Promise<void> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(2);\n await this.db.query(\n `\n DELETE FROM ${this.tableName}\n WHERE queue = $1${prefixConditions}`,\n [this.queueName, ...prefixParams]\n );\n }\n\n /**\n * Looks up cached output for a given input\n * Uses input fingerprinting for efficient matching\n * @returns The cached output or null if not found\n */\n public async outputForInput(input: Input): Promise<Output | null> {\n const fingerprint = await makeFingerprint(input);\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(3);\n const result = await this.db.query(\n `\n SELECT output\n FROM ${this.tableName}\n WHERE fingerprint = $1 AND queue = $2 AND status = 'COMPLETED'${prefixConditions}`,\n [fingerprint, this.queueName, ...prefixParams]\n );\n if (!result || result.rows.length === 0) return null;\n return result.rows[0].output;\n }\n\n /**\n * Aborts a job by setting its status to \"ABORTING\".\n * This method will signal the corresponding AbortController so that\n * the job's execute() method (if it supports an AbortSignal parameter)\n * can clean up and exit.\n */\n public async abort(jobId: unknown): Promise<void> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(3);\n await this.db.query(\n `\n UPDATE ${this.tableName} \n SET status = 'ABORTING' \n WHERE id = $1 AND queue = $2${prefixConditions}`,\n [jobId, this.queueName, ...prefixParams]\n );\n }\n\n /**\n * Releases a claimed job back to PENDING without incrementing run_attempts.\n * @param jobId - The id of the claimed job to release.\n */\n public async release(jobId: unknown): Promise<void> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(3);\n await this.db.query(\n `\n UPDATE ${this.tableName}\n SET status = 'PENDING',\n worker_id = NULL,\n progress = 0,\n progress_message = '',\n progress_details = NULL\n WHERE id = $1 AND queue = $2${prefixConditions}`,\n [jobId, this.queueName, ...prefixParams]\n );\n }\n\n /**\n * Retrieves all jobs for a given job run ID.\n * @param job_run_id - The ID of the job run to retrieve\n * @returns An array of jobs\n */\n public async getByRunId(job_run_id: string): Promise<Array<JobStorageFormat<Input, Output>>> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(3);\n const result = await this.db.query(\n `\n SELECT * FROM ${this.tableName} WHERE job_run_id = $1 AND queue = $2${prefixConditions}`,\n [job_run_id, this.queueName, ...prefixParams]\n );\n if (!result) return [];\n return result.rows;\n }\n\n /**\n * Implements the abstract saveProgress method from JobQueue\n */\n public async saveProgress(\n jobId: unknown,\n progress: number,\n message: string,\n details: Record<string, any>\n ): Promise<void> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(6);\n await this.db.query(\n `\n UPDATE ${this.tableName} \n SET progress = $1,\n progress_message = $2,\n progress_details = $3\n WHERE id = $4 AND queue = $5${prefixConditions}`,\n [\n progress,\n message,\n details ? JSON.stringify(details) : null,\n jobId,\n this.queueName,\n ...prefixParams,\n ]\n );\n }\n\n /**\n * Deletes a job by its ID\n */\n public async delete(jobId: unknown): Promise<void> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(3);\n await this.db.query(\n `DELETE FROM ${this.tableName} WHERE id = $1 AND queue = $2${prefixConditions}`,\n [jobId, this.queueName, ...prefixParams]\n );\n }\n\n /**\n * Delete jobs with a specific status older than a cutoff date\n * @param status - Status of jobs to delete\n * @param olderThanMs - Delete jobs completed more than this many milliseconds ago\n */\n public async deleteJobsByStatusAndAge(status: JobStatus, olderThanMs: number): Promise<void> {\n const cutoffDate = new Date(Date.now() - olderThanMs).toISOString();\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(4);\n await this.db.query(\n `DELETE FROM ${this.tableName} \n WHERE queue = $1 \n AND status = $2 \n AND completed_at IS NOT NULL \n AND completed_at <= $3${prefixConditions}`,\n [this.queueName, status, cutoffDate, ...prefixParams]\n );\n }\n\n /**\n * Subscribe to INSERT/UPDATE notifications via PostgreSQL LISTEN/NOTIFY.\n * Replaces 100ms-poll fallback for cluster Postgres deployments — workers\n * wake within network-latency of an actual change rather than on a timer.\n *\n * Acquires a dedicated client from the pool (LISTEN occupies a connection\n * for its lifetime). On unsubscribe, runs UNLISTEN and releases the client.\n * On connection loss, attempts to reconnect with bounded backoff and\n * re-LISTEN. After every successful (re)connect — including the initial\n * one — emits a synthetic `{ type: \"RESYNC\" }` event so subscribers can\n * re-poll state and pick up any rows inserted during the disconnect window\n * (or between subscribe and the first NOTIFY landing).\n *\n * Throws synchronously when the underlying pool lacks `connect()`\n * (single-connection wrappers like PGLite) so the caller's try/catch can\n * fall back to polling. JobQueueServer.start does this and logs at debug.\n *\n * `options.prefixFilter` follows {@link QueueSubscribeOptions.prefixFilter}:\n * `undefined` means \"use the storage instance's configured prefixValues\",\n * `{}` means \"receive all changes regardless of prefix\".\n */\n public subscribeToChanges(\n callback: (change: QueueChangePayload<Input, Output>) => void,\n options?: QueueSubscribeOptions\n ): () => void {\n type PoolWithConnect = { connect: () => Promise<ListenClient> };\n const poolMaybe = this.db as unknown as Partial<PoolWithConnect>;\n if (typeof poolMaybe.connect !== \"function\") {\n // Detect synchronously so callers can catch and fall back to polling\n // without leaving a dangling unhandled promise rejection behind.\n throw new Error(\n \"PostgresQueueStorage.subscribeToChanges requires a pg.Pool (got a single-connection wrapper)\"\n );\n }\n const pool = poolMaybe as PoolWithConnect;\n\n const channel = this.notifyChannelName();\n // undefined -> default to instance prefixValues; {} -> no filtering;\n // partial -> filter by the provided subset (matches QueueSubscribeOptions docs).\n const effectivePrefixFilter: Readonly<Record<string, string | number>> | null =\n options?.prefixFilter === undefined\n ? this.prefixes.length > 0\n ? this.prefixValues\n : null\n : Object.keys(options.prefixFilter).length === 0\n ? null\n : options.prefixFilter;\n\n let unsubscribed = false;\n let activeClient: ListenClient | null = null;\n let reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n let backoffMs = 250;\n\n const dispatch = (change: QueueChangePayload<Input, Output>): void => {\n try {\n callback(change);\n } catch (err) {\n // Never let user callbacks tear down the listener loop.\n getLogger().debug(\"PostgresQueueStorage subscribe callback threw\", {\n channel,\n changeType: change.type,\n error: err,\n });\n }\n };\n\n const matchesPrefix = (\n change: QueueChangePayload<Input, Output>,\n filter: Readonly<Record<string, string | number>>\n ): boolean => {\n const row = (change.new ?? change.old) as Record<string, unknown> | undefined;\n if (!row) return false;\n for (const [k, v] of Object.entries(filter)) {\n if (row[k] !== v) return false;\n }\n return true;\n };\n\n // Hydrate the row referenced by a notification. Postgres NOTIFY is capped\n // at 8 KB so we ship only {id, queue, status} in the payload and fetch the\n // full row here — keeps subscriber payloads consistent with other backends\n // (e.g. Supabase realtime, IndexedDb) and lets prefixFilter inspect the\n // prefix columns the row actually has.\n const hydrate = async (\n id: unknown\n ): Promise<JobStorageFormat<Input, Output> | undefined> => {\n try {\n return await this.get(id);\n } catch {\n return undefined;\n }\n };\n\n const handleNotification = (msg: { channel: string; payload?: string }): void => {\n if (msg.channel !== channel || !msg.payload) return;\n let parsed: { op: string; id: number; queue: string; status: string };\n try {\n parsed = JSON.parse(msg.payload);\n } catch {\n return;\n }\n void (async () => {\n const op = parsed.op;\n const fallback = {\n id: parsed.id,\n queue: parsed.queue,\n status: parsed.status,\n } as unknown as JobStorageFormat<Input, Output>;\n const fullRow = op === \"DELETE\" ? undefined : await hydrate(parsed.id);\n const change: QueueChangePayload<Input, Output> = {\n type: op === \"INSERT\" ? \"INSERT\" : op === \"DELETE\" ? \"DELETE\" : \"UPDATE\",\n new: op === \"DELETE\" ? undefined : (fullRow ?? fallback),\n old: op === \"DELETE\" ? fallback : undefined,\n };\n if (effectivePrefixFilter && !matchesPrefix(change, effectivePrefixFilter)) return;\n dispatch(change);\n })();\n };\n\n const connect = async (): Promise<void> => {\n if (unsubscribed) return;\n try {\n const client = await pool.connect();\n if (unsubscribed) {\n client.release();\n return;\n }\n activeClient = client;\n client.on(\"notification\", handleNotification);\n client.on(\"error\", () => scheduleReconnect());\n await client.query(`LISTEN ${channel}`);\n backoffMs = 250; // reset on successful (re)connect\n // Synthetic resync: any rows inserted between subscribe and LISTEN\n // landing (or during a reconnect window) have no NOTIFY backing.\n // Fire a no-payload event so subscribers can re-poll state.\n dispatch({ type: \"RESYNC\" });\n } catch {\n scheduleReconnect();\n }\n };\n\n const scheduleReconnect = (): void => {\n if (unsubscribed || reconnectTimer) return;\n const c = activeClient;\n activeClient = null;\n try {\n c?.removeAllListeners?.(\"notification\");\n c?.removeAllListeners?.(\"error\");\n c?.release();\n } catch {\n // best-effort\n }\n const delay = Math.min(backoffMs, 30_000);\n backoffMs = Math.min(backoffMs * 2, 30_000);\n reconnectTimer = setTimeout(() => {\n reconnectTimer = null;\n void connect();\n }, delay);\n };\n\n void connect();\n\n return () => {\n unsubscribed = true;\n if (reconnectTimer) {\n clearTimeout(reconnectTimer);\n reconnectTimer = null;\n }\n const c = activeClient;\n activeClient = null;\n if (c) {\n // Best-effort UNLISTEN; ignore errors (connection may already be dead).\n c.query(`UNLISTEN ${channel}`)\n .catch(() => {})\n .finally(() => {\n try {\n c.removeAllListeners?.(\"notification\");\n c.removeAllListeners?.(\"error\");\n c.release();\n } catch {\n // best-effort\n }\n });\n }\n };\n }\n}\n",
|
|
44
|
+
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Sqlite } from \"@workglow/storage/sqlite\";\nimport { createServiceToken, makeFingerprint, sleep, uuid4 } from \"@workglow/util\";\nimport {\n IQueueStorage,\n JobStatus,\n JobStorageFormat,\n PrefixColumn,\n QueueChangePayload,\n QueueStorageOptions,\n QueueSubscribeOptions,\n} from \"./IQueueStorage\";\n\nexport const SQLITE_QUEUE_STORAGE =\n createServiceToken<IQueueStorage<any, any>>(\"jobqueue.storage.sqlite\");\n\ntype JobRowWithJsonStrings<Input, Output> = JobStorageFormat<Input, Output> & {\n input: string;\n output: string | null;\n progress_details: string | null;\n};\n\n/**\n * Extended options for SQLite queue storage including prefix support\n */\nexport interface SqliteQueueStorageOptions extends QueueStorageOptions {\n readonly deleteAfterCompletionMs?: number;\n readonly deleteAfterFailureMs?: number;\n}\n\n/**\n * SQLite implementation of a job queue.\n * Provides storage and retrieval for job execution states using SQLite.\n */\nexport class SqliteQueueStorage<Input, Output> implements IQueueStorage<Input, Output> {\n /**\n * SQLite is in-process only at the application layer (no LISTEN/NOTIFY,\n * no shared client across processes). Even if the underlying file is\n * shared via NFS, the queue contract requires cross-process change\n * notification we don't provide here, so callers must treat it as\n * `\"process\"` scope.\n */\n public readonly scope = \"process\" as const;\n /** The prefix column definitions */\n protected readonly prefixes: readonly PrefixColumn[];\n /** The prefix values for filtering */\n protected readonly prefixValues: Readonly<Record<string, string | number>>;\n /** The table name for the job queue */\n protected readonly tableName: string;\n\n constructor(\n protected db: Sqlite.Database,\n protected queueName: string,\n protected options?: SqliteQueueStorageOptions\n ) {\n this.prefixes = options?.prefixes ?? [];\n this.prefixValues = options?.prefixValues ?? {};\n // Generate table name based on prefix configuration to avoid column conflicts\n if (this.prefixes.length > 0) {\n const prefixNames = this.prefixes.map((p) => p.name).join(\"_\");\n this.tableName = `job_queue_${prefixNames}`;\n } else {\n this.tableName = \"job_queue\";\n }\n }\n\n /**\n * Gets the SQL column type for a prefix column (SQLite uses TEXT for uuid)\n */\n private getPrefixColumnType(type: PrefixColumn[\"type\"]): string {\n return type === \"uuid\" ? \"TEXT\" : \"INTEGER\";\n }\n\n /**\n * Builds the prefix columns SQL for CREATE TABLE\n */\n private buildPrefixColumnsSql(): string {\n if (this.prefixes.length === 0) return \"\";\n return (\n this.prefixes\n .map((p) => `${p.name} ${this.getPrefixColumnType(p.type)} NOT NULL`)\n .join(\",\\n \") + \",\\n \"\n );\n }\n\n /**\n * Builds prefix column names for use in queries\n */\n private getPrefixColumnNames(): string[] {\n return this.prefixes.map((p) => p.name);\n }\n\n /**\n * Builds WHERE clause conditions for prefix filtering\n * @returns The conditions string with placeholders\n */\n private buildPrefixWhereClause(): string {\n if (this.prefixes.length === 0) {\n return \"\";\n }\n const conditions = this.prefixes.map((p) => `${p.name} = ?`).join(\" AND \");\n return \" AND \" + conditions;\n }\n\n /**\n * Gets prefix values as an array in column order\n */\n private getPrefixParamValues(): Array<string | number> {\n return this.prefixes.map((p) => this.prefixValues[p.name]);\n }\n\n public async setupDatabase(): Promise<void> {\n await sleep(0);\n const prefixColumnsSql = this.buildPrefixColumnsSql();\n const prefixColumnNames = this.getPrefixColumnNames();\n const prefixIndexPrefix =\n prefixColumnNames.length > 0 ? prefixColumnNames.join(\", \") + \", \" : \"\";\n const indexSuffix = prefixColumnNames.length > 0 ? \"_\" + prefixColumnNames.join(\"_\") : \"\";\n\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS ${this.tableName} (\n id INTEGER PRIMARY KEY,\n ${prefixColumnsSql}fingerprint text NOT NULL,\n queue text NOT NULL,\n job_run_id text NOT NULL,\n status TEXT NOT NULL default 'PENDING',\n input TEXT NOT NULL,\n output TEXT,\n run_attempts INTEGER default 0,\n max_retries INTEGER default 23,\n run_after TEXT NOT NULL,\n last_ran_at TEXT,\n created_at TEXT NOT NULL,\n completed_at TEXT,\n deadline_at TEXT,\n error TEXT,\n error_code TEXT,\n progress REAL DEFAULT 0,\n progress_message TEXT DEFAULT '',\n progress_details TEXT NULL,\n worker_id TEXT\n );\n \n CREATE INDEX IF NOT EXISTS job_queue_fetcher${indexSuffix}_idx ON ${this.tableName} (${prefixIndexPrefix}queue, status, run_after);\n CREATE INDEX IF NOT EXISTS job_queue_fingerprint${indexSuffix}_idx ON ${this.tableName} (${prefixIndexPrefix}queue, fingerprint, status);\n CREATE INDEX IF NOT EXISTS job_queue_job_run_id${indexSuffix}_idx ON ${this.tableName} (${prefixIndexPrefix}queue, job_run_id);\n `);\n }\n\n /**\n * Adds a new job to the queue.\n * @param job - The job to add\n * @returns The ID of the added job\n */\n public async add(job: JobStorageFormat<Input, Output>): Promise<unknown> {\n const now = new Date().toISOString();\n job.job_run_id = job.job_run_id ?? uuid4();\n job.queue = this.queueName;\n job.fingerprint = await makeFingerprint(job.input);\n job.status = JobStatus.PENDING;\n job.progress = 0;\n job.progress_message = \"\";\n job.progress_details = null;\n job.created_at = now;\n job.run_after = now;\n\n const prefixColumnNames = this.getPrefixColumnNames();\n const prefixColumnsInsert =\n prefixColumnNames.length > 0 ? prefixColumnNames.join(\", \") + \", \" : \"\";\n const prefixPlaceholders =\n prefixColumnNames.length > 0 ? prefixColumnNames.map(() => \"?\").join(\", \") + \", \" : \"\";\n const prefixParamValues = this.getPrefixParamValues();\n\n const AddQuery = `\n INSERT INTO ${this.tableName}(\n ${prefixColumnsInsert}queue, \n fingerprint, \n input, \n run_after, \n deadline_at, \n max_retries, \n job_run_id, \n progress, \n progress_message, \n progress_details,\n created_at\n )\n VALUES (${prefixPlaceholders}?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n RETURNING id`;\n\n const stmt = this.db.prepare<unknown[], { id: string }>(AddQuery);\n\n const result = stmt.get(\n ...prefixParamValues,\n job.queue,\n job.fingerprint,\n JSON.stringify(job.input),\n job.run_after,\n job.deadline_at ?? null,\n job.max_retries!,\n job.job_run_id,\n job.progress,\n job.progress_message,\n job.progress_details ? JSON.stringify(job.progress_details) : null,\n job.created_at\n ) as { id: string } | undefined;\n\n job.id = result?.id;\n return result?.id;\n }\n\n /**\n * Retrieves a job by its ID.\n * @param id - The ID of the job to retrieve\n * @returns The job if found, undefined otherwise\n */\n public async get(id: unknown): Promise<JobStorageFormat<Input, Output> | undefined> {\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n const JobQuery = `\n SELECT *\n FROM ${this.tableName}\n WHERE id = ? AND queue = ?${prefixConditions}\n LIMIT 1`;\n const stmt = this.db.prepare<\n unknown[],\n JobStorageFormat<Input, Output> & {\n input: string;\n output: string | null;\n progress_details: string | null;\n }\n >(JobQuery);\n const result = stmt.get(String(id), this.queueName, ...prefixParams);\n if (!result) return undefined;\n\n // Parse JSON fields\n if (result.input) result.input = JSON.parse(result.input);\n if (result.output) result.output = JSON.parse(result.output);\n if (result.progress_details) result.progress_details = JSON.parse(result.progress_details);\n return result;\n }\n\n /**\n * Retrieves a slice of jobs from the queue.\n * @param num - Maximum number of jobs to return\n * @returns An array of jobs\n */\n public async peek(\n status: JobStatus = JobStatus.PENDING,\n num: number = 100\n ): Promise<Array<JobStorageFormat<Input, Output>>> {\n num = Math.max(1, Math.min(10000, Math.floor(Number(num) || 100))); // Validate and clamp to safe range\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n const FutureJobQuery = `\n SELECT * \n FROM ${this.tableName}\n WHERE queue = ?\n AND status = ?${prefixConditions}\n ORDER BY run_after ASC\n LIMIT ${num}`;\n const stmt = this.db.prepare<\n unknown[],\n JobStorageFormat<Input, Output> & {\n input: string;\n output: string | null;\n progress_details: string | null;\n }\n >(FutureJobQuery);\n const result = stmt.all(this.queueName, status, ...prefixParams);\n return (result || []).map((details: JobRowWithJsonStrings<Input, Output>) => {\n // Parse JSON fields\n if (details.input) details.input = JSON.parse(details.input);\n if (details.output) details.output = JSON.parse(details.output);\n if (details.progress_details) details.progress_details = JSON.parse(details.progress_details);\n\n return details;\n });\n }\n\n /**\n * Aborts a job by setting its status to \"ABORTING\".\n * This method will signal the corresponding AbortController so that\n * the job's execute() method (if it supports an AbortSignal parameter)\n * can clean up and exit.\n */\n public async abort(jobId: unknown): Promise<void> {\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n const AbortQuery = `\n UPDATE ${this.tableName}\n SET status = ? \n WHERE id = ? AND queue = ?${prefixConditions}`;\n const stmt = this.db.prepare(AbortQuery);\n stmt.run(JobStatus.ABORTING, String(jobId), this.queueName, ...prefixParams);\n }\n\n /**\n * Releases a claimed job back to PENDING without incrementing run_attempts.\n * @param jobId - The id of the claimed job to release.\n */\n public async release(jobId: unknown): Promise<void> {\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n const ReleaseQuery = `\n UPDATE ${this.tableName}\n SET status = ?,\n worker_id = NULL,\n progress = 0,\n progress_message = '',\n progress_details = NULL\n WHERE id = ? AND queue = ?${prefixConditions}`;\n const stmt = this.db.prepare(ReleaseQuery);\n stmt.run(JobStatus.PENDING, String(jobId), this.queueName, ...prefixParams);\n }\n\n /**\n * Retrieves all jobs for a given job run ID.\n * @param job_run_id - The ID of the job run to retrieve\n * @returns An array of jobs\n */\n public async getByRunId(job_run_id: string): Promise<Array<JobStorageFormat<Input, Output>>> {\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n const JobsByRunIdQuery = `\n SELECT *\n FROM ${this.tableName}\n WHERE job_run_id = ? AND queue = ?${prefixConditions}`;\n const stmt = this.db.prepare<\n unknown[],\n JobStorageFormat<Input, Output> & {\n input: string;\n output: string | null;\n progress_details: string | null;\n }\n >(JobsByRunIdQuery);\n const result = stmt.all(job_run_id, this.queueName, ...prefixParams);\n return (result || []).map((details: JobRowWithJsonStrings<Input, Output>) => {\n // Parse JSON fields\n if (details.input) details.input = JSON.parse(details.input);\n if (details.output) details.output = JSON.parse(details.output);\n if (details.progress_details) details.progress_details = JSON.parse(details.progress_details);\n\n return details;\n });\n }\n\n /**\n * Retrieves the next available job that is ready to be processed,\n * and updates its status to PROCESSING.\n *\n * @param workerId - Worker ID to associate with the job\n * @returns The next job or undefined if no job is available\n */\n public async next(workerId: string): Promise<JobStorageFormat<Input, Output> | undefined> {\n const now = new Date().toISOString();\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n // Then, get the next job to process\n const stmt = this.db.prepare<\n unknown[],\n JobStorageFormat<Input, Output> & {\n input: string;\n output: string | null;\n progress_details: string | null;\n }\n >(\n `\n UPDATE ${this.tableName} \n SET status = ?, last_ran_at = ?, worker_id = ?\n WHERE id = (\n SELECT id \n FROM ${this.tableName} \n WHERE queue = ? \n AND status = ?${prefixConditions}\n AND run_after <= ? \n ORDER BY run_after ASC \n LIMIT 1\n )\n RETURNING *`\n );\n const result = stmt.get(\n JobStatus.PROCESSING,\n now,\n workerId,\n this.queueName,\n JobStatus.PENDING,\n ...prefixParams,\n now\n );\n if (!result) return undefined;\n\n // Parse JSON fields\n if (result.input) result.input = JSON.parse(result.input);\n if (result.output) result.output = JSON.parse(result.output);\n if (result.progress_details) result.progress_details = JSON.parse(result.progress_details);\n\n return result;\n }\n\n /**\n * Retrieves the number of jobs in the queue with a specific status.\n * @param status - The status of the jobs to count\n * @returns The count of jobs with the specified status\n */\n public async size(status = JobStatus.PENDING): Promise<number> {\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n const sizeQuery = `\n SELECT COUNT(*) as count\n FROM ${this.tableName}\n WHERE queue = ?\n AND status = ?${prefixConditions}`;\n const stmt = this.db.prepare<unknown[], { count: number }>(sizeQuery);\n const result = stmt.get(this.queueName, status, ...prefixParams) as any;\n return result.count;\n }\n\n /**\n * Marks a job as complete with its output or error.\n * Enhanced error handling:\n * - Increments the retry count.\n * - For a retryable error, updates run_after with the retry date.\n * - Marks the job as FAILED for permanent or generic errors.\n * - Marks the job as DISABLED for disabled jobs.\n */\n public async complete(job: JobStorageFormat<Input, Output>): Promise<void> {\n const now = new Date().toISOString();\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n let updateQuery: string;\n let params: Array<string | number | null>;\n if (job.status === JobStatus.DISABLED) {\n updateQuery = `\n UPDATE ${this.tableName} \n SET \n status = ?, \n progress = 100, \n progress_message = '', \n progress_details = NULL, \n completed_at = ? \n WHERE id = ? AND queue = ?${prefixConditions}`;\n params = [job.status, now, job.id as string, this.queueName, ...prefixParams];\n } else {\n updateQuery = `\n UPDATE ${this.tableName} \n SET \n output = ?, \n error = ?, \n error_code = ?, \n status = ?, \n progress = 100, \n progress_message = '', \n progress_details = NULL, \n last_ran_at = ?,\n completed_at = ?,\n run_attempts = run_attempts + 1\n WHERE id = ? AND queue = ?${prefixConditions}`;\n params = [\n job.output ? JSON.stringify(job.output) : null,\n job.error ?? null,\n job.error_code ?? null,\n job.status!,\n now,\n now,\n job.id as string,\n this.queueName,\n ...prefixParams,\n ];\n }\n const stmt = this.db.prepare(updateQuery);\n stmt.run(...params);\n }\n\n public async deleteAll(): Promise<void> {\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n const ClearQuery = `\n DELETE FROM ${this.tableName}\n WHERE queue = ?${prefixConditions}`;\n const stmt = this.db.prepare(ClearQuery);\n stmt.run(this.queueName, ...prefixParams);\n }\n\n /**\n * Looks up cached output for a given input\n * Uses input fingerprinting for efficient matching\n * @returns The cached output or null if not found\n */\n public async outputForInput(input: Input): Promise<Output | null> {\n const fingerprint = await makeFingerprint(input);\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n const OutputQuery = `\n SELECT output\n FROM ${this.tableName}\n WHERE queue = ? AND fingerprint = ? AND status = ?${prefixConditions}`;\n const stmt = this.db.prepare<unknown[], { output: string }>(OutputQuery);\n const result = stmt.get(this.queueName, fingerprint, JobStatus.COMPLETED, ...prefixParams);\n return result?.output ? JSON.parse(result.output) : null;\n }\n\n /**\n * Implements the abstract saveProgress method from JobQueue\n */\n public async saveProgress(\n jobId: unknown,\n progress: number,\n message: string,\n details: Record<string, any>\n ): Promise<void> {\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n const UpdateProgressQuery = `\n UPDATE ${this.tableName}\n SET progress = ?,\n progress_message = ?,\n progress_details = ?\n WHERE id = ? AND queue = ?${prefixConditions}`;\n\n const stmt = this.db.prepare(UpdateProgressQuery);\n stmt.run(\n progress,\n message,\n JSON.stringify(details),\n String(jobId),\n this.queueName,\n ...prefixParams\n );\n }\n\n /**\n * Deletes a job by its ID\n */\n public async delete(jobId: unknown): Promise<void> {\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n const DeleteQuery = `\n DELETE FROM ${this.tableName}\n WHERE id = ? AND queue = ?${prefixConditions}`;\n const stmt = this.db.prepare(DeleteQuery);\n stmt.run(String(jobId), this.queueName, ...prefixParams);\n }\n\n /**\n * Delete jobs with a specific status older than a cutoff date\n * @param status - Status of jobs to delete\n * @param olderThanMs - Delete jobs completed more than this many milliseconds ago\n */\n public async deleteJobsByStatusAndAge(status: JobStatus, olderThanMs: number): Promise<void> {\n const cutoffDate = new Date(Date.now() - olderThanMs).toISOString();\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n const DeleteQuery = `\n DELETE FROM ${this.tableName}\n WHERE queue = ?\n AND status = ?\n AND completed_at IS NOT NULL\n AND completed_at <= ?${prefixConditions}`;\n const stmt = this.db.prepare(DeleteQuery);\n stmt.run(this.queueName, status, cutoffDate, ...prefixParams);\n }\n\n /**\n * Subscribes to changes in the queue.\n * NOT IMPLEMENTED for SQLite storage.\n *\n * @throws Error always - subscribeToChanges is not supported for SQLite storage\n */\n public subscribeToChanges(\n callback: (change: QueueChangePayload<Input, Output>) => void,\n options?: QueueSubscribeOptions\n ): () => void {\n throw new Error(\"subscribeToChanges is not supported for SqliteQueueStorage\");\n }\n}\n",
|
|
45
|
+
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { RealtimeChannel, SupabaseClient } from \"@supabase/supabase-js\";\nimport { createServiceToken, deepEqual, makeFingerprint, uuid4 } from \"@workglow/util\";\nimport { PollingSubscriptionManager } from \"../util/PollingSubscriptionManager\";\nimport {\n IQueueStorage,\n JobStatus,\n JobStorageFormat,\n PrefixColumn,\n QueueChangePayload,\n QueueChangeType,\n QueueStorageOptions,\n QueueSubscribeOptions,\n} from \"./IQueueStorage\";\n\nexport const SUPABASE_QUEUE_STORAGE = createServiceToken<IQueueStorage<any, any>>(\n \"jobqueue.storage.supabase\"\n);\n\n/**\n * Supabase implementation of a job queue.\n * Provides storage and retrieval for job execution states using Supabase.\n */\nexport class SupabaseQueueStorage<Input, Output> implements IQueueStorage<Input, Output> {\n public readonly scope = \"cluster\" as const;\n protected readonly client: SupabaseClient;\n protected readonly prefixes: readonly PrefixColumn[];\n protected readonly prefixValues: Readonly<Record<string, string | number>>;\n protected readonly tableName: string;\n private realtimeChannel: RealtimeChannel | null = null;\n private pollingManager: PollingSubscriptionManager<\n JobStorageFormat<Input, Output>,\n unknown,\n QueueChangePayload<Input, Output>\n > | null = null;\n\n constructor(\n client: SupabaseClient,\n protected readonly queueName: string,\n options?: QueueStorageOptions\n ) {\n this.client = client as SupabaseClient;\n this.prefixes = options?.prefixes ?? [];\n this.prefixValues = options?.prefixValues ?? {};\n // Generate table name based on prefix configuration to avoid column conflicts\n if (this.prefixes.length > 0) {\n const prefixNames = this.prefixes.map((p) => p.name).join(\"_\");\n this.tableName = `job_queue_${prefixNames}`;\n } else {\n this.tableName = \"job_queue\";\n }\n }\n\n /**\n * Gets the SQL column type for a prefix column (Supabase supports UUID natively)\n */\n private getPrefixColumnType(type: PrefixColumn[\"type\"]): string {\n return type === \"uuid\" ? \"UUID\" : \"INTEGER\";\n }\n\n /**\n * Builds the prefix columns SQL for CREATE TABLE\n */\n private buildPrefixColumnsSql(): string {\n if (this.prefixes.length === 0) return \"\";\n return (\n this.prefixes\n .map((p) => `${p.name} ${this.getPrefixColumnType(p.type)} NOT NULL`)\n .join(\",\\n \") + \",\\n \"\n );\n }\n\n /**\n * Builds prefix column names for use in queries\n */\n private getPrefixColumnNames(): string[] {\n return this.prefixes.map((p) => p.name);\n }\n\n /**\n * Applies prefix filters to a Supabase query builder\n */\n private applyPrefixFilters<T>(query: T): T {\n let result = query as any;\n for (const prefix of this.prefixes) {\n result = result.eq(prefix.name, this.prefixValues[prefix.name]);\n }\n return result as T;\n }\n\n /**\n * Gets prefix values as an object for inserts\n */\n private getPrefixInsertValues(): Record<string, string | number> {\n const values: Record<string, string | number> = {};\n for (const prefix of this.prefixes) {\n values[prefix.name] = this.prefixValues[prefix.name];\n }\n return values;\n }\n\n /**\n * Builds WHERE clause conditions for prefix filtering with inline values (for raw SQL)\n * @returns SQL conditions string with values inlined\n */\n private buildPrefixWhereSql(): string {\n if (this.prefixes.length === 0) {\n return \"\";\n }\n const conditions = this.prefixes\n .map((p) => {\n const value = this.prefixValues[p.name];\n if (p.type === \"uuid\") {\n const validated = this.validateSqlValue(String(value), `prefix \"${p.name}\"`);\n return `${p.name} = '${this.escapeSqlString(validated)}'`;\n }\n const numValue = Number(value ?? 0);\n if (!Number.isFinite(numValue)) {\n throw new Error(`Invalid numeric prefix value for \"${p.name}\": ${value}`);\n }\n return `${p.name} = ${numValue}`;\n })\n .join(\" AND \");\n return \" AND \" + conditions;\n }\n\n /**\n * Regex for validating SQL literal-safe strings.\n * Used for quoted values (e.g. queue names/IDs) and only allows alphanumeric\n * characters, underscores, hyphens, colons, and periods.\n */\n private static readonly SAFE_SQL_VALUE_RE = /^[a-zA-Z0-9_\\-.:]+$/;\n\n /**\n * Validates that a string value is safe for use as a quoted SQL literal.\n * Throws an error if the value contains characters outside SAFE_SQL_VALUE_RE.\n */\n private validateSqlValue(value: string, context: string): string {\n if (!SupabaseQueueStorage.SAFE_SQL_VALUE_RE.test(value)) {\n throw new Error(\n `Unsafe value for ${context}: \"${value}\". Values must match /^[a-zA-Z0-9_\\\\-.:]+$/.`\n );\n }\n return value;\n }\n\n /**\n * Escapes a string value for use in SQL\n */\n private escapeSqlString(value: string): string {\n return value.replace(/'/g, \"''\");\n }\n\n public async setupDatabase(): Promise<void> {\n // Note: For Supabase, table creation should typically be done through migrations\n // This setup assumes the table already exists or uses exec_sql RPC function\n const createTypeSql = `CREATE TYPE job_status AS ENUM (${Object.values(JobStatus)\n .map((v) => `'${v}'`)\n .join(\",\")})`;\n\n const { error: typeError } = await this.client.rpc(\"exec_sql\", { query: createTypeSql });\n // Ignore error if type already exists (code 42710)\n if (typeError && typeError.code !== \"42710\") {\n throw typeError;\n }\n\n const prefixColumnsSql = this.buildPrefixColumnsSql();\n const prefixColumnNames = this.getPrefixColumnNames();\n const prefixIndexPrefix =\n prefixColumnNames.length > 0 ? prefixColumnNames.join(\", \") + \", \" : \"\";\n const indexSuffix = prefixColumnNames.length > 0 ? \"_\" + prefixColumnNames.join(\"_\") : \"\";\n\n const createTableSql = `\n CREATE TABLE IF NOT EXISTS ${this.tableName} (\n id SERIAL NOT NULL,\n ${prefixColumnsSql}fingerprint text NOT NULL,\n queue text NOT NULL,\n job_run_id text NOT NULL,\n status job_status NOT NULL default 'PENDING',\n input jsonb NOT NULL,\n output jsonb,\n run_attempts integer default 0,\n max_retries integer default 20,\n run_after timestamp with time zone DEFAULT now(),\n last_ran_at timestamp with time zone,\n created_at timestamp with time zone DEFAULT now(),\n deadline_at timestamp with time zone,\n completed_at timestamp with time zone,\n error text,\n error_code text,\n progress real DEFAULT 0,\n progress_message text DEFAULT '',\n progress_details jsonb,\n worker_id text\n )`;\n\n const { error: tableError } = await this.client.rpc(\"exec_sql\", { query: createTableSql });\n if (tableError) {\n // Ignore error if table already exists (code 42P07)\n if (tableError.code !== \"42P07\") {\n throw tableError;\n }\n }\n\n // Create indexes with prefix columns prepended\n const indexes = [\n `CREATE INDEX IF NOT EXISTS job_fetcher${indexSuffix}_idx ON ${this.tableName} (${prefixIndexPrefix}id, status, run_after)`,\n `CREATE INDEX IF NOT EXISTS job_queue_fetcher${indexSuffix}_idx ON ${this.tableName} (${prefixIndexPrefix}queue, status, run_after)`,\n `CREATE INDEX IF NOT EXISTS jobs_fingerprint${indexSuffix}_unique_idx ON ${this.tableName} (${prefixIndexPrefix}queue, fingerprint, status)`,\n ];\n\n for (const indexSql of indexes) {\n await this.client.rpc(\"exec_sql\", { query: indexSql });\n // Ignore index creation errors\n }\n }\n\n /**\n * Adds a new job to the queue.\n * @param job - The job to add\n * @returns The ID of the added job\n */\n public async add(job: JobStorageFormat<Input, Output>): Promise<unknown> {\n const now = new Date().toISOString();\n job.queue = this.queueName;\n job.job_run_id = job.job_run_id ?? uuid4();\n job.fingerprint = await makeFingerprint(job.input);\n job.status = JobStatus.PENDING;\n job.progress = 0;\n job.progress_message = \"\";\n job.progress_details = null;\n job.created_at = now;\n job.run_after = now;\n\n const prefixInsertValues = this.getPrefixInsertValues();\n\n const { data, error } = await this.client\n .from(this.tableName)\n .insert({\n ...prefixInsertValues,\n queue: job.queue,\n fingerprint: job.fingerprint,\n input: job.input,\n run_after: job.run_after,\n created_at: job.created_at,\n deadline_at: job.deadline_at,\n max_retries: job.max_retries,\n job_run_id: job.job_run_id,\n progress: job.progress,\n progress_message: job.progress_message,\n progress_details: job.progress_details,\n })\n .select(\"id\")\n .single();\n\n if (error) throw error;\n if (!data) throw new Error(\"Failed to add to queue\");\n\n job.id = data.id;\n return job.id;\n }\n\n /**\n * Retrieves a job by its ID.\n * @param id - The ID of the job to retrieve\n * @returns The job if found, undefined otherwise\n */\n public async get(id: unknown): Promise<JobStorageFormat<Input, Output> | undefined> {\n let query = this.client\n .from(this.tableName)\n .select(\"*\")\n .eq(\"id\", id)\n .eq(\"queue\", this.queueName);\n\n query = this.applyPrefixFilters(query);\n\n const { data, error } = await query.single();\n\n if (error) {\n if (error.code === \"PGRST116\") return undefined; // Not found\n throw error;\n }\n\n return data as JobStorageFormat<Input, Output> | undefined;\n }\n\n /**\n * Retrieves a slice of jobs from the queue.\n * @param status - The status to filter by\n * @param num - Maximum number of jobs to return\n * @returns An array of jobs\n */\n public async peek(\n status: JobStatus = JobStatus.PENDING,\n num: number = 100\n ): Promise<JobStorageFormat<Input, Output>[]> {\n num = Number(num) || 100;\n\n let query = this.client\n .from(this.tableName)\n .select(\"*\")\n .eq(\"queue\", this.queueName)\n .eq(\"status\", status);\n\n query = this.applyPrefixFilters(query);\n\n const { data, error } = await query.order(\"run_after\", { ascending: true }).limit(num);\n\n if (error) throw error;\n return (data as JobStorageFormat<Input, Output>[]) ?? [];\n }\n\n /**\n * Retrieves the next available job that is ready to be processed.\n * Uses atomic UPDATE with subquery SELECT FOR UPDATE SKIP LOCKED to prevent race conditions.\n * @param workerId - Worker ID to associate with the job (required)\n * @returns The next job or undefined if no job is available\n */\n public async next(workerId: string): Promise<JobStorageFormat<Input, Output> | undefined> {\n const prefixConditions = this.buildPrefixWhereSql();\n const validatedQueueName = this.validateSqlValue(this.queueName, \"queueName\");\n const validatedWorkerId = this.validateSqlValue(workerId, \"workerId\");\n const escapedQueueName = this.escapeSqlString(validatedQueueName);\n const escapedWorkerId = this.escapeSqlString(validatedWorkerId);\n\n // Use the same atomic UPDATE...WHERE id = (SELECT...FOR UPDATE SKIP LOCKED) pattern as PostgresQueueStorage\n const sql = `\n UPDATE ${this.tableName}\n SET status = '${JobStatus.PROCESSING}', last_ran_at = NOW() AT TIME ZONE 'UTC', worker_id = '${escapedWorkerId}'\n WHERE id = (\n SELECT id\n FROM ${this.tableName}\n WHERE queue = '${escapedQueueName}'\n AND status = '${JobStatus.PENDING}'\n ${prefixConditions}\n AND run_after <= NOW() AT TIME ZONE 'UTC'\n ORDER BY run_after ASC\n FOR UPDATE SKIP LOCKED\n LIMIT 1\n )\n RETURNING *`;\n\n const { data, error } = await this.client.rpc(\"exec_sql\", { query: sql });\n\n if (error) throw error;\n\n // exec_sql returns result rows as an array\n if (!data || !Array.isArray(data) || data.length === 0) {\n return undefined;\n }\n\n return data[0] as JobStorageFormat<Input, Output>;\n }\n\n /**\n * Retrieves the number of jobs in the queue with a specific status.\n * @param status - The status of the jobs to count\n * @returns The count of jobs with the specified status\n */\n public async size(status = JobStatus.PENDING): Promise<number> {\n let query = this.client\n .from(this.tableName)\n .select(\"*\", { count: \"exact\", head: true })\n .eq(\"queue\", this.queueName)\n .eq(\"status\", status);\n\n query = this.applyPrefixFilters(query);\n\n const { count, error } = await query;\n\n if (error) throw error;\n return count ?? 0;\n }\n\n /**\n * Gets all jobs from the queue that match the current prefix values.\n * Used internally for polling-based subscriptions.\n *\n * @returns An array of jobs\n */\n private async getAllJobs(): Promise<Array<JobStorageFormat<Input, Output>>> {\n let query = this.client.from(this.tableName).select(\"*\").eq(\"queue\", this.queueName);\n\n query = this.applyPrefixFilters(query);\n\n const { data, error } = await query;\n\n if (error) throw error;\n return (data ?? []) as Array<JobStorageFormat<Input, Output>>;\n }\n\n /**\n * Marks a job as complete with its output or error.\n * Enhanced error handling:\n * - For a retryable error, increments run_attempts and updates run_after.\n * - Marks a job as FAILED immediately for permanent or generic errors.\n */\n public async complete(jobDetails: JobStorageFormat<Input, Output>): Promise<void> {\n const now = new Date().toISOString();\n\n // Handle disabled without changing attempts\n if (jobDetails.status === JobStatus.DISABLED) {\n let query = this.client\n .from(this.tableName)\n .update({\n status: jobDetails.status,\n progress: 100,\n progress_message: \"\",\n progress_details: null,\n completed_at: now,\n last_ran_at: now,\n })\n .eq(\"id\", jobDetails.id)\n .eq(\"queue\", this.queueName);\n query = this.applyPrefixFilters(query);\n const { error } = await query;\n if (error) throw error;\n return;\n }\n\n // Read current attempts to compute next value deterministically\n let getQuery = this.client\n .from(this.tableName)\n .select(\"run_attempts, max_retries\")\n .eq(\"id\", jobDetails.id as number)\n .eq(\"queue\", this.queueName);\n getQuery = this.applyPrefixFilters(getQuery);\n const { data: current, error: getError } = await getQuery.single();\n if (getError) throw getError;\n const currentAttempts = (current?.run_attempts as number | undefined) ?? 0;\n const maxRetries = (current?.max_retries as number | undefined) ?? jobDetails.max_retries ?? 10;\n const nextAttempts = currentAttempts + 1;\n\n if (jobDetails.status === JobStatus.PENDING) {\n // Check if the next attempt would exceed max retries\n if (nextAttempts > maxRetries) {\n // Update to FAILED status instead of rescheduling\n let failQuery = this.client\n .from(this.tableName)\n .update({\n status: JobStatus.FAILED,\n error: \"Max retries reached\",\n error_code: \"MAX_RETRIES_REACHED\",\n progress: 100,\n progress_message: \"\",\n progress_details: null,\n completed_at: now,\n last_ran_at: now,\n })\n .eq(\"id\", jobDetails.id)\n .eq(\"queue\", this.queueName);\n failQuery = this.applyPrefixFilters(failQuery);\n const { error: failError } = await failQuery;\n if (failError) throw failError;\n return;\n }\n\n // Reschedule the job\n let query = this.client\n .from(this.tableName)\n .update({\n error: jobDetails.error ?? null,\n error_code: jobDetails.error_code ?? null,\n status: jobDetails.status,\n run_after: jobDetails.run_after!,\n progress: 0,\n progress_message: \"\",\n progress_details: null,\n run_attempts: nextAttempts,\n last_ran_at: now,\n })\n .eq(\"id\", jobDetails.id)\n .eq(\"queue\", this.queueName);\n query = this.applyPrefixFilters(query);\n const { error } = await query;\n if (error) throw error;\n return;\n }\n\n if (jobDetails.status === JobStatus.COMPLETED || jobDetails.status === JobStatus.FAILED) {\n let query = this.client\n .from(this.tableName)\n .update({\n output: jobDetails.output ?? null,\n error: jobDetails.error ?? null,\n error_code: jobDetails.error_code ?? null,\n status: jobDetails.status,\n progress: 100,\n progress_message: \"\",\n progress_details: null,\n run_attempts: nextAttempts,\n completed_at: now,\n last_ran_at: now,\n })\n .eq(\"id\", jobDetails.id)\n .eq(\"queue\", this.queueName);\n query = this.applyPrefixFilters(query);\n const { error } = await query;\n if (error) throw error;\n return;\n }\n\n // Transitional states: PROCESSING/ABORTING etc - increment attempts like other stores\n let query = this.client\n .from(this.tableName)\n .update({\n status: jobDetails.status,\n output: jobDetails.output ?? null,\n error: jobDetails.error ?? null,\n error_code: jobDetails.error_code ?? null,\n run_after: jobDetails.run_after ?? null,\n run_attempts: nextAttempts,\n last_ran_at: now,\n })\n .eq(\"id\", jobDetails.id)\n .eq(\"queue\", this.queueName);\n query = this.applyPrefixFilters(query);\n const { error } = await query;\n if (error) throw error;\n }\n\n /**\n * Releases a claimed job without consuming a retry attempt.\n */\n public async release(jobId: unknown): Promise<void> {\n let query = this.client\n .from(this.tableName)\n .update({\n status: JobStatus.PENDING,\n worker_id: null,\n progress: 0,\n progress_message: \"\",\n progress_details: null,\n })\n .eq(\"id\", jobId)\n .eq(\"queue\", this.queueName);\n\n query = this.applyPrefixFilters(query);\n const { error } = await query;\n if (error) throw error;\n }\n\n /**\n * Clears all jobs from the queue.\n */\n public async deleteAll(): Promise<void> {\n let query = this.client.from(this.tableName).delete().eq(\"queue\", this.queueName);\n query = this.applyPrefixFilters(query);\n const { error } = await query;\n\n if (error) throw error;\n }\n\n /**\n * Looks up cached output for a given input\n * Uses input fingerprinting for efficient matching\n * @returns The cached output or null if not found\n */\n public async outputForInput(input: Input): Promise<Output | null> {\n const fingerprint = await makeFingerprint(input);\n\n let query = this.client\n .from(this.tableName)\n .select(\"output\")\n .eq(\"fingerprint\", fingerprint)\n .eq(\"queue\", this.queueName)\n .eq(\"status\", JobStatus.COMPLETED);\n\n query = this.applyPrefixFilters(query);\n\n const { data, error } = await query.single();\n\n if (error) {\n if (error.code === \"PGRST116\") return null; // Not found\n throw error;\n }\n\n return data?.output ?? null;\n }\n\n /**\n * Aborts a job by setting its status to \"ABORTING\".\n * This method will signal the corresponding AbortController so that\n * the job's execute() method (if it supports an AbortSignal parameter)\n * can clean up and exit.\n */\n public async abort(jobId: unknown): Promise<void> {\n let query = this.client\n .from(this.tableName)\n .update({ status: JobStatus.ABORTING })\n .eq(\"id\", jobId)\n .eq(\"queue\", this.queueName);\n\n query = this.applyPrefixFilters(query);\n const { error } = await query;\n\n if (error) throw error;\n }\n\n /**\n * Retrieves all jobs for a given job run ID.\n * @param job_run_id - The ID of the job run to retrieve\n * @returns An array of jobs\n */\n public async getByRunId(job_run_id: string): Promise<Array<JobStorageFormat<Input, Output>>> {\n let query = this.client\n .from(this.tableName)\n .select(\"*\")\n .eq(\"job_run_id\", job_run_id)\n .eq(\"queue\", this.queueName);\n\n query = this.applyPrefixFilters(query);\n const { data, error } = await query;\n\n if (error) throw error;\n return (data as Array<JobStorageFormat<Input, Output>>) ?? [];\n }\n\n /**\n * Implements the saveProgress method\n */\n public async saveProgress(\n jobId: unknown,\n progress: number,\n message: string,\n details: Record<string, any>\n ): Promise<void> {\n let query = this.client\n .from(this.tableName)\n .update({\n progress,\n progress_message: message,\n progress_details: details,\n })\n .eq(\"id\", jobId)\n .eq(\"queue\", this.queueName);\n\n query = this.applyPrefixFilters(query);\n const { error } = await query;\n\n if (error) throw error;\n }\n\n /**\n * Deletes a job by its ID\n */\n public async delete(jobId: unknown): Promise<void> {\n let query = this.client\n .from(this.tableName)\n .delete()\n .eq(\"id\", jobId)\n .eq(\"queue\", this.queueName);\n\n query = this.applyPrefixFilters(query);\n const { error } = await query;\n\n if (error) throw error;\n }\n\n /**\n * Delete jobs with a specific status older than a cutoff date\n * @param status - Status of jobs to delete\n * @param olderThanMs - Delete jobs completed more than this many milliseconds ago\n */\n public async deleteJobsByStatusAndAge(status: JobStatus, olderThanMs: number): Promise<void> {\n const cutoffDate = new Date(Date.now() - olderThanMs).toISOString();\n\n let query = this.client\n .from(this.tableName)\n .delete()\n .eq(\"queue\", this.queueName)\n .eq(\"status\", status)\n .not(\"completed_at\", \"is\", null)\n .lte(\"completed_at\", cutoffDate);\n\n query = this.applyPrefixFilters(query);\n const { error } = await query;\n\n if (error) throw error;\n }\n\n /**\n * Checks if a job from a realtime payload matches the specified prefix filter\n * @param job - The job record from the realtime payload\n * @param prefixFilter - The prefix filter to match against (undefined = use instance prefixes, {} = no filter)\n */\n private matchesPrefixFilter(\n job: Record<string, unknown> | undefined,\n prefixFilter?: Readonly<Record<string, string | number>>\n ): boolean {\n if (!job) return false;\n\n // Check queue name first\n if (job.queue !== this.queueName) {\n return false;\n }\n\n // If prefixFilter is explicitly an empty object, no prefix filtering\n if (prefixFilter && Object.keys(prefixFilter).length === 0) {\n return true;\n }\n\n // Use provided prefixFilter or fall back to instance's prefixValues\n const filterValues = prefixFilter ?? this.prefixValues;\n\n // If no filter values, match all\n if (Object.keys(filterValues).length === 0) {\n return true;\n }\n\n // Check each filter value\n for (const [key, value] of Object.entries(filterValues)) {\n if (job[key] !== value) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Checks if a prefix filter is custom (different from instance's prefixes).\n */\n private isCustomPrefixFilter(prefixFilter?: Readonly<Record<string, string | number>>): boolean {\n // No filter specified - use instance prefixes (not custom)\n if (prefixFilter === undefined) {\n return false;\n }\n // Empty filter - receive all (custom)\n if (Object.keys(prefixFilter).length === 0) {\n return true;\n }\n // Check if filter matches instance prefixes exactly\n const instanceKeys = Object.keys(this.prefixValues);\n const filterKeys = Object.keys(prefixFilter);\n if (instanceKeys.length !== filterKeys.length) {\n return true; // Different number of keys = custom\n }\n for (const key of instanceKeys) {\n if (this.prefixValues[key] !== prefixFilter[key]) {\n return true; // Different value = custom\n }\n }\n return false; // Matches instance prefixes exactly\n }\n\n /**\n * Gets all jobs from the queue with a custom prefix filter.\n * Used for subscriptions with custom prefix filters (filters at DB level).\n *\n * @param prefixFilter - The prefix values to filter by (empty object = all jobs)\n * @returns A promise that resolves to an array of jobs\n */\n private async getAllJobsWithFilter(\n prefixFilter: Readonly<Record<string, string | number>>\n ): Promise<Array<JobStorageFormat<Input, Output>>> {\n let query = this.client.from(this.tableName).select(\"*\").eq(\"queue\", this.queueName);\n\n // Apply the custom prefix filter\n for (const [key, value] of Object.entries(prefixFilter)) {\n query = query.eq(key, value);\n }\n\n const { data, error } = await query;\n\n if (error) throw error;\n return (data ?? []) as Array<JobStorageFormat<Input, Output>>;\n }\n\n /**\n * Subscribes to changes in the queue.\n * Uses Supabase realtime by default.\n *\n * @param callback - Function called when a change occurs\n * @param options - Subscription options including prefix filter\n * @returns Unsubscribe function\n */\n public subscribeToChanges(\n callback: (change: QueueChangePayload<Input, Output>) => void,\n options?: QueueSubscribeOptions\n ): () => void {\n return this.subscribeToChangesWithRealtime(callback, options?.prefixFilter);\n }\n\n /**\n * Subscribe using Supabase realtime (protected).\n *\n * @param callback - Function called when a change occurs\n * @param prefixFilter - Optional prefix filter (undefined = use instance prefixes, {} = no filter)\n * @returns Unsubscribe function\n */\n protected subscribeToChangesWithRealtime(\n callback: (change: QueueChangePayload<Input, Output>) => void,\n prefixFilter?: Readonly<Record<string, string | number>>\n ): () => void {\n const channelName = `queue-${this.tableName}-${this.queueName}-${Date.now()}`;\n\n this.realtimeChannel = this.client\n .channel(channelName)\n .on(\n \"postgres_changes\",\n {\n event: \"*\",\n schema: \"public\",\n table: this.tableName,\n filter: `queue=eq.${this.queueName}`,\n },\n (payload) => {\n // Filter by prefix values\n const newJob = payload.new as Record<string, unknown> | undefined;\n const oldJob = payload.old as Record<string, unknown> | undefined;\n\n // Check if either old or new job matches the filter\n const newMatches = this.matchesPrefixFilter(newJob, prefixFilter);\n const oldMatches = this.matchesPrefixFilter(oldJob, prefixFilter);\n\n if (!newMatches && !oldMatches) {\n return;\n }\n\n callback({\n type: payload.eventType.toUpperCase() as QueueChangeType,\n old:\n oldJob && Object.keys(oldJob).length > 0\n ? (oldJob as JobStorageFormat<Input, Output>)\n : undefined,\n new:\n newJob && Object.keys(newJob).length > 0\n ? (newJob as JobStorageFormat<Input, Output>)\n : undefined,\n });\n }\n )\n .subscribe();\n\n return () => {\n if (this.realtimeChannel) {\n this.client.removeChannel(this.realtimeChannel);\n this.realtimeChannel = null;\n }\n };\n }\n\n /**\n * Gets or creates the shared polling subscription manager for normal subscriptions (fallback).\n * This ensures all normal subscriptions share a single polling loop per interval.\n */\n private getPollingManager(): PollingSubscriptionManager<\n JobStorageFormat<Input, Output>,\n unknown,\n QueueChangePayload<Input, Output>\n > {\n if (!this.pollingManager) {\n this.pollingManager = new PollingSubscriptionManager<\n JobStorageFormat<Input, Output>,\n unknown,\n QueueChangePayload<Input, Output>\n >(\n async () => {\n // Fetch jobs with instance's prefix filter (efficient DB-level filtering)\n const jobs = await this.getAllJobs();\n return new Map(jobs.map((j) => [j.id, j]));\n },\n (a, b) => deepEqual(a, b),\n {\n insert: (item) => ({ type: \"INSERT\" as const, new: item }),\n update: (oldItem, newItem) => ({ type: \"UPDATE\" as const, old: oldItem, new: newItem }),\n delete: (item) => ({ type: \"DELETE\" as const, old: item }),\n }\n );\n }\n return this.pollingManager;\n }\n\n /**\n * Creates a dedicated polling subscription for custom prefix filters (fallback).\n * This runs separately from the normal polling manager with DB-level filtering.\n */\n private subscribeWithCustomPrefixFilterPolling(\n callback: (change: QueueChangePayload<Input, Output>) => void,\n prefixFilter: Readonly<Record<string, string | number>>,\n intervalMs: number\n ): () => void {\n let lastKnownJobs = new Map<unknown, JobStorageFormat<Input, Output>>();\n let cancelled = false;\n\n const poll = async () => {\n if (cancelled) return;\n try {\n const currentJobs = await this.getAllJobsWithFilter(prefixFilter);\n if (cancelled) return;\n const currentMap = new Map(currentJobs.map((j) => [j.id, j]));\n\n // Detect changes\n for (const [id, job] of currentMap) {\n const old = lastKnownJobs.get(id);\n if (!old) {\n callback({ type: \"INSERT\", new: job });\n } else if (!deepEqual(old, job)) {\n callback({ type: \"UPDATE\", old, new: job });\n }\n }\n\n for (const [id, job] of lastKnownJobs) {\n if (!currentMap.has(id)) {\n callback({ type: \"DELETE\", old: job });\n }\n }\n\n lastKnownJobs = currentMap;\n } catch {\n // Ignore polling errors\n }\n };\n\n const intervalId = setInterval(poll, intervalMs);\n poll(); // Initial poll\n\n return () => {\n cancelled = true;\n clearInterval(intervalId);\n };\n }\n\n /**\n * Subscribe using polling (protected, available as fallback).\n *\n * Normal subscriptions (no custom prefix filter) share a single polling loop for efficiency.\n * Custom prefix filter subscriptions get their own dedicated polling loop with DB-level filtering.\n *\n * @param callback - Function called when a change occurs\n * @param options - Subscription options including interval and prefix filter\n * @returns Unsubscribe function\n */\n protected subscribeToChangesWithPolling(\n callback: (change: QueueChangePayload<Input, Output>) => void,\n options?: QueueSubscribeOptions\n ): () => void {\n const intervalMs = options?.pollingIntervalMs ?? 1000;\n\n // Check if this is a custom prefix filter subscription\n if (this.isCustomPrefixFilter(options?.prefixFilter)) {\n // Custom prefix filter - use dedicated polling with DB-level filtering\n return this.subscribeWithCustomPrefixFilterPolling(\n callback,\n options!.prefixFilter!,\n intervalMs\n );\n }\n\n // Normal subscription - use shared polling manager (efficient)\n const manager = this.getPollingManager();\n return manager.subscribe(callback, { intervalMs });\n }\n}\n",
|
|
46
|
+
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { createServiceToken } from \"@workglow/util\";\nimport type { Pool } from \"@workglow/storage/postgres\";\nimport type { PrefixColumn } from \"../queue/IQueueStorage\";\nimport {\n IRateLimiterStorage,\n RateLimiterStorageOptions,\n RateLimiterStorageScope,\n} from \"./IRateLimiterStorage\";\n\nexport const POSTGRES_RATE_LIMITER_STORAGE = createServiceToken<IRateLimiterStorage>(\n \"ratelimiter.storage.postgres\"\n);\n\n/**\n * PostgreSQL implementation of rate limiter storage.\n * Manages execution records and next available times for rate limiting.\n */\nexport class PostgresRateLimiterStorage implements IRateLimiterStorage {\n public readonly scope: RateLimiterStorageScope = \"cluster\";\n /** The prefix column definitions */\n protected readonly prefixes: readonly PrefixColumn[];\n /** The prefix values for filtering */\n protected readonly prefixValues: Readonly<Record<string, string | number>>;\n /** The table name for execution tracking */\n protected readonly executionTableName: string;\n /** The table name for next available times */\n protected readonly nextAvailableTableName: string;\n\n constructor(\n protected readonly db: Pool,\n options?: RateLimiterStorageOptions\n ) {\n this.prefixes = options?.prefixes ?? [];\n this.prefixValues = options?.prefixValues ?? {};\n\n // Generate table names based on prefix configuration\n if (this.prefixes.length > 0) {\n const prefixNames = this.prefixes.map((p) => p.name).join(\"_\");\n this.executionTableName = `rate_limit_executions_${prefixNames}`;\n this.nextAvailableTableName = `rate_limit_next_available_${prefixNames}`;\n } else {\n this.executionTableName = \"rate_limit_executions\";\n this.nextAvailableTableName = \"rate_limit_next_available\";\n }\n }\n\n /**\n * Gets the SQL column type for a prefix column.\n */\n private getPrefixColumnType(type: PrefixColumn[\"type\"]): string {\n return type === \"uuid\" ? \"UUID\" : \"INTEGER\";\n }\n\n /**\n * Builds the prefix columns SQL for CREATE TABLE.\n */\n private buildPrefixColumnsSql(): string {\n if (this.prefixes.length === 0) return \"\";\n return (\n this.prefixes\n .map((p) => `${p.name} ${this.getPrefixColumnType(p.type)} NOT NULL`)\n .join(\",\\n \") + \",\\n \"\n );\n }\n\n /**\n * Builds prefix column names for use in queries.\n */\n private getPrefixColumnNames(): string[] {\n return this.prefixes.map((p) => p.name);\n }\n\n /**\n * Builds WHERE clause conditions for prefix filtering.\n * @param startParam - The starting parameter number for parameterized queries\n */\n private buildPrefixWhereClause(startParam: number): {\n conditions: string;\n params: Array<string | number>;\n } {\n if (this.prefixes.length === 0) {\n return { conditions: \"\", params: [] };\n }\n const conditions = this.prefixes.map((p, i) => `${p.name} = $${startParam + i}`).join(\" AND \");\n const params = this.prefixes.map((p) => this.prefixValues[p.name]);\n return { conditions: \" AND \" + conditions, params };\n }\n\n /**\n * Gets prefix values as an array in column order.\n */\n private getPrefixParamValues(): Array<string | number> {\n return this.prefixes.map((p) => this.prefixValues[p.name]);\n }\n\n public async setupDatabase(): Promise<void> {\n const prefixColumnsSql = this.buildPrefixColumnsSql();\n const prefixColumnNames = this.getPrefixColumnNames();\n const prefixIndexPrefix =\n prefixColumnNames.length > 0 ? prefixColumnNames.join(\", \") + \", \" : \"\";\n const indexSuffix = prefixColumnNames.length > 0 ? \"_\" + prefixColumnNames.join(\"_\") : \"\";\n\n await this.db.query(`\n CREATE TABLE IF NOT EXISTS ${this.executionTableName} (\n id SERIAL PRIMARY KEY,\n ${prefixColumnsSql}queue_name TEXT NOT NULL,\n executed_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()\n )\n `);\n\n await this.db.query(`\n CREATE INDEX IF NOT EXISTS rate_limit_exec_queue${indexSuffix}_idx \n ON ${this.executionTableName} (${prefixIndexPrefix}queue_name, executed_at)\n `);\n\n // For the next_available table, we need a composite primary key with prefixes\n const primaryKeyColumns =\n prefixColumnNames.length > 0 ? `${prefixColumnNames.join(\", \")}, queue_name` : \"queue_name\";\n\n await this.db.query(`\n CREATE TABLE IF NOT EXISTS ${this.nextAvailableTableName} (\n ${prefixColumnsSql}queue_name TEXT NOT NULL,\n next_available_at TIMESTAMP WITH TIME ZONE,\n PRIMARY KEY (${primaryKeyColumns})\n )\n `);\n }\n\n public async tryReserveExecution(\n queueName: string,\n maxExecutions: number,\n windowMs: number\n ): Promise<unknown | null> {\n const prefixColumnNames = this.getPrefixColumnNames();\n const prefixParamValues = this.getPrefixParamValues();\n const prefixCount = prefixColumnNames.length;\n\n // Parameter layout:\n // $1..$N prefix values (used in lock-key, count, next-available, and INSERT)\n // $(N+1) queueName\n // $(N+2) windowStart timestamp\n // $(N+3) maxExecutions\n const queueParam = `$${prefixCount + 1}`;\n const windowStartParam = `$${prefixCount + 2}`;\n\n // For the advisory lock we hash table-name + prefix values + queue-name into a bigint.\n // Use hashtextextended which returns int8 (advisory_xact_lock takes bigint).\n const lockKeyParts: string[] = [`'${this.executionTableName}'`];\n for (let i = 0; i < prefixCount; i++) {\n lockKeyParts.push(`$${i + 1}::text`);\n }\n lockKeyParts.push(`${queueParam}::text`);\n const lockKeyExpr = `hashtextextended(${lockKeyParts.join(\" || '|' || \")}, 0)`;\n\n const prefixWhere =\n prefixCount > 0\n ? \" AND \" +\n prefixColumnNames\n .map((p, i) => `${p} = $${i + 1}`)\n .join(\" AND \")\n : \"\";\n\n const prefixInsertCols = prefixCount > 0 ? prefixColumnNames.join(\", \") + \", \" : \"\";\n const prefixInsertPlaceholders =\n prefixCount > 0 ? prefixColumnNames.map((_, i) => `$${i + 1}`).join(\", \") + \", \" : \"\";\n\n const windowStart = new Date(Date.now() - windowMs).toISOString();\n\n // Use a dedicated client when the pool supports connect() (real pg.Pool)\n // — the advisory xact lock + transaction MUST run on the same connection\n // for atomicity. Without connect(), only known single-connection wrappers\n // (PGLitePool, raw PGlite) are safe, since they implicitly serialize all\n // queries through one underlying connection. Anything else (e.g. a custom\n // multi-connection adapter without connect()) would dispatch the lock and\n // the INSERT to different sessions, defeating the lock entirely.\n const supportsConnect =\n typeof (this.db as unknown as { connect?: unknown }).connect === \"function\";\n if (!supportsConnect) {\n // Without connect() we run BEGIN/advisory_lock/INSERT/COMMIT directly on\n // `db.query`. That's only safe if `db` is a single-connection wrapper\n // (every query goes through the same underlying session). Recognize:\n // - PGLitePool — our own wrapper class; constructor name preserved.\n // - PGlite — third-party, ships minified so `constructor.name`\n // can be obfuscated (observed: \"q\"). Detect via duck-typing on\n // methods PGlite uniquely exposes (`waitReady` Promise + `exec`).\n // Any other no-connect() pool would dispatch the lock and the INSERT\n // to potentially different sessions, breaking atomicity.\n const dbAny = this.db as unknown as {\n waitReady?: unknown;\n exec?: unknown;\n constructor?: { name?: string };\n };\n const ctorName = dbAny.constructor?.name;\n const looksLikePGlite =\n typeof dbAny.exec === \"function\" && dbAny.waitReady !== undefined;\n const looksLikePGLitePool = ctorName === \"PGLitePool\";\n if (!looksLikePGlite && !looksLikePGLitePool) {\n throw new Error(\n `PostgresRateLimiterStorage.tryReserveExecution requires a pg.Pool with connect() or a known single-connection wrapper (PGLitePool, PGlite); got ${ctorName ?? typeof this.db}. A multi-connection pool without connect() would dispatch the advisory lock and the INSERT to different sessions, breaking atomicity.`\n );\n }\n }\n const conn = supportsConnect\n ? await (this.db as unknown as { connect: () => Promise<{\n query: Pool[\"query\"];\n release: () => void;\n }> }).connect()\n : { query: this.db.query.bind(this.db), release: () => {} };\n\n try {\n await conn.query(\"BEGIN\");\n try {\n await conn.query(\n `SELECT pg_advisory_xact_lock(${lockKeyExpr})`,\n [...prefixParamValues, queueName]\n );\n\n const countResult = await conn.query(\n `\n SELECT COUNT(*)::int AS n\n FROM ${this.executionTableName}\n WHERE queue_name = ${queueParam} AND executed_at > ${windowStartParam}${prefixWhere}\n `,\n [...prefixParamValues, queueName, windowStart]\n );\n const n: number = countResult.rows[0]?.n ?? 0;\n if (n >= maxExecutions) {\n await conn.query(\"COMMIT\");\n return null;\n }\n\n const naResult = await conn.query(\n `\n SELECT next_available_at\n FROM ${this.nextAvailableTableName}\n WHERE queue_name = ${queueParam}${prefixWhere}\n `,\n [...prefixParamValues, queueName]\n );\n const nextAvailableAt: Date | null = naResult.rows[0]?.next_available_at ?? null;\n if (nextAvailableAt && new Date(nextAvailableAt).getTime() > Date.now()) {\n await conn.query(\"COMMIT\");\n return null;\n }\n\n const insertResult = await conn.query(\n `\n INSERT INTO ${this.executionTableName} (${prefixInsertCols}queue_name)\n VALUES (${prefixInsertPlaceholders}${queueParam})\n RETURNING id\n `,\n [...prefixParamValues, queueName]\n );\n await conn.query(\"COMMIT\");\n return insertResult.rows[0]?.id ?? null;\n } catch (err) {\n try {\n await conn.query(\"ROLLBACK\");\n } catch {\n // best-effort\n }\n throw err;\n }\n } finally {\n conn.release();\n }\n }\n\n public async releaseExecution(queueName: string, token: unknown): Promise<void> {\n if (token === null || token === undefined) return;\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(3);\n // Delete by id — NEVER by recency. Two concurrent acquirers can hold\n // tokens for different rows; deleting \"the most recent\" would release the\n // other worker's slot.\n await this.db.query(\n `DELETE FROM ${this.executionTableName} WHERE id = $1 AND queue_name = $2${prefixConditions}`,\n [token as string | number, queueName, ...prefixParams]\n );\n }\n\n public async recordExecution(queueName: string): Promise<void> {\n const prefixColumnNames = this.getPrefixColumnNames();\n const prefixColumnsInsert =\n prefixColumnNames.length > 0 ? prefixColumnNames.join(\", \") + \", \" : \"\";\n const prefixParamValues = this.getPrefixParamValues();\n const prefixParamPlaceholders =\n prefixColumnNames.length > 0\n ? prefixColumnNames.map((_, i) => `$${i + 1}`).join(\", \") + \", \"\n : \"\";\n const queueParamNum = prefixColumnNames.length + 1;\n\n await this.db.query(\n `\n INSERT INTO ${this.executionTableName} (${prefixColumnsInsert}queue_name)\n VALUES (${prefixParamPlaceholders}$${queueParamNum})\n `,\n [...prefixParamValues, queueName]\n );\n }\n\n public async getExecutionCount(queueName: string, windowStartTime: string): Promise<number> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(3);\n\n const result = await this.db.query(\n `\n SELECT COUNT(*) AS count\n FROM ${this.executionTableName}\n WHERE queue_name = $1 AND executed_at > $2${prefixConditions}\n `,\n [queueName, windowStartTime, ...prefixParams]\n );\n\n return parseInt(result.rows[0]?.count ?? \"0\", 10);\n }\n\n public async getOldestExecutionAtOffset(\n queueName: string,\n offset: number\n ): Promise<string | undefined> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(3);\n\n const result = await this.db.query(\n `\n SELECT executed_at\n FROM ${this.executionTableName}\n WHERE queue_name = $1${prefixConditions}\n ORDER BY executed_at ASC\n LIMIT 1 OFFSET $2\n `,\n [queueName, offset, ...prefixParams]\n );\n\n const executedAt = result.rows[0]?.executed_at;\n if (!executedAt) return undefined;\n return new Date(executedAt).toISOString();\n }\n\n public async getNextAvailableTime(queueName: string): Promise<string | undefined> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(2);\n\n const result = await this.db.query(\n `\n SELECT next_available_at\n FROM ${this.nextAvailableTableName}\n WHERE queue_name = $1${prefixConditions}\n `,\n [queueName, ...prefixParams]\n );\n\n const nextAvailableAt = result.rows[0]?.next_available_at;\n if (!nextAvailableAt) return undefined;\n return new Date(nextAvailableAt).toISOString();\n }\n\n public async setNextAvailableTime(queueName: string, nextAvailableAt: string): Promise<void> {\n const prefixColumnNames = this.getPrefixColumnNames();\n const prefixColumnsInsert =\n prefixColumnNames.length > 0 ? prefixColumnNames.join(\", \") + \", \" : \"\";\n const prefixParamValues = this.getPrefixParamValues();\n const prefixParamPlaceholders =\n prefixColumnNames.length > 0\n ? prefixColumnNames.map((_, i) => `$${i + 1}`).join(\", \") + \", \"\n : \"\";\n const baseParamStart = prefixColumnNames.length + 1;\n\n // Build the conflict columns for upsert\n const conflictColumns =\n prefixColumnNames.length > 0 ? `${prefixColumnNames.join(\", \")}, queue_name` : \"queue_name\";\n\n await this.db.query(\n `\n INSERT INTO ${this.nextAvailableTableName} (${prefixColumnsInsert}queue_name, next_available_at)\n VALUES (${prefixParamPlaceholders}$${baseParamStart}, $${baseParamStart + 1})\n ON CONFLICT (${conflictColumns})\n DO UPDATE SET next_available_at = EXCLUDED.next_available_at\n `,\n [...prefixParamValues, queueName, nextAvailableAt]\n );\n }\n\n public async clear(queueName: string): Promise<void> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(2);\n\n await this.db.query(\n `DELETE FROM ${this.executionTableName} WHERE queue_name = $1${prefixConditions}`,\n [queueName, ...prefixParams]\n );\n await this.db.query(\n `DELETE FROM ${this.nextAvailableTableName} WHERE queue_name = $1${prefixConditions}`,\n [queueName, ...prefixParams]\n );\n }\n}\n",
|
|
47
|
+
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Sqlite } from \"@workglow/storage/sqlite\";\nimport { createServiceToken, sleep, toSQLiteTimestamp } from \"@workglow/util\";\nimport type { PrefixColumn } from \"../queue/IQueueStorage\";\nimport {\n IRateLimiterStorage,\n RateLimiterStorageOptions,\n RateLimiterStorageScope,\n} from \"./IRateLimiterStorage\";\n\nexport const SQLITE_RATE_LIMITER_STORAGE = createServiceToken<IRateLimiterStorage>(\n \"ratelimiter.storage.sqlite\"\n);\n\n/**\n * SQLite implementation of rate limiter storage.\n * Manages execution records and next available times for rate limiting.\n */\nexport class SqliteRateLimiterStorage implements IRateLimiterStorage {\n /**\n * `\"process\"` because a typical SQLite deployment uses a single-process\n * file. Multi-process SQLite (multiple worker processes opening the same\n * file) is not safe for rate limiting even with WAL — separate processes\n * can interleave between BEGIN IMMEDIATE acquisition retries.\n */\n public readonly scope: RateLimiterStorageScope = \"process\";\n /** The prefix column definitions */\n protected readonly prefixes: readonly PrefixColumn[];\n /** The prefix values for filtering */\n protected readonly prefixValues: Readonly<Record<string, string | number>>;\n /** The table name for execution tracking */\n protected readonly executionTableName: string;\n /** The table name for next available times */\n protected readonly nextAvailableTableName: string;\n\n constructor(\n protected readonly db: Sqlite.Database,\n options?: RateLimiterStorageOptions\n ) {\n this.prefixes = options?.prefixes ?? [];\n this.prefixValues = options?.prefixValues ?? {};\n\n // Generate table names based on prefix configuration\n if (this.prefixes.length > 0) {\n const prefixNames = this.prefixes.map((p) => p.name).join(\"_\");\n this.executionTableName = `rate_limit_executions_${prefixNames}`;\n this.nextAvailableTableName = `rate_limit_next_available_${prefixNames}`;\n } else {\n this.executionTableName = \"rate_limit_executions\";\n this.nextAvailableTableName = \"rate_limit_next_available\";\n }\n }\n\n /**\n * Gets the SQL column type for a prefix column (SQLite uses TEXT for uuid).\n */\n private getPrefixColumnType(type: PrefixColumn[\"type\"]): string {\n return type === \"uuid\" ? \"TEXT\" : \"INTEGER\";\n }\n\n /**\n * Builds the prefix columns SQL for CREATE TABLE.\n */\n private buildPrefixColumnsSql(): string {\n if (this.prefixes.length === 0) return \"\";\n return (\n this.prefixes\n .map((p) => `${p.name} ${this.getPrefixColumnType(p.type)} NOT NULL`)\n .join(\",\\n \") + \",\\n \"\n );\n }\n\n /**\n * Builds prefix column names for use in queries.\n */\n private getPrefixColumnNames(): string[] {\n return this.prefixes.map((p) => p.name);\n }\n\n /**\n * Builds WHERE clause conditions for prefix filtering.\n */\n private buildPrefixWhereClause(): string {\n if (this.prefixes.length === 0) {\n return \"\";\n }\n const conditions = this.prefixes.map((p) => `${p.name} = ?`).join(\" AND \");\n return \" AND \" + conditions;\n }\n\n /**\n * Gets prefix values as an array in column order.\n */\n private getPrefixParamValues(): Array<string | number> {\n return this.prefixes.map((p) => this.prefixValues[p.name]);\n }\n\n public async setupDatabase(): Promise<void> {\n await sleep(0);\n const prefixColumnsSql = this.buildPrefixColumnsSql();\n const prefixColumnNames = this.getPrefixColumnNames();\n const prefixIndexPrefix =\n prefixColumnNames.length > 0 ? prefixColumnNames.join(\", \") + \", \" : \"\";\n const indexSuffix = prefixColumnNames.length > 0 ? \"_\" + prefixColumnNames.join(\"_\") : \"\";\n\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS ${this.executionTableName} (\n id INTEGER PRIMARY KEY,\n ${prefixColumnsSql}queue_name TEXT NOT NULL,\n executed_at TEXT DEFAULT CURRENT_TIMESTAMP\n );\n \n CREATE INDEX IF NOT EXISTS rate_limit_exec_queue${indexSuffix}_idx \n ON ${this.executionTableName} (${prefixIndexPrefix}queue_name, executed_at);\n `);\n\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS ${this.nextAvailableTableName} (\n ${prefixColumnsSql}queue_name TEXT PRIMARY KEY,\n next_available_at TEXT\n );\n `);\n }\n\n public async tryReserveExecution(\n queueName: string,\n maxExecutions: number,\n windowMs: number\n ): Promise<unknown | null> {\n const prefixColumnNames = this.getPrefixColumnNames();\n const prefixParamValues = this.getPrefixParamValues();\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixColumnsInsert =\n prefixColumnNames.length > 0 ? prefixColumnNames.join(\", \") + \", \" : \"\";\n const prefixPlaceholders =\n prefixColumnNames.length > 0 ? prefixColumnNames.map(() => \"?\").join(\", \") + \", \" : \"\";\n\n const windowStart = toSQLiteTimestamp(new Date(Date.now() - windowMs))!;\n\n // Use a synchronous transaction so the count + insert is atomic against\n // other writers. The canonical Sqlite.Database.transaction() returns void\n // by contract, so we capture the inserted id via a closure variable.\n let insertedId: number | bigint | null = null;\n const txn = this.db.transaction((): void => {\n const countStmt = this.db.prepare<unknown[], { count: number }>(`\n SELECT COUNT(*) AS count\n FROM ${this.executionTableName}\n WHERE queue_name = ? AND executed_at > ?${prefixConditions}\n `);\n const countRow = countStmt.get(queueName, windowStart, ...prefixParamValues);\n if ((countRow?.count ?? 0) >= maxExecutions) {\n return;\n }\n\n const naStmt = this.db.prepare<unknown[], { next_available_at: string }>(`\n SELECT next_available_at\n FROM ${this.nextAvailableTableName}\n WHERE queue_name = ?${prefixConditions}\n `);\n const naRow = naStmt.get(queueName, ...prefixParamValues);\n if (naRow?.next_available_at) {\n const nextAvailable = new Date(naRow.next_available_at + \"Z\").getTime();\n if (nextAvailable > Date.now()) {\n return;\n }\n }\n\n const insertStmt = this.db.prepare(`\n INSERT INTO ${this.executionTableName} (${prefixColumnsInsert}queue_name)\n VALUES (${prefixPlaceholders}?)\n `);\n const info = insertStmt.run(...prefixParamValues, queueName);\n insertedId = info.lastInsertRowid;\n });\n\n txn();\n if (insertedId == null) return null;\n // Coerce bigint to number when it fits — primary key here is a SQLite\n // INTEGER which always fits in JS Number for any practical row count.\n return typeof insertedId === \"bigint\" ? Number(insertedId) : insertedId;\n }\n\n public async releaseExecution(queueName: string, token: unknown): Promise<void> {\n if (token === null || token === undefined) return;\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n // Delete by id — NEVER by recency. Two concurrent acquirers can hold\n // tokens for different rows; deleting \"the most recent\" would release the\n // other worker's slot.\n this.db\n .prepare(\n `DELETE FROM ${this.executionTableName} WHERE id = ? AND queue_name = ?${prefixConditions}`\n )\n .run(token as number, queueName, ...prefixParams);\n }\n\n public async recordExecution(queueName: string): Promise<void> {\n const prefixColumnNames = this.getPrefixColumnNames();\n const prefixColumnsInsert =\n prefixColumnNames.length > 0 ? prefixColumnNames.join(\", \") + \", \" : \"\";\n const prefixPlaceholders =\n prefixColumnNames.length > 0 ? prefixColumnNames.map(() => \"?\").join(\", \") + \", \" : \"\";\n const prefixParamValues = this.getPrefixParamValues();\n\n const stmt = this.db.prepare(`\n INSERT INTO ${this.executionTableName} (${prefixColumnsInsert}queue_name)\n VALUES (${prefixPlaceholders}?)\n `);\n stmt.run(...prefixParamValues, queueName);\n }\n\n public async getExecutionCount(queueName: string, windowStartTime: string): Promise<number> {\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n const thresholdTime = toSQLiteTimestamp(new Date(windowStartTime));\n\n const stmt = this.db.prepare<unknown[], { count: number }>(`\n SELECT COUNT(*) AS count\n FROM ${this.executionTableName}\n WHERE queue_name = ? AND executed_at > ?${prefixConditions}\n `);\n const result = stmt.get(queueName, thresholdTime!, ...prefixParams);\n return result?.count ?? 0;\n }\n\n public async getOldestExecutionAtOffset(\n queueName: string,\n offset: number\n ): Promise<string | undefined> {\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n const stmt = this.db.prepare<unknown[], { executed_at: string }>(`\n SELECT executed_at\n FROM ${this.executionTableName}\n WHERE queue_name = ?${prefixConditions}\n ORDER BY executed_at ASC\n LIMIT 1 OFFSET ?\n `);\n const result = stmt.get(queueName, ...prefixParams, offset);\n if (!result) return undefined;\n // SQLite stores times without timezone, add Z for UTC\n return result.executed_at + \"Z\";\n }\n\n public async getNextAvailableTime(queueName: string): Promise<string | undefined> {\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n const stmt = this.db.prepare<unknown[], { next_available_at: string }>(`\n SELECT next_available_at\n FROM ${this.nextAvailableTableName}\n WHERE queue_name = ?${prefixConditions}\n `);\n const result = stmt.get(queueName, ...prefixParams);\n if (!result?.next_available_at) return undefined;\n // SQLite stores times without timezone, add Z for UTC\n return result.next_available_at + \"Z\";\n }\n\n public async setNextAvailableTime(queueName: string, nextAvailableAt: string): Promise<void> {\n const prefixColumnNames = this.getPrefixColumnNames();\n const prefixColumnsInsert =\n prefixColumnNames.length > 0 ? prefixColumnNames.join(\", \") + \", \" : \"\";\n const prefixPlaceholders =\n prefixColumnNames.length > 0 ? prefixColumnNames.map(() => \"?\").join(\", \") + \", \" : \"\";\n const prefixParamValues = this.getPrefixParamValues();\n\n const stmt = this.db.prepare(`\n INSERT INTO ${this.nextAvailableTableName} (${prefixColumnsInsert}queue_name, next_available_at)\n VALUES (${prefixPlaceholders}?, ?)\n ON CONFLICT(queue_name) DO UPDATE SET next_available_at = excluded.next_available_at\n `);\n stmt.run(...prefixParamValues, queueName, nextAvailableAt);\n }\n\n public async clear(queueName: string): Promise<void> {\n const prefixConditions = this.buildPrefixWhereClause();\n const prefixParams = this.getPrefixParamValues();\n\n this.db\n .prepare(`DELETE FROM ${this.executionTableName} WHERE queue_name = ?${prefixConditions}`)\n .run(queueName, ...prefixParams);\n this.db\n .prepare(`DELETE FROM ${this.nextAvailableTableName} WHERE queue_name = ?${prefixConditions}`)\n .run(queueName, ...prefixParams);\n }\n}\n",
|
|
48
|
+
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { SupabaseClient } from \"@supabase/supabase-js\";\nimport { createServiceToken } from \"@workglow/util\";\nimport type { PrefixColumn } from \"../queue/IQueueStorage\";\nimport {\n IRateLimiterStorage,\n RateLimiterStorageOptions,\n RateLimiterStorageScope,\n} from \"./IRateLimiterStorage\";\n\nexport const SUPABASE_RATE_LIMITER_STORAGE = createServiceToken<IRateLimiterStorage>(\n \"ratelimiter.storage.supabase\"\n);\n\n/**\n * Supabase implementation of rate limiter storage.\n * Manages execution records and next available times for rate limiting.\n */\nexport class SupabaseRateLimiterStorage implements IRateLimiterStorage {\n public readonly scope: RateLimiterStorageScope = \"cluster\";\n protected readonly client: SupabaseClient;\n protected readonly prefixes: readonly PrefixColumn[];\n protected readonly prefixValues: Readonly<Record<string, string | number>>;\n protected readonly executionTableName: string;\n protected readonly nextAvailableTableName: string;\n\n constructor(client: unknown, options?: RateLimiterStorageOptions) {\n this.client = client as SupabaseClient;\n this.prefixes = options?.prefixes ?? [];\n this.prefixValues = options?.prefixValues ?? {};\n\n // Generate table names based on prefix configuration\n if (this.prefixes.length > 0) {\n const prefixNames = this.prefixes.map((p) => p.name).join(\"_\");\n this.executionTableName = `rate_limit_executions_${prefixNames}`;\n this.nextAvailableTableName = `rate_limit_next_available_${prefixNames}`;\n } else {\n this.executionTableName = \"rate_limit_executions\";\n this.nextAvailableTableName = \"rate_limit_next_available\";\n }\n }\n\n /**\n * Gets the SQL column type for a prefix column (Supabase supports UUID natively).\n */\n private getPrefixColumnType(type: PrefixColumn[\"type\"]): string {\n return type === \"uuid\" ? \"UUID\" : \"INTEGER\";\n }\n\n /**\n * Builds the prefix columns SQL for CREATE TABLE.\n */\n private buildPrefixColumnsSql(): string {\n if (this.prefixes.length === 0) return \"\";\n return (\n this.prefixes\n .map((p) => `${p.name} ${this.getPrefixColumnType(p.type)} NOT NULL`)\n .join(\",\\n \") + \",\\n \"\n );\n }\n\n /**\n * Builds prefix column names for use in queries.\n */\n private getPrefixColumnNames(): string[] {\n return this.prefixes.map((p) => p.name);\n }\n\n /**\n * Applies prefix filters to a Supabase query builder.\n */\n private applyPrefixFilters<T>(query: T): T {\n let result = query as any;\n for (const prefix of this.prefixes) {\n result = result.eq(prefix.name, this.prefixValues[prefix.name]);\n }\n return result as T;\n }\n\n /**\n * Gets prefix values as an object for inserts.\n */\n private getPrefixInsertValues(): Record<string, string | number> {\n const values: Record<string, string | number> = {};\n for (const prefix of this.prefixes) {\n values[prefix.name] = this.prefixValues[prefix.name];\n }\n return values;\n }\n\n public async setupDatabase(): Promise<void> {\n const prefixColumnsSql = this.buildPrefixColumnsSql();\n const prefixColumnNames = this.getPrefixColumnNames();\n const prefixIndexPrefix =\n prefixColumnNames.length > 0 ? prefixColumnNames.join(\", \") + \", \" : \"\";\n const indexSuffix = prefixColumnNames.length > 0 ? \"_\" + prefixColumnNames.join(\"_\") : \"\";\n\n // Create execution tracking table\n const createExecTableSql = `\n CREATE TABLE IF NOT EXISTS ${this.executionTableName} (\n id SERIAL PRIMARY KEY,\n ${prefixColumnsSql}queue_name TEXT NOT NULL,\n executed_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()\n )\n `;\n\n const { error: execTableError } = await this.client.rpc(\"exec_sql\", {\n query: createExecTableSql,\n });\n if (execTableError && execTableError.code !== \"42P07\") {\n throw execTableError;\n }\n\n // Create index on execution table\n const createExecIndexSql = `\n CREATE INDEX IF NOT EXISTS rate_limit_exec_queue${indexSuffix}_idx \n ON ${this.executionTableName} (${prefixIndexPrefix}queue_name, executed_at)\n `;\n await this.client.rpc(\"exec_sql\", { query: createExecIndexSql });\n\n // Build primary key columns\n const primaryKeyColumns =\n prefixColumnNames.length > 0 ? `${prefixColumnNames.join(\", \")}, queue_name` : \"queue_name\";\n\n // Create next available table\n const createNextTableSql = `\n CREATE TABLE IF NOT EXISTS ${this.nextAvailableTableName} (\n ${prefixColumnsSql}queue_name TEXT NOT NULL,\n next_available_at TIMESTAMP WITH TIME ZONE,\n PRIMARY KEY (${primaryKeyColumns})\n )\n `;\n\n const { error: nextTableError } = await this.client.rpc(\"exec_sql\", {\n query: createNextTableSql,\n });\n if (nextTableError && nextTableError.code !== \"42P07\") {\n throw nextTableError;\n }\n\n // Install the atomic reserve function. The function takes the queue name,\n // window-start cutoff, and max executions; returns true iff a row was\n // inserted. Advisory xact lock keyed on (table, prefixes, queue) ensures\n // concurrent acquirers serialize without contending on unrelated buckets.\n const fnName = this.atomicReserveFunctionName();\n const prefixSig = this.prefixes\n .map((p) => `${p.name} ${this.getPrefixColumnType(p.type)}`)\n .join(\", \");\n const prefixSigPrefix = prefixSig ? prefixSig + \", \" : \"\";\n const prefixWhere =\n this.prefixes.length > 0\n ? \" AND \" + this.prefixes.map((p) => `${p.name} = _${p.name}`).join(\" AND \")\n : \"\";\n const prefixInsertCols =\n this.prefixes.length > 0 ? this.prefixes.map((p) => p.name).join(\", \") + \", \" : \"\";\n const prefixInsertVals =\n this.prefixes.length > 0 ? this.prefixes.map((p) => `_${p.name}`).join(\", \") + \", \" : \"\";\n const lockKeyParts = [`'${this.executionTableName}'`, ...this.prefixes.map((p) => `_${p.name}::text`), `_queue_name::text`];\n const lockKeyExpr = `hashtextextended(${lockKeyParts.join(\" || '|' || \")}, 0)`;\n\n const createFnSql = `\n CREATE OR REPLACE FUNCTION ${fnName}(\n ${prefixSigPrefix}_queue_name TEXT, _window_start TIMESTAMPTZ, _max_exec INT\n ) RETURNS BIGINT AS $fn$\n DECLARE\n _count INT;\n _next TIMESTAMPTZ;\n _new_id BIGINT;\n BEGIN\n PERFORM pg_advisory_xact_lock(${lockKeyExpr});\n SELECT COUNT(*) INTO _count FROM ${this.executionTableName}\n WHERE queue_name = _queue_name AND executed_at > _window_start${prefixWhere};\n IF _count >= _max_exec THEN RETURN NULL; END IF;\n SELECT next_available_at INTO _next FROM ${this.nextAvailableTableName}\n WHERE queue_name = _queue_name${prefixWhere};\n IF _next IS NOT NULL AND _next > NOW() THEN RETURN NULL; END IF;\n INSERT INTO ${this.executionTableName} (${prefixInsertCols}queue_name)\n VALUES (${prefixInsertVals}_queue_name)\n RETURNING id INTO _new_id;\n RETURN _new_id;\n END;\n $fn$ LANGUAGE plpgsql;\n `;\n const { error: fnError } = await this.client.rpc(\"exec_sql\", { query: createFnSql });\n if (fnError) {\n throw fnError;\n }\n }\n\n /** Stable function name derived from table name (Postgres identifiers ≤63 chars). */\n private atomicReserveFunctionName(): string {\n return `${this.executionTableName}_try_reserve`.slice(0, 63);\n }\n\n public async tryReserveExecution(\n queueName: string,\n maxExecutions: number,\n windowMs: number\n ): Promise<unknown | null> {\n const args: Record<string, unknown> = {\n _queue_name: queueName,\n _window_start: new Date(Date.now() - windowMs).toISOString(),\n _max_exec: maxExecutions,\n };\n for (const p of this.prefixes) {\n args[`_${p.name}`] = this.prefixValues[p.name];\n }\n // The PL/pgSQL function returns the inserted id BIGINT on success and\n // NULL when capacity is reached or external backoff is active.\n const { data, error } = await this.client.rpc(this.atomicReserveFunctionName(), args);\n if (error) throw error;\n // The function now returns the inserted row id BIGINT (or NULL when\n // capacity is reached). Real Supabase RPC returns the scalar directly;\n // the pglite-backed mock executes `SELECT * FROM fn()` and returns a row\n // array — accept both shapes.\n if (data === null || data === undefined) return null;\n if (Array.isArray(data)) {\n if (data.length === 0) return null;\n const first = Object.values(data[0] as Record<string, unknown>)[0];\n return first ?? null;\n }\n // Supabase RPC returns BIGINTs as either numbers or strings depending on\n // size; both are valid as opaque tokens.\n return data;\n }\n\n public async releaseExecution(queueName: string, token: unknown): Promise<void> {\n if (token === null || token === undefined) return;\n // Delete by id — NEVER by recency. Two concurrent acquirers can hold\n // tokens for different rows; deleting \"the most recent\" would release the\n // other worker's slot.\n let del = this.client\n .from(this.executionTableName)\n .delete()\n .eq(\"id\", token as number | string)\n .eq(\"queue_name\", queueName);\n del = this.applyPrefixFilters(del);\n const { error: delError } = await del;\n if (delError) throw delError;\n }\n\n public async recordExecution(queueName: string): Promise<void> {\n const prefixInsertValues = this.getPrefixInsertValues();\n\n const { error } = await this.client.from(this.executionTableName).insert({\n ...prefixInsertValues,\n queue_name: queueName,\n });\n\n if (error) throw error;\n }\n\n public async getExecutionCount(queueName: string, windowStartTime: string): Promise<number> {\n let query = this.client\n .from(this.executionTableName)\n .select(\"*\", { count: \"exact\", head: true })\n .eq(\"queue_name\", queueName)\n .gt(\"executed_at\", windowStartTime);\n\n query = this.applyPrefixFilters(query);\n\n const { count, error } = await query;\n\n if (error) throw error;\n return count ?? 0;\n }\n\n public async getOldestExecutionAtOffset(\n queueName: string,\n offset: number\n ): Promise<string | undefined> {\n let query = this.client\n .from(this.executionTableName)\n .select(\"executed_at\")\n .eq(\"queue_name\", queueName);\n\n query = this.applyPrefixFilters(query);\n\n const { data, error } = await query\n .order(\"executed_at\", { ascending: true })\n .range(offset, offset);\n\n if (error) throw error;\n if (!data || data.length === 0) return undefined;\n return new Date(data[0].executed_at).toISOString();\n }\n\n public async getNextAvailableTime(queueName: string): Promise<string | undefined> {\n let query = this.client\n .from(this.nextAvailableTableName)\n .select(\"next_available_at\")\n .eq(\"queue_name\", queueName);\n\n query = this.applyPrefixFilters(query);\n\n const { data, error } = await query.single();\n\n if (error) {\n if (error.code === \"PGRST116\") return undefined; // Not found\n throw error;\n }\n\n if (!data?.next_available_at) return undefined;\n return new Date(data.next_available_at).toISOString();\n }\n\n public async setNextAvailableTime(queueName: string, nextAvailableAt: string): Promise<void> {\n const prefixInsertValues = this.getPrefixInsertValues();\n\n const { error } = await this.client.from(this.nextAvailableTableName).upsert(\n {\n ...prefixInsertValues,\n queue_name: queueName,\n next_available_at: nextAvailableAt,\n },\n {\n onConflict:\n this.prefixes.length > 0\n ? `${this.getPrefixColumnNames().join(\",\")},queue_name`\n : \"queue_name\",\n }\n );\n\n if (error) throw error;\n }\n\n public async clear(queueName: string): Promise<void> {\n let execQuery = this.client.from(this.executionTableName).delete().eq(\"queue_name\", queueName);\n execQuery = this.applyPrefixFilters(execQuery);\n const { error: execError } = await execQuery;\n if (execError) throw execError;\n\n let nextQuery = this.client\n .from(this.nextAvailableTableName)\n .delete()\n .eq(\"queue_name\", queueName);\n nextQuery = this.applyPrefixFilters(nextQuery);\n const { error: nextError } = await nextQuery;\n if (nextError) throw nextError;\n }\n}\n",
|
|
49
49
|
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Pool } from \"@workglow/storage/postgres\";\nimport type {\n DataPortSchemaObject,\n FromSchema,\n TypedArray,\n TypedArrayConstructor,\n TypedArraySchemaOptions,\n} from \"@workglow/util/schema\";\nimport { cosineSimilarity } from \"@workglow/util/schema\";\nimport { PostgresTabularStorage } from \"../tabular/PostgresTabularStorage\";\nimport { StorageValidationError } from \"../tabular/StorageError\";\nimport type { HybridSearchOptions, IVectorStorage, VectorSearchOptions } from \"./IVectorStorage\";\nimport { getMetadataProperty, getVectorProperty } from \"./IVectorStorage\";\n\n/**\n * PostgreSQL vector repository implementation using pgvector extension.\n * Extends PostgresTabularStorage for storage.\n * Provides efficient vector similarity search with native database support.\n *\n * Requirements:\n * - PostgreSQL database with pgvector extension installed\n * - CREATE EXTENSION vector;\n *\n * @template Metadata - The metadata type\n * @template VectorCtor - Constructor for stored vectors (default {@link typeof Float32Array})\n */\n/**\n * Regex for validating metadata filter keys to prevent SQL injection.\n * Only allows alphanumeric characters and underscores, starting with a letter or underscore.\n */\nconst SAFE_IDENTIFIER_RE = /^[a-zA-Z_][a-zA-Z0-9_]*$/;\n\nexport class PostgresVectorStorage<\n Schema extends DataPortSchemaObject,\n PrimaryKeyNames extends ReadonlyArray<keyof Schema[\"properties\"]>,\n Metadata extends Record<string, unknown> = Record<string, unknown>,\n Entity = FromSchema<Schema, TypedArraySchemaOptions>,\n>\n extends PostgresTabularStorage<Schema, PrimaryKeyNames, Entity>\n implements IVectorStorage<Metadata, Schema, Entity, PrimaryKeyNames>\n{\n private vectorDimensions: number;\n private readonly vectorCtor: TypedArrayConstructor;\n private vectorPropertyName: keyof Entity;\n private metadataPropertyName: keyof Entity | undefined;\n\n /**\n * Creates a new PostgreSQL vector repository\n * @param db - PostgreSQL connection pool\n * @param table - The name of the table to use for storage\n * @param schema - The schema definition for the entity\n * @param primaryKeyNames - Array of property names that form the primary key\n * @param indexes - Array of columns or column arrays to make searchable\n * @param dimensions - The number of dimensions of the vector\n * @param vectorCtor - TypedArray constructor used when hydrating vectors from SQL text (e.g. {@link Float32Array})\n */\n constructor(\n db: Pool,\n table: string,\n schema: Schema,\n primaryKeyNames: PrimaryKeyNames,\n indexes: readonly (keyof NoInfer<Entity> | readonly (keyof NoInfer<Entity>)[])[] = [],\n dimensions: number,\n vectorCtor: TypedArrayConstructor = Float32Array\n ) {\n super(db, table, schema, primaryKeyNames, indexes);\n\n this.vectorDimensions = dimensions;\n this.vectorCtor = vectorCtor;\n\n // Cache vector and metadata property names from schema\n const vectorProp = getVectorProperty(schema);\n if (!vectorProp) {\n throw new Error(\"Schema must have a property with type array and format TypedArray\");\n }\n this.vectorPropertyName = vectorProp as keyof Entity;\n this.metadataPropertyName = getMetadataProperty(schema) as keyof Entity | undefined;\n }\n\n public override getVectorDimensions(): number {\n return this.vectorDimensions;\n }\n\n public async similaritySearch(\n query: TypedArray,\n options: VectorSearchOptions<Metadata> = {}\n ): Promise<Array<Entity & { score: number }>> {\n const { topK = 10, filter, scoreThreshold = 0 } = options;\n\n try {\n // Try native pgvector search first\n const queryVector = `[${Array.from(query).join(\",\")}]`;\n const vectorCol = String(this.vectorPropertyName);\n const metadataCol = this.metadataPropertyName ? String(this.metadataPropertyName) : null;\n\n let sql = `\n SELECT \n *,\n 1 - (${vectorCol} <=> $1::vector) as score\n FROM \"${this.table}\"\n `;\n\n const params: any[] = [queryVector];\n let paramIndex = 2;\n\n if (filter && Object.keys(filter).length > 0 && metadataCol) {\n const conditions: string[] = [];\n for (const [key, value] of Object.entries(filter)) {\n if (!SAFE_IDENTIFIER_RE.test(key)) {\n throw new StorageValidationError(\n `Invalid metadata filter key: \"${key}\". Keys must match /^[a-zA-Z_][a-zA-Z0-9_]*$/.`\n );\n }\n conditions.push(`${metadataCol}->>'${key}' = $${paramIndex}`);\n params.push(String(value));\n paramIndex++;\n }\n sql += ` WHERE ${conditions.join(\" AND \")}`;\n }\n\n if (scoreThreshold > 0) {\n sql += filter ? \" AND\" : \" WHERE\";\n sql += ` (1 - (${vectorCol} <=> $1::vector)) >= $${paramIndex}`;\n params.push(scoreThreshold);\n paramIndex++;\n }\n\n sql += ` ORDER BY ${vectorCol} <=> $1::vector LIMIT $${paramIndex}`;\n params.push(topK);\n\n const result = await this.db.query(sql, params);\n\n // Fetch vectors separately for each result\n const results: Array<Entity & { score: number }> = [];\n for (const row of result.rows) {\n const vectorResult = await this.db.query(\n `SELECT ${vectorCol}::text FROM \"${this.table}\" WHERE ${this.getPrimaryKeyWhereClause()}`,\n this.getPrimaryKeyValues(row)\n );\n const vectorStr = vectorResult.rows[0]?.[vectorCol] || \"[]\";\n const vectorArray = JSON.parse(vectorStr);\n\n results.push({\n ...row,\n [this.vectorPropertyName]: new this.vectorCtor(vectorArray),\n score: parseFloat(row.score),\n } as Entity & { score: number });\n }\n\n return results;\n } catch (error) {\n if (error instanceof StorageValidationError) {\n throw error; // Don't swallow validation errors\n }\n // Fall back to in-memory similarity calculation if pgvector is not available\n console.error(\"pgvector query failed, falling back to in-memory search:\", error);\n return this.searchFallback(query, options);\n }\n }\n\n async hybridSearch(query: TypedArray, options: HybridSearchOptions<Metadata>) {\n const { topK = 10, filter, scoreThreshold = 0, textQuery, vectorWeight = 0.7 } = options;\n\n if (!textQuery || textQuery.trim().length === 0) {\n return this.similaritySearch(query, { topK, filter, scoreThreshold });\n }\n\n try {\n // Try native hybrid search with pgvector + full-text\n const queryVector = `[${Array.from(query).join(\",\")}]`;\n // Use plainto_tsquery via parameterized query to avoid tsquery injection\n const tsQueryText = textQuery;\n const vectorCol = String(this.vectorPropertyName);\n const metadataCol = this.metadataPropertyName ? String(this.metadataPropertyName) : null;\n\n let sql = `\n SELECT \n *,\n (\n $2 * (1 - (${vectorCol} <=> $1::vector)) +\n $3 * ts_rank(to_tsvector('english', ${metadataCol || \"''\"}::text), plainto_tsquery('english', $4))\n ) as score\n FROM \"${this.table}\"\n `;\n\n const params: any[] = [queryVector, vectorWeight, 1 - vectorWeight, tsQueryText];\n let paramIndex = 5;\n\n if (filter && Object.keys(filter).length > 0 && metadataCol) {\n const conditions: string[] = [];\n for (const [key, value] of Object.entries(filter)) {\n if (!SAFE_IDENTIFIER_RE.test(key)) {\n throw new StorageValidationError(\n `Invalid metadata filter key: \"${key}\". Keys must match /^[a-zA-Z_][a-zA-Z0-9_]*$/.`\n );\n }\n conditions.push(`${metadataCol}->>'${key}' = $${paramIndex}`);\n params.push(String(value));\n paramIndex++;\n }\n sql += ` WHERE ${conditions.join(\" AND \")}`;\n }\n\n if (scoreThreshold > 0) {\n sql += filter ? \" AND\" : \" WHERE\";\n sql += ` (\n $2 * (1 - (${vectorCol} <=> $1::vector)) +\n $3 * ts_rank(to_tsvector('english', ${metadataCol || \"''\"}::text), plainto_tsquery('english', $4))\n ) >= $${paramIndex}`;\n params.push(scoreThreshold);\n paramIndex++;\n }\n\n sql += ` ORDER BY score DESC LIMIT $${paramIndex}`;\n params.push(topK);\n\n const result = await this.db.query(sql, params);\n\n // Fetch vectors separately for each result\n const results: Array<Entity & { score: number }> = [];\n for (const row of result.rows) {\n const vectorResult = await this.db.query(\n `SELECT ${vectorCol}::text FROM \"${this.table}\" WHERE ${this.getPrimaryKeyWhereClause()}`,\n this.getPrimaryKeyValues(row)\n );\n const vectorStr = vectorResult.rows[0]?.[vectorCol] || \"[]\";\n const vectorArray = JSON.parse(vectorStr);\n\n results.push({\n ...row,\n [this.vectorPropertyName]: new this.vectorCtor(vectorArray),\n score: parseFloat(row.score),\n } as Entity & { score: number });\n }\n\n return results;\n } catch (error) {\n if (error instanceof StorageValidationError) {\n throw error; // Don't swallow validation errors\n }\n // Fall back to in-memory hybrid search\n console.error(\"pgvector hybrid query failed, falling back to in-memory search:\", error);\n return this.hybridSearchFallback(query, options);\n }\n }\n\n /**\n * Fallback search using in-memory cosine similarity\n */\n private async searchFallback(query: TypedArray, options: VectorSearchOptions<Metadata>) {\n const { topK = 10, filter, scoreThreshold = 0 } = options;\n const allRows = (await this.getAll()) || [];\n const results: Array<Entity & { score: number }> = [];\n\n for (const row of allRows) {\n const vector = row[this.vectorPropertyName] as TypedArray;\n const metadata = this.metadataPropertyName\n ? (row[this.metadataPropertyName] as Metadata)\n : ({} as Metadata);\n\n if (filter && !this.matchesFilter(metadata, filter)) {\n continue;\n }\n\n const score = cosineSimilarity(query, vector);\n\n if (score >= scoreThreshold) {\n results.push({ ...row, score } as Entity & { score: number });\n }\n }\n\n results.sort((a, b) => b.score - a.score);\n const topResults = results.slice(0, topK);\n\n return topResults;\n }\n\n /**\n * Fallback hybrid search\n */\n private async hybridSearchFallback(query: TypedArray, options: HybridSearchOptions<Metadata>) {\n const { topK = 10, filter, scoreThreshold = 0, textQuery, vectorWeight = 0.7 } = options;\n\n const allRows = (await this.getAll()) || [];\n const results: Array<Entity & { score: number }> = [];\n const queryLower = textQuery.toLowerCase();\n const queryWords = queryLower.split(/\\s+/).filter((w) => w.length > 0);\n\n for (const row of allRows) {\n const vector = row[this.vectorPropertyName] as TypedArray;\n const metadata = this.metadataPropertyName\n ? (row[this.metadataPropertyName] as Metadata)\n : ({} as Metadata);\n\n if (filter && !this.matchesFilter(metadata, filter)) {\n continue;\n }\n\n const vectorScore = cosineSimilarity(query, vector);\n const metadataText = Object.values(metadata ?? {})\n .join(\" \")\n .toLowerCase();\n let textScore = 0;\n if (queryWords.length > 0) {\n let matches = 0;\n for (const word of queryWords) {\n if (metadataText.includes(word)) {\n matches++;\n }\n }\n textScore = matches / queryWords.length;\n }\n\n const combinedScore = vectorWeight * vectorScore + (1 - vectorWeight) * textScore;\n\n if (combinedScore >= scoreThreshold) {\n results.push({ ...row, score: combinedScore } as Entity & { score: number });\n }\n }\n\n results.sort((a, b) => b.score - a.score);\n const topResults = results.slice(0, topK);\n\n return topResults;\n }\n\n private getPrimaryKeyWhereClause(): string {\n const conditions = this.primaryKeyNames.map((key, idx) => `${String(key)} = $${idx + 1}`);\n return conditions.join(\" AND \");\n }\n\n private getPrimaryKeyValues(row: any): any[] {\n return this.primaryKeyNames.map((key) => row[key]);\n }\n\n private matchesFilter(metadata: Metadata, filter: Partial<Metadata>): boolean {\n for (const [key, value] of Object.entries(filter)) {\n if (metadata[key as keyof Metadata] !== value) {\n return false;\n }\n }\n return true;\n }\n}\n",
|
|
50
50
|
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { Sqlite } from \"@workglow/storage/sqlite\";\nimport type {\n DataPortSchemaObject,\n FromSchema,\n TypedArray,\n TypedArrayConstructor,\n TypedArraySchemaOptions,\n} from \"@workglow/util/schema\";\nimport { cosineSimilarity } from \"@workglow/util/schema\";\nimport { SqliteTabularStorage } from \"../tabular/SqliteTabularStorage\";\nimport type { HybridSearchOptions, IVectorStorage, VectorSearchOptions } from \"./IVectorStorage\";\nimport { getMetadataProperty, getVectorProperty } from \"./IVectorStorage\";\n\n/**\n * Check if metadata matches filter\n */\nfunction matchesFilter<Metadata>(metadata: Metadata, filter: Partial<Metadata>): boolean {\n for (const [key, value] of Object.entries(filter)) {\n if (metadata[key as keyof Metadata] !== value) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * SQLite vector repository implementation using tabular storage underneath.\n * Stores vectors as JSON-encoded arrays with metadata.\n *\n * @template Schema - The schema for the vector\n * @template PrimaryKeyNames - The primary key names for the vector\n * @template VectorCtor - Constructor for stored vectors (default {@link typeof Float32Array})\n * @template Metadata - The metadata type for the vector\n * @template Entity - The entity type for the vector\n */\nexport class SqliteVectorStorage<\n Schema extends DataPortSchemaObject,\n PrimaryKeyNames extends ReadonlyArray<keyof Schema[\"properties\"]>,\n Metadata extends Record<string, unknown> | undefined = Record<string, unknown>,\n Entity = FromSchema<Schema, TypedArraySchemaOptions>,\n>\n extends SqliteTabularStorage<Schema, PrimaryKeyNames, Entity>\n implements IVectorStorage<Metadata, Schema, Entity, PrimaryKeyNames>\n{\n private vectorDimensions: number;\n private readonly vectorCtor: TypedArrayConstructor;\n private vectorPropertyName: keyof Entity;\n private metadataPropertyName: keyof Entity | undefined;\n\n /**\n * Creates a new SQLite vector repository\n * @param dbOrPath - Either a Database instance or a path to the SQLite database file\n * @param table - The name of the table to use for storage (defaults to 'vectors')\n * @param schema - The schema for the entity\n * @param primaryKeyNames - Array of property names forming the primary key\n * @param indexes - Array of columns to index\n * @param dimensions - The number of dimensions of the vector\n * @param vectorCtor - TypedArray constructor used when deserializing JSON vectors (e.g. {@link Float32Array})\n */\n constructor(\n dbOrPath: string | Sqlite.Database,\n table: string = \"vectors\",\n schema: Schema,\n primaryKeyNames: PrimaryKeyNames,\n indexes: readonly (keyof NoInfer<Entity> | readonly (keyof NoInfer<Entity>)[])[] = [],\n dimensions: number,\n vectorCtor: TypedArrayConstructor = Float32Array\n ) {\n super(dbOrPath, table, schema, primaryKeyNames, indexes);\n\n this.vectorDimensions = dimensions;\n this.vectorCtor = vectorCtor;\n\n // Cache vector and metadata property names from schema\n const vectorProp = getVectorProperty(schema);\n if (!vectorProp) {\n throw new Error(\"Schema must have a property with type array and format TypedArray\");\n }\n this.vectorPropertyName = vectorProp as keyof Entity;\n this.metadataPropertyName = getMetadataProperty(schema) as keyof Entity | undefined;\n }\n\n getVectorDimensions(): number {\n return this.vectorDimensions;\n }\n\n /**\n * Deserialize vector from JSON string\n * Defaults to Float32Array for compatibility with typical embedding vectors\n */\n private deserializeVector(vectorJson: string): TypedArray {\n const array = JSON.parse(vectorJson);\n // Default to Float32Array for typical use case (embeddings)\n return new this.vectorCtor(array);\n }\n\n async similaritySearch(query: TypedArray, options: VectorSearchOptions<Metadata> = {}) {\n const { topK = 10, filter, scoreThreshold = 0 } = options;\n const results: Array<Entity & { score: number }> = [];\n\n const allEntities = (await this.getAll()) || [];\n\n for (const entity of allEntities) {\n // SQLite stores vectors as JSON strings, need to deserialize\n const vectorRaw = entity[this.vectorPropertyName] as unknown as string;\n const vector = this.deserializeVector(vectorRaw);\n const metadata = this.metadataPropertyName\n ? (entity[this.metadataPropertyName] as Metadata)\n : ({} as Metadata);\n\n // Apply filter if provided\n if (filter && !matchesFilter(metadata, filter)) {\n continue;\n }\n\n // Calculate similarity\n const score = cosineSimilarity(query, vector);\n\n // Apply threshold\n if (score < scoreThreshold) {\n continue;\n }\n\n results.push({\n ...entity,\n score,\n } as Entity & { score: number });\n }\n\n // Sort by score descending and take top K\n results.sort((a, b) => b.score - a.score);\n const topResults = results.slice(0, topK);\n\n return topResults;\n }\n\n async hybridSearch(query: TypedArray, options: HybridSearchOptions<Metadata>) {\n const { topK = 10, filter, scoreThreshold = 0, textQuery, vectorWeight = 0.7 } = options;\n\n if (!textQuery || textQuery.trim().length === 0) {\n // Fall back to regular vector search if no text query\n return this.similaritySearch(query, { topK, filter, scoreThreshold });\n }\n\n const results: Array<Entity & { score: number }> = [];\n const allEntities = (await this.getAll()) || [];\n const queryLower = textQuery.toLowerCase();\n const queryWords = queryLower.split(/\\s+/).filter((w) => w.length > 0);\n\n for (const entity of allEntities) {\n // SQLite stores vectors as JSON strings, need to deserialize\n const vectorRaw = entity[this.vectorPropertyName] as unknown as string;\n const vector = this.deserializeVector(vectorRaw);\n const metadata = this.metadataPropertyName\n ? (entity[this.metadataPropertyName] as Metadata)\n : ({} as Metadata);\n\n // Apply filter if provided\n if (filter && !matchesFilter(metadata, filter)) {\n continue;\n }\n\n // Calculate vector similarity\n const vectorScore = cosineSimilarity(query, vector);\n\n // Calculate text relevance (simple keyword matching)\n const metadataText = Object.values(metadata ?? {})\n .join(\" \")\n .toLowerCase();\n let textScore = 0;\n if (queryWords.length > 0) {\n let matches = 0;\n for (const word of queryWords) {\n if (metadataText.includes(word)) {\n matches++;\n }\n }\n textScore = matches / queryWords.length;\n }\n\n // Combine scores\n const combinedScore = vectorWeight * vectorScore + (1 - vectorWeight) * textScore;\n\n // Apply threshold\n if (combinedScore < scoreThreshold) {\n continue;\n }\n\n results.push({\n ...entity,\n score: combinedScore,\n } as Entity & { score: number });\n }\n\n // Sort by combined score descending and take top K\n results.sort((a, b) => b.score - a.score);\n const topResults = results.slice(0, topK);\n\n return topResults;\n }\n}\n",
|
|
51
51
|
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { Sqlite } from \"@workglow/storage/sqlite\";\nimport type {\n DataPortSchemaObject,\n FromSchema,\n TypedArray,\n TypedArrayConstructor,\n TypedArraySchemaOptions,\n} from \"@workglow/util/schema\";\nimport { cosineSimilarity } from \"@workglow/util/schema\";\nimport { SqliteTabularStorage } from \"../tabular/SqliteTabularStorage\";\nimport type { HybridSearchOptions, IVectorStorage, VectorSearchOptions } from \"./IVectorStorage\";\nimport { getMetadataProperty, getVectorProperty } from \"./IVectorStorage\";\n\n/**\n * Maps TypedArray constructor types to their sqlite-vector encoding function names\n * and corresponding distance metric types.\n */\nconst VECTOR_TYPE_MAP: Record<string, string> = {\n Float32Array: \"f32\",\n Float64Array: \"f32\", // sqlite-vector doesn't support f64, convert to f32\n Int8Array: \"i8\",\n Uint8Array: \"u8\",\n Int16Array: \"f16\", // approximate mapping\n};\n\n/**\n * Gets the sqlite-vector encoding function suffix for a given TypedArray type\n */\nfunction getVectorTypeSuffix(vectorCtor: TypedArrayConstructor): string {\n return VECTOR_TYPE_MAP[vectorCtor.name] || \"f32\";\n}\n\n/**\n * Gets the sqlite-vector type string for vector_init options\n */\nfunction getVectorTypeOption(vectorCtor: TypedArrayConstructor): string {\n const typeMap: Record<string, string> = {\n Float32Array: \"FLOAT32\",\n Float64Array: \"FLOAT32\",\n Int8Array: \"INT8\",\n Uint8Array: \"UINT8\",\n Int16Array: \"FLOAT16\",\n };\n return typeMap[vectorCtor.name] || \"FLOAT32\";\n}\n\n/**\n * Check if metadata matches filter\n */\nfunction matchesFilter<Metadata>(metadata: Metadata, filter: Partial<Metadata>): boolean {\n for (const [key, value] of Object.entries(filter)) {\n if (metadata[key as keyof Metadata] !== value) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Escape a SQL identifier (table/column name) by doubling any backtick characters,\n * then wrapping in backticks. This prevents SQL injection via identifier names.\n */\nfunction escapeIdentifier(name: string): string {\n return \"`\" + name.replace(/`/g, \"``\") + \"`\";\n}\n\n/**\n * SQLite vector storage implementation using the @sqliteai/sqlite-vector extension.\n * Provides native vector similarity search via SQLite virtual table functions\n * instead of in-memory brute-force search.\n *\n * Requirements:\n * - @sqliteai/sqlite-vector package installed\n * - Extension loaded via db.loadExtension(getExtensionPath())\n *\n * Vectors are stored as BLOBs using sqlite-vector encoding functions (vector_as_f32, etc.)\n * and searched using vector_full_scan for efficient KNN queries.\n *\n * @template Schema - The schema for the vector storage\n * @template PrimaryKeyNames - The primary key names\n * @template VectorCtor - Constructor for stored vectors (default {@link typeof Float32Array})\n * @template Metadata - The metadata type\n */\nexport class SqliteAiVectorStorage<\n Schema extends DataPortSchemaObject,\n PrimaryKeyNames extends ReadonlyArray<keyof Schema[\"properties\"]>,\n Metadata extends Record<string, unknown> | undefined = Record<string, unknown>,\n Entity = FromSchema<Schema, TypedArraySchemaOptions>,\n>\n extends SqliteTabularStorage<Schema, PrimaryKeyNames, Entity>\n implements IVectorStorage<Metadata, Schema, Entity, PrimaryKeyNames>\n{\n private vectorDimensions: number;\n private readonly vectorCtor: TypedArrayConstructor;\n private vectorPropertyName: keyof Entity;\n private metadataPropertyName: keyof Entity | undefined;\n private vectorTypeSuffix: string;\n private extensionLoaded: boolean = false;\n\n /**\n * Creates a new SQLite AI vector storage\n * @param dbOrPath - Either a Database instance or a path to the SQLite database file\n * @param table - The name of the table to use for storage\n * @param schema - The schema for the entity\n * @param primaryKeyNames - Array of property names forming the primary key\n * @param indexes - Array of columns to index\n * @param dimensions - The number of dimensions of the vector\n * @param vectorCtor - TypedArray constructor for stored vectors (e.g. {@link Float32Array})\n */\n constructor(\n dbOrPath: string | Sqlite.Database,\n table: string = \"vectors\",\n schema: Schema,\n primaryKeyNames: PrimaryKeyNames,\n indexes: readonly (keyof NoInfer<Entity> | readonly (keyof NoInfer<Entity>)[])[] = [],\n dimensions: number,\n vectorCtor: TypedArrayConstructor = Float32Array\n ) {\n super(dbOrPath, table, schema, primaryKeyNames, indexes);\n\n this.vectorDimensions = dimensions;\n this.vectorCtor = vectorCtor;\n this.vectorTypeSuffix = getVectorTypeSuffix(vectorCtor);\n\n // Cache vector and metadata property names from schema\n const vectorProp = getVectorProperty(schema);\n if (!vectorProp) {\n throw new Error(\"Schema must have a property with type array and format TypedArray\");\n }\n this.vectorPropertyName = vectorProp as keyof Entity;\n this.metadataPropertyName = getMetadataProperty(schema) as keyof Entity | undefined;\n }\n\n getVectorDimensions(): number {\n return this.vectorDimensions;\n }\n\n /**\n * Load the sqlite-vector extension and initialize vector indexing on the vector column.\n * Extension loading is best-effort: if unavailable, operations fall back to in-memory search.\n */\n public override async setupDatabase(): Promise<void> {\n // Always create the table first via the parent class\n await super.setupDatabase();\n\n // Try to load the sqlite-vector extension if not already loaded\n if (!this.extensionLoaded) {\n try {\n // Try to load the extension - the caller may have already loaded it\n const { getExtensionPath } = await import(\"@sqliteai/sqlite-vector\");\n this.database.loadExtension(getExtensionPath());\n this.extensionLoaded = true;\n } catch {\n // Extension might already be loaded by the caller; verify with vector_version()\n try {\n this.database.exec(\"SELECT vector_version()\");\n this.extensionLoaded = true;\n } catch {\n // Extension is unavailable; operations will fall back to in-memory search\n }\n }\n }\n\n // Initialize the vector column for sqlite-vector indexing (only if extension is available)\n if (this.extensionLoaded) {\n const vectorCol = String(this.vectorPropertyName);\n const vectorType = getVectorTypeOption(this.vectorCtor);\n try {\n this.database\n .prepare(\"SELECT vector_init(?, ?, ?)\")\n .run(\n this.table,\n vectorCol,\n `dimension=${this.vectorDimensions},type=${vectorType},distance=COSINE`\n );\n } catch {\n // vector_init may fail if already initialized, that's OK\n }\n }\n }\n\n /**\n * Encode a vector as a BLOB using sqlite-vector functions.\n * Returns a JSON string representation suitable for vector_as_f32() etc.\n */\n private encodeVectorJson(vector: TypedArray): string {\n return `[${Array.from(vector).join(\",\")}]`;\n }\n\n /**\n * Decode a vector BLOB from SQLite back to a TypedArray.\n * sqlite-vector stores vectors as BLOBs, but when we SELECT them\n * they come back as Buffer/Uint8Array. We also handle JSON string fallback.\n */\n private decodeVector(raw: unknown): TypedArray {\n if (raw instanceof Uint8Array || (typeof Buffer !== \"undefined\" && raw instanceof Buffer)) {\n // Normalize to a Uint8Array view so we respect byteOffset/byteLength for Buffer as well.\n const view =\n raw instanceof Uint8Array\n ? raw\n : new Uint8Array(\n (raw as Buffer).buffer,\n (raw as Buffer).byteOffset,\n (raw as Buffer).byteLength\n );\n\n if (this.vectorCtor.name === \"Float32Array\" || this.vectorCtor === Float32Array) {\n return new Float32Array(view.buffer, view.byteOffset, this.vectorDimensions) as TypedArray;\n }\n // For other types, read as float32 and convert\n const f32 = new Float32Array(view.buffer, view.byteOffset, this.vectorDimensions);\n return new this.vectorCtor(Array.from(f32));\n }\n if (typeof raw === \"string\") {\n // JSON string fallback\n const array = JSON.parse(raw);\n return new this.vectorCtor(array);\n }\n if (Array.isArray(raw)) {\n return new this.vectorCtor(raw);\n }\n throw new Error(`Cannot decode vector from type: ${typeof raw}`);\n }\n\n /**\n * Override jsToSqlValue to encode vectors as BLOBs via sqlite-vector functions\n */\n protected override jsToSqlValue(\n column: string,\n value: Entity[keyof Entity]\n ): ReturnType<SqliteTabularStorage<Schema, PrimaryKeyNames, Entity>[\"jsToSqlValue\"]> {\n if (column === String(this.vectorPropertyName) && value != null) {\n // For vector columns, encode as JSON string for sqlite-vector\n const vector = value as unknown as TypedArray;\n return this.encodeVectorJson(vector) as any;\n }\n return super.jsToSqlValue(column, value);\n }\n\n /**\n * Override sqlToJsValue to decode vector BLOBs back to TypedArrays\n */\n protected override sqlToJsValue(column: string, value: any): Entity[keyof Entity] {\n if (column === String(this.vectorPropertyName) && value != null) {\n return this.decodeVector(value) as Entity[keyof Entity];\n }\n return super.sqlToJsValue(column, value);\n }\n\n /**\n * Override mapTypeToSQL to use BLOB for vector columns instead of TEXT\n */\n protected override mapTypeToSQL(typeDef: any): string {\n if (typeof typeDef !== \"boolean\" && typeDef.type === \"array\") {\n const format = typeDef.format as string | undefined;\n if (format === \"TypedArray\" || format?.startsWith(\"TypedArray:\")) {\n return \"BLOB\";\n }\n }\n return super.mapTypeToSQL(typeDef);\n }\n\n /**\n * Override put to use sqlite-vector encoding for vector data.\n * Builds a custom INSERT OR REPLACE that wraps the vector column\n * with vector_as_fXX() to encode as a native vector BLOB.\n * Falls back to base class put() if the extension is not available.\n */\n public override async put(entity: any): Promise<Entity> {\n if (!this.extensionLoaded) {\n return super.put(entity);\n }\n\n const db = this.database;\n const vectorCol = String(this.vectorPropertyName);\n\n // Handle auto-generated keys (UUID generation)\n let entityToInsert = entity;\n if (this.hasAutoGeneratedKey() && this.autoGeneratedKeyName) {\n const keyName = String(this.autoGeneratedKeyName);\n const clientProvidedValue = (entity as Record<string, unknown>)[keyName];\n const hasClientValue = clientProvidedValue !== undefined && clientProvidedValue !== null;\n const clientProvidedKeys = this.clientProvidedKeys;\n const autoGeneratedKeyStrategy = this.autoGeneratedKeyStrategy;\n\n if (\n autoGeneratedKeyStrategy === \"uuid\" &&\n !hasClientValue &&\n clientProvidedKeys !== \"always\"\n ) {\n const generatedValue = this.generateKeyValue(keyName, \"uuid\");\n entityToInsert = { ...entity, [keyName]: generatedValue };\n }\n }\n\n // Build column lists and values\n const allColumns: string[] = [];\n const placeholders: string[] = [];\n const params: any[] = [];\n\n // Primary key columns\n const pkColumns = this.primaryKeyColumns() as string[];\n for (const col of pkColumns) {\n const autoGeneratedKeyStrategy = this.autoGeneratedKeyStrategy;\n const isAutoKey = this.isAutoGeneratedKey(col);\n if (isAutoKey && autoGeneratedKeyStrategy === \"autoincrement\") {\n const clientProvidedKeys = this.clientProvidedKeys;\n const clientValue = (entityToInsert as Record<string, unknown>)[col];\n if (clientProvidedKeys === \"if-missing\" && clientValue != null) {\n allColumns.push(col);\n placeholders.push(\"?\");\n params.push((this as any).jsToSqlValue(col, clientValue));\n }\n continue;\n }\n allColumns.push(col);\n placeholders.push(\"?\");\n params.push(this.jsToSqlValue(col, (entityToInsert as Record<string, unknown>)[col] as any));\n }\n\n // Value columns\n const valueColumns = this.valueColumns() as string[];\n for (const col of valueColumns) {\n allColumns.push(col);\n const value = (entityToInsert as Record<string, unknown>)[col];\n\n if (col === vectorCol && value != null) {\n // Use vector_as_fXX() for the vector column\n placeholders.push(`vector_as_${this.vectorTypeSuffix}(?)`);\n params.push(this.encodeVectorJson(value as TypedArray));\n } else {\n placeholders.push(\"?\");\n params.push(this.jsToSqlValue(col, value as any));\n }\n }\n\n const columnList = allColumns.map((c) => `\\`${c}\\``).join(\", \");\n const placeholderList = placeholders.join(\", \");\n\n const sql = `\n INSERT OR REPLACE INTO ${escapeIdentifier(this.table)} (${columnList})\n VALUES (${placeholderList})\n RETURNING *\n `;\n\n // Ensure all params are SQLite-compatible\n for (let i = 0; i < params.length; i++) {\n if (params[i] === undefined) {\n params[i] = null;\n } else if (params[i] !== null && typeof params[i] === \"object\") {\n const p = params[i];\n if (\n !(p instanceof Uint8Array) &&\n (typeof Buffer === \"undefined\" || !(p instanceof Buffer))\n ) {\n params[i] = JSON.stringify(p);\n }\n }\n }\n\n const stmt = db.prepare(sql);\n // @ts-ignore - SQLite typing for variadic bindings\n const updatedEntity = stmt.get(...params) as Entity;\n\n // Convert all columns according to schema\n const updatedRecord = updatedEntity as Record<string, unknown>;\n for (const k in this.schema.properties) {\n updatedRecord[k] = this.sqlToJsValue(k, updatedRecord[k] as any);\n }\n\n this.events.emit(\"put\", updatedEntity);\n return updatedEntity;\n }\n\n /**\n * Perform similarity search using sqlite-vector's vector_full_scan.\n * Uses native COSINE distance computation in SQLite rather than in-memory JS.\n * Falls back to in-memory search if the extension is unavailable.\n */\n async similaritySearch(query: TypedArray, options: VectorSearchOptions<Metadata> = {}) {\n if (!this.extensionLoaded) {\n return this.searchFallback(query, options);\n }\n\n const { topK = 10, filter, scoreThreshold = 0 } = options;\n const db = this.database;\n const tableName = this.table;\n const vectorCol = String(this.vectorPropertyName);\n const metadataCol = this.metadataPropertyName ? String(this.metadataPropertyName) : null;\n\n try {\n const queryJson = this.encodeVectorJson(query);\n const queryBlob = db\n .prepare(`SELECT vector_as_${this.vectorTypeSuffix}(?) as v`)\n .get(queryJson) as { v: Buffer };\n\n if (filter && Object.keys(filter).length > 0) {\n // When filtering, use streaming mode (no k parameter) so we can filter rows\n const sql = `\n SELECT t.*, v.distance\n FROM ${escapeIdentifier(tableName)} AS t\n JOIN vector_full_scan(?, ?, ?) AS v\n ON t.rowid = v.rowid\n ORDER BY v.distance ASC\n `;\n const stmt = db.prepare(sql);\n const rows = stmt.all(tableName, vectorCol, queryBlob.v) as Array<\n Record<string, unknown> & { distance: number }\n >;\n\n const results: Array<Entity & { score: number }> = [];\n for (const row of rows) {\n // Convert distance to similarity score (cosine distance to cosine similarity)\n const score = 1 - row.distance;\n\n if (score < scoreThreshold) {\n continue;\n }\n\n // Convert SQL values to JS\n const entity = { ...row } as Record<string, unknown>;\n delete entity.distance;\n for (const k in this.schema.properties) {\n entity[k] = this.sqlToJsValue(k, entity[k] as any);\n }\n\n // Apply metadata filter (use empty object if no metadata column)\n const metadata = metadataCol ? (entity[metadataCol] as Metadata) : ({} as Metadata);\n if (filter && !matchesFilter(metadata, filter)) {\n continue;\n }\n\n results.push({ ...entity, score } as Entity & { score: number });\n\n if (results.length >= topK) {\n break;\n }\n }\n\n results.sort((a, b) => b.score - a.score);\n return results.slice(0, topK);\n }\n\n // No filter - use top-k mode for efficiency\n const sql = `\n SELECT t.*, v.distance\n FROM ${escapeIdentifier(tableName)} AS t\n JOIN vector_full_scan(?, ?, ?, ?) AS v\n ON t.rowid = v.rowid\n ORDER BY v.distance ASC\n `;\n const stmt = db.prepare(sql);\n const rows = stmt.all(tableName, vectorCol, queryBlob.v, topK) as Array<\n Record<string, unknown> & { distance: number }\n >;\n\n const results: Array<Entity & { score: number }> = [];\n for (const row of rows) {\n const score = 1 - row.distance;\n\n if (score < scoreThreshold) {\n continue;\n }\n\n const entity = { ...row } as Record<string, unknown>;\n delete entity.distance;\n for (const k in this.schema.properties) {\n entity[k] = this.sqlToJsValue(k, entity[k] as any);\n }\n\n results.push({ ...entity, score } as Entity & { score: number });\n }\n\n return results;\n } catch (error) {\n // Fall back to in-memory similarity calculation if sqlite-vector fails\n console.warn(\"sqlite-vector query failed, falling back to in-memory search:\", error);\n return this.searchFallback(query, options);\n }\n }\n\n /**\n * Hybrid search combining vector similarity with text relevance.\n * Uses sqlite-vector for the vector component and keyword matching for text.\n * Falls back to in-memory search if the extension is unavailable.\n */\n async hybridSearch(query: TypedArray, options: HybridSearchOptions<Metadata>) {\n const { topK = 10, filter, scoreThreshold = 0, textQuery, vectorWeight = 0.7 } = options;\n\n if (!textQuery || textQuery.trim().length === 0) {\n return this.similaritySearch(query, { topK, filter, scoreThreshold });\n }\n\n if (!this.extensionLoaded) {\n return this.hybridSearchFallback(query, options);\n }\n\n const db = this.database;\n const tableName = this.table;\n const vectorCol = String(this.vectorPropertyName);\n const metadataCol = this.metadataPropertyName ? String(this.metadataPropertyName) : null;\n\n try {\n const queryJson = this.encodeVectorJson(query);\n const queryBlob = db\n .prepare(`SELECT vector_as_${this.vectorTypeSuffix}(?) as v`)\n .get(queryJson) as { v: Buffer };\n\n // Use streaming mode for hybrid search to allow text scoring on all results\n const sql = `\n SELECT t.*, v.distance\n FROM ${escapeIdentifier(tableName)} AS t\n JOIN vector_full_scan(?, ?, ?) AS v\n ON t.rowid = v.rowid\n ORDER BY v.distance ASC\n `;\n const stmt = db.prepare(sql);\n const rows = stmt.all(tableName, vectorCol, queryBlob.v) as Array<\n Record<string, unknown> & { distance: number }\n >;\n\n const queryLower = textQuery.toLowerCase();\n const queryWords = queryLower.split(/\\s+/).filter((w) => w.length > 0);\n const results: Array<Entity & { score: number }> = [];\n\n for (const row of rows) {\n const vectorScore = 1 - row.distance;\n\n const entity = { ...row } as Record<string, unknown>;\n delete entity.distance;\n for (const k in this.schema.properties) {\n entity[k] = this.sqlToJsValue(k, entity[k] as any);\n }\n\n const metadata = metadataCol ? (entity[metadataCol] as Metadata) : ({} as Metadata);\n\n // Apply metadata filter\n if (filter && !matchesFilter(metadata, filter)) {\n continue;\n }\n\n // Calculate text relevance\n const metadataText = Object.values(metadata ?? {})\n .join(\" \")\n .toLowerCase();\n let textScore = 0;\n if (queryWords.length > 0) {\n let matches = 0;\n for (const word of queryWords) {\n if (metadataText.includes(word)) {\n matches++;\n }\n }\n textScore = matches / queryWords.length;\n }\n\n const combinedScore = vectorWeight * vectorScore + (1 - vectorWeight) * textScore;\n\n if (combinedScore < scoreThreshold) {\n continue;\n }\n\n results.push({ ...entity, score: combinedScore } as Entity & { score: number });\n }\n\n results.sort((a, b) => b.score - a.score);\n return results.slice(0, topK);\n } catch (error) {\n console.warn(\"sqlite-vector hybrid query failed, falling back to in-memory search:\", error);\n return this.hybridSearchFallback(query, options);\n }\n }\n\n /**\n * Fallback search using in-memory cosine similarity\n */\n private async searchFallback(query: TypedArray, options: VectorSearchOptions<Metadata>) {\n const { topK = 10, filter, scoreThreshold = 0 } = options;\n const allRows = (await this.getAll()) || [];\n const results: Array<Entity & { score: number }> = [];\n\n for (const row of allRows) {\n const vector = row[this.vectorPropertyName] as TypedArray;\n const metadata = this.metadataPropertyName\n ? (row[this.metadataPropertyName] as Metadata)\n : ({} as Metadata);\n\n if (filter && !matchesFilter(metadata, filter)) {\n continue;\n }\n\n const score = cosineSimilarity(query, vector);\n\n if (score >= scoreThreshold) {\n results.push({ ...row, score } as Entity & { score: number });\n }\n }\n\n results.sort((a, b) => b.score - a.score);\n return results.slice(0, topK);\n }\n\n /**\n * Fallback hybrid search using in-memory computation\n */\n private async hybridSearchFallback(query: TypedArray, options: HybridSearchOptions<Metadata>) {\n const { topK = 10, filter, scoreThreshold = 0, textQuery, vectorWeight = 0.7 } = options;\n\n const allRows = (await this.getAll()) || [];\n const results: Array<Entity & { score: number }> = [];\n const queryLower = textQuery.toLowerCase();\n const queryWords = queryLower.split(/\\s+/).filter((w) => w.length > 0);\n\n for (const row of allRows) {\n const vector = row[this.vectorPropertyName] as TypedArray;\n const metadata = this.metadataPropertyName\n ? (row[this.metadataPropertyName] as Metadata)\n : ({} as Metadata);\n\n if (filter && !matchesFilter(metadata, filter)) {\n continue;\n }\n\n const vectorScore = cosineSimilarity(query, vector);\n const metadataText = Object.values(metadata ?? {})\n .join(\" \")\n .toLowerCase();\n let textScore = 0;\n if (queryWords.length > 0) {\n let matches = 0;\n for (const word of queryWords) {\n if (metadataText.includes(word)) {\n matches++;\n }\n }\n textScore = matches / queryWords.length;\n }\n\n const combinedScore = vectorWeight * vectorScore + (1 - vectorWeight) * textScore;\n\n if (combinedScore >= scoreThreshold) {\n results.push({ ...row, score: combinedScore } as Entity & { score: number });\n }\n }\n\n results.sort((a, b) => b.score - a.score);\n return results.slice(0, topK);\n }\n}\n",
|
|
52
52
|
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { JsonSchema } from \"@workglow/util/schema\";\nimport { createServiceToken } from \"@workglow/util\";\nimport { IndexedDbTabularStorage } from \"../tabular/IndexedDbTabularStorage\";\nimport { DefaultKeyValueKey, DefaultKeyValueSchema, IKvStorage } from \"./IKvStorage\";\nimport { KvViaTabularStorage } from \"./KvViaTabularStorage\";\n\nexport const IDB_KV_REPOSITORY = createServiceToken<IKvStorage<string, any, any>>(\n \"storage.kvRepository.indexedDb\"\n);\n\n/**\n * A key-value repository implementation that uses IndexedDB for persistent storage in the browser.\n * Leverages a tabular repository abstraction for IndexedDB operations.\n *\n * @template Key - The type of the primary key\n * @template Value - The type of the value being stored\n * @template Combined - Combined type of Key & Value\n */\nexport class IndexedDbKvStorage extends KvViaTabularStorage {\n public tabularRepository: IndexedDbTabularStorage<\n typeof DefaultKeyValueSchema,\n typeof DefaultKeyValueKey\n >;\n\n /**\n * Creates a new KvStorage instance\n */\n constructor(\n public dbName: string,\n keySchema: JsonSchema = { type: \"string\" },\n valueSchema: JsonSchema = {}\n ) {\n super(keySchema, valueSchema);\n this.tabularRepository = new IndexedDbTabularStorage(\n dbName,\n DefaultKeyValueSchema,\n DefaultKeyValueKey\n );\n }\n}\n",
|
|
53
|
-
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { createServiceToken, deepEqual, makeFingerprint, uuid4 } from \"@workglow/util\";\nimport { DataPortSchemaObject, FromSchema, TypedArraySchemaOptions } from \"@workglow/util/schema\";\nimport { HybridSubscriptionManager } from \"../util/HybridSubscriptionManager\";\nimport {\n ensureIndexedDbTable,\n ExpectedIndexDefinition,\n MigrationOptions,\n} from \"../util/IndexedDbTable\";\nimport {\n BaseTabularStorage,\n ClientProvidedKeysOption,\n KeyGenerationStrategy,\n} from \"./BaseTabularStorage\";\nimport {\n AnyTabularStorage,\n AutoGeneratedKeys,\n CoveringIndexQueryOptions,\n DeleteSearchCriteria,\n InsertEntity,\n isSearchCondition,\n QueryOptions,\n SearchCriteria,\n SearchOperator,\n SimplifyPrimaryKey,\n TabularChangePayload,\n TabularSubscribeOptions,\n} from \"./ITabularStorage\";\nimport { pickCoveringIndex } from \"./coveringIndexPicker\";\n\nexport const IDB_TABULAR_REPOSITORY = createServiceToken<AnyTabularStorage>(\n \"storage.tabularRepository.indexedDb\"\n);\n\n/**\n * Polling change-detection comparator for the hybrid subscription manager.\n *\n * Naively comparing entities via serialized equality is correct but\n * O(size-of-entity) per poll. That falls apart for tables\n * holding large blobs — e.g. an `activities` row whose `output_data` carries\n * a multi-megabyte `Uint8ClampedArray`: each poll cycle (default 1 s) would\n * stringify ~16 MB per row × N rows, locking the main thread.\n *\n * Fast path: if both rows expose a string `updated_at`, compare just those.\n * The repositories in this codebase bump `updated_at` on every write (see\n * `ActivityRepository.updateActivity`), so the timestamp is a sufficient\n * change witness. Fall back to the structural compare for tables that don't\n * follow that convention so correctness is preserved everywhere.\n */\nfunction compareEntitiesForChange<T>(a: T, b: T): boolean {\n const au = (a as { updated_at?: unknown })?.updated_at;\n const bu = (b as { updated_at?: unknown })?.updated_at;\n if (typeof au === \"string\" && typeof bu === \"string\") {\n return au === bu;\n }\n return deepEqual(a, b);\n}\n\n/**\n * A tabular repository implementation using IndexedDB for browser-based storage.\n *\n * @template Schema - The schema definition for the entity\n * @template PrimaryKeyNames - Array of property names that form the primary key\n */\nexport class IndexedDbTabularStorage<\n Schema extends DataPortSchemaObject,\n PrimaryKeyNames extends ReadonlyArray<keyof Schema[\"properties\"]>,\n // computed types\n Entity = FromSchema<Schema, TypedArraySchemaOptions>,\n PrimaryKey = SimplifyPrimaryKey<Entity, PrimaryKeyNames>,\n Value = Omit<Entity, PrimaryKeyNames[number] & keyof Entity>,\n InsertType extends InsertEntity<Entity, AutoGeneratedKeys<Schema>> = InsertEntity<\n Entity,\n AutoGeneratedKeys<Schema>\n >,\n> extends BaseTabularStorage<Schema, PrimaryKeyNames, Entity, PrimaryKey, Value, InsertType> {\n /** Promise that resolves to the IndexedDB database instance */\n private db: IDBDatabase | undefined;\n /** Promise to track ongoing database setup to prevent concurrent setup calls */\n private setupPromise: Promise<IDBDatabase> | null = null;\n /** Migration options for database schema changes */\n private migrationOptions: MigrationOptions;\n /** Shared hybrid subscription manager */\n private hybridManager: HybridSubscriptionManager<\n Entity,\n string,\n TabularChangePayload<Entity>\n > | null = null;\n /** Hybrid subscription options */\n private readonly hybridOptions: {\n readonly useBroadcastChannel: boolean;\n readonly backupPollingIntervalMs: number;\n };\n /**\n * Indexes safe for cursor-based narrowing. An IDB index excludes records\n * whose keyPath has any undefined component, so iterating an index can miss\n * records when an indexed column is optional in the schema. Native\n * `count(range)` and cursor scans are only correct over indexes whose every\n * column is required. Computed lazily on first use.\n */\n private cursorSafeIndexes: Array<Array<keyof Entity>> | undefined;\n\n /**\n * Creates a new IndexedDB-based tabular repository.\n * @param table - Name of the IndexedDB store to use.\n * @param schema - Schema defining the structure of the entity\n * @param primaryKeyNames - Array of property names that form the primary key\n * @param indexes - Array of columns or column arrays to make searchable. Each string or single column creates a single-column index,\n * while each array creates a compound index with columns in the specified order.\n * @param migrationOptions - Options for handling database schema migrations\n * @param clientProvidedKeys - How to handle client-provided values for auto-generated keys\n */\n constructor(\n public table: string = \"tabular_store\",\n schema: Schema,\n primaryKeyNames: PrimaryKeyNames,\n indexes: readonly (keyof NoInfer<Entity> | readonly (keyof NoInfer<Entity>)[])[] = [],\n migrationOptions: MigrationOptions & {\n readonly useBroadcastChannel?: boolean;\n readonly backupPollingIntervalMs?: number;\n } = {},\n clientProvidedKeys: ClientProvidedKeysOption = \"if-missing\"\n ) {\n super(schema, primaryKeyNames, indexes, clientProvidedKeys);\n this.migrationOptions = migrationOptions;\n this.hybridOptions = {\n useBroadcastChannel: migrationOptions.useBroadcastChannel ?? true,\n backupPollingIntervalMs: migrationOptions.backupPollingIntervalMs ?? 5000,\n };\n }\n\n /**\n * Internal method to get the database, setting it up if needed.\n * This ensures lazy initialization of the database.\n */\n private async getDb(): Promise<IDBDatabase> {\n if (this.db) return this.db;\n await this.setupDatabase();\n return this.db!;\n }\n\n /**\n * Sets up the IndexedDB database table with the required schema and indexes.\n * Must be called before using any other methods.\n */\n public override async setupDatabase(): Promise<void> {\n if (this.db) return;\n if (this.setupPromise) {\n await this.setupPromise;\n return;\n }\n\n this.setupPromise = this.performSetup();\n try {\n this.db = await this.setupPromise;\n } finally {\n this.setupPromise = null;\n }\n }\n\n /**\n * Internal method to perform the actual database setup\n */\n private async performSetup(): Promise<IDBDatabase> {\n const pkColumns = super.primaryKeyColumns() as string[];\n\n // Create index definitions for both single and compound indexes\n const expectedIndexes: ExpectedIndexDefinition[] = [];\n\n for (const spec of this.indexes) {\n // Handle compound index\n const columns = spec as Array<keyof Entity>;\n // Skip if this is just the primary key or a prefix of it\n if (columns.length <= pkColumns.length) {\n const isPkPrefix = columns.every((col, idx) => col === pkColumns[idx]);\n if (isPkPrefix) continue;\n }\n\n // Create compound index name and keyPath\n const columnNames = columns.map((col) => String(col));\n const indexName = columnNames.join(\"_\");\n expectedIndexes.push({\n name: indexName,\n keyPath: columnNames.length === 1 ? columnNames[0] : columnNames,\n options: { unique: false },\n });\n }\n\n const primaryKey = pkColumns.length === 1 ? pkColumns[0] : pkColumns;\n\n // Determine if we should use autoIncrement\n // IndexedDB autoIncrement only works with single numeric keys\n const useAutoIncrement =\n this.hasAutoGeneratedKey() &&\n this.autoGeneratedKeyStrategy === \"autoincrement\" &&\n pkColumns.length === 1;\n\n // Ensure that our table is created/upgraded only if the structure (indexes) has changed.\n return await ensureIndexedDbTable(\n this.table,\n primaryKey,\n expectedIndexes,\n this.migrationOptions,\n useAutoIncrement\n );\n }\n\n /**\n * Generates a key value for UUID keys\n * Integer autoincrement keys are handled by IndexedDB's autoIncrement\n * @param columnName - Name of the column to generate a key for\n * @param strategy - The generation strategy to use\n * @returns The generated key value\n */\n protected override generateKeyValue(\n columnName: string,\n strategy: KeyGenerationStrategy\n ): string | number {\n if (strategy === \"uuid\") {\n return uuid4();\n }\n // autoincrement is handled by IndexedDB's autoIncrement option\n throw new Error(\n `IndexedDB autoincrement keys are generated by the database, not client-side. Column: ${columnName}`\n );\n }\n\n /**\n * Stores a row in the repository.\n * @param record - The entity to store (may be missing auto-generated keys).\n * @returns The stored entity\n * @emits put - Emitted when the value is successfully stored\n */\n async put(record: InsertType): Promise<Entity> {\n const db = await this.getDb();\n let recordToStore = record as unknown as Entity;\n\n // Handle auto-generated keys\n if (this.hasAutoGeneratedKey() && this.autoGeneratedKeyName) {\n const keyName = String(this.autoGeneratedKeyName);\n const clientProvidedValue = (record as Record<string, unknown>)[keyName];\n const hasClientValue = clientProvidedValue !== undefined && clientProvidedValue !== null;\n\n if (this.autoGeneratedKeyStrategy === \"uuid\") {\n // UUID generation - must be done client-side\n let shouldGenerate = false;\n if (this.clientProvidedKeys === \"never\") {\n shouldGenerate = true;\n } else if (this.clientProvidedKeys === \"always\") {\n if (!hasClientValue) {\n throw new Error(\n `Auto-generated key \"${keyName}\" is required when clientProvidedKeys is \"always\"`\n );\n }\n shouldGenerate = false;\n } else {\n // \"if-missing\"\n shouldGenerate = !hasClientValue;\n }\n\n if (shouldGenerate) {\n const generatedValue = this.generateKeyValue(keyName, \"uuid\");\n recordToStore = { ...record, [keyName]: generatedValue } as Entity;\n }\n } else if (this.autoGeneratedKeyStrategy === \"autoincrement\") {\n // Autoincrement handled by IndexedDB\n // If clientProvidedKeys is \"always\", require the value\n if (this.clientProvidedKeys === \"always\" && !hasClientValue) {\n throw new Error(\n `Auto-generated key \"${keyName}\" is required when clientProvidedKeys is \"always\"`\n );\n }\n // If clientProvidedKeys is \"never\", omit the key to let IDB generate\n if (this.clientProvidedKeys === \"never\") {\n const { [keyName]: _, ...rest } = record as Record<string, unknown>;\n recordToStore = rest as Entity;\n }\n // \"if-missing\": use client value if provided, omit if not\n }\n }\n\n // Merge key and value, ensuring all fields are at the root level for indexing\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.table, \"readwrite\");\n const store = transaction.objectStore(this.table);\n const request = store.put(recordToStore);\n request.onerror = () => {\n reject(request.error);\n };\n request.onsuccess = () => {\n // For autoincrement keys, we need to update the record with the generated key\n if (\n this.hasAutoGeneratedKey() &&\n this.autoGeneratedKeyName &&\n this.autoGeneratedKeyStrategy === \"autoincrement\"\n ) {\n const keyName = String(this.autoGeneratedKeyName);\n if (recordToStore[keyName as keyof Entity] === undefined) {\n // Get the generated key from the request result\n recordToStore = { ...recordToStore, [keyName]: request.result } as Entity;\n }\n }\n this.events.emit(\"put\", recordToStore);\n resolve(recordToStore);\n };\n transaction.oncomplete = () => {\n // Notify hybrid manager of local change\n this.hybridManager?.notifyLocalChange();\n };\n });\n }\n\n /**\n * Stores multiple rows in the repository in a bulk operation.\n * @param records - Array of entities to store (may be missing auto-generated keys).\n * @returns Array of stored entities\n * @emits put - Emitted for each record successfully stored\n */\n async putBulk(records: InsertType[]): Promise<Entity[]> {\n // Use individual put calls to ensure auto-generated keys are handled correctly\n return await Promise.all(records.map((record) => this.put(record)));\n }\n\n protected override getPrimaryKeyAsOrderedArray(key: PrimaryKey) {\n return super\n .getPrimaryKeyAsOrderedArray(key)\n .map((value) => (typeof value === \"bigint\" ? value.toString() : value));\n }\n\n private getIndexedKey(key: PrimaryKey): any {\n const keys = super\n .getPrimaryKeyAsOrderedArray(key)\n .map((value) => (typeof value === \"bigint\" ? value.toString() : value));\n return keys.length === 1 ? keys[0] : keys;\n }\n\n /**\n * Retrieves a value from the repository by its key.\n * @param key - The key object.\n * @returns The value object or undefined if not found.\n * @emits get - Emitted when the value is successfully retrieved\n */\n async get(key: PrimaryKey): Promise<Entity | undefined> {\n const db = await this.getDb();\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.table, \"readonly\");\n const store = transaction.objectStore(this.table);\n const request = store.get(this.getIndexedKey(key));\n request.onerror = () => reject(request.error);\n request.onsuccess = () => {\n if (!request.result) {\n this.events.emit(\"get\", key, undefined);\n resolve(undefined);\n return;\n }\n this.events.emit(\"get\", key, request.result);\n resolve(request.result);\n };\n });\n }\n\n /**\n * Returns an array of all entries in the repository, with optional ordering, offset, and limit.\n * @param options - Optional ordering, limit, and offset options\n * @returns Array of all entries in the repository.\n */\n async getAll(options?: QueryOptions<Entity>): Promise<Entity[] | undefined> {\n this.validateGetAllOptions(options);\n const db = await this.getDb();\n const transaction = db.transaction(this.table, \"readonly\");\n const store = transaction.objectStore(this.table);\n const request = store.getAll();\n return new Promise((resolve, reject) => {\n request.onerror = () => reject(request.error);\n request.onsuccess = () => {\n let values: Entity[] = request.result;\n if (values.length === 0) {\n resolve(undefined);\n return;\n }\n\n if (options?.orderBy && options.orderBy.length > 0) {\n values.sort((a, b) => {\n for (const { column, direction } of options.orderBy!) {\n const aVal = a[column] as string | number | null | undefined;\n const bVal = b[column] as string | number | null | undefined;\n if (aVal == null && bVal == null) continue;\n if (aVal == null) return direction === \"ASC\" ? -1 : 1;\n if (bVal == null) return direction === \"ASC\" ? 1 : -1;\n if (aVal < bVal) return direction === \"ASC\" ? -1 : 1;\n if (aVal > bVal) return direction === \"ASC\" ? 1 : -1;\n }\n return 0;\n });\n }\n\n if (options?.offset !== undefined) {\n values = values.slice(options.offset);\n }\n\n if (options?.limit !== undefined) {\n values = values.slice(0, options.limit);\n }\n\n resolve(values.length > 0 ? values : undefined);\n };\n });\n }\n\n /**\n * Deletes a row from the repository.\n * @param key - The key object to delete.\n */\n async delete(key: PrimaryKey): Promise<void> {\n const db = await this.getDb();\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.table, \"readwrite\");\n const store = transaction.objectStore(this.table);\n const request = store.delete(this.getIndexedKey(key));\n request.onerror = () => reject(request.error);\n request.onsuccess = () => {\n this.events.emit(\"delete\", key as keyof Entity);\n resolve();\n };\n transaction.oncomplete = () => {\n // Notify hybrid manager of local change\n this.hybridManager?.notifyLocalChange();\n };\n });\n }\n\n /**\n * Deletes all records from the repository.\n * @emits clearall - Emitted when all values are deleted\n */\n async deleteAll(): Promise<void> {\n const db = await this.getDb();\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.table, \"readwrite\");\n const store = transaction.objectStore(this.table);\n const request = store.clear();\n request.onerror = () => reject(request.error);\n request.onsuccess = () => {\n this.events.emit(\"clearall\");\n resolve();\n };\n transaction.oncomplete = () => {\n // Notify hybrid manager of local change\n this.hybridManager?.notifyLocalChange();\n };\n });\n }\n\n /**\n * Returns the total number of rows in the repository.\n * @returns Count of stored items.\n */\n async size(): Promise<number> {\n const db = await this.getDb();\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.table, \"readonly\");\n const store = transaction.objectStore(this.table);\n const request = store.count();\n request.onerror = () => reject(request.error);\n request.onsuccess = () => resolve(request.result);\n });\n }\n\n /**\n * Returns the subset of configured indexes safe to use for cursor-based\n * narrowing — those whose every column is required by the schema. IDB\n * excludes records with undefined keyPath components from indexes, so\n * iterating an index would silently miss records when any indexed column\n * is optional.\n */\n private getCursorSafeIndexes(): Array<Array<keyof Entity>> {\n if (this.cursorSafeIndexes) return this.cursorSafeIndexes;\n const required = new Set(this.schema.required ?? []);\n this.cursorSafeIndexes = this.indexes.filter((columns) =>\n columns.every((column) => required.has(String(column)))\n );\n return this.cursorSafeIndexes;\n }\n\n /**\n * Picks the best index to narrow a criteria-based scan, preferring indexes\n * whose prefix covers every criteria column (so callers can use the native\n * `count()` API) and falling back to the longest equality-prefix match.\n *\n * Upper bound uses `[]` as a sentinel that compares greater than any\n * primitive value at the next index position (per IndexedDB key ordering:\n * array > binary > string > date > number). Assumes subsequent indexed\n * columns hold primitive values — array-valued columns would compare\n * greater than `[]` and slip outside the range.\n */\n private createIndexedRange(\n store: IDBObjectStore,\n criteria: SearchCriteria<Entity>\n ):\n | {\n source: IDBObjectStore | IDBIndex;\n range: IDBKeyRange | undefined;\n coversCriteria: boolean;\n }\n | undefined {\n const criteriaColumns = Object.keys(criteria) as Array<keyof Entity>;\n if (criteriaColumns.length === 0) return undefined;\n\n let best:\n | {\n indexName: string;\n prefixValues: unknown[];\n fullMatch: boolean;\n coversCriteria: boolean;\n }\n | undefined;\n\n for (const indexColumns of this.getCursorSafeIndexes()) {\n const prefixValues: unknown[] = [];\n for (const column of indexColumns) {\n const value = this.getEqualityCriterionValue(criteria, column);\n if (value === undefined) break;\n prefixValues.push(value);\n }\n\n if (prefixValues.length === 0) continue;\n\n const indexedPrefix = indexColumns.slice(0, prefixValues.length);\n const coversCriteria = criteriaColumns.every((column) => indexedPrefix.includes(column));\n\n const better =\n !best ||\n (coversCriteria && !best.coversCriteria) ||\n (coversCriteria === best.coversCriteria && prefixValues.length > best.prefixValues.length);\n\n if (better) {\n best = {\n indexName: indexColumns.map((column) => String(column)).join(\"_\"),\n prefixValues,\n fullMatch: prefixValues.length === indexColumns.length,\n coversCriteria,\n };\n }\n }\n\n if (!best) return undefined;\n\n const range = best.fullMatch\n ? IDBKeyRange.only(best.prefixValues.length === 1 ? best.prefixValues[0] : best.prefixValues)\n : IDBKeyRange.bound(best.prefixValues, [...best.prefixValues, []]);\n\n return {\n source: store.index(best.indexName),\n range,\n coversCriteria: best.coversCriteria,\n };\n }\n\n /**\n * Counts rows matching the specified search criteria.\n *\n * Uses the native `count()` API when an index prefix covers every criteria\n * column. Otherwise narrows via the longest matching index prefix and\n * filters the remaining columns during cursor iteration. Falls back to a\n * full store scan only when no index applies.\n */\n override async count(criteria?: SearchCriteria<Entity>): Promise<number> {\n if (!criteria || Object.keys(criteria).length === 0) {\n return await this.size();\n }\n\n this.validateQueryParams(criteria);\n const db = await this.getDb();\n\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.table, \"readonly\");\n const store = transaction.objectStore(this.table);\n const plan = this.createIndexedRange(store, criteria);\n\n if (plan?.coversCriteria) {\n const request = plan.source.count(plan.range);\n request.onerror = () => reject(request.error);\n request.onsuccess = () => resolve(request.result);\n return;\n }\n\n const source = plan?.source ?? store;\n const range = plan?.range;\n let count = 0;\n const request = source.openCursor(range);\n request.onerror = () => reject(request.error);\n request.onsuccess = () => {\n const cursor = request.result;\n if (!cursor) {\n resolve(count);\n return;\n }\n if (this.matchesCriteria(cursor.value as Entity, criteria)) {\n count += 1;\n }\n cursor.continue();\n };\n });\n }\n\n /**\n * Fetches a page of records from the repository.\n * @param offset - Number of records to skip\n * @param limit - Maximum number of records to return\n * @returns Array of entities or undefined if no records found\n */\n async getBulk(offset: number, limit: number): Promise<Entity[] | undefined> {\n if (offset < 0) {\n throw new RangeError(`offset must be non-negative, got ${offset}`);\n }\n if (limit <= 0) {\n return undefined;\n }\n\n const db = await this.getDb();\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.table, \"readonly\");\n const store = transaction.objectStore(this.table);\n const request = store.openCursor();\n const entities: Entity[] = [];\n let skipped = false;\n\n request.onerror = () => reject(request.error);\n request.onsuccess = () => {\n const cursor = request.result;\n if (cursor) {\n // Skip to offset using advance\n if (!skipped && offset > 0) {\n skipped = true;\n cursor.advance(offset);\n return;\n }\n\n // Collect records up to the limit\n entities.push(cursor.value);\n if (entities.length === limit) {\n resolve(entities);\n return;\n }\n cursor.continue();\n } else {\n // No more records\n resolve(entities.length > 0 ? entities : undefined);\n }\n };\n });\n }\n\n /**\n * Checks if a record matches all criteria conditions.\n * @param record - The record to check\n * @param criteria - The search criteria\n * @returns true if all conditions match\n */\n private matchesCriteria(record: Entity, criteria: DeleteSearchCriteria<Entity>): boolean {\n for (const column of Object.keys(criteria) as Array<keyof Entity>) {\n const criterion = criteria[column];\n const recordValue = record[column];\n\n let operator: SearchOperator = \"=\";\n let value: Entity[keyof Entity];\n\n if (isSearchCondition(criterion)) {\n operator = criterion.operator;\n value = criterion.value as Entity[keyof Entity];\n } else {\n value = criterion as Entity[keyof Entity];\n }\n\n // Skip null values for comparison operators\n if (operator !== \"=\" && (recordValue === null || recordValue === undefined)) {\n return false;\n }\n\n switch (operator) {\n case \"=\":\n if (recordValue !== value) return false;\n break;\n case \"<\":\n if (!(recordValue < value)) return false;\n break;\n case \"<=\":\n if (!(recordValue <= value)) return false;\n break;\n case \">\":\n if (!(recordValue > value)) return false;\n break;\n case \">=\":\n if (!(recordValue >= value)) return false;\n break;\n default:\n return false;\n }\n }\n return true;\n }\n\n /**\n * Deletes all entries matching the specified search criteria.\n * Supports multiple columns with optional comparison operators.\n *\n * @param criteria - Object with column names as keys and values or SearchConditions\n */\n async deleteSearch(criteria: DeleteSearchCriteria<Entity>): Promise<void> {\n const criteriaKeys = Object.keys(criteria) as Array<keyof Entity>;\n if (criteriaKeys.length === 0) {\n return;\n }\n\n const db = await this.getDb();\n\n return new Promise(async (resolve, reject) => {\n try {\n const transaction = db.transaction(this.table, \"readwrite\");\n const store = transaction.objectStore(this.table);\n\n // Set up transaction event handlers\n transaction.oncomplete = () => {\n this.events.emit(\"delete\", criteriaKeys[0] as keyof Entity);\n // Notify hybrid manager of local change\n this.hybridManager?.notifyLocalChange();\n resolve();\n };\n\n transaction.onerror = () => {\n reject(transaction.error);\n };\n\n // Get all records and filter\n const getAllRequest = store.getAll();\n\n getAllRequest.onsuccess = () => {\n const allRecords: Entity[] = getAllRequest.result;\n\n // Filter records that match all criteria\n const recordsToDelete = allRecords.filter((record) =>\n this.matchesCriteria(record, criteria)\n );\n\n if (recordsToDelete.length === 0) {\n // No records to delete\n return;\n }\n\n // Delete each record that matches the criteria\n for (const record of recordsToDelete) {\n // Extract the primary key from the record\n const primaryKey = this.primaryKeyColumns().reduce((key, col) => {\n // @ts-ignore - We know these properties exist on the record\n key[col] = record[col];\n return key;\n }, {} as PrimaryKey);\n\n // Delete the record using the primary key\n const request = store.delete(this.getIndexedKey(primaryKey));\n\n request.onerror = () => {\n console.error(\"Error deleting record:\", request.error);\n };\n }\n };\n\n getAllRequest.onerror = () => {\n reject(getAllRequest.error);\n };\n } catch (error) {\n reject(error);\n }\n });\n }\n\n private getEqualityCriterionValue(\n criteria: SearchCriteria<Entity>,\n column: keyof Entity\n ): Entity[keyof Entity] | undefined {\n const criterion = criteria[column];\n if (criterion === undefined) return undefined;\n if (isSearchCondition(criterion)) {\n return criterion.operator === \"=\" ? (criterion.value as Entity[keyof Entity]) : undefined;\n }\n return criterion as Entity[keyof Entity];\n }\n\n private compareByOrder(a: Entity, b: Entity, options?: QueryOptions<Entity>): number {\n if (!options?.orderBy) return 0;\n for (const { column, direction } of options.orderBy) {\n const aVal = a[column] as string | number | null | undefined;\n const bVal = b[column] as string | number | null | undefined;\n if (aVal == null && bVal == null) continue;\n if (aVal == null) return direction === \"ASC\" ? -1 : 1;\n if (bVal == null) return direction === \"ASC\" ? 1 : -1;\n if (aVal < bVal) return direction === \"ASC\" ? -1 : 1;\n if (aVal > bVal) return direction === \"ASC\" ? 1 : -1;\n }\n return 0;\n }\n\n private createIndexedQuery(\n store: IDBObjectStore,\n criteria: SearchCriteria<Entity>,\n options?: QueryOptions<Entity>\n ): {\n source: IDBObjectStore | IDBIndex;\n range: IDBKeyRange | undefined;\n direction: IDBCursorDirection;\n satisfiesOrder: boolean;\n appliedLimit: boolean;\n appliedOffset: boolean;\n skipRemaining: number;\n } {\n const orderBy = options?.orderBy ?? [];\n let best:\n | {\n indexName: string;\n prefixValues: unknown[];\n fullMatch: boolean;\n satisfiesOrder: boolean;\n direction: IDBCursorDirection;\n }\n | undefined;\n\n for (const indexColumns of this.getCursorSafeIndexes()) {\n const prefixValues: unknown[] = [];\n for (const column of indexColumns) {\n const value = this.getEqualityCriterionValue(criteria, column);\n if (value === undefined) break;\n prefixValues.push(value);\n }\n\n if (prefixValues.length === 0) continue;\n\n const remainingColumns = indexColumns.slice(prefixValues.length);\n let redundantOrderPrefixLength = 0;\n while (\n redundantOrderPrefixLength < orderBy.length &&\n redundantOrderPrefixLength < prefixValues.length &&\n orderBy[redundantOrderPrefixLength]?.column === indexColumns[redundantOrderPrefixLength]\n ) {\n redundantOrderPrefixLength++;\n }\n const normalizedOrderBy = orderBy.slice(redundantOrderPrefixLength);\n const satisfiesOrder =\n normalizedOrderBy.length === 0 ||\n (normalizedOrderBy.length <= remainingColumns.length &&\n normalizedOrderBy.every((order, index) => order.column === remainingColumns[index]) &&\n orderBy.every((order) => order.direction === orderBy[0]?.direction));\n\n if (!satisfiesOrder && best) continue;\n\n if (\n !best ||\n (satisfiesOrder && !best.satisfiesOrder) ||\n prefixValues.length > best.prefixValues.length\n ) {\n best = {\n indexName: indexColumns.map((column) => String(column)).join(\"_\"),\n prefixValues,\n fullMatch: prefixValues.length === indexColumns.length,\n satisfiesOrder,\n direction: orderBy[0]?.direction === \"DESC\" ? \"prev\" : \"next\",\n };\n }\n }\n\n const appliedLimit = Boolean(best?.satisfiesOrder && options?.limit !== undefined);\n const appliedOffset = Boolean(best?.satisfiesOrder && options?.offset !== undefined);\n\n if (!best) {\n return {\n source: store,\n range: undefined,\n direction: orderBy[0]?.direction === \"DESC\" ? \"prev\" : \"next\",\n satisfiesOrder: false,\n appliedLimit: false,\n appliedOffset: false,\n skipRemaining: 0,\n };\n }\n\n const source = store.index(best.indexName);\n // See createIndexedRange for the `[]` upper-bound sentinel rationale.\n const keyRange = best.fullMatch\n ? IDBKeyRange.only(best.prefixValues.length === 1 ? best.prefixValues[0] : best.prefixValues)\n : IDBKeyRange.bound(best.prefixValues, [...best.prefixValues, []]);\n\n return {\n source,\n range: keyRange,\n direction: best.direction,\n satisfiesOrder: best.satisfiesOrder,\n appliedLimit,\n appliedOffset,\n skipRemaining: appliedOffset ? (options?.offset ?? 0) : 0,\n };\n }\n\n /**\n * Queries entries matching the specified search criteria with optional ordering, limit, and offset.\n *\n * @param criteria - Object with column names as keys and values or SearchConditions\n * @param options - Optional ordering, limit, and offset options\n * @returns Array of matching entities or undefined if no matches found\n */\n async query(\n criteria: SearchCriteria<Entity>,\n options?: QueryOptions<Entity>\n ): Promise<Entity[] | undefined> {\n this.validateQueryParams(criteria, options);\n const db = await this.getDb();\n\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.table, \"readonly\");\n const store = transaction.objectStore(this.table);\n const indexedQuery = this.createIndexedQuery(store, criteria, options);\n const results: Entity[] = [];\n const request = indexedQuery.source.openCursor(indexedQuery.range, indexedQuery.direction);\n\n request.onsuccess = () => {\n const cursor = request.result;\n if (!cursor) {\n let finalResults = results;\n\n if (!indexedQuery.satisfiesOrder && options?.orderBy && options.orderBy.length > 0) {\n finalResults = [...finalResults].sort((a, b) => this.compareByOrder(a, b, options));\n }\n\n if (!indexedQuery.appliedOffset && options?.offset !== undefined) {\n finalResults = finalResults.slice(options.offset);\n }\n\n if (!indexedQuery.appliedLimit && options?.limit !== undefined) {\n finalResults = finalResults.slice(0, options.limit);\n }\n\n const result = finalResults.length > 0 ? finalResults : undefined;\n this.events.emit(\"query\", criteria as Partial<Entity>, result);\n resolve(result);\n return;\n }\n\n const record = cursor.value as Entity;\n if (this.matchesCriteria(record, criteria)) {\n if (indexedQuery.skipRemaining > 0) {\n indexedQuery.skipRemaining -= 1;\n } else {\n results.push(record);\n if (indexedQuery.appliedLimit && results.length === options?.limit) {\n const result = results.length > 0 ? results : undefined;\n this.events.emit(\"query\", criteria as Partial<Entity>, result);\n resolve(result);\n return;\n }\n }\n }\n\n cursor.continue();\n };\n\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Strict, projected query served entirely by a covering compound index.\n * Uses `openKeyCursor` — never reads `cursor.value` — so only the index key\n * bytes are loaded into memory. Ideal for tables with large value blobs.\n *\n * Throws {@link CoveringIndexMissingError} when no registered index can serve\n * the request (i.e. the index does not cover all select + orderBy columns).\n */\n override async queryIndex<K extends keyof Entity & string>(\n criteria: SearchCriteria<Entity>,\n options: CoveringIndexQueryOptions<Entity, K>\n ): Promise<Pick<Entity, K>[]> {\n this.validateSelect(options);\n this.validateQueryParams(criteria, options);\n\n const registered = this.indexes.map((cols) => {\n const cs = Array.isArray(cols) ? (cols as string[]) : [cols as string];\n return { name: cs.join(\"_\"), keyPath: cs };\n });\n\n const picked = pickCoveringIndex({\n table: this.table,\n indexes: registered,\n criteriaColumns: Object.keys(criteria),\n orderByColumns: (options.orderBy ?? []).map((o) => ({\n column: String(o.column),\n direction: o.direction,\n })),\n selectColumns: options.select.map(String),\n primaryKeyColumns: this.primaryKeyColumns().map(String),\n });\n\n const db = await this.getDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(this.table, \"readonly\");\n const store = tx.objectStore(this.table);\n const idx = store.index(picked.name);\n\n // Build the equality prefix key range from criteria values.\n // Only push columns whose criterion is a direct equality value (plain value or operator \"=\").\n // Any non-equality operator (>, <, etc.) breaks the prefix; the existing in-cursor\n // compareWithOperator filter below handles those columns.\n const prefix: unknown[] = [];\n for (const col of picked.keyPath) {\n const c = (criteria as Record<string, unknown>)[col];\n if (c === undefined && !(col in (criteria as Record<string, unknown>))) break;\n if (isSearchCondition(c)) {\n if (c.operator !== \"=\") break;\n prefix.push(c.value);\n } else {\n prefix.push(c);\n }\n }\n // Use IDBKeyRange.bound with [] upper sentinel for prefix scans on compound keys.\n // `[...prefix, []]` is greater than any key starting with prefix in IDB's comparison.\n const range =\n prefix.length === 0\n ? undefined\n : prefix.length === picked.keyPath.length\n ? IDBKeyRange.only(prefix.length === 1 ? prefix[0] : prefix)\n : IDBKeyRange.bound(prefix, [...prefix, []]);\n\n const direction: IDBCursorDirection = picked.reverseDirection ? \"prev\" : \"next\";\n // openKeyCursor — never reads cursor.value, only the index key and primaryKey\n const request = idx.openKeyCursor(range, direction);\n const out: Pick<Entity, K>[] = [];\n let toSkip = options.offset ?? 0;\n\n // Precompute lookup maps for the cursor loop (O(keyPath) once, not per-row)\n const keyPathPositions = new Map<string, number>();\n picked.keyPath.forEach((col, i) => keyPathPositions.set(col, i));\n\n const pkCols = this.primaryKeyColumns().map(String);\n const pkPositions = new Map<string, number>();\n pkCols.forEach((col, i) => pkPositions.set(col, i));\n\n request.onsuccess = () => {\n const cursor = request.result;\n if (!cursor) {\n resolve(out);\n return;\n }\n\n const key = cursor.key;\n\n // Decode projected columns from the index key array and primaryKey\n const row = {} as Record<string, unknown>;\n for (const col of options.select) {\n const colStr = String(col);\n const pos = keyPathPositions.get(colStr);\n if (pos !== undefined) {\n // Column is in the index key path — extract from key array\n row[colStr] = Array.isArray(key) ? key[pos] : key;\n } else {\n // Column must be a primary key column — use cursor.primaryKey\n if (pkCols.length === 1 && colStr === pkCols[0]) {\n row[colStr] = cursor.primaryKey;\n } else {\n const pkPos = pkPositions.get(colStr);\n if (pkPos !== undefined) {\n row[colStr] = Array.isArray(cursor.primaryKey)\n ? (cursor.primaryKey as unknown[])[pkPos]\n : cursor.primaryKey;\n }\n }\n }\n }\n\n // Apply non-equality criteria for index positions beyond the equality prefix\n let matches = true;\n for (const [col, crit] of Object.entries(criteria as Record<string, unknown>)) {\n if (!isSearchCondition(crit)) continue; // equality already handled by range\n const pos = keyPathPositions.get(col);\n if (pos === undefined) continue;\n const valFromKey = Array.isArray(key) ? (key as unknown[])[pos] : key;\n if (!compareWithOperator(valFromKey, crit.operator, crit.value)) {\n matches = false;\n break;\n }\n }\n\n if (matches) {\n if (toSkip > 0) {\n toSkip -= 1;\n } else {\n out.push(row as Pick<Entity, K>);\n if (options.limit !== undefined && out.length >= options.limit) {\n resolve(out);\n return;\n }\n }\n }\n\n cursor.continue();\n };\n\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Gets or creates the shared hybrid subscription manager.\n * This ensures all subscriptions share a single manager.\n */\n private getHybridManager(): HybridSubscriptionManager<\n Entity,\n string,\n TabularChangePayload<Entity>\n > {\n if (!this.hybridManager) {\n // Generate unique channel name based on table name\n const channelName = `indexeddb-tabular-${this.table}`;\n\n this.hybridManager = new HybridSubscriptionManager<\n Entity,\n string,\n TabularChangePayload<Entity>\n >(\n channelName,\n async () => {\n // Fetch all entities and create a map keyed by entity fingerprint\n const entities = (await this.getAll()) || [];\n const map = new Map<string, Entity>();\n for (const entity of entities) {\n const { key } = this.separateKeyValueFromCombined(entity);\n const fingerprint = await makeFingerprint(key);\n map.set(fingerprint, entity);\n }\n return map;\n },\n compareEntitiesForChange,\n {\n insert: (item) => ({ type: \"INSERT\" as const, new: item }),\n update: (oldItem, newItem) => ({ type: \"UPDATE\" as const, old: oldItem, new: newItem }),\n delete: (item) => ({ type: \"DELETE\" as const, old: item }),\n },\n {\n defaultIntervalMs: 1000,\n useBroadcastChannel: this.hybridOptions.useBroadcastChannel,\n backupPollingIntervalMs: this.hybridOptions.backupPollingIntervalMs,\n }\n );\n }\n return this.hybridManager;\n }\n\n /**\n * Subscribes to changes in the repository.\n * Uses polling since IndexedDB has no native cross-tab change notifications.\n *\n * @param callback - Function called when a change occurs\n * @param options - Optional subscription options including polling interval\n * @returns Unsubscribe function\n */\n public override subscribeToChanges(\n callback: (change: TabularChangePayload<Entity>) => void,\n options?: TabularSubscribeOptions\n ): () => void {\n // Note: We don't await setupDatabase() here to keep the method synchronous\n // The getAll() method in the hybrid manager will call setupDatabase() when needed\n const intervalMs = options?.pollingIntervalMs ?? 1000;\n const manager = this.getHybridManager();\n return manager.subscribe(callback, { intervalMs });\n }\n\n /**\n * Destroys this repository and frees up resources.\n */\n public override destroy(): void {\n if (this.hybridManager) {\n this.hybridManager.destroy();\n this.hybridManager = null;\n }\n this.db?.close();\n }\n}\n\n/**\n * Compare two values using a SearchOperator. Used by queryIndex to evaluate\n * non-equality criteria that cannot be expressed as an IDBKeyRange prefix.\n */\nfunction compareWithOperator(a: unknown, op: SearchOperator, b: unknown): boolean {\n const av = a as string | number | null | undefined;\n const bv = b as string | number;\n switch (op) {\n case \"=\":\n return av === bv;\n case \"<\":\n return av !== null && av !== undefined && av < bv;\n case \"<=\":\n return av !== null && av !== undefined && av <= bv;\n case \">\":\n return av !== null && av !== undefined && av > bv;\n case \">=\":\n return av !== null && av !== undefined && av >= bv;\n }\n}\n",
|
|
53
|
+
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { createServiceToken, deepEqual, makeFingerprint, uuid4 } from \"@workglow/util\";\nimport { DataPortSchemaObject, FromSchema, TypedArraySchemaOptions } from \"@workglow/util/schema\";\nimport { HybridSubscriptionManager } from \"../util/HybridSubscriptionManager\";\nimport {\n ensureIndexedDbTable,\n ExpectedIndexDefinition,\n MigrationOptions,\n} from \"../util/IndexedDbTable\";\nimport {\n BaseTabularStorage,\n ClientProvidedKeysOption,\n KeyGenerationStrategy,\n} from \"./BaseTabularStorage\";\nimport {\n AnyTabularStorage,\n AutoGeneratedKeys,\n CoveringIndexQueryOptions,\n DeleteSearchCriteria,\n InsertEntity,\n isSearchCondition,\n QueryOptions,\n SearchCriteria,\n SearchOperator,\n SimplifyPrimaryKey,\n TabularChangePayload,\n TabularSubscribeOptions,\n} from \"./ITabularStorage\";\nimport { pickCoveringIndex } from \"./coveringIndexPicker\";\n\nexport const IDB_TABULAR_REPOSITORY = createServiceToken<AnyTabularStorage>(\n \"storage.tabularRepository.indexedDb\"\n);\n\n/**\n * Polling change-detection comparator for the hybrid subscription manager.\n *\n * Naively comparing entities via serialized equality is correct but\n * O(size-of-entity) per poll. That falls apart for tables\n * holding large blobs — e.g. an `activities` row whose `output_data` carries\n * a multi-megabyte `Uint8ClampedArray`: each poll cycle (default 1 s) would\n * stringify ~16 MB per row × N rows, locking the main thread.\n *\n * Fast path: if both rows expose a string `updated_at`, compare just those.\n * The repositories in this codebase bump `updated_at` on every write (see\n * `ActivityRepository.updateActivity`), so the timestamp is a sufficient\n * change witness. Fall back to the structural compare for tables that don't\n * follow that convention so correctness is preserved everywhere.\n */\nfunction compareEntitiesForChange<T>(a: T, b: T): boolean {\n const au = (a as { updated_at?: unknown })?.updated_at;\n const bu = (b as { updated_at?: unknown })?.updated_at;\n if (typeof au === \"string\" && typeof bu === \"string\") {\n return au === bu;\n }\n return deepEqual(a, b);\n}\n\n/**\n * A tabular repository implementation using IndexedDB for browser-based storage.\n *\n * @template Schema - The schema definition for the entity\n * @template PrimaryKeyNames - Array of property names that form the primary key\n */\nexport class IndexedDbTabularStorage<\n Schema extends DataPortSchemaObject,\n PrimaryKeyNames extends ReadonlyArray<keyof Schema[\"properties\"]>,\n // computed types\n Entity = FromSchema<Schema, TypedArraySchemaOptions>,\n PrimaryKey = SimplifyPrimaryKey<Entity, PrimaryKeyNames>,\n Value = Omit<Entity, PrimaryKeyNames[number] & keyof Entity>,\n InsertType extends InsertEntity<Entity, AutoGeneratedKeys<Schema>> = InsertEntity<\n Entity,\n AutoGeneratedKeys<Schema>\n >,\n> extends BaseTabularStorage<Schema, PrimaryKeyNames, Entity, PrimaryKey, Value, InsertType> {\n /** Promise that resolves to the IndexedDB database instance */\n private db: IDBDatabase | undefined;\n /** Promise to track ongoing database setup to prevent concurrent setup calls */\n private setupPromise: Promise<IDBDatabase> | null = null;\n /** Migration options for database schema changes */\n private migrationOptions: MigrationOptions;\n /** Shared hybrid subscription manager */\n private hybridManager: HybridSubscriptionManager<\n Entity,\n string,\n TabularChangePayload<Entity>\n > | null = null;\n /** Hybrid subscription options */\n private readonly hybridOptions: {\n readonly useBroadcastChannel: boolean;\n readonly backupPollingIntervalMs: number;\n };\n /**\n * Indexes safe for cursor-based narrowing. An IDB index excludes records\n * whose keyPath has any undefined component, so iterating an index can miss\n * records when an indexed column is optional in the schema. Native\n * `count(range)` and cursor scans are only correct over indexes whose every\n * column is required. Computed lazily on first use.\n */\n private cursorSafeIndexes: Array<Array<keyof Entity>> | undefined;\n\n /**\n * Creates a new IndexedDB-based tabular repository.\n * @param table - Name of the IndexedDB store to use.\n * @param schema - Schema defining the structure of the entity\n * @param primaryKeyNames - Array of property names that form the primary key\n * @param indexes - Array of columns or column arrays to make searchable. Each string or single column creates a single-column index,\n * while each array creates a compound index with columns in the specified order.\n * @param migrationOptions - Options for handling database schema migrations\n * @param clientProvidedKeys - How to handle client-provided values for auto-generated keys\n */\n constructor(\n public table: string = \"tabular_store\",\n schema: Schema,\n primaryKeyNames: PrimaryKeyNames,\n indexes: readonly (keyof NoInfer<Entity> | readonly (keyof NoInfer<Entity>)[])[] = [],\n migrationOptions: MigrationOptions & {\n readonly useBroadcastChannel?: boolean;\n readonly backupPollingIntervalMs?: number;\n } = {},\n clientProvidedKeys: ClientProvidedKeysOption = \"if-missing\"\n ) {\n super(schema, primaryKeyNames, indexes, clientProvidedKeys);\n this.migrationOptions = migrationOptions;\n this.hybridOptions = {\n useBroadcastChannel: migrationOptions.useBroadcastChannel ?? true,\n backupPollingIntervalMs: migrationOptions.backupPollingIntervalMs ?? 5000,\n };\n }\n\n /**\n * Internal method to get the database, setting it up if needed.\n * This ensures lazy initialization of the database.\n */\n private async getDb(): Promise<IDBDatabase> {\n if (this.db) return this.db;\n await this.setupDatabase();\n return this.db!;\n }\n\n /**\n * Sets up the IndexedDB database table with the required schema and indexes.\n * Must be called before using any other methods.\n */\n public override async setupDatabase(): Promise<void> {\n if (this.db) return;\n if (this.setupPromise) {\n await this.setupPromise;\n return;\n }\n\n this.setupPromise = this.performSetup();\n try {\n this.db = await this.setupPromise;\n } finally {\n this.setupPromise = null;\n }\n }\n\n /**\n * Internal method to perform the actual database setup\n */\n private async performSetup(): Promise<IDBDatabase> {\n const pkColumns = super.primaryKeyColumns() as string[];\n\n // Create index definitions for both single and compound indexes\n const expectedIndexes: ExpectedIndexDefinition[] = [];\n\n for (const spec of this.indexes) {\n // Handle compound index\n const columns = spec as Array<keyof Entity>;\n // Skip if this is just the primary key or a prefix of it\n if (columns.length <= pkColumns.length) {\n const isPkPrefix = columns.every((col, idx) => col === pkColumns[idx]);\n if (isPkPrefix) continue;\n }\n\n // Create compound index name and keyPath\n const columnNames = columns.map((col) => String(col));\n const indexName = columnNames.join(\"_\");\n expectedIndexes.push({\n name: indexName,\n keyPath: columnNames.length === 1 ? columnNames[0] : columnNames,\n options: { unique: false },\n });\n }\n\n const primaryKey = pkColumns.length === 1 ? pkColumns[0] : pkColumns;\n\n // Determine if we should use autoIncrement\n // IndexedDB autoIncrement only works with single numeric keys\n const useAutoIncrement =\n this.hasAutoGeneratedKey() &&\n this.autoGeneratedKeyStrategy === \"autoincrement\" &&\n pkColumns.length === 1;\n\n // Ensure that our table is created/upgraded only if the structure (indexes) has changed.\n return await ensureIndexedDbTable(\n this.table,\n primaryKey,\n expectedIndexes,\n this.migrationOptions,\n useAutoIncrement\n );\n }\n\n /**\n * Generates a key value for UUID keys\n * Integer autoincrement keys are handled by IndexedDB's autoIncrement\n * @param columnName - Name of the column to generate a key for\n * @param strategy - The generation strategy to use\n * @returns The generated key value\n */\n protected override generateKeyValue(\n columnName: string,\n strategy: KeyGenerationStrategy\n ): string | number {\n if (strategy === \"uuid\") {\n return uuid4();\n }\n // autoincrement is handled by IndexedDB's autoIncrement option\n throw new Error(\n `IndexedDB autoincrement keys are generated by the database, not client-side. Column: ${columnName}`\n );\n }\n\n /**\n * Stores a row in the repository.\n * @param record - The entity to store (may be missing auto-generated keys).\n * @returns The stored entity\n * @emits put - Emitted when the value is successfully stored\n */\n async put(record: InsertType): Promise<Entity> {\n const db = await this.getDb();\n let recordToStore = record as unknown as Entity;\n\n // Handle auto-generated keys\n if (this.hasAutoGeneratedKey() && this.autoGeneratedKeyName) {\n const keyName = String(this.autoGeneratedKeyName);\n const clientProvidedValue = (record as Record<string, unknown>)[keyName];\n const hasClientValue = clientProvidedValue !== undefined && clientProvidedValue !== null;\n\n if (this.autoGeneratedKeyStrategy === \"uuid\") {\n // UUID generation - must be done client-side\n let shouldGenerate = false;\n if (this.clientProvidedKeys === \"never\") {\n shouldGenerate = true;\n } else if (this.clientProvidedKeys === \"always\") {\n if (!hasClientValue) {\n throw new Error(\n `Auto-generated key \"${keyName}\" is required when clientProvidedKeys is \"always\"`\n );\n }\n shouldGenerate = false;\n } else {\n // \"if-missing\"\n shouldGenerate = !hasClientValue;\n }\n\n if (shouldGenerate) {\n const generatedValue = this.generateKeyValue(keyName, \"uuid\");\n recordToStore = { ...record, [keyName]: generatedValue } as Entity;\n }\n } else if (this.autoGeneratedKeyStrategy === \"autoincrement\") {\n // Autoincrement handled by IndexedDB\n // If clientProvidedKeys is \"always\", require the value\n if (this.clientProvidedKeys === \"always\" && !hasClientValue) {\n throw new Error(\n `Auto-generated key \"${keyName}\" is required when clientProvidedKeys is \"always\"`\n );\n }\n // If clientProvidedKeys is \"never\", omit the key to let IDB generate\n if (this.clientProvidedKeys === \"never\") {\n const { [keyName]: _, ...rest } = record as Record<string, unknown>;\n recordToStore = rest as Entity;\n }\n // \"if-missing\": use client value if provided, omit if not\n }\n }\n\n // Merge key and value, ensuring all fields are at the root level for indexing\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.table, \"readwrite\");\n const store = transaction.objectStore(this.table);\n const request = store.put(recordToStore);\n request.onerror = () => {\n reject(request.error);\n };\n request.onsuccess = () => {\n // For autoincrement keys, we need to update the record with the generated key\n if (\n this.hasAutoGeneratedKey() &&\n this.autoGeneratedKeyName &&\n this.autoGeneratedKeyStrategy === \"autoincrement\"\n ) {\n const keyName = String(this.autoGeneratedKeyName);\n if (recordToStore[keyName as keyof Entity] === undefined) {\n // Get the generated key from the request result\n recordToStore = { ...recordToStore, [keyName]: request.result } as Entity;\n }\n }\n this.events.emit(\"put\", recordToStore);\n resolve(recordToStore);\n };\n transaction.oncomplete = () => {\n // Notify hybrid manager of local change\n this.hybridManager?.notifyLocalChange();\n };\n });\n }\n\n /**\n * Stores multiple rows in the repository in a bulk operation.\n * @param records - Array of entities to store (may be missing auto-generated keys).\n * @returns Array of stored entities\n * @emits put - Emitted for each record successfully stored\n */\n async putBulk(records: InsertType[]): Promise<Entity[]> {\n // Use individual put calls to ensure auto-generated keys are handled correctly\n return await Promise.all(records.map((record) => this.put(record)));\n }\n\n protected override getPrimaryKeyAsOrderedArray(key: PrimaryKey) {\n return super\n .getPrimaryKeyAsOrderedArray(key)\n .map((value) => (typeof value === \"bigint\" ? value.toString() : value));\n }\n\n private getIndexedKey(key: PrimaryKey): any {\n const keys = super\n .getPrimaryKeyAsOrderedArray(key)\n .map((value) => (typeof value === \"bigint\" ? value.toString() : value));\n return keys.length === 1 ? keys[0] : keys;\n }\n\n /**\n * Retrieves a value from the repository by its key.\n * @param key - The key object.\n * @returns The value object or undefined if not found.\n * @emits get - Emitted when the value is successfully retrieved\n */\n async get(key: PrimaryKey): Promise<Entity | undefined> {\n const db = await this.getDb();\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.table, \"readonly\");\n const store = transaction.objectStore(this.table);\n const request = store.get(this.getIndexedKey(key));\n request.onerror = () => reject(request.error);\n request.onsuccess = () => {\n if (!request.result) {\n this.events.emit(\"get\", key, undefined);\n resolve(undefined);\n return;\n }\n this.events.emit(\"get\", key, request.result);\n resolve(request.result);\n };\n });\n }\n\n /**\n * Returns an array of all entries in the repository, with optional ordering, offset, and limit.\n * @param options - Optional ordering, limit, and offset options\n * @returns Array of all entries in the repository.\n */\n async getAll(options?: QueryOptions<Entity>): Promise<Entity[] | undefined> {\n this.validateGetAllOptions(options);\n const db = await this.getDb();\n const transaction = db.transaction(this.table, \"readonly\");\n const store = transaction.objectStore(this.table);\n const request = store.getAll();\n return new Promise((resolve, reject) => {\n request.onerror = () => reject(request.error);\n request.onsuccess = () => {\n let values: Entity[] = request.result;\n if (values.length === 0) {\n resolve(undefined);\n return;\n }\n\n if (options?.orderBy && options.orderBy.length > 0) {\n values.sort((a, b) => {\n for (const { column, direction } of options.orderBy!) {\n const aVal = a[column] as string | number | null | undefined;\n const bVal = b[column] as string | number | null | undefined;\n if (aVal == null && bVal == null) continue;\n if (aVal == null) return direction === \"ASC\" ? -1 : 1;\n if (bVal == null) return direction === \"ASC\" ? 1 : -1;\n if (aVal < bVal) return direction === \"ASC\" ? -1 : 1;\n if (aVal > bVal) return direction === \"ASC\" ? 1 : -1;\n }\n return 0;\n });\n }\n\n if (options?.offset !== undefined) {\n values = values.slice(options.offset);\n }\n\n if (options?.limit !== undefined) {\n values = values.slice(0, options.limit);\n }\n\n resolve(values.length > 0 ? values : undefined);\n };\n });\n }\n\n /**\n * Deletes a row from the repository.\n * @param key - The key object to delete.\n */\n async delete(key: PrimaryKey): Promise<void> {\n const db = await this.getDb();\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.table, \"readwrite\");\n const store = transaction.objectStore(this.table);\n const request = store.delete(this.getIndexedKey(key));\n request.onerror = () => reject(request.error);\n request.onsuccess = () => {\n this.events.emit(\"delete\", key as keyof Entity);\n resolve();\n };\n transaction.oncomplete = () => {\n // Notify hybrid manager of local change\n this.hybridManager?.notifyLocalChange();\n };\n });\n }\n\n /**\n * Deletes all records from the repository.\n * @emits clearall - Emitted when all values are deleted\n */\n async deleteAll(): Promise<void> {\n const db = await this.getDb();\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.table, \"readwrite\");\n const store = transaction.objectStore(this.table);\n const request = store.clear();\n request.onerror = () => reject(request.error);\n request.onsuccess = () => {\n this.events.emit(\"clearall\");\n resolve();\n };\n transaction.oncomplete = () => {\n // Notify hybrid manager of local change\n this.hybridManager?.notifyLocalChange();\n };\n });\n }\n\n /**\n * Returns the total number of rows in the repository.\n * @returns Count of stored items.\n */\n async size(): Promise<number> {\n const db = await this.getDb();\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.table, \"readonly\");\n const store = transaction.objectStore(this.table);\n const request = store.count();\n request.onerror = () => reject(request.error);\n request.onsuccess = () => resolve(request.result);\n });\n }\n\n /**\n * Returns the subset of configured indexes safe to use for cursor-based\n * narrowing — those whose every column is required by the schema. IDB\n * excludes records with undefined keyPath components from indexes, so\n * iterating an index would silently miss records when any indexed column\n * is optional.\n */\n private getCursorSafeIndexes(): Array<Array<keyof Entity>> {\n if (this.cursorSafeIndexes) return this.cursorSafeIndexes;\n const required = new Set(this.schema.required ?? []);\n this.cursorSafeIndexes = this.indexes.filter((columns) =>\n columns.every((column) => required.has(String(column)))\n );\n return this.cursorSafeIndexes;\n }\n\n /**\n * Picks the best index to narrow a criteria-based scan, preferring indexes\n * whose prefix covers every criteria column (so callers can use the native\n * `count()` API) and falling back to the longest equality-prefix match.\n *\n * Upper bound uses `[]` as a sentinel that compares greater than any\n * primitive value at the next index position (per IndexedDB key ordering:\n * array > binary > string > date > number). Assumes subsequent indexed\n * columns hold primitive values — array-valued columns would compare\n * greater than `[]` and slip outside the range.\n */\n private createIndexedRange(\n store: IDBObjectStore,\n criteria: SearchCriteria<Entity>\n ):\n | {\n source: IDBObjectStore | IDBIndex;\n range: IDBKeyRange | undefined;\n coversCriteria: boolean;\n }\n | undefined {\n const criteriaColumns = Object.keys(criteria) as Array<keyof Entity>;\n if (criteriaColumns.length === 0) return undefined;\n\n let best:\n | {\n indexName: string;\n prefixValues: unknown[];\n fullMatch: boolean;\n coversCriteria: boolean;\n }\n | undefined;\n\n for (const indexColumns of this.getCursorSafeIndexes()) {\n const prefixValues: unknown[] = [];\n for (const column of indexColumns) {\n const value = this.getEqualityCriterionValue(criteria, column);\n if (value === undefined) break;\n prefixValues.push(value);\n }\n\n if (prefixValues.length === 0) continue;\n\n const indexedPrefix = indexColumns.slice(0, prefixValues.length);\n const coversCriteria = criteriaColumns.every((column) => indexedPrefix.includes(column));\n\n const better =\n !best ||\n (coversCriteria && !best.coversCriteria) ||\n (coversCriteria === best.coversCriteria && prefixValues.length > best.prefixValues.length);\n\n if (better) {\n best = {\n indexName: indexColumns.map((column) => String(column)).join(\"_\"),\n prefixValues,\n fullMatch: prefixValues.length === indexColumns.length,\n coversCriteria,\n };\n }\n }\n\n if (!best) return undefined;\n\n const range = best.fullMatch\n ? IDBKeyRange.only(best.prefixValues.length === 1 ? best.prefixValues[0] : best.prefixValues)\n : IDBKeyRange.bound(best.prefixValues, [...best.prefixValues, []]);\n\n return {\n source: store.index(best.indexName),\n range,\n coversCriteria: best.coversCriteria,\n };\n }\n\n /**\n * Counts rows matching the specified search criteria.\n *\n * Uses the native `count()` API when an index prefix covers every criteria\n * column. Otherwise narrows via the longest matching index prefix and\n * filters the remaining columns during cursor iteration. Falls back to a\n * full store scan only when no index applies.\n */\n override async count(criteria?: SearchCriteria<Entity>): Promise<number> {\n if (!criteria || Object.keys(criteria).length === 0) {\n return await this.size();\n }\n\n this.validateQueryParams(criteria);\n const db = await this.getDb();\n\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.table, \"readonly\");\n const store = transaction.objectStore(this.table);\n const plan = this.createIndexedRange(store, criteria);\n\n if (plan?.coversCriteria) {\n const request = plan.source.count(plan.range);\n request.onerror = () => reject(request.error);\n request.onsuccess = () => resolve(request.result);\n return;\n }\n\n const source = plan?.source ?? store;\n const range = plan?.range;\n let count = 0;\n const request = source.openCursor(range);\n request.onerror = () => reject(request.error);\n request.onsuccess = () => {\n const cursor = request.result;\n if (!cursor) {\n resolve(count);\n return;\n }\n if (this.matchesCriteria(cursor.value as Entity, criteria)) {\n count += 1;\n }\n cursor.continue();\n };\n });\n }\n\n /**\n * Fetches a page of records from the repository.\n * @param offset - Number of records to skip\n * @param limit - Maximum number of records to return\n * @returns Array of entities or undefined if no records found\n */\n async getBulk(offset: number, limit: number): Promise<Entity[] | undefined> {\n if (offset < 0) {\n throw new RangeError(`offset must be non-negative, got ${offset}`);\n }\n if (limit <= 0) {\n return undefined;\n }\n\n const db = await this.getDb();\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.table, \"readonly\");\n const store = transaction.objectStore(this.table);\n const request = store.openCursor();\n const entities: Entity[] = [];\n let skipped = false;\n\n request.onerror = () => reject(request.error);\n request.onsuccess = () => {\n const cursor = request.result;\n if (cursor) {\n // Skip to offset using advance\n if (!skipped && offset > 0) {\n skipped = true;\n cursor.advance(offset);\n return;\n }\n\n // Collect records up to the limit\n entities.push(cursor.value);\n if (entities.length === limit) {\n resolve(entities);\n return;\n }\n cursor.continue();\n } else {\n // No more records\n resolve(entities.length > 0 ? entities : undefined);\n }\n };\n });\n }\n\n /**\n * Checks if a record matches all criteria conditions.\n * @param record - The record to check\n * @param criteria - The search criteria\n * @returns true if all conditions match\n */\n private matchesCriteria(record: Entity, criteria: DeleteSearchCriteria<Entity>): boolean {\n for (const column of Object.keys(criteria) as Array<keyof Entity>) {\n const criterion = criteria[column];\n const recordValue = record[column];\n\n let operator: SearchOperator = \"=\";\n let value: Entity[keyof Entity];\n\n if (isSearchCondition(criterion)) {\n operator = criterion.operator;\n value = criterion.value as Entity[keyof Entity];\n } else {\n value = criterion as Entity[keyof Entity];\n }\n\n // Skip null values for comparison operators\n if (operator !== \"=\" && (recordValue === null || recordValue === undefined)) {\n return false;\n }\n\n switch (operator) {\n case \"=\":\n if (recordValue !== value) return false;\n break;\n case \"<\":\n if (!(recordValue < value)) return false;\n break;\n case \"<=\":\n if (!(recordValue <= value)) return false;\n break;\n case \">\":\n if (!(recordValue > value)) return false;\n break;\n case \">=\":\n if (!(recordValue >= value)) return false;\n break;\n default:\n return false;\n }\n }\n return true;\n }\n\n /**\n * Deletes all entries matching the specified search criteria.\n * Supports multiple columns with optional comparison operators.\n *\n * @param criteria - Object with column names as keys and values or SearchConditions\n */\n async deleteSearch(criteria: DeleteSearchCriteria<Entity>): Promise<void> {\n const criteriaKeys = Object.keys(criteria) as Array<keyof Entity>;\n if (criteriaKeys.length === 0) {\n return;\n }\n\n const db = await this.getDb();\n\n return new Promise(async (resolve, reject) => {\n try {\n const transaction = db.transaction(this.table, \"readwrite\");\n const store = transaction.objectStore(this.table);\n\n // Set up transaction event handlers\n transaction.oncomplete = () => {\n this.events.emit(\"delete\", criteriaKeys[0] as keyof Entity);\n // Notify hybrid manager of local change\n this.hybridManager?.notifyLocalChange();\n resolve();\n };\n\n transaction.onerror = () => {\n reject(transaction.error);\n };\n\n // Get all records and filter\n const getAllRequest = store.getAll();\n\n getAllRequest.onsuccess = () => {\n const allRecords: Entity[] = getAllRequest.result;\n\n // Filter records that match all criteria\n const recordsToDelete = allRecords.filter((record) =>\n this.matchesCriteria(record, criteria)\n );\n\n if (recordsToDelete.length === 0) {\n // No records to delete\n return;\n }\n\n // Delete each record that matches the criteria\n for (const record of recordsToDelete) {\n // Extract the primary key from the record\n const primaryKey = this.primaryKeyColumns().reduce((key, col) => {\n // @ts-ignore - We know these properties exist on the record\n key[col] = record[col];\n return key;\n }, {} as PrimaryKey);\n\n // Delete the record using the primary key\n const request = store.delete(this.getIndexedKey(primaryKey));\n\n request.onerror = () => {\n console.error(\"Error deleting record:\", request.error);\n };\n }\n };\n\n getAllRequest.onerror = () => {\n reject(getAllRequest.error);\n };\n } catch (error) {\n reject(error);\n }\n });\n }\n\n private getEqualityCriterionValue(\n criteria: SearchCriteria<Entity>,\n column: keyof Entity\n ): Entity[keyof Entity] | undefined {\n const criterion = criteria[column];\n if (criterion === undefined) return undefined;\n if (isSearchCondition(criterion)) {\n return criterion.operator === \"=\" ? (criterion.value as Entity[keyof Entity]) : undefined;\n }\n return criterion as Entity[keyof Entity];\n }\n\n private compareByOrder(a: Entity, b: Entity, options?: QueryOptions<Entity>): number {\n if (!options?.orderBy) return 0;\n for (const { column, direction } of options.orderBy) {\n const aVal = a[column] as string | number | null | undefined;\n const bVal = b[column] as string | number | null | undefined;\n if (aVal == null && bVal == null) continue;\n if (aVal == null) return direction === \"ASC\" ? -1 : 1;\n if (bVal == null) return direction === \"ASC\" ? 1 : -1;\n if (aVal < bVal) return direction === \"ASC\" ? -1 : 1;\n if (aVal > bVal) return direction === \"ASC\" ? 1 : -1;\n }\n return 0;\n }\n\n private createIndexedQuery(\n store: IDBObjectStore,\n criteria: SearchCriteria<Entity>,\n options?: QueryOptions<Entity>\n ): {\n source: IDBObjectStore | IDBIndex;\n range: IDBKeyRange | undefined;\n direction: IDBCursorDirection;\n satisfiesOrder: boolean;\n appliedLimit: boolean;\n appliedOffset: boolean;\n skipRemaining: number;\n } {\n const orderBy = options?.orderBy ?? [];\n let best:\n | {\n indexName: string;\n prefixValues: unknown[];\n fullMatch: boolean;\n satisfiesOrder: boolean;\n direction: IDBCursorDirection;\n }\n | undefined;\n\n for (const indexColumns of this.getCursorSafeIndexes()) {\n const prefixValues: unknown[] = [];\n for (const column of indexColumns) {\n const value = this.getEqualityCriterionValue(criteria, column);\n if (value === undefined) break;\n prefixValues.push(value);\n }\n\n if (prefixValues.length === 0) continue;\n\n const remainingColumns = indexColumns.slice(prefixValues.length);\n let redundantOrderPrefixLength = 0;\n while (\n redundantOrderPrefixLength < orderBy.length &&\n redundantOrderPrefixLength < prefixValues.length &&\n orderBy[redundantOrderPrefixLength]?.column === indexColumns[redundantOrderPrefixLength]\n ) {\n redundantOrderPrefixLength++;\n }\n const normalizedOrderBy = orderBy.slice(redundantOrderPrefixLength);\n const satisfiesOrder =\n normalizedOrderBy.length === 0 ||\n (normalizedOrderBy.length <= remainingColumns.length &&\n normalizedOrderBy.every((order, index) => order.column === remainingColumns[index]) &&\n orderBy.every((order) => order.direction === orderBy[0]?.direction));\n\n if (!satisfiesOrder && best) continue;\n\n if (\n !best ||\n (satisfiesOrder && !best.satisfiesOrder) ||\n prefixValues.length > best.prefixValues.length\n ) {\n best = {\n indexName: indexColumns.map((column) => String(column)).join(\"_\"),\n prefixValues,\n fullMatch: prefixValues.length === indexColumns.length,\n satisfiesOrder,\n direction: orderBy[0]?.direction === \"DESC\" ? \"prev\" : \"next\",\n };\n }\n }\n\n const appliedLimit = Boolean(best?.satisfiesOrder && options?.limit !== undefined);\n const appliedOffset = Boolean(best?.satisfiesOrder && options?.offset !== undefined);\n\n if (!best) {\n return {\n source: store,\n range: undefined,\n direction: orderBy[0]?.direction === \"DESC\" ? \"prev\" : \"next\",\n satisfiesOrder: false,\n appliedLimit: false,\n appliedOffset: false,\n skipRemaining: 0,\n };\n }\n\n const source = store.index(best.indexName);\n // See createIndexedRange for the `[]` upper-bound sentinel rationale.\n const keyRange = best.fullMatch\n ? IDBKeyRange.only(best.prefixValues.length === 1 ? best.prefixValues[0] : best.prefixValues)\n : IDBKeyRange.bound(best.prefixValues, [...best.prefixValues, []]);\n\n return {\n source,\n range: keyRange,\n direction: best.direction,\n satisfiesOrder: best.satisfiesOrder,\n appliedLimit,\n appliedOffset,\n skipRemaining: appliedOffset ? (options?.offset ?? 0) : 0,\n };\n }\n\n /**\n * Queries entries matching the specified search criteria with optional ordering, limit, and offset.\n *\n * @param criteria - Object with column names as keys and values or SearchConditions\n * @param options - Optional ordering, limit, and offset options\n * @returns Array of matching entities or undefined if no matches found\n */\n async query(\n criteria: SearchCriteria<Entity>,\n options?: QueryOptions<Entity>\n ): Promise<Entity[] | undefined> {\n this.validateQueryParams(criteria, options);\n const db = await this.getDb();\n\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.table, \"readonly\");\n const store = transaction.objectStore(this.table);\n const indexedQuery = this.createIndexedQuery(store, criteria, options);\n const results: Entity[] = [];\n const request = indexedQuery.source.openCursor(indexedQuery.range, indexedQuery.direction);\n\n request.onsuccess = () => {\n const cursor = request.result;\n if (!cursor) {\n let finalResults = results;\n\n if (!indexedQuery.satisfiesOrder && options?.orderBy && options.orderBy.length > 0) {\n finalResults = [...finalResults].sort((a, b) => this.compareByOrder(a, b, options));\n }\n\n if (!indexedQuery.appliedOffset && options?.offset !== undefined) {\n finalResults = finalResults.slice(options.offset);\n }\n\n if (!indexedQuery.appliedLimit && options?.limit !== undefined) {\n finalResults = finalResults.slice(0, options.limit);\n }\n\n const result = finalResults.length > 0 ? finalResults : undefined;\n this.events.emit(\"query\", criteria as Partial<Entity>, result);\n resolve(result);\n return;\n }\n\n const record = cursor.value as Entity;\n if (this.matchesCriteria(record, criteria)) {\n if (indexedQuery.skipRemaining > 0) {\n indexedQuery.skipRemaining -= 1;\n } else {\n results.push(record);\n if (indexedQuery.appliedLimit && results.length === options?.limit) {\n const result = results.length > 0 ? results : undefined;\n this.events.emit(\"query\", criteria as Partial<Entity>, result);\n resolve(result);\n return;\n }\n }\n }\n\n cursor.continue();\n };\n\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Strict, projected query served entirely by a covering compound index.\n * Uses `openKeyCursor` — never reads `cursor.value` — so only the index key\n * bytes are loaded into memory. Ideal for tables with large value blobs.\n *\n * Throws {@link CoveringIndexMissingError} when no registered index can serve\n * the request (i.e. the index does not cover all select + orderBy columns).\n */\n override async queryIndex<K extends keyof Entity & string>(\n criteria: SearchCriteria<Entity>,\n options: CoveringIndexQueryOptions<Entity, K>\n ): Promise<Pick<Entity, K>[]> {\n this.validateSelect(options);\n this.validateQueryParams(criteria, options);\n\n const registered = this.indexes.map((cols) => {\n const cs = Array.isArray(cols) ? (cols as string[]) : [cols as string];\n return { name: cs.join(\"_\"), keyPath: cs };\n });\n\n const picked = pickCoveringIndex({\n table: this.table,\n indexes: registered,\n criteriaColumns: Object.keys(criteria),\n orderByColumns: (options.orderBy ?? []).map((o) => ({\n column: String(o.column),\n direction: o.direction,\n })),\n selectColumns: options.select.map(String),\n primaryKeyColumns: this.primaryKeyColumns().map(String),\n });\n\n const db = await this.getDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(this.table, \"readonly\");\n const store = tx.objectStore(this.table);\n const idx = store.index(picked.name);\n\n // Build the equality prefix key range from criteria values.\n // Only push columns whose criterion is a direct equality value (plain value or operator \"=\").\n // Any non-equality operator (>, <, etc.) breaks the prefix; the existing in-cursor\n // compareWithOperator filter below handles those columns.\n const prefix: unknown[] = [];\n for (const col of picked.keyPath) {\n const c = (criteria as Record<string, unknown>)[col];\n if (c === undefined && !(col in (criteria as Record<string, unknown>))) break;\n if (isSearchCondition(c)) {\n if (c.operator !== \"=\") break;\n prefix.push(c.value);\n } else {\n prefix.push(c);\n }\n }\n // Use IDBKeyRange.bound with [] upper sentinel for prefix scans on compound keys.\n // `[...prefix, []]` is greater than any key starting with prefix in IDB's comparison.\n const range =\n prefix.length === 0\n ? undefined\n : prefix.length === picked.keyPath.length\n ? IDBKeyRange.only(prefix.length === 1 ? prefix[0] : prefix)\n : IDBKeyRange.bound(prefix, [...prefix, []]);\n\n const direction: IDBCursorDirection = picked.reverseDirection ? \"prev\" : \"next\";\n // openKeyCursor — never reads cursor.value, only the index key and primaryKey\n const request = idx.openKeyCursor(range, direction);\n const out: Pick<Entity, K>[] = [];\n let toSkip = options.offset ?? 0;\n\n // Precompute lookup maps for the cursor loop (O(keyPath) once, not per-row)\n const keyPathPositions = new Map<string, number>();\n picked.keyPath.forEach((col, i) => keyPathPositions.set(col, i));\n\n const pkCols = this.primaryKeyColumns().map(String);\n const pkPositions = new Map<string, number>();\n pkCols.forEach((col, i) => pkPositions.set(col, i));\n\n request.onsuccess = () => {\n const cursor = request.result;\n if (!cursor) {\n resolve(out);\n return;\n }\n\n const key = cursor.key;\n\n // Decode projected columns from the index key array and primaryKey\n const row = {} as Record<string, unknown>;\n for (const col of options.select) {\n const colStr = String(col);\n const pos = keyPathPositions.get(colStr);\n if (pos !== undefined) {\n // Column is in the index key path — extract from key array\n row[colStr] = Array.isArray(key) ? key[pos] : key;\n } else {\n // Column must be a primary key column — use cursor.primaryKey\n if (pkCols.length === 1 && colStr === pkCols[0]) {\n row[colStr] = cursor.primaryKey;\n } else {\n const pkPos = pkPositions.get(colStr);\n if (pkPos !== undefined) {\n row[colStr] = Array.isArray(cursor.primaryKey)\n ? (cursor.primaryKey as unknown[])[pkPos]\n : cursor.primaryKey;\n }\n }\n }\n }\n\n // Apply criteria for index positions beyond the equality prefix.\n // Positions [0, prefix.length) are guaranteed-equal by the IDBKeyRange,\n // so they don't need re-checking. Positions >= prefix.length must be\n // filtered here — this includes plain-value equalities trailing a\n // non-equality break (criteria like `{a:1, b:>=5, c:3}` with prefix=[1]\n // need an in-cursor `c === 3` check) and any SearchCondition.\n let matches = true;\n for (const [col, crit] of Object.entries(criteria as Record<string, unknown>)) {\n const pos = keyPathPositions.get(col);\n if (pos === undefined) continue;\n if (pos < prefix.length) continue; // covered by IDBKeyRange\n const valFromKey = Array.isArray(key) ? (key as unknown[])[pos] : key;\n const op: SearchOperator = isSearchCondition(crit) ? crit.operator : \"=\";\n const val = isSearchCondition(crit) ? crit.value : crit;\n if (!compareWithOperator(valFromKey, op, val)) {\n matches = false;\n break;\n }\n }\n\n if (matches) {\n if (toSkip > 0) {\n toSkip -= 1;\n } else {\n out.push(row as Pick<Entity, K>);\n if (options.limit !== undefined && out.length >= options.limit) {\n resolve(out);\n return;\n }\n }\n }\n\n cursor.continue();\n };\n\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Gets or creates the shared hybrid subscription manager.\n * This ensures all subscriptions share a single manager.\n */\n private getHybridManager(): HybridSubscriptionManager<\n Entity,\n string,\n TabularChangePayload<Entity>\n > {\n if (!this.hybridManager) {\n // Generate unique channel name based on table name\n const channelName = `indexeddb-tabular-${this.table}`;\n\n this.hybridManager = new HybridSubscriptionManager<\n Entity,\n string,\n TabularChangePayload<Entity>\n >(\n channelName,\n async () => {\n // Fetch all entities and create a map keyed by entity fingerprint\n const entities = (await this.getAll()) || [];\n const map = new Map<string, Entity>();\n for (const entity of entities) {\n const { key } = this.separateKeyValueFromCombined(entity);\n const fingerprint = await makeFingerprint(key);\n map.set(fingerprint, entity);\n }\n return map;\n },\n compareEntitiesForChange,\n {\n insert: (item) => ({ type: \"INSERT\" as const, new: item }),\n update: (oldItem, newItem) => ({ type: \"UPDATE\" as const, old: oldItem, new: newItem }),\n delete: (item) => ({ type: \"DELETE\" as const, old: item }),\n },\n {\n defaultIntervalMs: 1000,\n useBroadcastChannel: this.hybridOptions.useBroadcastChannel,\n backupPollingIntervalMs: this.hybridOptions.backupPollingIntervalMs,\n }\n );\n }\n return this.hybridManager;\n }\n\n /**\n * Subscribes to changes in the repository.\n * Uses polling since IndexedDB has no native cross-tab change notifications.\n *\n * @param callback - Function called when a change occurs\n * @param options - Optional subscription options including polling interval\n * @returns Unsubscribe function\n */\n public override subscribeToChanges(\n callback: (change: TabularChangePayload<Entity>) => void,\n options?: TabularSubscribeOptions\n ): () => void {\n // Note: We don't await setupDatabase() here to keep the method synchronous\n // The getAll() method in the hybrid manager will call setupDatabase() when needed\n const intervalMs = options?.pollingIntervalMs ?? 1000;\n const manager = this.getHybridManager();\n return manager.subscribe(callback, { intervalMs });\n }\n\n /**\n * Destroys this repository and frees up resources.\n */\n public override destroy(): void {\n if (this.hybridManager) {\n this.hybridManager.destroy();\n this.hybridManager = null;\n }\n this.db?.close();\n }\n}\n\n/**\n * Compare two values using a SearchOperator. Used by queryIndex to evaluate\n * non-equality criteria that cannot be expressed as an IDBKeyRange prefix.\n */\nfunction compareWithOperator(a: unknown, op: SearchOperator, b: unknown): boolean {\n const av = a as string | number | null | undefined;\n const bv = b as string | number;\n switch (op) {\n case \"=\":\n return av === bv;\n case \"<\":\n return av !== null && av !== undefined && av < bv;\n case \"<=\":\n return av !== null && av !== undefined && av <= bv;\n case \">\":\n return av !== null && av !== undefined && av > bv;\n case \">=\":\n return av !== null && av !== undefined && av >= bv;\n }\n}\n",
|
|
54
54
|
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Production-ready IndexedDB table management with proper migration support.\n// Handles schema evolution without data loss by incrementally migrating the database\n// structure and transforming existing data as needed.\n\nimport { deepEqual } from \"@workglow/util\";\n\nexport interface ExpectedIndexDefinition {\n name: string;\n keyPath: string | string[];\n options?: IDBIndexParameters;\n}\n\nexport interface MigrationContext {\n db: IDBDatabase;\n transaction: IDBTransaction;\n oldVersion: number;\n newVersion: number;\n tableName: string;\n}\n\nexport interface DataTransformer {\n (oldData: any): any | Promise<any>;\n}\n\nexport interface MigrationOptions {\n /** Custom data transformer to apply during migration */\n dataTransformer?: DataTransformer;\n /** Whether to allow destructive operations (delete and recreate). Default: false */\n allowDestructiveMigration?: boolean;\n /** Callback for migration progress/logging */\n onMigrationProgress?: (message: string, progress?: number) => void;\n /** Callback for migration errors (non-fatal warnings) */\n onMigrationWarning?: (message: string, error?: Error) => void;\n}\n\ninterface SchemaSnapshot {\n version: number;\n primaryKey: string | string[];\n indexes: ExpectedIndexDefinition[];\n recordCount?: number;\n timestamp: number;\n}\n\nconst METADATA_STORE_NAME = \"__schema_metadata__\";\n\n/**\n * Stores metadata about the database schema for migration tracking\n */\nasync function saveSchemaMetadata(\n db: IDBDatabase,\n tableName: string,\n snapshot: SchemaSnapshot\n): Promise<void> {\n return new Promise((resolve, reject) => {\n try {\n const transaction = db.transaction(METADATA_STORE_NAME, \"readwrite\");\n const store = transaction.objectStore(METADATA_STORE_NAME);\n const request = store.put({ ...snapshot, tableName }, tableName);\n\n request.onsuccess = () => resolve();\n request.onerror = () => reject(request.error);\n transaction.onerror = () => reject(transaction.error);\n } catch (err) {\n // Metadata store might not exist in old databases, that's OK\n resolve();\n }\n });\n}\n\n/**\n * Opens an IndexedDB database with proper error handling\n */\nasync function openIndexedDbTable(\n tableName: string,\n version?: number,\n upgradeNeededCallback?: (event: IDBVersionChangeEvent) => void\n): Promise<IDBDatabase> {\n return new Promise((resolve, reject) => {\n const openRequest = indexedDB.open(tableName, version);\n\n openRequest.onsuccess = (event) => {\n const db = (event.target as IDBOpenDBRequest).result;\n\n // Handle unexpected close\n db.onversionchange = () => {\n db.close();\n };\n\n resolve(db);\n };\n\n openRequest.onupgradeneeded = (event) => {\n if (upgradeNeededCallback) {\n upgradeNeededCallback(event);\n }\n };\n\n openRequest.onerror = () => {\n const error = openRequest.error;\n // Check if it's a VersionError - this means the database exists at a higher version\n if (error && error.name === \"VersionError\") {\n reject(\n new Error(\n `Database ${tableName} exists at a higher version. Cannot open at version ${version || \"current\"}.`\n )\n );\n } else {\n reject(error);\n }\n };\n openRequest.onblocked = () => {\n reject(\n new Error(`Database ${tableName} is blocked. Close all other tabs using this database.`)\n );\n };\n });\n}\n\n/**\n * Deletes an IndexedDB database completely\n */\nasync function deleteIndexedDbTable(tableName: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const deleteRequest = indexedDB.deleteDatabase(tableName);\n\n deleteRequest.onsuccess = () => resolve();\n deleteRequest.onerror = () => reject(deleteRequest.error);\n deleteRequest.onblocked = () => {\n reject(\n new Error(`Cannot delete database ${tableName}. Close all other tabs using this database.`)\n );\n };\n });\n}\n\n/**\n * Compares two schema definitions to determine what changes are needed\n */\ninterface SchemaDiff {\n indexesToAdd: ExpectedIndexDefinition[];\n indexesToRemove: string[];\n indexesToModify: ExpectedIndexDefinition[];\n primaryKeyChanged: boolean;\n needsObjectStoreRecreation: boolean;\n}\n\nfunction compareSchemas(\n store: IDBObjectStore,\n expectedPrimaryKey: string | string[],\n expectedIndexes: ExpectedIndexDefinition[]\n): SchemaDiff {\n const diff: SchemaDiff = {\n indexesToAdd: [],\n indexesToRemove: [],\n indexesToModify: [],\n primaryKeyChanged: false,\n needsObjectStoreRecreation: false,\n };\n\n // Check primary key\n const actualKeyPath = store.keyPath;\n const normalizedExpected = Array.isArray(expectedPrimaryKey)\n ? expectedPrimaryKey\n : expectedPrimaryKey;\n const normalizedActual = Array.isArray(actualKeyPath) ? actualKeyPath : actualKeyPath;\n\n if (!deepEqual(normalizedExpected, normalizedActual)) {\n diff.primaryKeyChanged = true;\n diff.needsObjectStoreRecreation = true;\n return diff; // If primary key changed, we need full recreation\n }\n\n // Build a map of existing indexes\n const existingIndexes = new Map<string, IDBIndex>();\n for (let i = 0; i < store.indexNames.length; i++) {\n const indexName = store.indexNames[i];\n existingIndexes.set(indexName, store.index(indexName));\n }\n\n // Check for indexes to add or modify\n for (const expectedIdx of expectedIndexes) {\n const existingIdx = existingIndexes.get(expectedIdx.name);\n\n if (!existingIdx) {\n diff.indexesToAdd.push(expectedIdx);\n } else {\n // Compare index properties\n const expectedKeyPath = Array.isArray(expectedIdx.keyPath)\n ? expectedIdx.keyPath\n : [expectedIdx.keyPath];\n const actualKeyPath = Array.isArray(existingIdx.keyPath)\n ? existingIdx.keyPath\n : [existingIdx.keyPath];\n\n const keyPathChanged = !deepEqual(expectedKeyPath, actualKeyPath);\n const uniqueChanged = existingIdx.unique !== (expectedIdx.options?.unique ?? false);\n const multiEntryChanged =\n existingIdx.multiEntry !== (expectedIdx.options?.multiEntry ?? false);\n\n if (keyPathChanged || uniqueChanged || multiEntryChanged) {\n diff.indexesToModify.push(expectedIdx);\n }\n\n existingIndexes.delete(expectedIdx.name);\n }\n }\n\n // Remaining indexes should be removed\n diff.indexesToRemove = Array.from(existingIndexes.keys());\n\n return diff;\n}\n\n/**\n * Reads all data from a store\n */\nasync function readAllData(store: IDBObjectStore): Promise<any[]> {\n return new Promise((resolve, reject) => {\n const request = store.getAll();\n request.onsuccess = () => resolve(request.result || []);\n request.onerror = () => reject(request.error);\n });\n}\n\n/**\n * Performs a non-destructive migration by adding/removing indexes\n */\nasync function performIncrementalMigration(\n db: IDBDatabase,\n tableName: string,\n diff: SchemaDiff,\n options: MigrationOptions = {}\n): Promise<IDBDatabase> {\n const currentVersion = db.version;\n const newVersion = currentVersion + 1;\n\n db.close();\n\n options.onMigrationProgress?.(\n `Migrating ${tableName} from version ${currentVersion} to ${newVersion}...`,\n 0\n );\n\n return openIndexedDbTable(tableName, newVersion, (event: IDBVersionChangeEvent) => {\n const transaction = (event.target as IDBOpenDBRequest).transaction!;\n const store = transaction.objectStore(tableName);\n\n // Remove outdated indexes\n for (const indexName of diff.indexesToRemove) {\n options.onMigrationProgress?.(`Removing index: ${indexName}`, 0.2);\n store.deleteIndex(indexName);\n }\n\n // Remove and recreate modified indexes\n for (const indexDef of diff.indexesToModify) {\n options.onMigrationProgress?.(`Updating index: ${indexDef.name}`, 0.4);\n if (store.indexNames.contains(indexDef.name)) {\n store.deleteIndex(indexDef.name);\n }\n store.createIndex(indexDef.name, indexDef.keyPath, indexDef.options);\n }\n\n // Add new indexes\n for (const indexDef of diff.indexesToAdd) {\n options.onMigrationProgress?.(`Adding index: ${indexDef.name}`, 0.6);\n store.createIndex(indexDef.name, indexDef.keyPath, indexDef.options);\n }\n\n options.onMigrationProgress?.(`Migration complete`, 1.0);\n });\n}\n\n/**\n * Performs a destructive migration by recreating the object store\n * This is needed when the primary key changes\n */\nasync function performDestructiveMigration(\n db: IDBDatabase,\n tableName: string,\n primaryKey: string | string[],\n expectedIndexes: ExpectedIndexDefinition[],\n options: MigrationOptions = {},\n autoIncrement: boolean = false\n): Promise<IDBDatabase> {\n if (!options.allowDestructiveMigration) {\n throw new Error(\n `Destructive migration required for ${tableName} but not allowed. ` +\n `Primary key has changed. Set allowDestructiveMigration=true to proceed with data loss, ` +\n `or provide a dataTransformer to migrate data.`\n );\n }\n\n const currentVersion = db.version;\n const newVersion = currentVersion + 1;\n\n options.onMigrationProgress?.(\n `Performing destructive migration of ${tableName}. Reading existing data...`,\n 0\n );\n\n // Read all existing data\n let existingData: any[] = [];\n try {\n const transaction = db.transaction(tableName, \"readonly\");\n const store = transaction.objectStore(tableName);\n existingData = await readAllData(store);\n options.onMigrationProgress?.(`Read ${existingData.length} records`, 0.3);\n } catch (err) {\n options.onMigrationWarning?.(\n `Failed to read existing data during migration: ${err}`,\n err as Error\n );\n }\n\n db.close();\n\n // Apply data transformer if provided\n if (options.dataTransformer && existingData.length > 0) {\n options.onMigrationProgress?.(`Transforming ${existingData.length} records...`, 0.4);\n try {\n const transformed = [];\n for (let i = 0; i < existingData.length; i++) {\n const record = existingData[i];\n const transformedRecord = await options.dataTransformer(record);\n if (transformedRecord !== undefined && transformedRecord !== null) {\n transformed.push(transformedRecord);\n }\n if (i % 100 === 0) {\n options.onMigrationProgress?.(\n `Transformed ${i}/${existingData.length} records`,\n 0.4 + (i / existingData.length) * 0.3\n );\n }\n }\n existingData = transformed;\n options.onMigrationProgress?.(`Transformation complete: ${existingData.length} records`, 0.7);\n } catch (err) {\n options.onMigrationWarning?.(\n `Data transformation failed: ${err}. Some data may be lost.`,\n err as Error\n );\n existingData = [];\n }\n }\n\n // Open with new version and recreate object store\n options.onMigrationProgress?.(`Recreating object store...`, 0.75);\n\n const newDb = await openIndexedDbTable(tableName, newVersion, (event: IDBVersionChangeEvent) => {\n const db = (event.target as IDBOpenDBRequest).result;\n\n // Delete old object store if it exists\n if (db.objectStoreNames.contains(tableName)) {\n db.deleteObjectStore(tableName);\n }\n\n // Create new object store with new schema\n const store = db.createObjectStore(tableName, { keyPath: primaryKey, autoIncrement });\n\n // Create indexes\n for (const idx of expectedIndexes) {\n store.createIndex(idx.name, idx.keyPath, idx.options);\n }\n\n // Restore data\n if (existingData.length > 0) {\n options.onMigrationProgress?.(`Restoring ${existingData.length} records...`, 0.8);\n\n for (const record of existingData) {\n try {\n store.put(record);\n } catch (err) {\n options.onMigrationWarning?.(`Failed to restore record: ${err}`, err as Error);\n }\n }\n }\n });\n\n options.onMigrationProgress?.(`Destructive migration complete`, 1.0);\n\n return newDb;\n}\n\n/**\n * Creates a new database with the specified schema\n */\nasync function createNewDatabase(\n tableName: string,\n primaryKey: string | string[],\n expectedIndexes: ExpectedIndexDefinition[],\n options: MigrationOptions = {},\n autoIncrement: boolean = false\n): Promise<IDBDatabase> {\n options.onMigrationProgress?.(`Creating new database: ${tableName}`, 0);\n\n // Delete existing database if it exists to avoid version conflicts\n try {\n await deleteIndexedDbTable(tableName);\n // Wait a bit for deletion to complete\n await new Promise((resolve) => setTimeout(resolve, 50));\n } catch (err) {\n // Ignore errors - database might not exist\n }\n\n const version = 1;\n\n const db = await openIndexedDbTable(tableName, version, (event: IDBVersionChangeEvent) => {\n const db = (event.target as IDBOpenDBRequest).result;\n\n // Create metadata store\n if (!db.objectStoreNames.contains(METADATA_STORE_NAME)) {\n db.createObjectStore(METADATA_STORE_NAME, { keyPath: \"tableName\" });\n }\n\n // Create main object store\n const store = db.createObjectStore(tableName, { keyPath: primaryKey, autoIncrement });\n\n // Create indexes\n for (const idx of expectedIndexes) {\n store.createIndex(idx.name, idx.keyPath, idx.options);\n }\n });\n\n // Save schema metadata\n const snapshot: SchemaSnapshot = {\n version: db.version,\n primaryKey,\n indexes: expectedIndexes,\n recordCount: 0,\n timestamp: Date.now(),\n };\n\n await saveSchemaMetadata(db, tableName, snapshot);\n\n options.onMigrationProgress?.(`Database created successfully`, 1.0);\n\n return db;\n}\n\n/**\n * Ensures that an IndexedDB table exists with the specified schema.\n * Performs migrations as needed without data loss when possible.\n */\nexport async function ensureIndexedDbTable(\n tableName: string,\n primaryKey: string | string[],\n expectedIndexes: ExpectedIndexDefinition[] = [],\n options: MigrationOptions = {},\n autoIncrement: boolean = false\n): Promise<IDBDatabase> {\n try {\n // Try to open existing database at current version (or create if doesn't exist)\n let db: IDBDatabase;\n let wasJustCreated = false;\n try {\n // Open without version - this will open at current version if exists, or create at version 1 if doesn't exist\n db = await openIndexedDbTable(tableName);\n\n // Check if database was just created (version 1 and no object stores)\n // This happens when indexedDB.open creates a new database without stores\n if (db.version === 1 && !db.objectStoreNames.contains(tableName)) {\n wasJustCreated = true;\n db.close();\n }\n } catch (err: any) {\n // If opening fails, database might not exist or there's a version conflict\n // Try to create it fresh\n options.onMigrationProgress?.(\n `Database ${tableName} does not exist or has version conflict, creating...`,\n 0\n );\n return await createNewDatabase(\n tableName,\n primaryKey,\n expectedIndexes,\n options,\n autoIncrement\n );\n }\n\n // If database was just created, we need to create the stores\n // We'll upgrade from version 1 to version 1 (which triggers onupgradeneeded with oldVersion=0)\n // Actually, we need to explicitly create at version 1 with stores\n if (wasJustCreated) {\n options.onMigrationProgress?.(`Creating new database: ${tableName}`, 0);\n // Delete the empty database and create it properly at version 1\n try {\n await deleteIndexedDbTable(tableName);\n await new Promise((resolve) => setTimeout(resolve, 50));\n } catch (err) {\n // Ignore errors\n }\n\n // Create at version 1 with stores\n db = await openIndexedDbTable(tableName, 1, (event: IDBVersionChangeEvent) => {\n const db = (event.target as IDBOpenDBRequest).result;\n\n // Create metadata store\n if (!db.objectStoreNames.contains(METADATA_STORE_NAME)) {\n db.createObjectStore(METADATA_STORE_NAME, { keyPath: \"tableName\" });\n }\n\n // Create main object store\n const store = db.createObjectStore(tableName, { keyPath: primaryKey, autoIncrement });\n\n // Create indexes\n for (const idx of expectedIndexes) {\n store.createIndex(idx.name, idx.keyPath, idx.options);\n }\n });\n\n // Save schema metadata\n const snapshot: SchemaSnapshot = {\n version: db.version,\n primaryKey,\n indexes: expectedIndexes,\n recordCount: 0,\n timestamp: Date.now(),\n };\n await saveSchemaMetadata(db, tableName, snapshot);\n\n options.onMigrationProgress?.(`Database created successfully`, 1.0);\n return db;\n }\n\n // Ensure metadata store exists\n if (!db.objectStoreNames.contains(METADATA_STORE_NAME)) {\n const currentVersion = db.version;\n db.close();\n\n db = await openIndexedDbTable(\n tableName,\n currentVersion + 1,\n (event: IDBVersionChangeEvent) => {\n const db = (event.target as IDBOpenDBRequest).result;\n if (!db.objectStoreNames.contains(METADATA_STORE_NAME)) {\n db.createObjectStore(METADATA_STORE_NAME, { keyPath: \"tableName\" });\n }\n }\n );\n }\n\n // Check if table structure matches expected\n if (!db.objectStoreNames.contains(tableName)) {\n // Object store doesn't exist, create it\n options.onMigrationProgress?.(`Object store ${tableName} does not exist, creating...`, 0);\n db.close();\n return await createNewDatabase(\n tableName,\n primaryKey,\n expectedIndexes,\n options,\n autoIncrement\n );\n }\n\n // Compare schemas to determine what migration is needed\n const transaction = db.transaction(tableName, \"readonly\");\n const store = transaction.objectStore(tableName);\n const diff = compareSchemas(store, primaryKey, expectedIndexes);\n\n await new Promise<void>((resolve) => {\n transaction.oncomplete = () => resolve();\n transaction.onerror = () => resolve();\n });\n\n // Determine migration strategy\n const needsMigration =\n diff.indexesToAdd.length > 0 ||\n diff.indexesToRemove.length > 0 ||\n diff.indexesToModify.length > 0 ||\n diff.needsObjectStoreRecreation;\n\n if (!needsMigration) {\n // Schema matches, no migration needed\n options.onMigrationProgress?.(`Schema for ${tableName} is up to date`, 1.0);\n\n // Update metadata anyway to keep timestamp current\n const snapshot: SchemaSnapshot = {\n version: db.version,\n primaryKey,\n indexes: expectedIndexes,\n timestamp: Date.now(),\n };\n await saveSchemaMetadata(db, tableName, snapshot);\n\n return db;\n }\n\n // Perform appropriate migration\n if (diff.needsObjectStoreRecreation) {\n options.onMigrationProgress?.(\n `Schema change requires object store recreation for ${tableName}`,\n 0\n );\n db = await performDestructiveMigration(\n db,\n tableName,\n primaryKey,\n expectedIndexes,\n options,\n autoIncrement\n );\n } else {\n options.onMigrationProgress?.(`Performing incremental migration for ${tableName}`, 0);\n db = await performIncrementalMigration(db, tableName, diff, options);\n }\n\n // Save updated metadata\n const snapshot: SchemaSnapshot = {\n version: db.version,\n primaryKey,\n indexes: expectedIndexes,\n timestamp: Date.now(),\n };\n await saveSchemaMetadata(db, tableName, snapshot);\n\n return db;\n } catch (err) {\n options.onMigrationWarning?.(`Migration failed for ${tableName}: ${err}`, err as Error);\n throw err;\n }\n}\n\n/**\n * Utility function to delete a database (for testing or cleanup)\n */\nexport async function dropIndexedDbTable(tableName: string): Promise<void> {\n return deleteIndexedDbTable(tableName);\n}\n",
|
|
55
|
-
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { createServiceToken } from \"@workglow/util\";\nimport {\n ensureIndexedDbTable,\n ExpectedIndexDefinition,\n MigrationOptions,\n} from \"../util/IndexedDbTable\";\nimport type { PrefixColumn } from \"../queue/IQueueStorage\";\nimport { IRateLimiterStorage, RateLimiterStorageOptions } from \"./IRateLimiterStorage\";\n\nexport const INDEXED_DB_RATE_LIMITER_STORAGE = createServiceToken<IRateLimiterStorage>(\n \"ratelimiter.storage.indexedDb\"\n);\n\n/**\n * Extended options for IndexedDB rate limiter storage including prefix support.\n */\nexport interface IndexedDbRateLimiterStorageOptions\n extends RateLimiterStorageOptions, MigrationOptions {}\n\n/**\n * Execution record stored in IndexedDB.\n */\ninterface ExecutionRecord {\n readonly id?: string;\n readonly queue_name: string;\n readonly executed_at: string;\n readonly [key: string]: unknown;\n}\n\n/**\n * Next available record stored in IndexedDB.\n */\ninterface NextAvailableRecord {\n readonly queue_name: string;\n readonly next_available_at: string;\n readonly [key: string]: unknown;\n}\n\n/**\n * IndexedDB implementation of rate limiter storage.\n * Manages execution records and next available times for rate limiting.\n */\nexport class IndexedDbRateLimiterStorage implements IRateLimiterStorage {\n private executionDb: IDBDatabase | undefined;\n private nextAvailableDb: IDBDatabase | undefined;\n private readonly executionTableName: string;\n private readonly nextAvailableTableName: string;\n private readonly migrationOptions: MigrationOptions;\n /** The prefix column definitions */\n protected readonly prefixes: readonly PrefixColumn[];\n /** The prefix values for filtering */\n protected readonly prefixValues: Readonly<Record<string, string | number>>;\n\n constructor(options: IndexedDbRateLimiterStorageOptions = {}) {\n this.migrationOptions = options;\n this.prefixes = options.prefixes ?? [];\n this.prefixValues = options.prefixValues ?? {};\n\n // Generate table names based on prefix configuration\n if (this.prefixes.length > 0) {\n const prefixNames = this.prefixes.map((p) => p.name).join(\"_\");\n this.executionTableName = `rate_limit_executions_${prefixNames}`;\n this.nextAvailableTableName = `rate_limit_next_available_${prefixNames}`;\n } else {\n this.executionTableName = \"rate_limit_executions\";\n this.nextAvailableTableName = \"rate_limit_next_available\";\n }\n }\n\n /**\n * Gets prefix column names for use in indexes.\n */\n private getPrefixColumnNames(): string[] {\n return this.prefixes.map((p) => p.name);\n }\n\n /**\n * Checks if a record matches the current prefix values.\n */\n private matchesPrefixes(record: Record<string, unknown>): boolean {\n for (const [key, value] of Object.entries(this.prefixValues)) {\n if (record[key] !== value) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Gets prefix values as an array in column order for index key construction.\n */\n private getPrefixKeyValues(): Array<string | number> {\n return this.prefixes.map((p) => this.prefixValues[p.name]);\n }\n\n private async getExecutionDb(): Promise<IDBDatabase> {\n if (this.executionDb) return this.executionDb;\n await this.setupDatabase();\n return this.executionDb!;\n }\n\n private async getNextAvailableDb(): Promise<IDBDatabase> {\n if (this.nextAvailableDb) return this.nextAvailableDb;\n await this.setupDatabase();\n return this.nextAvailableDb!;\n }\n\n public async setupDatabase(): Promise<void> {\n const prefixColumnNames = this.getPrefixColumnNames();\n\n // Build index key paths with prefixes prepended\n const buildKeyPath = (basePath: string[]): string[] => {\n return [...prefixColumnNames, ...basePath];\n };\n\n const executionIndexes: ExpectedIndexDefinition[] = [\n {\n name: \"queue_executed_at\",\n keyPath: buildKeyPath([\"queue_name\", \"executed_at\"]),\n options: { unique: false },\n },\n ];\n\n this.executionDb = await ensureIndexedDbTable(\n this.executionTableName,\n \"id\",\n executionIndexes,\n this.migrationOptions\n );\n\n const nextAvailableIndexes: ExpectedIndexDefinition[] = [\n {\n name: \"queue_name\",\n keyPath: buildKeyPath([\"queue_name\"]),\n options: { unique: true },\n },\n ];\n\n this.nextAvailableDb = await ensureIndexedDbTable(\n this.nextAvailableTableName,\n buildKeyPath([\"queue_name\"]).join(\"_\"),\n nextAvailableIndexes,\n this.migrationOptions\n );\n }\n\n public async recordExecution(queueName: string): Promise<void> {\n const db = await this.getExecutionDb();\n const tx = db.transaction(this.executionTableName, \"readwrite\");\n const store = tx.objectStore(this.executionTableName);\n\n const record: ExecutionRecord = {\n id: crypto.randomUUID(),\n queue_name: queueName,\n executed_at: new Date().toISOString(),\n };\n\n // Add prefix values to the record\n for (const [key, value] of Object.entries(this.prefixValues)) {\n (record as Record<string, unknown>)[key] = value;\n }\n\n return new Promise((resolve, reject) => {\n const request = store.add(record);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n request.onerror = () => reject(request.error);\n });\n }\n\n public async getExecutionCount(queueName: string, windowStartTime: string): Promise<number> {\n const db = await this.getExecutionDb();\n const tx = db.transaction(this.executionTableName, \"readonly\");\n const store = tx.objectStore(this.executionTableName);\n const index = store.index(\"queue_executed_at\");\n const prefixKeyValues = this.getPrefixKeyValues();\n\n return new Promise((resolve, reject) => {\n let count = 0;\n const keyRange = IDBKeyRange.bound(\n [...prefixKeyValues, queueName, windowStartTime],\n [...prefixKeyValues, queueName, \"\\uffff\"],\n true, // exclude lower bound (windowStartTime)\n false\n );\n const request = index.openCursor(keyRange);\n\n request.onsuccess = (event) => {\n const cursor = (event.target as IDBRequest<IDBCursorWithValue>).result;\n if (cursor) {\n const record = cursor.value as ExecutionRecord;\n if (this.matchesPrefixes(record)) {\n count++;\n }\n cursor.continue();\n }\n };\n\n tx.oncomplete = () => resolve(count);\n tx.onerror = () => reject(tx.error);\n request.onerror = () => reject(request.error);\n });\n }\n\n public async getOldestExecutionAtOffset(\n queueName: string,\n offset: number\n ): Promise<string | undefined> {\n const db = await this.getExecutionDb();\n const tx = db.transaction(this.executionTableName, \"readonly\");\n const store = tx.objectStore(this.executionTableName);\n const index = store.index(\"queue_executed_at\");\n const prefixKeyValues = this.getPrefixKeyValues();\n\n return new Promise((resolve, reject) => {\n const executions: string[] = [];\n const keyRange = IDBKeyRange.bound(\n [...prefixKeyValues, queueName, \"\"],\n [...prefixKeyValues, queueName, \"\\uffff\"]\n );\n const request = index.openCursor(keyRange);\n\n request.onsuccess = (event) => {\n const cursor = (event.target as IDBRequest<IDBCursorWithValue>).result;\n if (cursor) {\n const record = cursor.value as ExecutionRecord;\n if (this.matchesPrefixes(record)) {\n executions.push(record.executed_at);\n }\n cursor.continue();\n }\n };\n\n tx.oncomplete = () => {\n // Sort by executed_at ascending\n executions.sort();\n resolve(executions[offset]);\n };\n tx.onerror = () => reject(tx.error);\n request.onerror = () => reject(request.error);\n });\n }\n\n public async getNextAvailableTime(queueName: string): Promise<string | undefined> {\n const db = await this.getNextAvailableDb();\n const tx = db.transaction(this.nextAvailableTableName, \"readonly\");\n const store = tx.objectStore(this.nextAvailableTableName);\n const prefixKeyValues = this.getPrefixKeyValues();\n const key = [...prefixKeyValues, queueName].join(\"_\");\n\n return new Promise((resolve, reject) => {\n const request = store.get(key);\n request.onsuccess = () => {\n const record = request.result as NextAvailableRecord | undefined;\n if (record && this.matchesPrefixes(record)) {\n resolve(record.next_available_at);\n } else {\n resolve(undefined);\n }\n };\n request.onerror = () => reject(request.error);\n tx.onerror = () => reject(tx.error);\n });\n }\n\n public async setNextAvailableTime(queueName: string, nextAvailableAt: string): Promise<void> {\n const db = await this.getNextAvailableDb();\n const tx = db.transaction(this.nextAvailableTableName, \"readwrite\");\n const store = tx.objectStore(this.nextAvailableTableName);\n const prefixKeyValues = this.getPrefixKeyValues();\n const key = [...prefixKeyValues, queueName].join(\"_\");\n\n const record: NextAvailableRecord & { [key: string]: unknown } = {\n queue_name: queueName,\n next_available_at: nextAvailableAt,\n };\n\n // Add prefix values to the record\n for (const [k, value] of Object.entries(this.prefixValues)) {\n record[k] = value;\n }\n\n // Set the key field\n (record as Record<string, unknown>)[\n this.getPrefixColumnNames().concat([\"queue_name\"]).join(\"_\")\n ] = key;\n\n return new Promise((resolve, reject) => {\n const request = store.put(record);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n request.onerror = () => reject(request.error);\n });\n }\n\n public async clear(queueName: string): Promise<void> {\n // Clear executions\n const execDb = await this.getExecutionDb();\n const execTx = execDb.transaction(this.executionTableName, \"readwrite\");\n const execStore = execTx.objectStore(this.executionTableName);\n const execIndex = execStore.index(\"queue_executed_at\");\n const prefixKeyValues = this.getPrefixKeyValues();\n\n await new Promise<void>((resolve, reject) => {\n const keyRange = IDBKeyRange.bound(\n [...prefixKeyValues, queueName, \"\"],\n [...prefixKeyValues, queueName, \"\\uffff\"]\n );\n const request = execIndex.openCursor(keyRange);\n\n request.onsuccess = (event) => {\n const cursor = (event.target as IDBRequest<IDBCursorWithValue>).result;\n if (cursor) {\n const record = cursor.value as ExecutionRecord;\n if (this.matchesPrefixes(record)) {\n cursor.delete();\n }\n cursor.continue();\n }\n };\n\n execTx.oncomplete = () => resolve();\n execTx.onerror = () => reject(execTx.error);\n request.onerror = () => reject(request.error);\n });\n\n // Clear next available\n const nextDb = await this.getNextAvailableDb();\n const nextTx = nextDb.transaction(this.nextAvailableTableName, \"readwrite\");\n const nextStore = nextTx.objectStore(this.nextAvailableTableName);\n const key = [...prefixKeyValues, queueName].join(\"_\");\n\n await new Promise<void>((resolve, reject) => {\n const request = nextStore.delete(key);\n nextTx.oncomplete = () => resolve();\n nextTx.onerror = () => reject(nextTx.error);\n request.onerror = () => reject(request.error);\n });\n }\n}\n",
|
|
56
|
-
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { createServiceToken, deepEqual, makeFingerprint, uuid4 } from \"@workglow/util\";\nimport { HybridSubscriptionManager } from \"../util/HybridSubscriptionManager\";\nimport {\n ensureIndexedDbTable,\n ExpectedIndexDefinition,\n MigrationOptions,\n} from \"../util/IndexedDbTable\";\nimport {\n IQueueStorage,\n JobStatus,\n JobStorageFormat,\n PrefixColumn,\n QueueChangePayload,\n QueueStorageOptions,\n QueueSubscribeOptions,\n} from \"./IQueueStorage\";\n\nexport const INDEXED_DB_QUEUE_STORAGE = createServiceToken<IQueueStorage<any, any>>(\n \"jobqueue.storage.indexedDb\"\n);\n\n/**\n * Extended options for IndexedDB queue storage including prefix support\n */\nexport interface IndexedDbQueueStorageOptions extends QueueStorageOptions, MigrationOptions {\n /** Enable BroadcastChannel notifications (default: true) */\n readonly useBroadcastChannel?: boolean;\n /** Backup polling interval in ms (default: 5000, 0 to disable) */\n readonly backupPollingIntervalMs?: number;\n}\n\n/**\n * IndexedDB implementation of a job queue storage.\n * Provides storage and retrieval for job execution states using IndexedDB.\n */\nexport class IndexedDbQueueStorage<Input, Output> implements IQueueStorage<Input, Output> {\n private db: IDBDatabase | undefined;\n private readonly tableName: string;\n private readonly migrationOptions: MigrationOptions;\n /** The prefix column definitions */\n protected readonly prefixes: readonly PrefixColumn[];\n /** The prefix values for filtering */\n protected readonly prefixValues: Readonly<Record<string, string | number>>;\n /** Shared hybrid subscription manager */\n private hybridManager: HybridSubscriptionManager<\n JobStorageFormat<Input, Output>,\n unknown,\n QueueChangePayload<Input, Output>\n > | null = null;\n /** Hybrid subscription options */\n private readonly hybridOptions: {\n readonly useBroadcastChannel: boolean;\n readonly backupPollingIntervalMs: number;\n };\n\n constructor(\n public readonly queueName: string,\n options: IndexedDbQueueStorageOptions = {}\n ) {\n this.migrationOptions = options;\n this.prefixes = options.prefixes ?? [];\n this.prefixValues = options.prefixValues ?? {};\n this.hybridOptions = {\n useBroadcastChannel: options.useBroadcastChannel ?? true,\n backupPollingIntervalMs: options.backupPollingIntervalMs ?? 5000,\n };\n // Generate table name based on prefix configuration to avoid conflicts\n if (this.prefixes.length > 0) {\n const prefixNames = this.prefixes.map((p) => p.name).join(\"_\");\n this.tableName = `jobs_${prefixNames}`;\n } else {\n this.tableName = \"jobs\";\n }\n }\n\n /**\n * Gets prefix column names for use in indexes\n */\n private getPrefixColumnNames(): string[] {\n return this.prefixes.map((p) => p.name);\n }\n\n /**\n * Checks if a job matches the current prefix values\n */\n private matchesPrefixes(job: JobStorageFormat<Input, Output> & Record<string, unknown>): boolean {\n for (const [key, value] of Object.entries(this.prefixValues)) {\n if (job[key] !== value) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Gets prefix values as an array in column order for index key construction\n */\n private getPrefixKeyValues(): Array<string | number> {\n return this.prefixes.map((p) => this.prefixValues[p.name]);\n }\n\n private async getDb(): Promise<IDBDatabase> {\n if (this.db) return this.db;\n await this.setupDatabase();\n return this.db!;\n }\n\n /**\n * Sets up the IndexedDB database table with the required schema and indexes.\n * Must be called before using any other methods.\n */\n public async setupDatabase(): Promise<void> {\n const prefixColumnNames = this.getPrefixColumnNames();\n\n // Build index key paths with prefixes prepended\n const buildKeyPath = (basePath: string[]): string[] => {\n return [...prefixColumnNames, ...basePath];\n };\n\n const expectedIndexes: ExpectedIndexDefinition[] = [\n {\n name: \"queue_status\",\n keyPath: buildKeyPath([\"queue\", \"status\"]),\n options: { unique: false },\n },\n {\n name: \"queue_status_run_after\",\n keyPath: buildKeyPath([\"queue\", \"status\", \"run_after\"]),\n options: { unique: false },\n },\n {\n name: \"queue_job_run_id\",\n keyPath: buildKeyPath([\"queue\", \"job_run_id\"]),\n options: { unique: false },\n },\n {\n name: \"queue_fingerprint_status\",\n keyPath: buildKeyPath([\"queue\", \"fingerprint\", \"status\"]),\n options: { unique: false },\n },\n ];\n\n this.db = await ensureIndexedDbTable(\n this.tableName,\n \"id\",\n expectedIndexes,\n this.migrationOptions\n );\n }\n\n /**\n * Adds a job to the queue.\n * @param job - The job to add to the queue.\n * @returns A promise that resolves to the job id.\n */\n public async add(job: JobStorageFormat<Input, Output>): Promise<unknown> {\n const db = await this.getDb();\n const now = new Date().toISOString();\n const jobWithPrefixes = job as JobStorageFormat<Input, Output> & Record<string, unknown>;\n jobWithPrefixes.id = jobWithPrefixes.id ?? uuid4();\n jobWithPrefixes.job_run_id = jobWithPrefixes.job_run_id ?? uuid4();\n jobWithPrefixes.queue = this.queueName;\n jobWithPrefixes.fingerprint = await makeFingerprint(jobWithPrefixes.input);\n jobWithPrefixes.status = JobStatus.PENDING;\n jobWithPrefixes.progress = 0;\n jobWithPrefixes.progress_message = \"\";\n jobWithPrefixes.progress_details = null;\n jobWithPrefixes.created_at = now;\n jobWithPrefixes.run_after = now;\n\n // Add prefix values to the job\n for (const [key, value] of Object.entries(this.prefixValues)) {\n jobWithPrefixes[key] = value;\n }\n\n const tx = db.transaction(this.tableName, \"readwrite\");\n const store = tx.objectStore(this.tableName);\n\n return new Promise((resolve, reject) => {\n const request = store.add(jobWithPrefixes);\n\n // Don't resolve until transaction is complete\n tx.oncomplete = () => {\n // Notify hybrid manager of local change\n this.hybridManager?.notifyLocalChange();\n resolve(jobWithPrefixes.id);\n };\n tx.onerror = () => reject(tx.error);\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Retrieves a job from the queue by its id.\n * @param id - The id of the job to retrieve.\n * @returns A promise that resolves to the job or undefined if the job is not found.\n */\n async get(id: unknown): Promise<JobStorageFormat<Input, Output> | undefined> {\n const db = await this.getDb();\n const tx = db.transaction(this.tableName, \"readonly\");\n const store = tx.objectStore(this.tableName);\n const request = store.get(id as string);\n return new Promise((resolve, reject) => {\n request.onsuccess = () => {\n const job = request.result as\n | (JobStorageFormat<Input, Output> & Record<string, unknown>)\n | undefined;\n // Filter by queue name and prefix values to ensure job belongs to this queue\n if (job && job.queue === this.queueName && this.matchesPrefixes(job)) {\n resolve(job);\n } else {\n resolve(undefined);\n }\n };\n request.onerror = () => reject(request.error);\n tx.onerror = () => reject(tx.error);\n });\n }\n\n /**\n * Retrieves a slice of jobs from the queue.\n * @param status - The status of the jobs to retrieve.\n * @param num - The number of jobs to retrieve.\n * @returns A promise that resolves to an array of jobs.\n */\n public async peek(\n status: JobStatus = JobStatus.PENDING,\n num: number = 100\n ): Promise<JobStorageFormat<Input, Output>[]> {\n const db = await this.getDb();\n const tx = db.transaction(this.tableName, \"readonly\");\n const store = tx.objectStore(this.tableName);\n const index = store.index(\"queue_status_run_after\");\n const prefixKeyValues = this.getPrefixKeyValues();\n\n return new Promise((resolve, reject) => {\n const ret = new Map<unknown, JobStorageFormat<Input, Output>>();\n // Create a key range for the compound index: from [prefixes..., queue, status, \"\"] to [prefixes..., queue, status, \"\\uffff\"]\n const keyRange = IDBKeyRange.bound(\n [...prefixKeyValues, this.queueName, status, \"\"],\n [...prefixKeyValues, this.queueName, status, \"\\uffff\"]\n );\n const cursorRequest = index.openCursor(keyRange);\n\n const handleCursor = (e: Event) => {\n const cursor = (e.target as IDBRequest<IDBCursorWithValue>).result;\n if (!cursor || ret.size >= num) {\n resolve(Array.from(ret.values()));\n return;\n }\n const job = cursor.value as JobStorageFormat<Input, Output> & Record<string, unknown>;\n // Verify prefix match and use Map to ensure no duplicates by job ID\n if (this.matchesPrefixes(job)) {\n ret.set(cursor.value.id, cursor.value);\n }\n cursor.continue();\n };\n\n cursorRequest.onsuccess = handleCursor;\n cursorRequest.onerror = () => reject(cursorRequest.error);\n tx.onerror = () => reject(tx.error);\n });\n }\n\n /**\n * Retrieves the next job from the queue using optimistic locking. In case multiple workers\n * claim the same job, the first worker to claim it will process it and the other workers will return undefined.\n * This ONLY happens if workers are running in multiple tabs.\n *\n * IndexedDB uses snapshot isolation, so concurrent transactions can both see the same\n * PENDING job. To prevent processing the same job multiple times, this method:\n * 1. Claims a job by setting it to PROCESSING with a unique claim token\n * 2. After the transaction completes, re-reads the job to verify the claim succeeded\n * 3. If another worker claimed it first (different claim token), returns undefined\n *\n * @param workerId - Worker ID to associate with the job (required)\n * @returns A promise that resolves to the next job or undefined if the queue is empty.\n */\n public async next(workerId: string): Promise<JobStorageFormat<Input, Output> | undefined> {\n const db = await this.getDb();\n const tx = db.transaction(this.tableName, \"readwrite\");\n const store = tx.objectStore(this.tableName);\n const index = store.index(\"queue_status_run_after\");\n const now = new Date().toISOString();\n const prefixKeyValues = this.getPrefixKeyValues();\n\n // This ensures we can verify that we actually won the race to claim this job\n const claimToken = workerId;\n\n const jobToReturn = await new Promise<JobStorageFormat<Input, Output> | undefined>(\n (resolve, reject) => {\n const cursorRequest = index.openCursor(\n IDBKeyRange.bound(\n [...prefixKeyValues, this.queueName, JobStatus.PENDING, \"\"],\n [...prefixKeyValues, this.queueName, JobStatus.PENDING, now],\n false,\n false\n )\n );\n\n let claimedJob: JobStorageFormat<Input, Output> | undefined;\n let cursorStopped = false;\n\n cursorRequest.onsuccess = (e) => {\n const cursor = (e.target as IDBRequest<IDBCursorWithValue>).result;\n if (!cursor) {\n // Cursor exhausted - resolve with whatever we found (or undefined)\n return;\n }\n\n // If we already found and updated a job, stop iterating\n if (cursorStopped) {\n return;\n }\n\n const job = cursor.value as JobStorageFormat<Input, Output> & Record<string, unknown>;\n // Verify the job belongs to this queue, matches prefixes, and is still in PENDING state\n if (\n job.queue !== this.queueName ||\n job.status !== JobStatus.PENDING ||\n !this.matchesPrefixes(job)\n ) {\n cursor.continue();\n return;\n }\n\n // Claim the job with our unique token\n job.status = JobStatus.PROCESSING;\n job.last_ran_at = now;\n job.worker_id = claimToken;\n\n try {\n const updateRequest = store.put(job);\n updateRequest.onsuccess = () => {\n claimedJob = job;\n cursorStopped = true;\n // Stop cursor iteration - we've claimed a job\n };\n updateRequest.onerror = (err) => {\n console.error(\"Failed to update job status:\", err);\n cursor.continue();\n };\n } catch (err) {\n console.error(\"Error updating job:\", err);\n cursor.continue();\n }\n };\n\n cursorRequest.onerror = () => reject(cursorRequest.error);\n\n // Wait for transaction to complete before resolving\n tx.oncomplete = () => {\n // Notify hybrid manager of local change\n if (claimedJob) {\n this.hybridManager?.notifyLocalChange();\n }\n resolve(claimedJob);\n };\n tx.onerror = () => reject(tx.error);\n }\n );\n\n // If we didn't find any job to claim, return undefined\n if (!jobToReturn) {\n return undefined;\n }\n\n // Verify we actually won the race by re-reading the job\n // This is the optimistic locking check - if another worker claimed it first,\n // their claim token will be there instead of ours\n const verifiedJob = await this.get(jobToReturn.id);\n\n if (!verifiedJob) {\n // Job was deleted - we lost the race\n return undefined;\n }\n\n if (verifiedJob.worker_id !== claimToken) {\n // Another worker claimed this job - we lost the race\n return undefined;\n }\n\n if (verifiedJob.status !== JobStatus.PROCESSING) {\n // Job status changed (e.g., another worker completed it already) - we lost the race\n return undefined;\n }\n\n // We successfully claimed the job\n return verifiedJob;\n }\n\n /**\n * Retrieves the number of jobs in the queue.\n * Returns the count of jobs in the queue.\n */\n public async size(status = JobStatus.PENDING): Promise<number> {\n const db = await this.getDb();\n const prefixKeyValues = this.getPrefixKeyValues();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(this.tableName, \"readonly\");\n const store = tx.objectStore(this.tableName);\n const index = store.index(\"queue_status\");\n const keyRange = IDBKeyRange.only([...prefixKeyValues, this.queueName, status]);\n const request = index.count(keyRange);\n\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n tx.onerror = () => reject(tx.error);\n });\n }\n\n /**\n * Marks a job as complete with its output or error.\n */\n public async complete(job: JobStorageFormat<Input, Output>): Promise<void> {\n const db = await this.getDb();\n const tx = db.transaction(this.tableName, \"readwrite\");\n const store = tx.objectStore(this.tableName);\n\n return new Promise((resolve, reject) => {\n const getReq = store.get(job.id as string);\n getReq.onsuccess = () => {\n const existing = getReq.result as\n | (JobStorageFormat<Input, Output> & Record<string, unknown>)\n | undefined;\n // Verify job belongs to this queue and matches prefixes\n if (!existing || existing.queue !== this.queueName || !this.matchesPrefixes(existing)) {\n reject(\n new Error(`Job ${job.id} not found or does not belong to queue ${this.queueName}`)\n );\n return;\n }\n const currentAttempts = existing.run_attempts ?? 0;\n job.run_attempts = currentAttempts + 1;\n // Ensure queue is set correctly\n job.queue = this.queueName;\n\n // Ensure prefix values are preserved\n const jobWithPrefixes = job as JobStorageFormat<Input, Output> & Record<string, unknown>;\n for (const [key, value] of Object.entries(this.prefixValues)) {\n jobWithPrefixes[key] = value;\n }\n\n const putReq = store.put(jobWithPrefixes);\n putReq.onsuccess = () => {};\n putReq.onerror = () => reject(putReq.error);\n };\n getReq.onerror = () => reject(getReq.error);\n\n // Don't resolve until transaction is complete\n tx.oncomplete = () => {\n // Notify hybrid manager of local change\n this.hybridManager?.notifyLocalChange();\n resolve();\n };\n tx.onerror = () => reject(tx.error);\n });\n }\n\n /**\n * Releases a claimed job without consuming a retry attempt.\n */\n public async release(id: unknown): Promise<void> {\n const job = await this.get(id);\n if (!job) return;\n\n job.status = JobStatus.PENDING;\n job.worker_id = null;\n job.progress = 0;\n job.progress_message = \"\";\n job.progress_details = null;\n\n await this.put(job);\n }\n\n /**\n * Aborts a job in the queue.\n */\n public async abort(id: unknown): Promise<void> {\n const job = await this.get(id);\n if (!job) return;\n\n job.status = JobStatus.ABORTING;\n await this.complete(job);\n }\n\n /**\n * Gets jobs by their run ID.\n */\n public async getByRunId(job_run_id: string): Promise<JobStorageFormat<Input, Output>[]> {\n const db = await this.getDb();\n const tx = db.transaction(this.tableName, \"readonly\");\n const store = tx.objectStore(this.tableName);\n const index = store.index(\"queue_job_run_id\");\n const prefixKeyValues = this.getPrefixKeyValues();\n const keyRange = IDBKeyRange.only([...prefixKeyValues, this.queueName, job_run_id]);\n const request = index.getAll(keyRange);\n\n return new Promise((resolve, reject) => {\n request.onsuccess = () => {\n // Filter results to ensure they match prefixes\n const results = (request.result || []).filter(\n (job: JobStorageFormat<Input, Output> & Record<string, unknown>) =>\n this.matchesPrefixes(job)\n );\n resolve(results);\n };\n request.onerror = () => reject(request.error);\n tx.onerror = () => reject(tx.error);\n });\n }\n\n /**\n * Deletes all jobs from the queue.\n */\n public async deleteAll(): Promise<void> {\n const db = await this.getDb();\n const tx = db.transaction(this.tableName, \"readwrite\");\n const store = tx.objectStore(this.tableName);\n const index = store.index(\"queue_status\");\n const prefixKeyValues = this.getPrefixKeyValues();\n\n return new Promise((resolve, reject) => {\n // Use a cursor to iterate through all jobs for this queue with prefix\n const keyRange = IDBKeyRange.bound(\n [...prefixKeyValues, this.queueName, \"\"],\n [...prefixKeyValues, this.queueName, \"\\uffff\"]\n );\n const request = index.openCursor(keyRange);\n\n request.onsuccess = (event) => {\n const cursor = (event.target as IDBRequest<IDBCursorWithValue>).result;\n if (cursor) {\n const job = cursor.value as JobStorageFormat<Input, Output> & Record<string, unknown>;\n // Verify job belongs to this queue and matches prefixes before deleting\n if (job.queue === this.queueName && this.matchesPrefixes(job)) {\n const deleteRequest = cursor.delete();\n deleteRequest.onsuccess = () => {\n cursor.continue();\n };\n deleteRequest.onerror = () => {\n // Continue even if delete fails\n cursor.continue();\n };\n } else {\n cursor.continue();\n }\n }\n };\n\n tx.oncomplete = () => {\n // Notify hybrid manager of local change\n this.hybridManager?.notifyLocalChange();\n resolve();\n };\n tx.onerror = () => reject(tx.error);\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Gets the output for a given input.\n */\n public async outputForInput(input: Input): Promise<Output | null> {\n const fingerprint = await makeFingerprint(input);\n const db = await this.getDb();\n const tx = db.transaction(this.tableName, \"readonly\");\n const store = tx.objectStore(this.tableName);\n const index = store.index(\"queue_fingerprint_status\");\n const prefixKeyValues = this.getPrefixKeyValues();\n const request = index.get([\n ...prefixKeyValues,\n this.queueName,\n fingerprint,\n JobStatus.COMPLETED,\n ]);\n\n return new Promise((resolve, reject) => {\n request.onsuccess = () => {\n const job = request.result as\n | (JobStorageFormat<Input, Output> & Record<string, unknown>)\n | undefined;\n if (job && this.matchesPrefixes(job)) {\n resolve(job.output ?? null);\n } else {\n resolve(null);\n }\n };\n request.onerror = () => reject(request.error);\n tx.onerror = () => reject(tx.error);\n });\n }\n\n /**\n * Saves progress updates for a job.\n */\n public async saveProgress(\n id: unknown,\n progress: number,\n message: string,\n details: Record<string, any> | null\n ): Promise<void> {\n const job = await this.get(id);\n if (!job) throw new Error(`Job ${id} not found`);\n\n job.progress = progress;\n job.progress_message = message;\n job.progress_details = details;\n\n await this.put(job);\n }\n\n /**\n * Persists a job to the store without modifying run_attempts or other completion logic.\n */\n private async put(job: JobStorageFormat<Input, Output>): Promise<void> {\n const db = await this.getDb();\n const tx = db.transaction(this.tableName, \"readwrite\");\n const store = tx.objectStore(this.tableName);\n\n // Ensure queue is set correctly\n job.queue = this.queueName;\n\n // Ensure prefix values are preserved\n const jobWithPrefixes = job as JobStorageFormat<Input, Output> & Record<string, unknown>;\n for (const [key, value] of Object.entries(this.prefixValues)) {\n jobWithPrefixes[key] = value;\n }\n\n return new Promise((resolve, reject) => {\n const putReq = store.put(jobWithPrefixes);\n putReq.onerror = () => reject(putReq.error);\n tx.oncomplete = () => {\n // Notify hybrid manager of local change\n this.hybridManager?.notifyLocalChange();\n resolve();\n };\n tx.onerror = () => reject(tx.error);\n });\n }\n\n /**\n * Deletes a job by its ID.\n */\n public async delete(id: unknown): Promise<void> {\n const job = await this.get(id);\n if (!job) return;\n\n const db = await this.getDb();\n const tx = db.transaction(this.tableName, \"readwrite\");\n const store = tx.objectStore(this.tableName);\n const request = store.delete(id as string);\n\n return new Promise((resolve, reject) => {\n request.onsuccess = () => resolve();\n request.onerror = () => reject(request.error);\n tx.oncomplete = () => {\n // Notify hybrid manager of local change\n this.hybridManager?.notifyLocalChange();\n };\n tx.onerror = () => reject(tx.error);\n });\n }\n\n /**\n * Delete jobs with a specific status older than a cutoff date\n * @param status - Status of jobs to delete\n * @param olderThanMs - Delete jobs completed more than this many milliseconds ago\n */\n public async deleteJobsByStatusAndAge(status: JobStatus, olderThanMs: number): Promise<void> {\n const db = await this.getDb();\n const tx = db.transaction(this.tableName, \"readwrite\");\n const store = tx.objectStore(this.tableName);\n const index = store.index(\"queue_status\");\n const cutoffDate = new Date(Date.now() - olderThanMs).toISOString();\n const prefixKeyValues = this.getPrefixKeyValues();\n const keyRange = IDBKeyRange.only([...prefixKeyValues, this.queueName, status]);\n\n return new Promise((resolve, reject) => {\n const request = index.openCursor(keyRange);\n\n request.onsuccess = (event) => {\n const cursor = (event.target as IDBRequest<IDBCursorWithValue>).result;\n if (cursor) {\n const job = cursor.value as JobStorageFormat<Input, Output> & Record<string, unknown>;\n // Verify job belongs to this queue, matches prefixes, and matches criteria\n if (\n job.queue === this.queueName &&\n this.matchesPrefixes(job) &&\n job.status === status &&\n job.completed_at &&\n job.completed_at <= cutoffDate\n ) {\n cursor.delete();\n }\n cursor.continue();\n }\n };\n\n tx.oncomplete = () => {\n // Notify hybrid manager of local change\n this.hybridManager?.notifyLocalChange();\n resolve();\n };\n tx.onerror = () => reject(tx.error);\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Gets all jobs from the queue that match the current prefix values.\n * Used internally for normal polling-based subscriptions (efficient - filters at DB level).\n *\n * @returns A promise that resolves to an array of jobs\n */\n private async getAllJobs(): Promise<Array<JobStorageFormat<Input, Output>>> {\n const db = await this.getDb();\n const tx = db.transaction(this.tableName, \"readonly\");\n const store = tx.objectStore(this.tableName);\n const index = store.index(\"queue_status\");\n const prefixKeyValues = this.getPrefixKeyValues();\n\n return new Promise((resolve, reject) => {\n const jobs: Array<JobStorageFormat<Input, Output>> = [];\n // Use a key range that covers all statuses for this queue with prefixes\n const keyRange = IDBKeyRange.bound(\n [...prefixKeyValues, this.queueName, \"\"],\n [...prefixKeyValues, this.queueName, \"\\uffff\"]\n );\n const request = index.openCursor(keyRange);\n\n request.onsuccess = (event) => {\n const cursor = (event.target as IDBRequest<IDBCursorWithValue>).result;\n if (cursor) {\n const job = cursor.value as JobStorageFormat<Input, Output> & Record<string, unknown>;\n if (job.queue === this.queueName && this.matchesPrefixes(job)) {\n jobs.push(job);\n }\n cursor.continue();\n }\n };\n\n tx.oncomplete = () => resolve(jobs);\n tx.onerror = () => reject(tx.error);\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Gets all jobs from the queue with a custom prefix filter.\n * Used for subscriptions with custom prefix filters (filters at DB level where possible).\n *\n * @param prefixFilter - The prefix values to filter by (empty object = all jobs)\n * @returns A promise that resolves to an array of jobs\n */\n private async getAllJobsWithFilter(\n prefixFilter: Readonly<Record<string, string | number>>\n ): Promise<Array<JobStorageFormat<Input, Output>>> {\n const db = await this.getDb();\n const tx = db.transaction(this.tableName, \"readonly\");\n const store = tx.objectStore(this.tableName);\n\n return new Promise((resolve, reject) => {\n const jobs: Array<JobStorageFormat<Input, Output>> = [];\n const request = store.openCursor();\n\n request.onsuccess = (event) => {\n const cursor = (event.target as IDBRequest<IDBCursorWithValue>).result;\n if (cursor) {\n const job = cursor.value as JobStorageFormat<Input, Output> & Record<string, unknown>;\n // Filter by queue name\n if (job.queue !== this.queueName) {\n cursor.continue();\n return;\n }\n // If empty filter, include all jobs for this queue\n if (Object.keys(prefixFilter).length === 0) {\n jobs.push(job);\n } else {\n // Check each filter value\n let matches = true;\n for (const [key, value] of Object.entries(prefixFilter)) {\n if (job[key] !== value) {\n matches = false;\n break;\n }\n }\n if (matches) {\n jobs.push(job);\n }\n }\n cursor.continue();\n }\n };\n\n tx.oncomplete = () => resolve(jobs);\n tx.onerror = () => reject(tx.error);\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Checks if a prefix filter is custom (different from instance's prefixes).\n */\n private isCustomPrefixFilter(prefixFilter?: Readonly<Record<string, string | number>>): boolean {\n // No filter specified - use instance prefixes (not custom)\n if (prefixFilter === undefined) {\n return false;\n }\n // Empty filter - receive all (custom)\n if (Object.keys(prefixFilter).length === 0) {\n return true;\n }\n // Check if filter matches instance prefixes exactly\n const instanceKeys = Object.keys(this.prefixValues);\n const filterKeys = Object.keys(prefixFilter);\n if (instanceKeys.length !== filterKeys.length) {\n return true; // Different number of keys = custom\n }\n for (const key of instanceKeys) {\n if (this.prefixValues[key] !== prefixFilter[key]) {\n return true; // Different value = custom\n }\n }\n return false; // Matches instance prefixes exactly\n }\n\n /**\n * Gets or creates the shared hybrid subscription manager for normal subscriptions.\n * This ensures all normal subscriptions share a single manager.\n */\n private getHybridManager(): HybridSubscriptionManager<\n JobStorageFormat<Input, Output>,\n unknown,\n QueueChangePayload<Input, Output>\n > {\n if (!this.hybridManager) {\n // Generate unique channel name based on queue name and table name\n const channelName = `indexeddb-queue-${this.tableName}-${this.queueName}`;\n\n this.hybridManager = new HybridSubscriptionManager<\n JobStorageFormat<Input, Output>,\n unknown,\n QueueChangePayload<Input, Output>\n >(\n channelName,\n async () => {\n // Fetch jobs with instance's prefix filter (efficient DB-level filtering)\n const jobs = await this.getAllJobs();\n return new Map(jobs.map((j) => [j.id, j]));\n },\n (a, b) => deepEqual(a, b),\n {\n insert: (item) => ({ type: \"INSERT\" as const, new: item }),\n update: (oldItem, newItem) => ({ type: \"UPDATE\" as const, old: oldItem, new: newItem }),\n delete: (item) => ({ type: \"DELETE\" as const, old: item }),\n },\n {\n defaultIntervalMs: 1000,\n useBroadcastChannel: this.hybridOptions.useBroadcastChannel,\n backupPollingIntervalMs: this.hybridOptions.backupPollingIntervalMs,\n }\n );\n }\n return this.hybridManager;\n }\n\n /**\n * Creates a dedicated polling subscription for custom prefix filters.\n * This runs separately from the normal polling manager.\n */\n private subscribeWithCustomPrefixFilter(\n callback: (change: QueueChangePayload<Input, Output>) => void,\n prefixFilter: Readonly<Record<string, string | number>>,\n intervalMs: number\n ): () => void {\n let lastKnownJobs = new Map<unknown, JobStorageFormat<Input, Output>>();\n let cancelled = false;\n\n const poll = async () => {\n if (cancelled) return;\n try {\n const currentJobs = await this.getAllJobsWithFilter(prefixFilter);\n if (cancelled) return;\n const currentMap = new Map(currentJobs.map((j) => [j.id, j]));\n\n // Detect changes\n for (const [id, job] of currentMap) {\n const old = lastKnownJobs.get(id);\n if (!old) {\n callback({ type: \"INSERT\", new: job });\n } else if (!deepEqual(old, job)) {\n callback({ type: \"UPDATE\", old, new: job });\n }\n }\n\n for (const [id, job] of lastKnownJobs) {\n if (!currentMap.has(id)) {\n callback({ type: \"DELETE\", old: job });\n }\n }\n\n lastKnownJobs = currentMap;\n } catch {\n // Ignore polling errors\n }\n };\n\n const intervalId = setInterval(poll, intervalMs);\n poll(); // Initial poll\n\n return () => {\n cancelled = true;\n clearInterval(intervalId);\n };\n }\n\n /**\n * Subscribes to changes in the queue.\n * Uses polling since IndexedDB has no native cross-tab change notifications.\n *\n * Normal subscriptions (no custom prefix filter) share a single polling loop for efficiency.\n * Custom prefix filter subscriptions get their own dedicated polling loop with DB-level filtering.\n *\n * @param callback - Function called when a change occurs\n * @param options - Subscription options including polling interval and prefix filter\n * @returns Unsubscribe function\n */\n public subscribeToChanges(\n callback: (change: QueueChangePayload<Input, Output>) => void,\n options?: QueueSubscribeOptions\n ): () => void {\n const intervalMs = options?.pollingIntervalMs ?? 1000;\n\n // Check if this is a custom prefix filter subscription\n if (this.isCustomPrefixFilter(options?.prefixFilter)) {\n // Custom prefix filter - use dedicated polling with DB-level filtering\n return this.subscribeWithCustomPrefixFilter(callback, options!.prefixFilter!, intervalMs);\n }\n\n // Normal subscription - use shared hybrid manager (efficient)\n const manager = this.getHybridManager();\n return manager.subscribe(callback, { intervalMs });\n }\n\n /**\n * Cleanup method to destroy the hybrid manager\n */\n destroy(): void {\n if (this.hybridManager) {\n this.hybridManager.destroy();\n this.hybridManager = null;\n }\n }\n}\n",
|
|
55
|
+
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { createServiceToken } from \"@workglow/util\";\nimport {\n ensureIndexedDbTable,\n ExpectedIndexDefinition,\n MigrationOptions,\n} from \"../util/IndexedDbTable\";\nimport type { PrefixColumn } from \"../queue/IQueueStorage\";\nimport {\n IRateLimiterStorage,\n RateLimiterStorageOptions,\n RateLimiterStorageScope,\n} from \"./IRateLimiterStorage\";\n\nexport const INDEXED_DB_RATE_LIMITER_STORAGE = createServiceToken<IRateLimiterStorage>(\n \"ratelimiter.storage.indexedDb\"\n);\n\n/**\n * Extended options for IndexedDB rate limiter storage including prefix support.\n */\nexport interface IndexedDbRateLimiterStorageOptions\n extends RateLimiterStorageOptions, MigrationOptions {}\n\n/**\n * Execution record stored in IndexedDB.\n */\ninterface ExecutionRecord {\n readonly id?: string;\n readonly queue_name: string;\n readonly executed_at: string;\n readonly [key: string]: unknown;\n}\n\n/**\n * Next available record stored in IndexedDB.\n */\ninterface NextAvailableRecord {\n readonly queue_name: string;\n readonly next_available_at: string;\n readonly [key: string]: unknown;\n}\n\n/**\n * IndexedDB implementation of rate limiter storage.\n * Manages execution records and next available times for rate limiting.\n *\n * Atomicity is `\"process\"`-scoped (browser tab) and the `next_available_at`\n * pre-check inside {@link tryReserveExecution} runs in a separate IDB\n * transaction from the count-and-insert. See {@link tryReserveExecution} for\n * the full caveat — do not assume cross-store atomicity.\n */\nexport class IndexedDbRateLimiterStorage implements IRateLimiterStorage {\n /**\n * `\"process\"` — IndexedDB is per-origin and shared across tabs but not across\n * processes (different machines, server processes). Within a single tab the\n * `readwrite` transaction below provides atomicity.\n */\n public readonly scope: RateLimiterStorageScope = \"process\";\n private executionDb: IDBDatabase | undefined;\n private nextAvailableDb: IDBDatabase | undefined;\n private readonly executionTableName: string;\n private readonly nextAvailableTableName: string;\n private readonly migrationOptions: MigrationOptions;\n /** The prefix column definitions */\n protected readonly prefixes: readonly PrefixColumn[];\n /** The prefix values for filtering */\n protected readonly prefixValues: Readonly<Record<string, string | number>>;\n\n constructor(options: IndexedDbRateLimiterStorageOptions = {}) {\n this.migrationOptions = options;\n this.prefixes = options.prefixes ?? [];\n this.prefixValues = options.prefixValues ?? {};\n\n // Generate table names based on prefix configuration\n if (this.prefixes.length > 0) {\n const prefixNames = this.prefixes.map((p) => p.name).join(\"_\");\n this.executionTableName = `rate_limit_executions_${prefixNames}`;\n this.nextAvailableTableName = `rate_limit_next_available_${prefixNames}`;\n } else {\n this.executionTableName = \"rate_limit_executions\";\n this.nextAvailableTableName = \"rate_limit_next_available\";\n }\n }\n\n /**\n * Gets prefix column names for use in indexes.\n */\n private getPrefixColumnNames(): string[] {\n return this.prefixes.map((p) => p.name);\n }\n\n /**\n * Checks if a record matches the current prefix values.\n */\n private matchesPrefixes(record: Record<string, unknown>): boolean {\n for (const [key, value] of Object.entries(this.prefixValues)) {\n if (record[key] !== value) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Gets prefix values as an array in column order for index key construction.\n */\n private getPrefixKeyValues(): Array<string | number> {\n return this.prefixes.map((p) => this.prefixValues[p.name]);\n }\n\n private async getExecutionDb(): Promise<IDBDatabase> {\n if (this.executionDb) return this.executionDb;\n await this.setupDatabase();\n return this.executionDb!;\n }\n\n private async getNextAvailableDb(): Promise<IDBDatabase> {\n if (this.nextAvailableDb) return this.nextAvailableDb;\n await this.setupDatabase();\n return this.nextAvailableDb!;\n }\n\n public async setupDatabase(): Promise<void> {\n const prefixColumnNames = this.getPrefixColumnNames();\n\n // Build index key paths with prefixes prepended\n const buildKeyPath = (basePath: string[]): string[] => {\n return [...prefixColumnNames, ...basePath];\n };\n\n const executionIndexes: ExpectedIndexDefinition[] = [\n {\n name: \"queue_executed_at\",\n keyPath: buildKeyPath([\"queue_name\", \"executed_at\"]),\n options: { unique: false },\n },\n ];\n\n this.executionDb = await ensureIndexedDbTable(\n this.executionTableName,\n \"id\",\n executionIndexes,\n this.migrationOptions\n );\n\n const nextAvailableIndexes: ExpectedIndexDefinition[] = [\n {\n name: \"queue_name\",\n keyPath: buildKeyPath([\"queue_name\"]),\n options: { unique: true },\n },\n ];\n\n this.nextAvailableDb = await ensureIndexedDbTable(\n this.nextAvailableTableName,\n buildKeyPath([\"queue_name\"]).join(\"_\"),\n nextAvailableIndexes,\n this.migrationOptions\n );\n }\n\n /**\n * Atomically reserves an execution slot in IndexedDB.\n *\n * Atomicity caveat: this implementation only serializes the `count + insert`\n * pair (under a single `readwrite` IDB transaction over the executions\n * store). The `next_available_at` lookup is a soft pre-check performed\n * BEFORE the tx, because the executions and next-available object stores\n * live in separate `IDBDatabase` instances by design (one\n * `ensureIndexedDbTable` call each) and IDB transaction scope cannot cross\n * databases. This is acceptable for IndexedDB's `\"process\"` scope: rate-\n * limit overshoot from a stale next-available read is bounded by single-\n * tab serial execution, and the stricter count check is what protects the\n * primary maxExecutions invariant.\n */\n public async tryReserveExecution(\n queueName: string,\n maxExecutions: number,\n windowMs: number\n ): Promise<unknown | null> {\n // Soft pre-check against external backoff. Done before opening the tx\n // because next-available lives in a separate IDBDatabase.\n const nextIso = await this.getNextAvailableTime(queueName);\n if (nextIso && new Date(nextIso).getTime() > Date.now()) {\n return null;\n }\n\n const execDb = await this.getExecutionDb();\n const prefixKeyValues = this.getPrefixKeyValues();\n const windowStartIso = new Date(Date.now() - windowMs).toISOString();\n const execTx = execDb.transaction(this.executionTableName, \"readwrite\");\n const execStore = execTx.objectStore(this.executionTableName);\n const insertedId = crypto.randomUUID();\n\n return new Promise<unknown | null>((resolve, reject) => {\n let liveCount = 0;\n let didInsert = false;\n const liveRange = IDBKeyRange.bound(\n [...prefixKeyValues, queueName, windowStartIso],\n [...prefixKeyValues, queueName, \"\"],\n true,\n false\n );\n const cursorReq = execStore.index(\"queue_executed_at\").openCursor(liveRange);\n\n cursorReq.onsuccess = (event) => {\n const cursor = (event.target as IDBRequest<IDBCursorWithValue>).result;\n if (cursor) {\n const record = cursor.value as ExecutionRecord;\n if (this.matchesPrefixes(record)) {\n liveCount++;\n }\n cursor.continue();\n return;\n }\n\n if (liveCount >= maxExecutions) {\n // Aborting fires execTx.onabort below, which resolves with `false`.\n // No INSERT happened, so capacity is preserved.\n execTx.abort();\n return;\n }\n\n const record: ExecutionRecord = {\n id: insertedId,\n queue_name: queueName,\n executed_at: new Date().toISOString(),\n };\n for (const [k, v] of Object.entries(this.prefixValues)) {\n (record as Record<string, unknown>)[k] = v;\n }\n const addReq = execStore.add(record);\n didInsert = true;\n addReq.onerror = () => {\n try {\n execTx.abort();\n } catch {\n // already aborted\n }\n reject(addReq.error);\n };\n };\n\n cursorReq.onerror = () => reject(cursorReq.error);\n execTx.oncomplete = () => resolve(didInsert ? insertedId : null);\n execTx.onerror = () => reject(execTx.error);\n execTx.onabort = () => resolve(null);\n });\n }\n\n public async releaseExecution(queueName: string, token: unknown): Promise<void> {\n if (token === null || token === undefined) return;\n const db = await this.getExecutionDb();\n const tx = db.transaction(this.executionTableName, \"readwrite\");\n const store = tx.objectStore(this.executionTableName);\n return new Promise<void>((resolve, reject) => {\n // Delete by id — NEVER by recency. Two concurrent acquirers can hold\n // tokens for different rows; deleting \"the most recent\" would release\n // the other worker's slot.\n const req = store.delete(token as IDBValidKey);\n req.onerror = () => reject(req.error);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n }\n\n public async recordExecution(queueName: string): Promise<void> {\n const db = await this.getExecutionDb();\n const tx = db.transaction(this.executionTableName, \"readwrite\");\n const store = tx.objectStore(this.executionTableName);\n\n const record: ExecutionRecord = {\n id: crypto.randomUUID(),\n queue_name: queueName,\n executed_at: new Date().toISOString(),\n };\n\n // Add prefix values to the record\n for (const [key, value] of Object.entries(this.prefixValues)) {\n (record as Record<string, unknown>)[key] = value;\n }\n\n return new Promise((resolve, reject) => {\n const request = store.add(record);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n request.onerror = () => reject(request.error);\n });\n }\n\n public async getExecutionCount(queueName: string, windowStartTime: string): Promise<number> {\n const db = await this.getExecutionDb();\n const tx = db.transaction(this.executionTableName, \"readonly\");\n const store = tx.objectStore(this.executionTableName);\n const index = store.index(\"queue_executed_at\");\n const prefixKeyValues = this.getPrefixKeyValues();\n\n return new Promise((resolve, reject) => {\n let count = 0;\n const keyRange = IDBKeyRange.bound(\n [...prefixKeyValues, queueName, windowStartTime],\n [...prefixKeyValues, queueName, \"\\uffff\"],\n true, // exclude lower bound (windowStartTime)\n false\n );\n const request = index.openCursor(keyRange);\n\n request.onsuccess = (event) => {\n const cursor = (event.target as IDBRequest<IDBCursorWithValue>).result;\n if (cursor) {\n const record = cursor.value as ExecutionRecord;\n if (this.matchesPrefixes(record)) {\n count++;\n }\n cursor.continue();\n }\n };\n\n tx.oncomplete = () => resolve(count);\n tx.onerror = () => reject(tx.error);\n request.onerror = () => reject(request.error);\n });\n }\n\n public async getOldestExecutionAtOffset(\n queueName: string,\n offset: number\n ): Promise<string | undefined> {\n const db = await this.getExecutionDb();\n const tx = db.transaction(this.executionTableName, \"readonly\");\n const store = tx.objectStore(this.executionTableName);\n const index = store.index(\"queue_executed_at\");\n const prefixKeyValues = this.getPrefixKeyValues();\n\n return new Promise((resolve, reject) => {\n const executions: string[] = [];\n const keyRange = IDBKeyRange.bound(\n [...prefixKeyValues, queueName, \"\"],\n [...prefixKeyValues, queueName, \"\\uffff\"]\n );\n const request = index.openCursor(keyRange);\n\n request.onsuccess = (event) => {\n const cursor = (event.target as IDBRequest<IDBCursorWithValue>).result;\n if (cursor) {\n const record = cursor.value as ExecutionRecord;\n if (this.matchesPrefixes(record)) {\n executions.push(record.executed_at);\n }\n cursor.continue();\n }\n };\n\n tx.oncomplete = () => {\n // Sort by executed_at ascending\n executions.sort();\n resolve(executions[offset]);\n };\n tx.onerror = () => reject(tx.error);\n request.onerror = () => reject(request.error);\n });\n }\n\n public async getNextAvailableTime(queueName: string): Promise<string | undefined> {\n const db = await this.getNextAvailableDb();\n const tx = db.transaction(this.nextAvailableTableName, \"readonly\");\n const store = tx.objectStore(this.nextAvailableTableName);\n const prefixKeyValues = this.getPrefixKeyValues();\n const key = [...prefixKeyValues, queueName].join(\"_\");\n\n return new Promise((resolve, reject) => {\n const request = store.get(key);\n request.onsuccess = () => {\n const record = request.result as NextAvailableRecord | undefined;\n if (record && this.matchesPrefixes(record)) {\n resolve(record.next_available_at);\n } else {\n resolve(undefined);\n }\n };\n request.onerror = () => reject(request.error);\n tx.onerror = () => reject(tx.error);\n });\n }\n\n public async setNextAvailableTime(queueName: string, nextAvailableAt: string): Promise<void> {\n const db = await this.getNextAvailableDb();\n const tx = db.transaction(this.nextAvailableTableName, \"readwrite\");\n const store = tx.objectStore(this.nextAvailableTableName);\n const prefixKeyValues = this.getPrefixKeyValues();\n const key = [...prefixKeyValues, queueName].join(\"_\");\n\n const record: NextAvailableRecord & { [key: string]: unknown } = {\n queue_name: queueName,\n next_available_at: nextAvailableAt,\n };\n\n // Add prefix values to the record\n for (const [k, value] of Object.entries(this.prefixValues)) {\n record[k] = value;\n }\n\n // Set the key field\n (record as Record<string, unknown>)[\n this.getPrefixColumnNames().concat([\"queue_name\"]).join(\"_\")\n ] = key;\n\n return new Promise((resolve, reject) => {\n const request = store.put(record);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n request.onerror = () => reject(request.error);\n });\n }\n\n public async clear(queueName: string): Promise<void> {\n // Clear executions\n const execDb = await this.getExecutionDb();\n const execTx = execDb.transaction(this.executionTableName, \"readwrite\");\n const execStore = execTx.objectStore(this.executionTableName);\n const execIndex = execStore.index(\"queue_executed_at\");\n const prefixKeyValues = this.getPrefixKeyValues();\n\n await new Promise<void>((resolve, reject) => {\n const keyRange = IDBKeyRange.bound(\n [...prefixKeyValues, queueName, \"\"],\n [...prefixKeyValues, queueName, \"\\uffff\"]\n );\n const request = execIndex.openCursor(keyRange);\n\n request.onsuccess = (event) => {\n const cursor = (event.target as IDBRequest<IDBCursorWithValue>).result;\n if (cursor) {\n const record = cursor.value as ExecutionRecord;\n if (this.matchesPrefixes(record)) {\n cursor.delete();\n }\n cursor.continue();\n }\n };\n\n execTx.oncomplete = () => resolve();\n execTx.onerror = () => reject(execTx.error);\n request.onerror = () => reject(request.error);\n });\n\n // Clear next available\n const nextDb = await this.getNextAvailableDb();\n const nextTx = nextDb.transaction(this.nextAvailableTableName, \"readwrite\");\n const nextStore = nextTx.objectStore(this.nextAvailableTableName);\n const key = [...prefixKeyValues, queueName].join(\"_\");\n\n await new Promise<void>((resolve, reject) => {\n const request = nextStore.delete(key);\n nextTx.oncomplete = () => resolve();\n nextTx.onerror = () => reject(nextTx.error);\n request.onerror = () => reject(request.error);\n });\n }\n}\n",
|
|
56
|
+
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { createServiceToken, deepEqual, makeFingerprint, uuid4 } from \"@workglow/util\";\nimport { HybridSubscriptionManager } from \"../util/HybridSubscriptionManager\";\nimport {\n ensureIndexedDbTable,\n ExpectedIndexDefinition,\n MigrationOptions,\n} from \"../util/IndexedDbTable\";\nimport {\n IQueueStorage,\n JobStatus,\n JobStorageFormat,\n PrefixColumn,\n QueueChangePayload,\n QueueStorageOptions,\n QueueSubscribeOptions,\n} from \"./IQueueStorage\";\n\nexport const INDEXED_DB_QUEUE_STORAGE = createServiceToken<IQueueStorage<any, any>>(\n \"jobqueue.storage.indexedDb\"\n);\n\n/**\n * Extended options for IndexedDB queue storage including prefix support\n */\nexport interface IndexedDbQueueStorageOptions extends QueueStorageOptions, MigrationOptions {\n /** Enable BroadcastChannel notifications (default: true) */\n readonly useBroadcastChannel?: boolean;\n /** Backup polling interval in ms (default: 5000, 0 to disable) */\n readonly backupPollingIntervalMs?: number;\n}\n\n/**\n * IndexedDB implementation of a job queue storage.\n * Provides storage and retrieval for job execution states using IndexedDB.\n */\nexport class IndexedDbQueueStorage<Input, Output> implements IQueueStorage<Input, Output> {\n public readonly scope = \"process\" as const;\n private db: IDBDatabase | undefined;\n private readonly tableName: string;\n private readonly migrationOptions: MigrationOptions;\n /** The prefix column definitions */\n protected readonly prefixes: readonly PrefixColumn[];\n /** The prefix values for filtering */\n protected readonly prefixValues: Readonly<Record<string, string | number>>;\n /** Shared hybrid subscription manager */\n private hybridManager: HybridSubscriptionManager<\n JobStorageFormat<Input, Output>,\n unknown,\n QueueChangePayload<Input, Output>\n > | null = null;\n /** Hybrid subscription options */\n private readonly hybridOptions: {\n readonly useBroadcastChannel: boolean;\n readonly backupPollingIntervalMs: number;\n };\n\n constructor(\n public readonly queueName: string,\n options: IndexedDbQueueStorageOptions = {}\n ) {\n this.migrationOptions = options;\n this.prefixes = options.prefixes ?? [];\n this.prefixValues = options.prefixValues ?? {};\n this.hybridOptions = {\n useBroadcastChannel: options.useBroadcastChannel ?? true,\n backupPollingIntervalMs: options.backupPollingIntervalMs ?? 5000,\n };\n // Generate table name based on prefix configuration to avoid conflicts\n if (this.prefixes.length > 0) {\n const prefixNames = this.prefixes.map((p) => p.name).join(\"_\");\n this.tableName = `jobs_${prefixNames}`;\n } else {\n this.tableName = \"jobs\";\n }\n }\n\n /**\n * Gets prefix column names for use in indexes\n */\n private getPrefixColumnNames(): string[] {\n return this.prefixes.map((p) => p.name);\n }\n\n /**\n * Checks if a job matches the current prefix values\n */\n private matchesPrefixes(job: JobStorageFormat<Input, Output> & Record<string, unknown>): boolean {\n for (const [key, value] of Object.entries(this.prefixValues)) {\n if (job[key] !== value) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Gets prefix values as an array in column order for index key construction\n */\n private getPrefixKeyValues(): Array<string | number> {\n return this.prefixes.map((p) => this.prefixValues[p.name]);\n }\n\n private async getDb(): Promise<IDBDatabase> {\n if (this.db) return this.db;\n await this.setupDatabase();\n return this.db!;\n }\n\n /**\n * Sets up the IndexedDB database table with the required schema and indexes.\n * Must be called before using any other methods.\n */\n public async setupDatabase(): Promise<void> {\n const prefixColumnNames = this.getPrefixColumnNames();\n\n // Build index key paths with prefixes prepended\n const buildKeyPath = (basePath: string[]): string[] => {\n return [...prefixColumnNames, ...basePath];\n };\n\n const expectedIndexes: ExpectedIndexDefinition[] = [\n {\n name: \"queue_status\",\n keyPath: buildKeyPath([\"queue\", \"status\"]),\n options: { unique: false },\n },\n {\n name: \"queue_status_run_after\",\n keyPath: buildKeyPath([\"queue\", \"status\", \"run_after\"]),\n options: { unique: false },\n },\n {\n name: \"queue_job_run_id\",\n keyPath: buildKeyPath([\"queue\", \"job_run_id\"]),\n options: { unique: false },\n },\n {\n name: \"queue_fingerprint_status\",\n keyPath: buildKeyPath([\"queue\", \"fingerprint\", \"status\"]),\n options: { unique: false },\n },\n ];\n\n this.db = await ensureIndexedDbTable(\n this.tableName,\n \"id\",\n expectedIndexes,\n this.migrationOptions\n );\n }\n\n /**\n * Adds a job to the queue.\n * @param job - The job to add to the queue.\n * @returns A promise that resolves to the job id.\n */\n public async add(job: JobStorageFormat<Input, Output>): Promise<unknown> {\n const db = await this.getDb();\n const now = new Date().toISOString();\n const jobWithPrefixes = job as JobStorageFormat<Input, Output> & Record<string, unknown>;\n jobWithPrefixes.id = jobWithPrefixes.id ?? uuid4();\n jobWithPrefixes.job_run_id = jobWithPrefixes.job_run_id ?? uuid4();\n jobWithPrefixes.queue = this.queueName;\n jobWithPrefixes.fingerprint = await makeFingerprint(jobWithPrefixes.input);\n jobWithPrefixes.status = JobStatus.PENDING;\n jobWithPrefixes.progress = 0;\n jobWithPrefixes.progress_message = \"\";\n jobWithPrefixes.progress_details = null;\n jobWithPrefixes.created_at = now;\n jobWithPrefixes.run_after = now;\n\n // Add prefix values to the job\n for (const [key, value] of Object.entries(this.prefixValues)) {\n jobWithPrefixes[key] = value;\n }\n\n const tx = db.transaction(this.tableName, \"readwrite\");\n const store = tx.objectStore(this.tableName);\n\n return new Promise((resolve, reject) => {\n const request = store.add(jobWithPrefixes);\n\n // Don't resolve until transaction is complete\n tx.oncomplete = () => {\n // Notify hybrid manager of local change\n this.hybridManager?.notifyLocalChange();\n resolve(jobWithPrefixes.id);\n };\n tx.onerror = () => reject(tx.error);\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Retrieves a job from the queue by its id.\n * @param id - The id of the job to retrieve.\n * @returns A promise that resolves to the job or undefined if the job is not found.\n */\n async get(id: unknown): Promise<JobStorageFormat<Input, Output> | undefined> {\n const db = await this.getDb();\n const tx = db.transaction(this.tableName, \"readonly\");\n const store = tx.objectStore(this.tableName);\n const request = store.get(id as string);\n return new Promise((resolve, reject) => {\n request.onsuccess = () => {\n const job = request.result as\n | (JobStorageFormat<Input, Output> & Record<string, unknown>)\n | undefined;\n // Filter by queue name and prefix values to ensure job belongs to this queue\n if (job && job.queue === this.queueName && this.matchesPrefixes(job)) {\n resolve(job);\n } else {\n resolve(undefined);\n }\n };\n request.onerror = () => reject(request.error);\n tx.onerror = () => reject(tx.error);\n });\n }\n\n /**\n * Retrieves a slice of jobs from the queue.\n * @param status - The status of the jobs to retrieve.\n * @param num - The number of jobs to retrieve.\n * @returns A promise that resolves to an array of jobs.\n */\n public async peek(\n status: JobStatus = JobStatus.PENDING,\n num: number = 100\n ): Promise<JobStorageFormat<Input, Output>[]> {\n const db = await this.getDb();\n const tx = db.transaction(this.tableName, \"readonly\");\n const store = tx.objectStore(this.tableName);\n const index = store.index(\"queue_status_run_after\");\n const prefixKeyValues = this.getPrefixKeyValues();\n\n return new Promise((resolve, reject) => {\n const ret = new Map<unknown, JobStorageFormat<Input, Output>>();\n // Create a key range for the compound index: from [prefixes..., queue, status, \"\"] to [prefixes..., queue, status, \"\\uffff\"]\n const keyRange = IDBKeyRange.bound(\n [...prefixKeyValues, this.queueName, status, \"\"],\n [...prefixKeyValues, this.queueName, status, \"\\uffff\"]\n );\n const cursorRequest = index.openCursor(keyRange);\n\n const handleCursor = (e: Event) => {\n const cursor = (e.target as IDBRequest<IDBCursorWithValue>).result;\n if (!cursor || ret.size >= num) {\n resolve(Array.from(ret.values()));\n return;\n }\n const job = cursor.value as JobStorageFormat<Input, Output> & Record<string, unknown>;\n // Verify prefix match and use Map to ensure no duplicates by job ID\n if (this.matchesPrefixes(job)) {\n ret.set(cursor.value.id, cursor.value);\n }\n cursor.continue();\n };\n\n cursorRequest.onsuccess = handleCursor;\n cursorRequest.onerror = () => reject(cursorRequest.error);\n tx.onerror = () => reject(tx.error);\n });\n }\n\n /**\n * Retrieves the next job from the queue using optimistic locking. In case multiple workers\n * claim the same job, the first worker to claim it will process it and the other workers will return undefined.\n * This ONLY happens if workers are running in multiple tabs.\n *\n * IndexedDB uses snapshot isolation, so concurrent transactions can both see the same\n * PENDING job. To prevent processing the same job multiple times, this method:\n * 1. Claims a job by setting it to PROCESSING with a unique claim token\n * 2. After the transaction completes, re-reads the job to verify the claim succeeded\n * 3. If another worker claimed it first (different claim token), returns undefined\n *\n * @param workerId - Worker ID to associate with the job (required)\n * @returns A promise that resolves to the next job or undefined if the queue is empty.\n */\n public async next(workerId: string): Promise<JobStorageFormat<Input, Output> | undefined> {\n const db = await this.getDb();\n const tx = db.transaction(this.tableName, \"readwrite\");\n const store = tx.objectStore(this.tableName);\n const index = store.index(\"queue_status_run_after\");\n const now = new Date().toISOString();\n const prefixKeyValues = this.getPrefixKeyValues();\n\n // This ensures we can verify that we actually won the race to claim this job\n const claimToken = workerId;\n\n const jobToReturn = await new Promise<JobStorageFormat<Input, Output> | undefined>(\n (resolve, reject) => {\n const cursorRequest = index.openCursor(\n IDBKeyRange.bound(\n [...prefixKeyValues, this.queueName, JobStatus.PENDING, \"\"],\n [...prefixKeyValues, this.queueName, JobStatus.PENDING, now],\n false,\n false\n )\n );\n\n let claimedJob: JobStorageFormat<Input, Output> | undefined;\n let cursorStopped = false;\n\n cursorRequest.onsuccess = (e) => {\n const cursor = (e.target as IDBRequest<IDBCursorWithValue>).result;\n if (!cursor) {\n // Cursor exhausted - resolve with whatever we found (or undefined)\n return;\n }\n\n // If we already found and updated a job, stop iterating\n if (cursorStopped) {\n return;\n }\n\n const job = cursor.value as JobStorageFormat<Input, Output> & Record<string, unknown>;\n // Verify the job belongs to this queue, matches prefixes, and is still in PENDING state\n if (\n job.queue !== this.queueName ||\n job.status !== JobStatus.PENDING ||\n !this.matchesPrefixes(job)\n ) {\n cursor.continue();\n return;\n }\n\n // Claim the job with our unique token\n job.status = JobStatus.PROCESSING;\n job.last_ran_at = now;\n job.worker_id = claimToken;\n\n try {\n const updateRequest = store.put(job);\n updateRequest.onsuccess = () => {\n claimedJob = job;\n cursorStopped = true;\n // Stop cursor iteration - we've claimed a job\n };\n updateRequest.onerror = (err) => {\n console.error(\"Failed to update job status:\", err);\n cursor.continue();\n };\n } catch (err) {\n console.error(\"Error updating job:\", err);\n cursor.continue();\n }\n };\n\n cursorRequest.onerror = () => reject(cursorRequest.error);\n\n // Wait for transaction to complete before resolving\n tx.oncomplete = () => {\n // Notify hybrid manager of local change\n if (claimedJob) {\n this.hybridManager?.notifyLocalChange();\n }\n resolve(claimedJob);\n };\n tx.onerror = () => reject(tx.error);\n }\n );\n\n // If we didn't find any job to claim, return undefined\n if (!jobToReturn) {\n return undefined;\n }\n\n // Verify we actually won the race by re-reading the job\n // This is the optimistic locking check - if another worker claimed it first,\n // their claim token will be there instead of ours\n const verifiedJob = await this.get(jobToReturn.id);\n\n if (!verifiedJob) {\n // Job was deleted - we lost the race\n return undefined;\n }\n\n if (verifiedJob.worker_id !== claimToken) {\n // Another worker claimed this job - we lost the race\n return undefined;\n }\n\n if (verifiedJob.status !== JobStatus.PROCESSING) {\n // Job status changed (e.g., another worker completed it already) - we lost the race\n return undefined;\n }\n\n // We successfully claimed the job\n return verifiedJob;\n }\n\n /**\n * Retrieves the number of jobs in the queue.\n * Returns the count of jobs in the queue.\n */\n public async size(status = JobStatus.PENDING): Promise<number> {\n const db = await this.getDb();\n const prefixKeyValues = this.getPrefixKeyValues();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(this.tableName, \"readonly\");\n const store = tx.objectStore(this.tableName);\n const index = store.index(\"queue_status\");\n const keyRange = IDBKeyRange.only([...prefixKeyValues, this.queueName, status]);\n const request = index.count(keyRange);\n\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n tx.onerror = () => reject(tx.error);\n });\n }\n\n /**\n * Marks a job as complete with its output or error.\n */\n public async complete(job: JobStorageFormat<Input, Output>): Promise<void> {\n const db = await this.getDb();\n const tx = db.transaction(this.tableName, \"readwrite\");\n const store = tx.objectStore(this.tableName);\n\n return new Promise((resolve, reject) => {\n const getReq = store.get(job.id as string);\n getReq.onsuccess = () => {\n const existing = getReq.result as\n | (JobStorageFormat<Input, Output> & Record<string, unknown>)\n | undefined;\n // Verify job belongs to this queue and matches prefixes\n if (!existing || existing.queue !== this.queueName || !this.matchesPrefixes(existing)) {\n reject(\n new Error(`Job ${job.id} not found or does not belong to queue ${this.queueName}`)\n );\n return;\n }\n const currentAttempts = existing.run_attempts ?? 0;\n job.run_attempts = currentAttempts + 1;\n // Ensure queue is set correctly\n job.queue = this.queueName;\n\n // Ensure prefix values are preserved\n const jobWithPrefixes = job as JobStorageFormat<Input, Output> & Record<string, unknown>;\n for (const [key, value] of Object.entries(this.prefixValues)) {\n jobWithPrefixes[key] = value;\n }\n\n const putReq = store.put(jobWithPrefixes);\n putReq.onsuccess = () => {};\n putReq.onerror = () => reject(putReq.error);\n };\n getReq.onerror = () => reject(getReq.error);\n\n // Don't resolve until transaction is complete\n tx.oncomplete = () => {\n // Notify hybrid manager of local change\n this.hybridManager?.notifyLocalChange();\n resolve();\n };\n tx.onerror = () => reject(tx.error);\n });\n }\n\n /**\n * Releases a claimed job without consuming a retry attempt.\n */\n public async release(id: unknown): Promise<void> {\n const job = await this.get(id);\n if (!job) return;\n\n job.status = JobStatus.PENDING;\n job.worker_id = null;\n job.progress = 0;\n job.progress_message = \"\";\n job.progress_details = null;\n\n await this.put(job);\n }\n\n /**\n * Aborts a job in the queue.\n */\n public async abort(id: unknown): Promise<void> {\n const job = await this.get(id);\n if (!job) return;\n\n job.status = JobStatus.ABORTING;\n await this.complete(job);\n }\n\n /**\n * Gets jobs by their run ID.\n */\n public async getByRunId(job_run_id: string): Promise<JobStorageFormat<Input, Output>[]> {\n const db = await this.getDb();\n const tx = db.transaction(this.tableName, \"readonly\");\n const store = tx.objectStore(this.tableName);\n const index = store.index(\"queue_job_run_id\");\n const prefixKeyValues = this.getPrefixKeyValues();\n const keyRange = IDBKeyRange.only([...prefixKeyValues, this.queueName, job_run_id]);\n const request = index.getAll(keyRange);\n\n return new Promise((resolve, reject) => {\n request.onsuccess = () => {\n // Filter results to ensure they match prefixes\n const results = (request.result || []).filter(\n (job: JobStorageFormat<Input, Output> & Record<string, unknown>) =>\n this.matchesPrefixes(job)\n );\n resolve(results);\n };\n request.onerror = () => reject(request.error);\n tx.onerror = () => reject(tx.error);\n });\n }\n\n /**\n * Deletes all jobs from the queue.\n */\n public async deleteAll(): Promise<void> {\n const db = await this.getDb();\n const tx = db.transaction(this.tableName, \"readwrite\");\n const store = tx.objectStore(this.tableName);\n const index = store.index(\"queue_status\");\n const prefixKeyValues = this.getPrefixKeyValues();\n\n return new Promise((resolve, reject) => {\n // Use a cursor to iterate through all jobs for this queue with prefix\n const keyRange = IDBKeyRange.bound(\n [...prefixKeyValues, this.queueName, \"\"],\n [...prefixKeyValues, this.queueName, \"\\uffff\"]\n );\n const request = index.openCursor(keyRange);\n\n request.onsuccess = (event) => {\n const cursor = (event.target as IDBRequest<IDBCursorWithValue>).result;\n if (cursor) {\n const job = cursor.value as JobStorageFormat<Input, Output> & Record<string, unknown>;\n // Verify job belongs to this queue and matches prefixes before deleting\n if (job.queue === this.queueName && this.matchesPrefixes(job)) {\n const deleteRequest = cursor.delete();\n deleteRequest.onsuccess = () => {\n cursor.continue();\n };\n deleteRequest.onerror = () => {\n // Continue even if delete fails\n cursor.continue();\n };\n } else {\n cursor.continue();\n }\n }\n };\n\n tx.oncomplete = () => {\n // Notify hybrid manager of local change\n this.hybridManager?.notifyLocalChange();\n resolve();\n };\n tx.onerror = () => reject(tx.error);\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Gets the output for a given input.\n */\n public async outputForInput(input: Input): Promise<Output | null> {\n const fingerprint = await makeFingerprint(input);\n const db = await this.getDb();\n const tx = db.transaction(this.tableName, \"readonly\");\n const store = tx.objectStore(this.tableName);\n const index = store.index(\"queue_fingerprint_status\");\n const prefixKeyValues = this.getPrefixKeyValues();\n const request = index.get([\n ...prefixKeyValues,\n this.queueName,\n fingerprint,\n JobStatus.COMPLETED,\n ]);\n\n return new Promise((resolve, reject) => {\n request.onsuccess = () => {\n const job = request.result as\n | (JobStorageFormat<Input, Output> & Record<string, unknown>)\n | undefined;\n if (job && this.matchesPrefixes(job)) {\n resolve(job.output ?? null);\n } else {\n resolve(null);\n }\n };\n request.onerror = () => reject(request.error);\n tx.onerror = () => reject(tx.error);\n });\n }\n\n /**\n * Saves progress updates for a job.\n */\n public async saveProgress(\n id: unknown,\n progress: number,\n message: string,\n details: Record<string, any> | null\n ): Promise<void> {\n const job = await this.get(id);\n if (!job) throw new Error(`Job ${id} not found`);\n\n job.progress = progress;\n job.progress_message = message;\n job.progress_details = details;\n\n await this.put(job);\n }\n\n /**\n * Persists a job to the store without modifying run_attempts or other completion logic.\n */\n private async put(job: JobStorageFormat<Input, Output>): Promise<void> {\n const db = await this.getDb();\n const tx = db.transaction(this.tableName, \"readwrite\");\n const store = tx.objectStore(this.tableName);\n\n // Ensure queue is set correctly\n job.queue = this.queueName;\n\n // Ensure prefix values are preserved\n const jobWithPrefixes = job as JobStorageFormat<Input, Output> & Record<string, unknown>;\n for (const [key, value] of Object.entries(this.prefixValues)) {\n jobWithPrefixes[key] = value;\n }\n\n return new Promise((resolve, reject) => {\n const putReq = store.put(jobWithPrefixes);\n putReq.onerror = () => reject(putReq.error);\n tx.oncomplete = () => {\n // Notify hybrid manager of local change\n this.hybridManager?.notifyLocalChange();\n resolve();\n };\n tx.onerror = () => reject(tx.error);\n });\n }\n\n /**\n * Deletes a job by its ID.\n */\n public async delete(id: unknown): Promise<void> {\n const job = await this.get(id);\n if (!job) return;\n\n const db = await this.getDb();\n const tx = db.transaction(this.tableName, \"readwrite\");\n const store = tx.objectStore(this.tableName);\n const request = store.delete(id as string);\n\n return new Promise((resolve, reject) => {\n request.onsuccess = () => resolve();\n request.onerror = () => reject(request.error);\n tx.oncomplete = () => {\n // Notify hybrid manager of local change\n this.hybridManager?.notifyLocalChange();\n };\n tx.onerror = () => reject(tx.error);\n });\n }\n\n /**\n * Delete jobs with a specific status older than a cutoff date\n * @param status - Status of jobs to delete\n * @param olderThanMs - Delete jobs completed more than this many milliseconds ago\n */\n public async deleteJobsByStatusAndAge(status: JobStatus, olderThanMs: number): Promise<void> {\n const db = await this.getDb();\n const tx = db.transaction(this.tableName, \"readwrite\");\n const store = tx.objectStore(this.tableName);\n const index = store.index(\"queue_status\");\n const cutoffDate = new Date(Date.now() - olderThanMs).toISOString();\n const prefixKeyValues = this.getPrefixKeyValues();\n const keyRange = IDBKeyRange.only([...prefixKeyValues, this.queueName, status]);\n\n return new Promise((resolve, reject) => {\n const request = index.openCursor(keyRange);\n\n request.onsuccess = (event) => {\n const cursor = (event.target as IDBRequest<IDBCursorWithValue>).result;\n if (cursor) {\n const job = cursor.value as JobStorageFormat<Input, Output> & Record<string, unknown>;\n // Verify job belongs to this queue, matches prefixes, and matches criteria\n if (\n job.queue === this.queueName &&\n this.matchesPrefixes(job) &&\n job.status === status &&\n job.completed_at &&\n job.completed_at <= cutoffDate\n ) {\n cursor.delete();\n }\n cursor.continue();\n }\n };\n\n tx.oncomplete = () => {\n // Notify hybrid manager of local change\n this.hybridManager?.notifyLocalChange();\n resolve();\n };\n tx.onerror = () => reject(tx.error);\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Gets all jobs from the queue that match the current prefix values.\n * Used internally for normal polling-based subscriptions (efficient - filters at DB level).\n *\n * @returns A promise that resolves to an array of jobs\n */\n private async getAllJobs(): Promise<Array<JobStorageFormat<Input, Output>>> {\n const db = await this.getDb();\n const tx = db.transaction(this.tableName, \"readonly\");\n const store = tx.objectStore(this.tableName);\n const index = store.index(\"queue_status\");\n const prefixKeyValues = this.getPrefixKeyValues();\n\n return new Promise((resolve, reject) => {\n const jobs: Array<JobStorageFormat<Input, Output>> = [];\n // Use a key range that covers all statuses for this queue with prefixes\n const keyRange = IDBKeyRange.bound(\n [...prefixKeyValues, this.queueName, \"\"],\n [...prefixKeyValues, this.queueName, \"\\uffff\"]\n );\n const request = index.openCursor(keyRange);\n\n request.onsuccess = (event) => {\n const cursor = (event.target as IDBRequest<IDBCursorWithValue>).result;\n if (cursor) {\n const job = cursor.value as JobStorageFormat<Input, Output> & Record<string, unknown>;\n if (job.queue === this.queueName && this.matchesPrefixes(job)) {\n jobs.push(job);\n }\n cursor.continue();\n }\n };\n\n tx.oncomplete = () => resolve(jobs);\n tx.onerror = () => reject(tx.error);\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Gets all jobs from the queue with a custom prefix filter.\n * Used for subscriptions with custom prefix filters (filters at DB level where possible).\n *\n * @param prefixFilter - The prefix values to filter by (empty object = all jobs)\n * @returns A promise that resolves to an array of jobs\n */\n private async getAllJobsWithFilter(\n prefixFilter: Readonly<Record<string, string | number>>\n ): Promise<Array<JobStorageFormat<Input, Output>>> {\n const db = await this.getDb();\n const tx = db.transaction(this.tableName, \"readonly\");\n const store = tx.objectStore(this.tableName);\n\n return new Promise((resolve, reject) => {\n const jobs: Array<JobStorageFormat<Input, Output>> = [];\n const request = store.openCursor();\n\n request.onsuccess = (event) => {\n const cursor = (event.target as IDBRequest<IDBCursorWithValue>).result;\n if (cursor) {\n const job = cursor.value as JobStorageFormat<Input, Output> & Record<string, unknown>;\n // Filter by queue name\n if (job.queue !== this.queueName) {\n cursor.continue();\n return;\n }\n // If empty filter, include all jobs for this queue\n if (Object.keys(prefixFilter).length === 0) {\n jobs.push(job);\n } else {\n // Check each filter value\n let matches = true;\n for (const [key, value] of Object.entries(prefixFilter)) {\n if (job[key] !== value) {\n matches = false;\n break;\n }\n }\n if (matches) {\n jobs.push(job);\n }\n }\n cursor.continue();\n }\n };\n\n tx.oncomplete = () => resolve(jobs);\n tx.onerror = () => reject(tx.error);\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Checks if a prefix filter is custom (different from instance's prefixes).\n */\n private isCustomPrefixFilter(prefixFilter?: Readonly<Record<string, string | number>>): boolean {\n // No filter specified - use instance prefixes (not custom)\n if (prefixFilter === undefined) {\n return false;\n }\n // Empty filter - receive all (custom)\n if (Object.keys(prefixFilter).length === 0) {\n return true;\n }\n // Check if filter matches instance prefixes exactly\n const instanceKeys = Object.keys(this.prefixValues);\n const filterKeys = Object.keys(prefixFilter);\n if (instanceKeys.length !== filterKeys.length) {\n return true; // Different number of keys = custom\n }\n for (const key of instanceKeys) {\n if (this.prefixValues[key] !== prefixFilter[key]) {\n return true; // Different value = custom\n }\n }\n return false; // Matches instance prefixes exactly\n }\n\n /**\n * Gets or creates the shared hybrid subscription manager for normal subscriptions.\n * This ensures all normal subscriptions share a single manager.\n */\n private getHybridManager(): HybridSubscriptionManager<\n JobStorageFormat<Input, Output>,\n unknown,\n QueueChangePayload<Input, Output>\n > {\n if (!this.hybridManager) {\n // Generate unique channel name based on queue name and table name\n const channelName = `indexeddb-queue-${this.tableName}-${this.queueName}`;\n\n this.hybridManager = new HybridSubscriptionManager<\n JobStorageFormat<Input, Output>,\n unknown,\n QueueChangePayload<Input, Output>\n >(\n channelName,\n async () => {\n // Fetch jobs with instance's prefix filter (efficient DB-level filtering)\n const jobs = await this.getAllJobs();\n return new Map(jobs.map((j) => [j.id, j]));\n },\n (a, b) => deepEqual(a, b),\n {\n insert: (item) => ({ type: \"INSERT\" as const, new: item }),\n update: (oldItem, newItem) => ({ type: \"UPDATE\" as const, old: oldItem, new: newItem }),\n delete: (item) => ({ type: \"DELETE\" as const, old: item }),\n },\n {\n defaultIntervalMs: 1000,\n useBroadcastChannel: this.hybridOptions.useBroadcastChannel,\n backupPollingIntervalMs: this.hybridOptions.backupPollingIntervalMs,\n }\n );\n }\n return this.hybridManager;\n }\n\n /**\n * Creates a dedicated polling subscription for custom prefix filters.\n * This runs separately from the normal polling manager.\n */\n private subscribeWithCustomPrefixFilter(\n callback: (change: QueueChangePayload<Input, Output>) => void,\n prefixFilter: Readonly<Record<string, string | number>>,\n intervalMs: number\n ): () => void {\n let lastKnownJobs = new Map<unknown, JobStorageFormat<Input, Output>>();\n let cancelled = false;\n\n const poll = async () => {\n if (cancelled) return;\n try {\n const currentJobs = await this.getAllJobsWithFilter(prefixFilter);\n if (cancelled) return;\n const currentMap = new Map(currentJobs.map((j) => [j.id, j]));\n\n // Detect changes\n for (const [id, job] of currentMap) {\n const old = lastKnownJobs.get(id);\n if (!old) {\n callback({ type: \"INSERT\", new: job });\n } else if (!deepEqual(old, job)) {\n callback({ type: \"UPDATE\", old, new: job });\n }\n }\n\n for (const [id, job] of lastKnownJobs) {\n if (!currentMap.has(id)) {\n callback({ type: \"DELETE\", old: job });\n }\n }\n\n lastKnownJobs = currentMap;\n } catch {\n // Ignore polling errors\n }\n };\n\n const intervalId = setInterval(poll, intervalMs);\n poll(); // Initial poll\n\n return () => {\n cancelled = true;\n clearInterval(intervalId);\n };\n }\n\n /**\n * Subscribes to changes in the queue.\n * Uses polling since IndexedDB has no native cross-tab change notifications.\n *\n * Normal subscriptions (no custom prefix filter) share a single polling loop for efficiency.\n * Custom prefix filter subscriptions get their own dedicated polling loop with DB-level filtering.\n *\n * @param callback - Function called when a change occurs\n * @param options - Subscription options including polling interval and prefix filter\n * @returns Unsubscribe function\n */\n public subscribeToChanges(\n callback: (change: QueueChangePayload<Input, Output>) => void,\n options?: QueueSubscribeOptions\n ): () => void {\n const intervalMs = options?.pollingIntervalMs ?? 1000;\n\n // Check if this is a custom prefix filter subscription\n if (this.isCustomPrefixFilter(options?.prefixFilter)) {\n // Custom prefix filter - use dedicated polling with DB-level filtering\n return this.subscribeWithCustomPrefixFilter(callback, options!.prefixFilter!, intervalMs);\n }\n\n // Normal subscription - use shared hybrid manager (efficient)\n const manager = this.getHybridManager();\n return manager.subscribe(callback, { intervalMs });\n }\n\n /**\n * Cleanup method to destroy the hybrid manager\n */\n destroy(): void {\n if (this.hybridManager) {\n this.hybridManager.destroy();\n this.hybridManager = null;\n }\n }\n}\n",
|
|
57
|
+
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { DataPortSchemaObject, FromSchema, TypedArraySchemaOptions } from \"@workglow/util/schema\";\nimport { createServiceToken } from \"@workglow/util\";\nimport { BaseTabularStorage, ClientProvidedKeysOption } from \"./BaseTabularStorage\";\nimport {\n AnyTabularStorage,\n AutoGeneratedKeys,\n CoveringIndexQueryOptions,\n DeleteSearchCriteria,\n InsertEntity,\n QueryOptions,\n SearchCriteria,\n SimplifyPrimaryKey,\n TabularSubscribeOptions,\n} from \"./ITabularStorage\";\nimport { InMemoryTabularStorage } from \"./InMemoryTabularStorage\";\n\nexport const SHARED_IN_MEMORY_TABULAR_REPOSITORY = createServiceToken<AnyTabularStorage>(\n \"storage.tabularRepository.sharedInMemory\"\n);\n\nconst SYNC_TIMEOUT = 1000;\nconst MAX_PENDING_MESSAGES = 1000;\n\n/**\n * Message types for BroadcastChannel communication\n */\ntype BroadcastMessage =\n | { type: \"SYNC_REQUEST\" }\n | { type: \"SYNC_RESPONSE\"; data: any[] }\n | { type: \"PUT\"; entity: any }\n | { type: \"PUT_BULK\"; entities: any[] }\n | { type: \"DELETE\"; key: any }\n | { type: \"DELETE_ALL\" }\n | { type: \"DELETE_SEARCH\"; criteria: DeleteSearchCriteria<any> };\n\n/**\n * A tabular repository implementation that shares data across browser tabs/windows\n * using BroadcastChannel API. Uses InMemoryTabularStorage internally and\n * synchronizes changes across all instances.\n *\n * @template Schema - The schema definition for the entity using JSON Schema\n * @template PrimaryKeyNames - Array of property names that form the primary key\n */\nexport class SharedInMemoryTabularStorage<\n Schema extends DataPortSchemaObject,\n PrimaryKeyNames extends ReadonlyArray<keyof Schema[\"properties\"]>,\n // computed types\n Entity = FromSchema<Schema, TypedArraySchemaOptions>,\n PrimaryKey = SimplifyPrimaryKey<Entity, PrimaryKeyNames>,\n Value = Omit<Entity, PrimaryKeyNames[number] & keyof Entity>,\n InsertType extends InsertEntity<Entity, AutoGeneratedKeys<Schema>> = InsertEntity<\n Entity,\n AutoGeneratedKeys<Schema>\n >,\n> extends BaseTabularStorage<Schema, PrimaryKeyNames, Entity, PrimaryKey, Value, InsertType> {\n private channel: BroadcastChannel | null = null;\n private channelName: string;\n private inMemoryRepo: InMemoryTabularStorage<Schema, PrimaryKeyNames, Entity, PrimaryKey>;\n private isInitialized = false;\n private syncInProgress = false;\n private pendingMessages: BroadcastMessage[] = [];\n\n /**\n * Creates a new SharedInMemoryTabularStorage instance\n * @param channelName - Unique name for the BroadcastChannel (defaults to \"tabular_store\")\n * @param schema - Schema defining the structure of the entity\n * @param primaryKeyNames - Array of property names that form the primary key\n * @param indexes - Array of columns or column arrays to make searchable. Each string or single column creates a single-column index,\n * while each array creates a compound index with columns in the specified order.\n * @param clientProvidedKeys - How to handle client-provided values for auto-generated keys\n */\n constructor(\n channelName: string = \"tabular_store\",\n schema: Schema,\n primaryKeyNames: PrimaryKeyNames,\n indexes: readonly (keyof NoInfer<Entity> | readonly (keyof NoInfer<Entity>)[])[] = [],\n clientProvidedKeys: ClientProvidedKeysOption = \"if-missing\"\n ) {\n super(schema, primaryKeyNames, indexes, clientProvidedKeys);\n this.channelName = channelName;\n this.inMemoryRepo = new InMemoryTabularStorage<Schema, PrimaryKeyNames, Entity, PrimaryKey>(\n schema,\n primaryKeyNames,\n indexes,\n clientProvidedKeys\n );\n\n this.setupEventForwarding();\n\n this.initializeBroadcastChannel();\n }\n\n /**\n * Checks if BroadcastChannel is available in the current environment\n */\n private isBroadcastChannelAvailable(): boolean {\n return typeof BroadcastChannel !== \"undefined\";\n }\n\n /**\n * Initializes the BroadcastChannel and sets up message handlers\n */\n private initializeBroadcastChannel(): void {\n if (!this.isBroadcastChannelAvailable()) {\n console.warn(\"BroadcastChannel is not available. Tab synchronization will not work.\");\n return;\n }\n\n try {\n this.channel = new BroadcastChannel(this.channelName);\n this.channel.onmessage = (event: MessageEvent<BroadcastMessage>) => {\n this.handleBroadcastMessage(event.data);\n };\n\n // Request sync from other tabs on initialization\n this.syncFromOtherTabs();\n } catch (error) {\n console.error(\"Failed to initialize BroadcastChannel:\", error);\n }\n }\n\n /**\n * Sets up event forwarding from the internal InMemoryTabularStorage\n */\n private setupEventForwarding(): void {\n this.inMemoryRepo.on(\"put\", (entity) => {\n this.events.emit(\"put\", entity);\n });\n this.inMemoryRepo.on(\"get\", (key, entity) => {\n this.events.emit(\"get\", key, entity);\n });\n this.inMemoryRepo.on(\"query\", (key, entities) => {\n this.events.emit(\"query\", key, entities);\n });\n this.inMemoryRepo.on(\"delete\", (key) => {\n this.events.emit(\"delete\", key);\n });\n this.inMemoryRepo.on(\"clearall\", () => {\n this.events.emit(\"clearall\");\n });\n }\n\n /**\n * Handles incoming BroadcastChannel messages\n */\n private async handleBroadcastMessage(message: BroadcastMessage): Promise<void> {\n if (this.syncInProgress && message.type !== \"SYNC_RESPONSE\") {\n // Queue messages during sync to replay after sync completes\n if (this.pendingMessages.length < MAX_PENDING_MESSAGES) {\n this.pendingMessages.push(message);\n }\n return;\n }\n\n switch (message.type) {\n case \"SYNC_REQUEST\":\n // Respond to sync request with current data\n const all = await this.inMemoryRepo.getAll();\n if (this.channel && all) {\n this.channel.postMessage({\n type: \"SYNC_RESPONSE\",\n data: all,\n } as BroadcastMessage);\n }\n break;\n\n case \"SYNC_RESPONSE\":\n // Copy data from the responding tab\n if (message.data && Array.isArray(message.data)) {\n await this.copyDataFromArray(message.data);\n }\n this.syncInProgress = false;\n await this.drainPendingMessages();\n break;\n\n case \"PUT\":\n // Apply put from another tab\n await this.inMemoryRepo.put(message.entity);\n break;\n\n case \"PUT_BULK\":\n // Apply bulk put from another tab\n await this.inMemoryRepo.putBulk(message.entities);\n break;\n\n case \"DELETE\":\n // Apply delete from another tab\n await this.inMemoryRepo.delete(message.key);\n break;\n\n case \"DELETE_ALL\":\n // Apply deleteAll from another tab\n await this.inMemoryRepo.deleteAll();\n break;\n\n case \"DELETE_SEARCH\":\n // Apply deleteSearch from another tab\n await this.inMemoryRepo.deleteSearch(message.criteria as DeleteSearchCriteria<Entity>);\n break;\n }\n }\n\n /**\n * Drains pending messages that were queued during sync.\n * Uses a while loop to handle messages that may be re-queued during draining\n * (e.g., if a replayed message triggers a new sync cycle).\n */\n private async drainPendingMessages(): Promise<void> {\n while (!this.syncInProgress && this.pendingMessages.length > 0) {\n const messages = this.pendingMessages;\n this.pendingMessages = [];\n for (const message of messages) {\n await this.handleBroadcastMessage(message);\n if (this.syncInProgress) {\n break;\n }\n }\n }\n }\n\n /**\n * Requests synchronization from other tabs\n */\n private syncFromOtherTabs(): void {\n if (!this.channel) return;\n\n this.syncInProgress = true;\n this.channel.postMessage({ type: \"SYNC_REQUEST\" } as BroadcastMessage);\n\n // Set a timeout to stop waiting for sync response\n setTimeout(() => {\n if (this.syncInProgress) {\n this.syncInProgress = false;\n void this.drainPendingMessages().catch((error) => {\n console.error(\"Failed to drain pending messages after sync timeout\", error);\n });\n }\n }, SYNC_TIMEOUT);\n }\n\n /**\n * Copies data from an array of entities into the repository\n */\n private async copyDataFromArray(entities: Entity[]): Promise<void> {\n if (entities.length === 0) return;\n\n // Clear existing data\n await this.inMemoryRepo.deleteAll();\n\n // Bulk insert the new data\n await this.inMemoryRepo.putBulk(entities);\n }\n\n /**\n * Broadcasts a message to other tabs\n */\n private broadcast(message: BroadcastMessage): void {\n if (this.channel) {\n this.channel.postMessage(message);\n }\n }\n\n /**\n * Sets up the database for the repository (syncs from other tabs)\n */\n public override async setupDatabase(): Promise<void> {\n if (this.isInitialized) return;\n this.isInitialized = true;\n await this.syncFromOtherTabs();\n }\n\n /**\n * Stores a key-value pair in the repository\n * @param value - The combined object to store\n * @returns The stored entity\n * @emits 'put' event with the stored entity when successful\n */\n public async put(value: InsertType): Promise<Entity> {\n const result = await this.inMemoryRepo.put(value);\n this.broadcast({ type: \"PUT\", entity: result });\n return result;\n }\n\n /**\n * Stores multiple key-value pairs in the repository in a bulk operation\n * @param values - Array of combined objects to store\n * @returns Array of stored entities\n * @emits 'put' event for each value stored\n */\n public async putBulk(values: InsertType[]): Promise<Entity[]> {\n const result = await this.inMemoryRepo.putBulk(values);\n this.broadcast({ type: \"PUT_BULK\", entities: result });\n return result;\n }\n\n /**\n * Retrieves a value by its key\n * @param key - The primary key object to look up\n * @returns The value object if found, undefined otherwise\n * @emits 'get' event with the fingerprint ID and value when found\n */\n async get(key: PrimaryKey): Promise<Entity | undefined> {\n return await this.inMemoryRepo.get(key);\n }\n\n /**\n * Deletes an entry by its key\n * @param value - The primary key object or entity of the entry to delete\n * @emits 'delete' event with the fingerprint ID when successful\n */\n async delete(value: PrimaryKey | Entity): Promise<void> {\n await this.inMemoryRepo.delete(value);\n const { key } = this.separateKeyValueFromCombined(value as Entity);\n this.broadcast({ type: \"DELETE\", key });\n }\n\n /**\n * Removes all entries from the repository\n * @emits 'clearall' event when successful\n */\n async deleteAll(): Promise<void> {\n await this.inMemoryRepo.deleteAll();\n this.broadcast({ type: \"DELETE_ALL\" });\n }\n\n /**\n * Returns an array of all entries in the repository, with optional ordering, offset, and limit.\n * @param options - Optional ordering, limit, and offset options\n * @returns Array of all entries in the repository\n */\n async getAll(options?: QueryOptions<Entity>): Promise<Entity[] | undefined> {\n return await this.inMemoryRepo.getAll(options);\n }\n\n /**\n * Returns the number of entries in the repository\n * @returns The total count of stored entries\n */\n async size(): Promise<number> {\n return await this.inMemoryRepo.size();\n }\n\n /**\n * Fetches a page of records from the repository.\n * @param offset - Number of records to skip\n * @param limit - Maximum number of records to return\n * @returns Array of entities or undefined if no records found\n */\n async getBulk(offset: number, limit: number): Promise<Entity[] | undefined> {\n return await this.inMemoryRepo.getBulk(offset, limit);\n }\n\n /**\n * Queries entries matching the specified search criteria with optional ordering and limit.\n *\n * @param criteria - Object with column names as keys and values or SearchConditions\n * @param options - Optional ordering and limit options\n * @returns Array of matching entities or undefined if no matches found\n */\n async query(\n criteria: SearchCriteria<Entity>,\n options?: QueryOptions<Entity>\n ): Promise<Entity[] | undefined> {\n return await this.inMemoryRepo.query(criteria, options);\n }\n\n override async queryIndex<K extends keyof Entity & string>(\n criteria: SearchCriteria<Entity>,\n options: CoveringIndexQueryOptions<Entity, K>\n ): Promise<Pick<Entity, K>[]> {\n return await this.inMemoryRepo.queryIndex(criteria, options);\n }\n\n /**\n * Deletes all entries matching the specified search criteria.\n * Supports multiple columns with optional comparison operators.\n *\n * @param criteria - Object with column names as keys and values or SearchConditions\n */\n async deleteSearch(criteria: DeleteSearchCriteria<Entity>): Promise<void> {\n await this.inMemoryRepo.deleteSearch(criteria);\n this.broadcast({\n type: \"DELETE_SEARCH\",\n criteria,\n });\n }\n\n /**\n * Subscribes to changes in the repository.\n * Delegates to the internal InMemoryTabularStorage which monitors local changes.\n * Changes from other tabs/windows are already propagated via BroadcastChannel.\n *\n * @param callback - Function called when a change occurs\n * @param options - Optional subscription options (not used for in-memory)\n * @returns Unsubscribe function\n */\n public override subscribeToChanges(\n callback: (change: any) => void,\n options?: TabularSubscribeOptions\n ): () => void {\n return this.inMemoryRepo.subscribeToChanges(callback, options);\n }\n\n /**\n * Cleanup method to close the BroadcastChannel\n */\n public override destroy(): void {\n if (this.channel) {\n this.channel.close();\n this.channel = null;\n }\n this.inMemoryRepo.destroy();\n }\n}\n",
|
|
57
58
|
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { createServiceToken } from \"@workglow/util\";\nimport type {\n DataPortSchemaObject,\n FromSchema,\n TypedArray,\n TypedArrayConstructor,\n TypedArraySchemaOptions,\n} from \"@workglow/util/schema\";\nimport { cosineSimilarity } from \"@workglow/util/schema\";\nimport type { ClientProvidedKeysOption } from \"../tabular/BaseTabularStorage\";\nimport { IndexedDbTabularStorage } from \"../tabular/IndexedDbTabularStorage\";\nimport type { MigrationOptions } from \"../util/IndexedDbTable\";\nimport type {\n AnyVectorStorage,\n HybridSearchOptions,\n IVectorStorage,\n VectorSearchOptions,\n} from \"./IVectorStorage\";\nimport { getMetadataProperty, getVectorProperty } from \"./IVectorStorage\";\n\nexport const IDB_VECTOR_REPOSITORY = createServiceToken<AnyVectorStorage>(\n \"storage.vectorRepository.indexedDb\"\n);\n\n/**\n * Check if metadata matches filter\n */\nfunction matchesFilter<Metadata>(metadata: Metadata, filter: Partial<Metadata>): boolean {\n for (const [key, value] of Object.entries(filter)) {\n if (metadata[key as keyof Metadata] !== value) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Simple full-text search scoring (keyword matching)\n */\nfunction textRelevance(text: string, query: string): number {\n const textLower = text.toLowerCase();\n const queryLower = query.toLowerCase();\n const queryWords = queryLower.split(/\\s+/).filter((w) => w.length > 0);\n if (queryWords.length === 0) {\n return 0;\n }\n let matches = 0;\n for (const word of queryWords) {\n if (textLower.includes(word)) {\n matches++;\n }\n }\n return matches / queryWords.length;\n}\n\n/**\n * IndexedDB vector storage implementation.\n * Extends IndexedDbTabularStorage for storage.\n * Suitable for browser applications that need persistent vector storage.\n * No vector serialization needed since IndexedDB supports TypedArrays\n * natively via structured clone.\n *\n * @template Schema - The schema definition for the entity\n * @template PrimaryKeyNames - The primary key names\n * @template Metadata - The metadata type for the vector\n * @template VectorCtor - Constructor for stored vectors (default {@link typeof Float32Array})\n * @template Entity - The entity type\n */\nexport class IndexedDbVectorStorage<\n Schema extends DataPortSchemaObject,\n PrimaryKeyNames extends ReadonlyArray<keyof Schema[\"properties\"]>,\n Metadata extends Record<string, unknown> = Record<string, unknown>,\n Entity = FromSchema<Schema, TypedArraySchemaOptions>,\n>\n extends IndexedDbTabularStorage<Schema, PrimaryKeyNames, Entity>\n implements IVectorStorage<Metadata, Schema, Entity, PrimaryKeyNames>\n{\n private vectorDimensions: number;\n private vectorPropertyName: keyof Entity;\n private metadataPropertyName: keyof Entity | undefined;\n\n /**\n * Creates a new IndexedDB vector storage\n * @param table - The name of the IndexedDB store (defaults to 'vectors')\n * @param schema - The schema definition for the entity\n * @param primaryKeyNames - Array of property names that form the primary key\n * @param indexes - Array of columns or column arrays to make searchable\n * @param dimensions - The number of dimensions of the vector\n * @param _vectorCtor - TypedArray constructor (unused, IndexedDB stores typed arrays natively)\n * @param migrationOptions - Options for handling database schema migrations\n * @param clientProvidedKeys - How to handle client-provided values for auto-generated keys\n */\n constructor(\n table: string = \"vectors\",\n schema: Schema,\n primaryKeyNames: PrimaryKeyNames,\n indexes: readonly (keyof NoInfer<Entity> | readonly (keyof NoInfer<Entity>)[])[] = [],\n dimensions: number,\n _vectorCtor: TypedArrayConstructor = Float32Array,\n migrationOptions: MigrationOptions = {},\n clientProvidedKeys: ClientProvidedKeysOption = \"if-missing\"\n ) {\n super(table, schema, primaryKeyNames, indexes, migrationOptions, clientProvidedKeys);\n\n this.vectorDimensions = dimensions;\n\n // Cache vector and metadata property names from schema\n const vectorProp = getVectorProperty(schema);\n if (!vectorProp) {\n throw new Error(\"Schema must have a property with type array and format TypedArray\");\n }\n this.vectorPropertyName = vectorProp as keyof Entity;\n this.metadataPropertyName = getMetadataProperty(schema) as keyof Entity | undefined;\n }\n\n /**\n * Get the vector dimensions\n * @returns The vector dimensions\n */\n getVectorDimensions(): number {\n return this.vectorDimensions;\n }\n\n async similaritySearch(\n query: TypedArray,\n options: VectorSearchOptions<Record<string, unknown>> = {}\n ) {\n const { topK = 10, filter, scoreThreshold = 0 } = options;\n const results: Array<Entity & { score: number }> = [];\n\n const allEntities = (await this.getAll()) || [];\n\n for (const entity of allEntities) {\n // IndexedDB stores TypedArrays natively via structured clone (no deserialization needed)\n const vector = entity[this.vectorPropertyName] as TypedArray;\n const metadata = this.metadataPropertyName\n ? (entity[this.metadataPropertyName] as Metadata)\n : ({} as Metadata);\n\n // Apply filter if provided\n if (filter && !matchesFilter(metadata, filter)) {\n continue;\n }\n\n // Calculate similarity\n const score = cosineSimilarity(query, vector);\n\n // Apply threshold\n if (score < scoreThreshold) {\n continue;\n }\n\n results.push({\n ...entity,\n score,\n } as Entity & { score: number });\n }\n\n // Sort by score descending and take top K\n results.sort((a, b) => b.score - a.score);\n const topResults = results.slice(0, topK);\n\n return topResults;\n }\n\n async hybridSearch(query: TypedArray, options: HybridSearchOptions<Record<string, unknown>>) {\n const { topK = 10, filter, scoreThreshold = 0, textQuery, vectorWeight = 0.7 } = options;\n\n if (!textQuery || textQuery.trim().length === 0) {\n // Fall back to regular vector search if no text query\n return this.similaritySearch(query, { topK, filter, scoreThreshold });\n }\n\n const results: Array<Entity & { score: number }> = [];\n const allEntities = (await this.getAll()) || [];\n\n for (const entity of allEntities) {\n // IndexedDB stores TypedArrays natively via structured clone (no deserialization needed)\n const vector = entity[this.vectorPropertyName] as TypedArray;\n const metadata = this.metadataPropertyName\n ? (entity[this.metadataPropertyName] as Metadata)\n : ({} as Metadata);\n\n // Apply filter if provided\n if (filter && !matchesFilter(metadata, filter)) {\n continue;\n }\n\n // Calculate vector similarity\n const vectorScore = cosineSimilarity(query, vector);\n\n // Calculate text relevance (simple keyword matching)\n const metadataText = Object.values(metadata).join(\" \").toLowerCase();\n const textScore = textRelevance(metadataText, textQuery);\n\n // Combine scores\n const combinedScore = vectorWeight * vectorScore + (1 - vectorWeight) * textScore;\n\n // Apply threshold\n if (combinedScore < scoreThreshold) {\n continue;\n }\n\n results.push({\n ...entity,\n score: combinedScore,\n } as Entity & { score: number });\n }\n\n // Sort by combined score descending and take top K\n results.sort((a, b) => b.score - a.score);\n const topResults = results.slice(0, topK);\n\n return topResults;\n }\n}\n"
|
|
58
59
|
],
|
|
59
|
-
"mappings": "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",
|
|
60
|
-
"debugId": "
|
|
60
|
+
"mappings": "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",
|
|
61
|
+
"debugId": "992341815F57641864756E2164756E21",
|
|
61
62
|
"names": []
|
|
62
63
|
}
|