UNPKG

firestore-queue

Version:

A powerful, scalable queue system built on Google Firestore with time-based indexing, auto-configuration, and connection reuse

354 lines 12.5 kB
import { z } from 'zod'; import { Timestamp } from 'firebase-admin/firestore'; /** * Core queue message schema with Zod validation */ export declare const QueueMessageSchema: z.ZodObject<{ id: z.ZodOptional<z.ZodString>; type: z.ZodString; payload: z.ZodAny; priority: z.ZodDefault<z.ZodNumber>; retryable: z.ZodDefault<z.ZodBoolean>; maxRetries: z.ZodDefault<z.ZodNumber>; retryCount: z.ZodDefault<z.ZodNumber>; ttlSeconds: z.ZodOptional<z.ZodNumber>; version: z.ZodDefault<z.ZodNumber>; scheduledFor: z.ZodOptional<z.ZodDate>; tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>; metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodAny>>; }, "strip", z.ZodTypeAny, { type: string; priority: number; retryable: boolean; maxRetries: number; retryCount: number; version: number; tags: string[]; metadata: Record<string, any>; id?: string | undefined; payload?: any; ttlSeconds?: number | undefined; scheduledFor?: Date | undefined; }, { type: string; id?: string | undefined; payload?: any; priority?: number | undefined; retryable?: boolean | undefined; maxRetries?: number | undefined; retryCount?: number | undefined; ttlSeconds?: number | undefined; version?: number | undefined; scheduledFor?: Date | undefined; tags?: string[] | undefined; metadata?: Record<string, any> | undefined; }>; export type QueueMessage = z.infer<typeof QueueMessageSchema>; /** * Input type for creating queue messages - optional properties with defaults */ export type QueueMessageInput = { id?: string; type: string; payload?: any; priority?: number; retryable?: boolean; maxRetries?: number; retryCount?: number; ttlSeconds?: number; version?: number; scheduledFor?: Date; tags?: string[]; metadata?: Record<string, any>; }; /** * Internal queue document schema (what's stored in Firestore) */ export declare const QueueDocumentSchema: z.ZodObject<{ type: z.ZodString; payload: z.ZodAny; priority: z.ZodDefault<z.ZodNumber>; retryable: z.ZodDefault<z.ZodBoolean>; maxRetries: z.ZodDefault<z.ZodNumber>; retryCount: z.ZodDefault<z.ZodNumber>; ttlSeconds: z.ZodOptional<z.ZodNumber>; version: z.ZodDefault<z.ZodNumber>; scheduledFor: z.ZodOptional<z.ZodDate>; tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>; metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodAny>>; } & { id: z.ZodString; status: z.ZodDefault<z.ZodEnum<["pending", "processing", "completed", "failed", "expired"]>>; createdAt: z.ZodType<Timestamp, z.ZodTypeDef, Timestamp>; updatedAt: z.ZodType<Timestamp, z.ZodTypeDef, Timestamp>; expiresAt: z.ZodOptional<z.ZodType<Timestamp, z.ZodTypeDef, Timestamp>>; processingStartedAt: z.ZodOptional<z.ZodType<Timestamp, z.ZodTypeDef, Timestamp>>; completedAt: z.ZodOptional<z.ZodType<Timestamp, z.ZodTypeDef, Timestamp>>; error: z.ZodOptional<z.ZodString>; lockedBy: z.ZodOptional<z.ZodString>; lockedUntil: z.ZodOptional<z.ZodType<Timestamp, z.ZodTypeDef, Timestamp>>; }, "strip", z.ZodTypeAny, { id: string; type: string; priority: number; retryable: boolean; maxRetries: number; retryCount: number; version: number; status: "pending" | "processing" | "completed" | "failed" | "expired"; tags: string[]; metadata: Record<string, any>; createdAt: Timestamp; updatedAt: Timestamp; payload?: any; ttlSeconds?: number | undefined; scheduledFor?: Date | undefined; expiresAt?: Timestamp | undefined; processingStartedAt?: Timestamp | undefined; completedAt?: Timestamp | undefined; error?: string | undefined; lockedBy?: string | undefined; lockedUntil?: Timestamp | undefined; }, { id: string; type: string; createdAt: Timestamp; updatedAt: Timestamp; payload?: any; priority?: number | undefined; retryable?: boolean | undefined; maxRetries?: number | undefined; retryCount?: number | undefined; ttlSeconds?: number | undefined; version?: number | undefined; scheduledFor?: Date | undefined; status?: "pending" | "processing" | "completed" | "failed" | "expired" | undefined; tags?: string[] | undefined; metadata?: Record<string, any> | undefined; expiresAt?: Timestamp | undefined; processingStartedAt?: Timestamp | undefined; completedAt?: Timestamp | undefined; error?: string | undefined; lockedBy?: string | undefined; lockedUntil?: Timestamp | undefined; }>; export type QueueDocument = z.infer<typeof QueueDocumentSchema>; /** * Consumer tracking schema */ export declare const ConsumerStateSchema: z.ZodObject<{ consumerId: z.ZodString; queueName: z.ZodString; lastProcessedTimestamp: z.ZodType<Timestamp, z.ZodTypeDef, Timestamp>; isActive: z.ZodDefault<z.ZodBoolean>; heartbeatAt: z.ZodType<Timestamp, z.ZodTypeDef, Timestamp>; processedCount: z.ZodDefault<z.ZodNumber>; errorCount: z.ZodDefault<z.ZodNumber>; lastError: z.ZodOptional<z.ZodString>; configuration: z.ZodDefault<z.ZodObject<{ batchSize: z.ZodDefault<z.ZodNumber>; pollIntervalMs: z.ZodDefault<z.ZodNumber>; lockTimeoutMs: z.ZodDefault<z.ZodNumber>; maxConcurrency: z.ZodDefault<z.ZodNumber>; }, "strip", z.ZodTypeAny, { batchSize: number; pollIntervalMs: number; lockTimeoutMs: number; maxConcurrency: number; }, { batchSize?: number | undefined; pollIntervalMs?: number | undefined; lockTimeoutMs?: number | undefined; maxConcurrency?: number | undefined; }>>; }, "strip", z.ZodTypeAny, { consumerId: string; queueName: string; lastProcessedTimestamp: Timestamp; isActive: boolean; heartbeatAt: Timestamp; processedCount: number; errorCount: number; configuration: { batchSize: number; pollIntervalMs: number; lockTimeoutMs: number; maxConcurrency: number; }; lastError?: string | undefined; }, { consumerId: string; queueName: string; lastProcessedTimestamp: Timestamp; heartbeatAt: Timestamp; isActive?: boolean | undefined; processedCount?: number | undefined; errorCount?: number | undefined; lastError?: string | undefined; configuration?: { batchSize?: number | undefined; pollIntervalMs?: number | undefined; lockTimeoutMs?: number | undefined; maxConcurrency?: number | undefined; } | undefined; }>; export type ConsumerState = z.infer<typeof ConsumerStateSchema>; /** * Queue configuration schema */ export declare const QueueConfigSchema: z.ZodObject<{ projectId: z.ZodString; databaseId: z.ZodDefault<z.ZodString>; queueCollection: z.ZodDefault<z.ZodString>; consumerCollection: z.ZodDefault<z.ZodString>; defaultTtlSeconds: z.ZodDefault<z.ZodNumber>; defaultBatchSize: z.ZodDefault<z.ZodNumber>; defaultPollIntervalMs: z.ZodDefault<z.ZodNumber>; enableAutoCleanup: z.ZodDefault<z.ZodBoolean>; cleanupIntervalMs: z.ZodDefault<z.ZodNumber>; retainCompletedSeconds: z.ZodDefault<z.ZodNumber>; enableTimeBasedSharding: z.ZodDefault<z.ZodBoolean>; shardIntervalHours: z.ZodDefault<z.ZodNumber>; autoCreateIndexes: z.ZodDefault<z.ZodBoolean>; serviceAccountPath: z.ZodOptional<z.ZodString>; firestoreInstance: z.ZodOptional<z.ZodAny>; consumers: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{ enabled: z.ZodDefault<z.ZodBoolean>; batchSize: z.ZodOptional<z.ZodNumber>; pollIntervalMs: z.ZodOptional<z.ZodNumber>; maxConcurrency: z.ZodDefault<z.ZodNumber>; messageTypes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; }, "strip", z.ZodTypeAny, { maxConcurrency: number; enabled: boolean; tags?: string[] | undefined; batchSize?: number | undefined; pollIntervalMs?: number | undefined; messageTypes?: string[] | undefined; }, { tags?: string[] | undefined; batchSize?: number | undefined; pollIntervalMs?: number | undefined; maxConcurrency?: number | undefined; enabled?: boolean | undefined; messageTypes?: string[] | undefined; }>>>; }, "strip", z.ZodTypeAny, { projectId: string; databaseId: string; queueCollection: string; consumerCollection: string; defaultTtlSeconds: number; defaultBatchSize: number; defaultPollIntervalMs: number; enableAutoCleanup: boolean; cleanupIntervalMs: number; retainCompletedSeconds: number; enableTimeBasedSharding: boolean; shardIntervalHours: number; autoCreateIndexes: boolean; consumers: Record<string, { maxConcurrency: number; enabled: boolean; tags?: string[] | undefined; batchSize?: number | undefined; pollIntervalMs?: number | undefined; messageTypes?: string[] | undefined; }>; serviceAccountPath?: string | undefined; firestoreInstance?: any; }, { projectId: string; databaseId?: string | undefined; queueCollection?: string | undefined; consumerCollection?: string | undefined; defaultTtlSeconds?: number | undefined; defaultBatchSize?: number | undefined; defaultPollIntervalMs?: number | undefined; enableAutoCleanup?: boolean | undefined; cleanupIntervalMs?: number | undefined; retainCompletedSeconds?: number | undefined; enableTimeBasedSharding?: boolean | undefined; shardIntervalHours?: number | undefined; autoCreateIndexes?: boolean | undefined; serviceAccountPath?: string | undefined; firestoreInstance?: any; consumers?: Record<string, { tags?: string[] | undefined; batchSize?: number | undefined; pollIntervalMs?: number | undefined; maxConcurrency?: number | undefined; enabled?: boolean | undefined; messageTypes?: string[] | undefined; }> | undefined; }>; export type QueueConfig = z.infer<typeof QueueConfigSchema>; /** * Batch processing result */ export interface BatchResult { processed: number; successful: number; failed: number; errors: Array<{ messageId: string; error: string; }>; } /** * Queue metrics */ export interface QueueMetrics { totalMessages: number; pendingMessages: number; processingMessages: number; completedMessages: number; failedMessages: number; expiredMessages: number; averageProcessingTimeMs: number; messagesByType: Record<string, number>; messagesByPriority: Record<number, number>; consumerHealth: Array<{ consumerId: string; isActive: boolean; lastHeartbeat: Date; processedCount: number; errorCount: number; }>; } /** * Message handler function type */ export type MessageHandler<T = any> = (messages: Array<{ id: string; type: string; payload: T; metadata: Record<string, any>; ack: () => Promise<void>; nack: (error?: string) => Promise<void>; updatePayload: (newPayload: T) => Promise<void>; }>) => Promise<void>; /** * Hook function types for extensibility */ export type BeforeEnqueueHook = (message: QueueMessage) => Promise<QueueMessage>; export type AfterEnqueueHook = (message: QueueDocument) => Promise<void>; export type BeforeProcessHook = (messages: QueueDocument[]) => Promise<QueueDocument[]>; export type AfterProcessHook = (results: BatchResult) => Promise<void>; /** * Queue events for monitoring */ export interface QueueEvents { 'message.enqueued': (message: QueueDocument) => void; 'message.processing': (message: QueueDocument, consumerId: string) => void; 'message.completed': (message: QueueDocument, consumerId: string) => void; 'message.failed': (message: QueueDocument, error: string, consumerId: string) => void; 'message.expired': (message: QueueDocument) => void; 'message.updated': (oldMessage: QueueDocument, newMessage: QueueDocument) => void; 'consumer.started': (consumerId: string) => void; 'consumer.stopped': (consumerId: string) => void; 'consumer.error': (consumerId: string, error: string) => void; 'batch.processed': (consumerId: string, result: BatchResult) => void; } //# sourceMappingURL=index.d.ts.map