@scpxl/nodejs-framework 1.0.48 → 1.0.50
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/application/base-application.d.ts.map +1 -1
- package/dist/application/base-application.js +10 -0
- package/dist/application/base-application.js.map +2 -2
- package/dist/application/index.d.ts +2 -0
- package/dist/application/index.d.ts.map +1 -1
- package/dist/application/index.js +3 -1
- package/dist/application/index.js.map +2 -2
- package/dist/application/worker-application.d.ts +72 -0
- package/dist/application/worker-application.d.ts.map +1 -0
- package/dist/application/worker-application.interface.d.ts +17 -0
- package/dist/application/worker-application.interface.d.ts.map +1 -0
- package/dist/application/worker-application.interface.js +1 -0
- package/dist/application/worker-application.interface.js.map +7 -0
- package/dist/application/worker-application.js +99 -0
- package/dist/application/worker-application.js.map +7 -0
- package/dist/lifecycle/lifecycle-manager.d.ts +6 -0
- package/dist/lifecycle/lifecycle-manager.d.ts.map +1 -1
- package/dist/lifecycle/lifecycle-manager.js +28 -0
- package/dist/lifecycle/lifecycle-manager.js.map +2 -2
- package/dist/queue/manager.d.ts +6 -0
- package/dist/queue/manager.d.ts.map +1 -1
- package/dist/queue/manager.js +39 -4
- package/dist/queue/manager.js.map +2 -2
- package/dist/queue/worker.d.ts +5 -0
- package/dist/queue/worker.d.ts.map +1 -1
- package/dist/queue/worker.js +8 -0
- package/dist/queue/worker.js.map +2 -2
- package/dist/redis/index.d.ts +1 -1
- package/dist/redis/index.d.ts.map +1 -1
- package/dist/redis/index.js +3 -2
- package/dist/redis/index.js.map +2 -2
- package/dist/redis/instance.js +1 -1
- package/dist/redis/instance.js.map +2 -2
- package/dist/redis/manager.d.ts +5 -0
- package/dist/redis/manager.d.ts.map +1 -1
- package/dist/redis/manager.js +13 -0
- package/dist/redis/manager.js.map +2 -2
- package/dist/util/file.d.ts +13 -2
- package/dist/util/file.d.ts.map +1 -1
- package/dist/util/file.js.map +2 -2
- package/dist/webserver/controller/entity.d.ts +1 -0
- package/dist/webserver/controller/entity.d.ts.map +1 -1
- package/dist/webserver/controller/entity.js +7 -0
- package/dist/webserver/controller/entity.js.map +2 -2
- package/dist/websocket/websocket-client-manager.d.ts +2 -0
- package/dist/websocket/websocket-client-manager.d.ts.map +1 -1
- package/dist/websocket/websocket-client-manager.js +8 -1
- package/dist/websocket/websocket-client-manager.js.map +2 -2
- package/dist/websocket/websocket-client.d.ts +5 -0
- package/dist/websocket/websocket-client.d.ts.map +1 -1
- package/dist/websocket/websocket-client.js +22 -0
- package/dist/websocket/websocket-client.js.map +2 -2
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lifecycle/lifecycle-manager.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n type Disposable,\n type LifecycleConfig,\n type LifecycleHook,\n LifecyclePhase,\n type ReadinessCheck,\n type ReadinessCheckResult,\n} from './types.js';\n\nexport class LifecycleManager {\n private _phase: LifecyclePhase = LifecyclePhase.CREATED;\n private config: LifecycleConfig;\n\n private initHooks: LifecycleHook[] = [];\n private startHooks: LifecycleHook[] = [];\n private readyHooks: LifecycleHook[] = [];\n private beforeShutdownHooks: LifecycleHook[] = [];\n private shutdownHooks: LifecycleHook[] = [];\n\n private disposables = new Set<Disposable>();\n private intervals = new Set<NodeJS.Timeout>();\n private timeouts = new Set<NodeJS.Timeout>();\n private abortControllers = new Set<AbortController>();\n\n private readinessChecks = new Map<string, ReadinessCheck>();\n private _isReady = false;\n\n constructor(config: Partial<LifecycleConfig> = {}) {\n this.config = {\n gracefulShutdown: {\n timeoutMs: config.gracefulShutdown?.timeoutMs ?? 10000,\n },\n readiness: {\n timeoutMs: config.readiness?.timeoutMs ?? 30000,\n checkIntervalMs: config.readiness?.checkIntervalMs ?? 100,\n },\n };\n }\n\n get phase(): LifecyclePhase {\n return this._phase;\n }\n\n get isShuttingDown(): boolean {\n return this._phase === LifecyclePhase.STOPPING || this._phase === LifecyclePhase.STOPPED;\n }\n\n get isReady(): boolean {\n return this._isReady && this._phase === LifecyclePhase.RUNNING;\n }\n\n onInit(fn: LifecycleHook): () => void {\n this.initHooks.push(fn);\n return () => {\n const i = this.initHooks.indexOf(fn);\n if (i >= 0) this.initHooks.splice(i, 1);\n };\n }\n\n onStart(fn: LifecycleHook): () => void {\n this.startHooks.push(fn);\n return () => {\n const i = this.startHooks.indexOf(fn);\n if (i >= 0) this.startHooks.splice(i, 1);\n };\n }\n\n onReady(fn: LifecycleHook): () => void {\n this.readyHooks.push(fn);\n return () => {\n const i = this.readyHooks.indexOf(fn);\n if (i >= 0) this.readyHooks.splice(i, 1);\n };\n }\n\n onBeforeShutdown(fn: LifecycleHook): () => void {\n this.beforeShutdownHooks.push(fn);\n return () => {\n const i = this.beforeShutdownHooks.indexOf(fn);\n if (i >= 0) this.beforeShutdownHooks.splice(i, 1);\n };\n }\n\n onShutdown(fn: LifecycleHook): () => void {\n this.shutdownHooks.push(fn);\n return () => {\n const i = this.shutdownHooks.indexOf(fn);\n if (i >= 0) this.shutdownHooks.splice(i, 1);\n };\n }\n\n addReadinessCheck(name: string, check: ReadinessCheck): () => void {\n this.readinessChecks.set(name, check);\n return () => {\n this.readinessChecks.delete(name);\n };\n }\n\n trackDisposable(disposable: Disposable | { dispose: () => void | Promise<void> }): Disposable {\n const d: Disposable =\n 'dispose' in disposable ? { dispose: () => (disposable as { dispose: () => void }).dispose() } : disposable;\n this.disposables.add(d);\n return d;\n }\n\n trackInterval(id: NodeJS.Timeout): NodeJS.Timeout {\n this.intervals.add(id);\n return id;\n }\n\n trackTimeout(id: NodeJS.Timeout): NodeJS.Timeout {\n this.timeouts.add(id);\n return id;\n }\n\n /**\n * Track an AbortController for automatic cleanup on shutdown.\n * When the lifecycle manager shuts down, it will call abort() on all tracked controllers.\n * @param controller - The AbortController to track\n * @returns The same AbortController for chaining\n */\n trackAbortController(controller: AbortController): AbortController {\n this.abortControllers.add(controller);\n return controller;\n }\n\n /**\n * Create and track a new AbortController.\n * Convenience method that creates a new controller and automatically tracks it.\n * @returns A new tracked AbortController\n */\n createAbortController(): AbortController {\n const controller = new AbortController();\n return this.trackAbortController(controller);\n }\n\n async initialize(): Promise<{ errors: unknown[] }> {\n if (this._phase !== LifecyclePhase.CREATED) {\n return { errors: [] };\n }\n this._phase = LifecyclePhase.INITIALIZING;\n\n const errors = await this.executeHooks(this.initHooks, 'init');\n return { errors };\n }\n\n async start(): Promise<{ errors: unknown[] }> {\n if (this._phase !== LifecyclePhase.INITIALIZING) {\n return { errors: [] };\n }\n this._phase = LifecyclePhase.STARTING;\n\n const errors = await this.executeHooks(this.startHooks, 'start');\n return { errors };\n }\n\n async ready(): Promise<{ errors: unknown[] }> {\n if (this._phase !== LifecyclePhase.STARTING) {\n return { errors: [] };\n }\n this._phase = LifecyclePhase.RUNNING;\n\n const errors = await this.executeHooks(this.readyHooks, 'ready');\n\n // Wait for readiness checks to pass\n const readinessResult = await this.waitForReadiness();\n if (readinessResult.errors.length > 0) {\n errors.push(...readinessResult.errors);\n }\n this._isReady = readinessResult.ready;\n\n return { errors };\n }\n\n async shutdown(): Promise<{ errors: unknown[]; timedOut: boolean }> {\n if (this.isShuttingDown) {\n return { errors: [], timedOut: false };\n }\n this._phase = LifecyclePhase.STOPPING;\n\n const timeoutMs = this.config.gracefulShutdown.timeoutMs;\n if (timeoutMs > 0) {\n const shutdownPromise = this.performShutdown().then(result => ({\n ...result,\n timedOut: false,\n }));\n const timeoutPromise = new Promise<{ errors: unknown[]; timedOut: boolean }>(resolve => {\n setTimeout(() => {\n resolve({ errors: ['Shutdown timeout exceeded'], timedOut: true });\n }, timeoutMs);\n });\n const result = await Promise.race([shutdownPromise, timeoutPromise]);\n this._phase = LifecyclePhase.STOPPED;\n return result;\n }\n\n const result = await this.performShutdown();\n this._phase = LifecyclePhase.STOPPED;\n return { errors: result.errors, timedOut: false };\n }\n\n private async performShutdown(): Promise<{ errors: unknown[] }> {\n const errors: unknown[] = [];\n\n // Execute before-shutdown hooks in registration order (FIFO)\n const beforeShutdownErrors = await this.executeHooks(this.beforeShutdownHooks, 'before-shutdown');\n errors.push(...beforeShutdownErrors);\n\n // Abort all tracked AbortControllers\n for (const controller of this.abortControllers) {\n try {\n controller.abort();\n } catch (e) {\n errors.push(e);\n }\n }\n this.abortControllers.clear();\n\n // Clear intervals and timeouts\n for (const id of this.intervals) {\n clearInterval(id);\n }\n for (const id of this.timeouts) {\n clearTimeout(id);\n }\n this.intervals.clear();\n this.timeouts.clear();\n\n // Dispose of tracked disposables\n for (const disposable of this.disposables) {\n try {\n await disposable.dispose();\n } catch (e) {\n errors.push(e);\n }\n }\n this.disposables.clear();\n\n // Execute shutdown hooks in reverse registration order (LIFO)\n const shutdownErrors = await this.executeHooks([...this.shutdownHooks].reverse(), 'shutdown');\n errors.push(...shutdownErrors);\n\n return { errors };\n }\n\n private async executeHooks(hooks: LifecycleHook[], _phase: string): Promise<unknown[]> {\n const errors: unknown[] = [];\n for (const hook of hooks) {\n try {\n await hook();\n } catch (e) {\n errors.push(e);\n }\n }\n return errors;\n }\n\n private async waitForReadiness(): Promise<{ ready: boolean; errors: unknown[] }> {\n if (this.readinessChecks.size === 0) {\n return { ready: true, errors: [] };\n }\n\n const timeoutMs = this.config.readiness?.timeoutMs ?? 30000;\n const checkIntervalMs = this.config.readiness?.checkIntervalMs ?? 100;\n const startTime = Date.now();\n const errors: unknown[] = [];\n\n while (Date.now() - startTime < timeoutMs) {\n const results = await this.executeReadinessChecks();\n const allReady = results.every(r => r.ready);\n\n if (allReady) {\n return { ready: true, errors };\n }\n\n // Collect unique errors from failed checks\n for (const result of results) {\n if (!result.ready && result.error) {\n const errorMessage = result.error.message;\n if (!errors.some(e => (e as Error)?.message === errorMessage)) {\n errors.push(result.error);\n }\n }\n }\n\n // Wait before next check\n await new Promise(resolve => setTimeout(resolve, checkIntervalMs));\n }\n\n return { ready: false, errors: [...errors, new Error('Readiness check timeout exceeded')] };\n }\n\n private async executeReadinessChecks(): Promise<ReadinessCheckResult[]> {\n const checkEntries = Array.from(this.readinessChecks.entries());\n\n const settledResults = await Promise.allSettled(\n checkEntries.map(async ([name, check]) => {\n try {\n const result = await check();\n return { name, ready: result };\n } catch (error) {\n return { name, ready: false, error: error as Error };\n }\n }),\n );\n\n return settledResults.map((settledResult, index) => {\n const checkEntry = checkEntries.at(index);\n if (!checkEntry) {\n throw new Error(`Missing check entry at index ${index}`);\n }\n const [name] = checkEntry;\n\n if (settledResult.status === 'fulfilled') {\n return settledResult.value;\n }\n\n return {\n name,\n ready: false,\n error: settledResult.reason as Error,\n };\n });\n }\n\n async getReadinessStatus(): Promise<{ ready: boolean; checks: ReadinessCheckResult[] }> {\n const checks = await this.executeReadinessChecks();\n const ready = this._isReady && this._phase === LifecyclePhase.RUNNING && checks.every(c => c.ready);\n return { ready, checks };\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import {\n type Disposable,\n type LifecycleConfig,\n type LifecycleHook,\n LifecyclePhase,\n type ReadinessCheck,\n type ReadinessCheckResult,\n} from './types.js';\n\nexport class LifecycleManager {\n private _phase: LifecyclePhase = LifecyclePhase.CREATED;\n private config: LifecycleConfig;\n\n private initHooks: LifecycleHook[] = [];\n private startHooks: LifecycleHook[] = [];\n private readyHooks: LifecycleHook[] = [];\n private beforeShutdownHooks: LifecycleHook[] = [];\n private shutdownHooks: LifecycleHook[] = [];\n\n private disposables = new Set<Disposable>();\n private intervals = new Set<NodeJS.Timeout>();\n private timeouts = new Set<NodeJS.Timeout>();\n private abortControllers = new Set<AbortController>();\n\n private readinessChecks = new Map<string, ReadinessCheck>();\n private _isReady = false;\n\n constructor(config: Partial<LifecycleConfig> = {}) {\n this.config = {\n gracefulShutdown: {\n timeoutMs: config.gracefulShutdown?.timeoutMs ?? 10000,\n },\n readiness: {\n timeoutMs: config.readiness?.timeoutMs ?? 30000,\n checkIntervalMs: config.readiness?.checkIntervalMs ?? 100,\n },\n };\n }\n\n get phase(): LifecyclePhase {\n return this._phase;\n }\n\n get isShuttingDown(): boolean {\n return this._phase === LifecyclePhase.STOPPING || this._phase === LifecyclePhase.STOPPED;\n }\n\n get isReady(): boolean {\n return this._isReady && this._phase === LifecyclePhase.RUNNING;\n }\n\n onInit(fn: LifecycleHook): () => void {\n this.initHooks.push(fn);\n return () => {\n const i = this.initHooks.indexOf(fn);\n if (i >= 0) this.initHooks.splice(i, 1);\n };\n }\n\n onStart(fn: LifecycleHook): () => void {\n this.startHooks.push(fn);\n return () => {\n const i = this.startHooks.indexOf(fn);\n if (i >= 0) this.startHooks.splice(i, 1);\n };\n }\n\n onReady(fn: LifecycleHook): () => void {\n this.readyHooks.push(fn);\n return () => {\n const i = this.readyHooks.indexOf(fn);\n if (i >= 0) this.readyHooks.splice(i, 1);\n };\n }\n\n onBeforeShutdown(fn: LifecycleHook): () => void {\n this.beforeShutdownHooks.push(fn);\n return () => {\n const i = this.beforeShutdownHooks.indexOf(fn);\n if (i >= 0) this.beforeShutdownHooks.splice(i, 1);\n };\n }\n\n onShutdown(fn: LifecycleHook): () => void {\n this.shutdownHooks.push(fn);\n return () => {\n const i = this.shutdownHooks.indexOf(fn);\n if (i >= 0) this.shutdownHooks.splice(i, 1);\n };\n }\n\n addReadinessCheck(name: string, check: ReadinessCheck): () => void {\n this.readinessChecks.set(name, check);\n return () => {\n this.readinessChecks.delete(name);\n };\n }\n\n trackDisposable(disposable: Disposable | { dispose: () => void | Promise<void> }): Disposable {\n const d: Disposable =\n 'dispose' in disposable ? { dispose: () => (disposable as { dispose: () => void }).dispose() } : disposable;\n this.disposables.add(d);\n return d;\n }\n\n trackInterval(id: NodeJS.Timeout): NodeJS.Timeout {\n this.intervals.add(id);\n return id;\n }\n\n trackTimeout(id: NodeJS.Timeout): NodeJS.Timeout {\n this.timeouts.add(id);\n return id;\n }\n\n /**\n * Track an AbortController for automatic cleanup on shutdown.\n * When the lifecycle manager shuts down, it will call abort() on all tracked controllers.\n * @param controller - The AbortController to track\n * @returns The same AbortController for chaining\n */\n trackAbortController(controller: AbortController): AbortController {\n this.abortControllers.add(controller);\n return controller;\n }\n\n /**\n * Create and track a new AbortController.\n * Convenience method that creates a new controller and automatically tracks it.\n * @returns A new tracked AbortController\n */\n createAbortController(): AbortController {\n const controller = new AbortController();\n return this.trackAbortController(controller);\n }\n\n async initialize(): Promise<{ errors: unknown[] }> {\n if (this._phase !== LifecyclePhase.CREATED) {\n return { errors: [] };\n }\n this._phase = LifecyclePhase.INITIALIZING;\n\n const errors = await this.executeHooks(this.initHooks, 'init');\n return { errors };\n }\n\n async start(): Promise<{ errors: unknown[] }> {\n if (this._phase !== LifecyclePhase.INITIALIZING) {\n return { errors: [] };\n }\n this._phase = LifecyclePhase.STARTING;\n\n const errors = await this.executeHooks(this.startHooks, 'start');\n return { errors };\n }\n\n async ready(): Promise<{ errors: unknown[] }> {\n if (this._phase !== LifecyclePhase.STARTING) {\n return { errors: [] };\n }\n this._phase = LifecyclePhase.RUNNING;\n\n const errors = await this.executeHooks(this.readyHooks, 'ready');\n\n // Wait for readiness checks to pass\n const readinessResult = await this.waitForReadiness();\n if (readinessResult.errors.length > 0) {\n errors.push(...readinessResult.errors);\n }\n this._isReady = readinessResult.ready;\n\n return { errors };\n }\n\n async shutdown(): Promise<{ errors: unknown[]; timedOut: boolean }> {\n if (this.isShuttingDown) {\n return { errors: [], timedOut: false };\n }\n this._phase = LifecyclePhase.STOPPING;\n\n const timeoutMs = this.config.gracefulShutdown.timeoutMs;\n if (timeoutMs > 0) {\n const shutdownPromise = this.performShutdown().then(result => ({\n ...result,\n timedOut: false,\n }));\n const timeoutPromise = new Promise<{ errors: unknown[]; timedOut: boolean }>(resolve => {\n setTimeout(() => {\n resolve({ errors: ['Shutdown timeout exceeded'], timedOut: true });\n }, timeoutMs);\n });\n const result = await Promise.race([shutdownPromise, timeoutPromise]);\n this._phase = LifecyclePhase.STOPPED;\n return result;\n }\n\n const result = await this.performShutdown();\n this._phase = LifecyclePhase.STOPPED;\n return { errors: result.errors, timedOut: false };\n }\n\n private async performShutdown(): Promise<{ errors: unknown[] }> {\n const errors: unknown[] = [];\n\n // Execute before-shutdown hooks in registration order (FIFO)\n const beforeShutdownErrors = await this.executeHooks(this.beforeShutdownHooks, 'before-shutdown');\n errors.push(...beforeShutdownErrors);\n\n // Abort all tracked AbortControllers\n for (const controller of this.abortControllers) {\n try {\n controller.abort();\n } catch (e) {\n errors.push(e);\n }\n }\n this.abortControllers.clear();\n\n // Clear intervals and timeouts\n for (const id of this.intervals) {\n clearInterval(id);\n }\n for (const id of this.timeouts) {\n clearTimeout(id);\n }\n this.intervals.clear();\n this.timeouts.clear();\n\n // Dispose of tracked disposables\n for (const disposable of this.disposables) {\n try {\n await disposable.dispose();\n } catch (e) {\n errors.push(e);\n }\n }\n this.disposables.clear();\n\n // Execute shutdown hooks in reverse registration order (LIFO)\n const shutdownErrors = await this.executeHooks([...this.shutdownHooks].reverse(), 'shutdown');\n errors.push(...shutdownErrors);\n\n return { errors };\n }\n\n private async executeHooks(hooks: LifecycleHook[], _phase: string): Promise<unknown[]> {\n const errors: unknown[] = [];\n for (const hook of hooks) {\n try {\n await hook();\n } catch (e) {\n errors.push(e);\n }\n }\n return errors;\n }\n\n private async waitForReadiness(): Promise<{ ready: boolean; errors: unknown[] }> {\n if (this.readinessChecks.size === 0) {\n return { ready: true, errors: [] };\n }\n\n const timeoutMs = this.config.readiness?.timeoutMs ?? 30000;\n const checkIntervalMs = this.config.readiness?.checkIntervalMs ?? 100;\n const startTime = Date.now();\n const errors: unknown[] = [];\n\n while (Date.now() - startTime < timeoutMs) {\n const results = await this.executeReadinessChecks();\n const allReady = results.every(r => r.ready);\n\n if (allReady) {\n return { ready: true, errors };\n }\n\n // Collect unique errors from failed checks\n for (const result of results) {\n if (!result.ready && result.error) {\n const errorMessage = result.error.message;\n if (!errors.some(e => (e as Error)?.message === errorMessage)) {\n errors.push(result.error);\n }\n }\n }\n\n // Wait before next check\n await new Promise(resolve => setTimeout(resolve, checkIntervalMs));\n }\n\n return { ready: false, errors: [...errors, new Error('Readiness check timeout exceeded')] };\n }\n\n private async executeReadinessChecks(): Promise<ReadinessCheckResult[]> {\n const checkEntries = Array.from(this.readinessChecks.entries());\n\n const settledResults = await Promise.allSettled(\n checkEntries.map(async ([name, check]) => {\n try {\n const result = await check();\n return { name, ready: result };\n } catch (error) {\n return { name, ready: false, error: error as Error };\n }\n }),\n );\n\n return settledResults.map((settledResult, index) => {\n const checkEntry = checkEntries.at(index);\n if (!checkEntry) {\n throw new Error(`Missing check entry at index ${index}`);\n }\n const [name] = checkEntry;\n\n if (settledResult.status === 'fulfilled') {\n return settledResult.value;\n }\n\n return {\n name,\n ready: false,\n error: settledResult.reason as Error,\n };\n });\n }\n\n async getReadinessStatus(): Promise<{ ready: boolean; checks: ReadinessCheckResult[] }> {\n const checks = await this.executeReadinessChecks();\n const ready = this._isReady && this._phase === LifecyclePhase.RUNNING && checks.every(c => c.ready);\n return { ready, checks };\n }\n\n /**\n * Reset the lifecycle manager to its initial state.\n * This clears all hooks, tracked resources, and readiness checks.\n * Useful for testing or when reinitializing the application.\n */\n reset(): void {\n // Clear all hooks\n this.initHooks.length = 0;\n this.startHooks.length = 0;\n this.readyHooks.length = 0;\n this.beforeShutdownHooks.length = 0;\n this.shutdownHooks.length = 0;\n\n // Clear all tracked resources\n for (const id of this.intervals) {\n clearInterval(id);\n }\n for (const id of this.timeouts) {\n clearTimeout(id);\n }\n for (const controller of this.abortControllers) {\n controller.abort();\n }\n\n this.disposables.clear();\n this.intervals.clear();\n this.timeouts.clear();\n this.abortControllers.clear();\n this.readinessChecks.clear();\n\n // Reset state\n this._phase = LifecyclePhase.CREATED;\n this._isReady = false;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["result"]
|
|
7
7
|
}
|
package/dist/queue/manager.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ export default class QueueManager {
|
|
|
18
18
|
private databaseInstance;
|
|
19
19
|
private eventManager?;
|
|
20
20
|
private queues;
|
|
21
|
+
private workers;
|
|
21
22
|
private jobProcessors;
|
|
22
23
|
constructor({ applicationConfig, options, queues: _queues, redisInstance, databaseInstance, eventManager, }: QueueManagerConstructorParams);
|
|
23
24
|
registerQueues({ queues }: {
|
|
@@ -36,6 +37,11 @@ export default class QueueManager {
|
|
|
36
37
|
}) => Promise<Job<QueueJobData<TPayload, TMetadata>, TResult, TName> | undefined>;
|
|
37
38
|
private workerProcessor;
|
|
38
39
|
listAllJobsWithStatus(): Promise<JobSummary[]>;
|
|
40
|
+
/**
|
|
41
|
+
* Disconnect all queues and workers, cleanup resources.
|
|
42
|
+
* Should be called during application shutdown.
|
|
43
|
+
*/
|
|
44
|
+
disconnect(): Promise<void>;
|
|
39
45
|
/**
|
|
40
46
|
* Log queue message
|
|
41
47
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/queue/manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,GAAG,EAAgD,MAAM,QAAQ,CAAC;AAEhF,OAAO,KAAK,EAAE,6BAA6B,EAAuB,MAAM,wBAAwB,CAAC;AAOjG,OAAO,KAAK,EAAY,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAElF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAItD,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;IAC5E,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,CAAC,OAAO,OAAO,YAAY;IAC/B,OAAO,CAAC,MAAM,CAAyB;IAEvC,OAAO,CAAC,iBAAiB,CAAoB;IAE7C,OAAO,CAAC,OAAO,CAAsB;IAErC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,gBAAgB,CAA0B;IAClD,OAAO,CAAC,YAAY,CAAC,CAAe;IAEpC,OAAO,CAAC,MAAM,CAAiC;IAE/C,OAAO,CAAC,aAAa,CAAyC;gBAElD,EACV,iBAAiB,EACjB,OAAO,EACP,MAAM,EAAE,OAAO,EACf,aAAa,EACb,gBAAgB,EAChB,YAAY,GACb,EAAE,6BAA6B;IAgBnB,cAAc,CAAC,EAAE,MAAM,EAAE,EAAE;QAAE,MAAM,EAAE,SAAS,EAAE,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAiC/E,OAAO,CAAC,aAAa;
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/queue/manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,GAAG,EAAgD,MAAM,QAAQ,CAAC;AAEhF,OAAO,KAAK,EAAE,6BAA6B,EAAuB,MAAM,wBAAwB,CAAC;AAOjG,OAAO,KAAK,EAAY,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAElF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAItD,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;IAC5E,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,CAAC,OAAO,OAAO,YAAY;IAC/B,OAAO,CAAC,MAAM,CAAyB;IAEvC,OAAO,CAAC,iBAAiB,CAAoB;IAE7C,OAAO,CAAC,OAAO,CAAsB;IAErC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,gBAAgB,CAA0B;IAClD,OAAO,CAAC,YAAY,CAAC,CAAe;IAEpC,OAAO,CAAC,MAAM,CAAiC;IAE/C,OAAO,CAAC,OAAO,CAAuC;IAEtD,OAAO,CAAC,aAAa,CAAyC;gBAElD,EACV,iBAAiB,EACjB,OAAO,EACP,MAAM,EAAE,OAAO,EACf,aAAa,EACb,gBAAgB,EAChB,YAAY,GACb,EAAE,6BAA6B;IAgBnB,cAAc,CAAC,EAAE,MAAM,EAAE,EAAE;QAAE,MAAM,EAAE,SAAS,EAAE,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAiC/E,OAAO,CAAC,aAAa;IAwErB,OAAO,CAAC,qBAAqB;IA0C7B,OAAO,CAAC,YAAY,CAElB;IAEF,OAAO,CAAC,cAAc,CAIpB;IAEF,OAAO,CAAC,eAAe,CAKrB;IAEF,OAAO,CAAC,cAAc,CAEpB;IAEK,aAAa,GAClB,QAAQ,SAAS,eAAe,GAAG,eAAe,EAClD,SAAS,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnE,OAAO,GAAG,OAAO,EACjB,KAAK,SAAS,MAAM,GAAG,MAAM,EAC7B,2BAIC;QACD,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,YAAY,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;KACzC,KAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,GAAG,SAAS,CAAC,CAyB7E;IAEF,OAAO,CAAC,eAAe,CA2ErB;IAEW,qBAAqB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IA6B3D;;;OAGG;IACU,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAoCxC;;OAEG;IACI,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAGlE"}
|
package/dist/queue/manager.js
CHANGED
|
@@ -16,6 +16,7 @@ class QueueManager {
|
|
|
16
16
|
databaseInstance;
|
|
17
17
|
eventManager;
|
|
18
18
|
queues = /* @__PURE__ */ new Map();
|
|
19
|
+
workers = /* @__PURE__ */ new Map();
|
|
19
20
|
jobProcessors = /* @__PURE__ */ new Map();
|
|
20
21
|
constructor({
|
|
21
22
|
applicationConfig,
|
|
@@ -93,7 +94,7 @@ class QueueManager {
|
|
|
93
94
|
autorun: true,
|
|
94
95
|
...queue.settings ?? {}
|
|
95
96
|
};
|
|
96
|
-
new QueueWorker({
|
|
97
|
+
const worker = new QueueWorker({
|
|
97
98
|
applicationConfig: this.applicationConfig,
|
|
98
99
|
queueManager: this,
|
|
99
100
|
name: queue.name,
|
|
@@ -101,6 +102,7 @@ class QueueManager {
|
|
|
101
102
|
options: workerOptions,
|
|
102
103
|
redisInstance: this.redisInstance
|
|
103
104
|
});
|
|
105
|
+
this.workers.set(queue.name, worker);
|
|
104
106
|
}
|
|
105
107
|
this.queues.set(queue.name, queueInstance);
|
|
106
108
|
if (this.applicationConfig.queue.log?.queueRegistered) {
|
|
@@ -173,10 +175,10 @@ class QueueManager {
|
|
|
173
175
|
return;
|
|
174
176
|
}
|
|
175
177
|
const job = await queue.add(jobId, data);
|
|
176
|
-
const dataStr = JSON.stringify(data);
|
|
177
|
-
const maxLogDataStrLength = 50;
|
|
178
|
-
const truncatedLogDataStr = dataStr.length > maxLogDataStrLength ? `${dataStr.substring(0, maxLogDataStrLength)}...` : dataStr;
|
|
179
178
|
if (this.applicationConfig.queue.log?.jobAdded) {
|
|
179
|
+
const dataStr = JSON.stringify(data);
|
|
180
|
+
const maxLogDataStrLength = 50;
|
|
181
|
+
const truncatedLogDataStr = dataStr.length > maxLogDataStrLength ? `${dataStr.substring(0, maxLogDataStrLength)}...` : dataStr;
|
|
180
182
|
this.log("Job added", {
|
|
181
183
|
Queue: queueId,
|
|
182
184
|
"Job ID": jobId,
|
|
@@ -267,6 +269,39 @@ class QueueManager {
|
|
|
267
269
|
}
|
|
268
270
|
return jobsSummary;
|
|
269
271
|
}
|
|
272
|
+
/**
|
|
273
|
+
* Disconnect all queues and workers, cleanup resources.
|
|
274
|
+
* Should be called during application shutdown.
|
|
275
|
+
*/
|
|
276
|
+
async disconnect() {
|
|
277
|
+
for (const [name, worker] of this.workers) {
|
|
278
|
+
try {
|
|
279
|
+
await worker.cleanup();
|
|
280
|
+
this.log("Worker closed", { Name: name });
|
|
281
|
+
} catch (error) {
|
|
282
|
+
Logger.error({
|
|
283
|
+
error,
|
|
284
|
+
message: `Failed to close worker: ${name}`
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
for (const [name, queue] of this.queues) {
|
|
289
|
+
try {
|
|
290
|
+
queue.removeAllListeners();
|
|
291
|
+
await queue.close();
|
|
292
|
+
this.log("Queue closed", { Name: name });
|
|
293
|
+
} catch (error) {
|
|
294
|
+
Logger.error({
|
|
295
|
+
error,
|
|
296
|
+
message: `Failed to close queue: ${name}`
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
this.workers.clear();
|
|
301
|
+
this.queues.clear();
|
|
302
|
+
this.jobProcessors.clear();
|
|
303
|
+
this.log("Queue manager disconnected");
|
|
304
|
+
}
|
|
270
305
|
/**
|
|
271
306
|
* Log queue message
|
|
272
307
|
*/
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/queue/manager.ts"],
|
|
4
|
-
"sourcesContent": ["import { type Job, Queue, type QueueOptions, type WorkerOptions } from 'bullmq';\nimport path from 'path';\nimport type { QueueManagerConstructorParams, QueueManagerOptions } from './manager.interface.js';\nimport type { RedisInstance } from '../redis/index.js';\nimport type { DatabaseInstance } from '../database/index.js';\nimport { Logger } from '../logger/index.js';\nimport QueueWorker from './worker.js';\nimport type BaseProcessor from './processor/base.js';\nimport { File, Helper, Loader, Time } from '../util/index.js';\nimport type { QueueJob, QueueJobData, QueueJobPayload } from './job.interface.js';\nimport type { ProcessorConstructor } from './processor/processor.interface.js';\nimport type { QueueItem } from './index.interface.js';\nimport type { ApplicationConfig } from '../application/base-application.interface.js';\nimport type EventManager from '../event/manager.js';\n\nexport interface JobSummary {\n id: string;\n name: string;\n queueName: string;\n state: 'active' | 'waiting' | 'completed' | 'failed' | 'delayed' | 'paused';\n attemptsMade: number;\n failedReason?: string;\n}\n\nexport default class QueueManager {\n private logger: typeof Logger = Logger;\n\n private applicationConfig: ApplicationConfig;\n\n private options: QueueManagerOptions;\n\n private redisInstance: RedisInstance;\n private databaseInstance: DatabaseInstance | null;\n private eventManager?: EventManager;\n\n private queues: Map<string, Queue> = new Map();\n\n private jobProcessors: Map<string, BaseProcessor> = new Map();\n\n constructor({\n applicationConfig,\n options,\n queues: _queues,\n redisInstance,\n databaseInstance,\n eventManager,\n }: QueueManagerConstructorParams) {\n // Merge options with defaults if provided\n if (options) {\n this.options = options;\n } else {\n // This shouldn't happen, but handle the edge case\n this.options = { processorsDirectory: '' };\n }\n\n this.applicationConfig = applicationConfig;\n\n this.redisInstance = redisInstance;\n this.databaseInstance = databaseInstance;\n this.eventManager = eventManager;\n }\n\n public async registerQueues({ queues }: { queues: QueueItem[] }): Promise<void> {\n if (!queues) {\n return;\n }\n\n // Check if processors directory exists\n const processorsDirectoryExists = await File.pathExists(this.options.processorsDirectory);\n\n if (!processorsDirectoryExists) {\n return;\n }\n\n try {\n const jobProcessorClasses = await Loader.loadModulesInDirectory<ProcessorConstructor>({\n directory: this.options.processorsDirectory,\n extensions: ['.ts', '.js'],\n });\n\n for (const queue of queues) {\n this.registerQueue({ queue, jobProcessorClasses });\n }\n\n if (this.applicationConfig.queue.log?.queuesRegistered) {\n this.log('Registered queue', {\n 'Queue Count': queues.length,\n 'Job Count': this.jobProcessors.size,\n });\n }\n } catch (error) {\n Logger.error({ error });\n }\n }\n\n private registerQueue({\n queue,\n jobProcessorClasses,\n }: {\n queue: QueueItem;\n jobProcessorClasses: Record<string, ProcessorConstructor>;\n }): void {\n if (!queue.jobs) {\n Logger.warn({\n message: 'No jobs found for queue, skip register',\n meta: {\n Name: queue.name,\n },\n });\n\n return;\n }\n\n // Merge framework defaults with queue-specific default job options\n const queueOptions: QueueOptions = {\n connection: this.redisInstance.client,\n defaultJobOptions: {\n removeOnComplete: true,\n removeOnFail: true,\n ...(queue.defaultJobOptions ?? {}),\n },\n };\n\n const queueInstance = new Queue(queue.name, queueOptions);\n\n queueInstance.on('error', this.onQueueError);\n queueInstance.on('waiting', this.onQueueWaiting);\n queueInstance.on('progress', this.onQueueProgress);\n queueInstance.on('removed', this.onQueueRemoved);\n\n if (!queue.isExternal) {\n // Build worker options, applying per-queue runtime settings\n const workerOptions: WorkerOptions = {\n connection: this.redisInstance.client,\n autorun: true,\n ...(queue.settings ?? {}),\n };\n\n new QueueWorker({\n applicationConfig: this.applicationConfig,\n queueManager: this,\n name: queue.name,\n processor: this.workerProcessor,\n options: workerOptions,\n redisInstance: this.redisInstance,\n });\n }\n\n this.queues.set(queue.name, queueInstance);\n\n if (this.applicationConfig.queue.log?.queueRegistered) {\n this.log('Registered queue', {\n Name: queue.name,\n Settings: queue.settings ? JSON.stringify(queue.settings) : 'default',\n });\n }\n\n // Register job processors\n this.registerJobProcessors({\n queue,\n jobs: queue.jobs,\n jobProcessorClasses,\n });\n }\n\n private registerJobProcessors({\n queue,\n jobs,\n jobProcessorClasses,\n }: {\n queue: QueueItem;\n jobs: QueueJob[];\n jobProcessorClasses: Record<string, ProcessorConstructor>;\n }): void {\n if (!jobs) {\n return;\n }\n\n const scriptFileExtension = Helper.getScriptFileExtension();\n\n for (const job of jobs) {\n if (!queue.isExternal) {\n const ProcessorClass = jobProcessorClasses[job.id];\n\n if (!ProcessorClass) {\n const jobPath = path.join(this.options.processorsDirectory, `${job.id}.${scriptFileExtension}`);\n\n throw new Error(`Processor class not found (Job ID: ${job.id} | Path: ${jobPath})`);\n }\n\n const processorInstance = new ProcessorClass(\n this,\n this.applicationConfig,\n this.redisInstance,\n this.databaseInstance,\n this.eventManager,\n );\n\n this.jobProcessors.set(job.id, processorInstance);\n }\n\n if (this.applicationConfig.queue.log?.jobRegistered) {\n this.log('Job registered', { ID: job.id });\n }\n }\n }\n\n private onQueueError = (error: Error): void => {\n Logger.error({ error });\n };\n\n private onQueueWaiting = (job: Job): void => {\n if (this.applicationConfig.queue.log?.queueWaiting) {\n this.log('Waiting...', { Queue: job.queueName, Job: job.id });\n }\n };\n\n private onQueueProgress = (jobId: string, progress: unknown): void => {\n this.log('Progress update', {\n 'Job ID': jobId,\n Progress: progress,\n });\n };\n\n private onQueueRemoved = (jobId: string): void => {\n this.log('Removed queue', { Job: jobId });\n };\n\n public addJobToQueue = async <\n TPayload extends QueueJobPayload = QueueJobPayload,\n TMetadata extends Record<string, unknown> = Record<string, unknown>,\n TResult = unknown,\n TName extends string = string,\n >({\n queueId,\n jobId,\n data,\n }: {\n queueId: string;\n jobId: TName;\n data: QueueJobData<TPayload, TMetadata>;\n }): Promise<Job<QueueJobData<TPayload, TMetadata>, TResult, TName> | undefined> => {\n const queue = this.queues.get(queueId);\n\n if (!queue) {\n this.log('Queue not found', { 'Queue ID': queueId });\n\n return;\n }\n\n const job = (await queue.add(jobId, data)) as Job<QueueJobData<TPayload, TMetadata>, TResult, TName>;\n\n const dataStr = JSON.stringify(data);\n\n const maxLogDataStrLength = 50;\n const truncatedLogDataStr =\n dataStr.length > maxLogDataStrLength ? `${dataStr.substring(0, maxLogDataStrLength)}...` : dataStr;\n\n if (this.applicationConfig.queue.log?.jobAdded) {\n this.log('Job added', {\n Queue: queueId,\n 'Job ID': jobId,\n Data: truncatedLogDataStr,\n });\n }\n\n return job;\n };\n\n private workerProcessor = async (job: Job): Promise<unknown> => {\n if (!job) {\n return;\n }\n\n const startTime = Time.now();\n\n // Add start time to job data\n if (typeof job.updateData === 'function') {\n try {\n await job.updateData({ ...job.data, startTime });\n } catch (error) {\n Logger.warn({\n message: 'Failed to persist job metadata before processing',\n meta: {\n Queue: job.queueName,\n 'Job Name': job.name,\n 'Job ID': job.id,\n Error: error instanceof Error ? error.message : String(error),\n },\n });\n }\n }\n\n this.log('Worker processing...', {\n Queue: job.queueName,\n 'Job Name': job.name,\n 'Job ID': job.id,\n });\n\n const processor = this.jobProcessors.get(job.name);\n\n if (!processor) {\n throw new Error(`No processor registered for job (Name: ${job.name})`);\n }\n\n let result: unknown;\n let error: Error | undefined;\n\n try {\n // Call beforeProcess hook\n await processor.beforeProcess({ job });\n\n // Execute main processing\n result = await processor.process({ job });\n\n return result;\n } catch (err) {\n error = err as Error;\n\n Logger.warn({\n message: 'Queue worker processing error',\n meta: {\n Queue: job.queueName,\n 'Job Name': job.name,\n 'Job ID': job.id,\n Error: error.message,\n },\n });\n\n Logger.error({ error });\n\n throw error; // Re-throw to mark job as failed\n } finally {\n // ALWAYS call afterProcess for cleanup (even on error)\n try {\n await processor.afterProcess({ job, result, error });\n } catch (cleanupError) {\n // Log but don't throw - cleanup errors shouldn't fail the job\n Logger.error({\n error: cleanupError,\n message: 'Error in processor afterProcess cleanup',\n });\n }\n }\n };\n\n public async listAllJobsWithStatus(): Promise<JobSummary[]> {\n const jobsSummary: JobSummary[] = [];\n\n for (const [queueName, queue] of this.queues) {\n const jobStates = ['active', 'waiting', 'completed', 'failed', 'delayed', 'paused'] as const;\n\n const jobsDetailsPromises = jobStates.map(async state => {\n const jobs = await queue.getJobs([state]);\n return jobs.map(\n (job): JobSummary => ({\n id: job.id ?? 'unknown',\n name: job.name ?? 'unknown',\n queueName,\n state,\n attemptsMade: job.attemptsMade,\n failedReason: job.failedReason,\n }),\n );\n });\n\n const results = await Promise.all(jobsDetailsPromises);\n const flattenedResults = results.flat();\n\n jobsSummary.push(...flattenedResults);\n }\n\n return jobsSummary;\n }\n\n /**\n * Log queue message\n */\n public log(message: string, meta?: Record<string, unknown>): void {\n this.logger.custom({ level: 'queue', message, meta });\n }\n}\n"],
|
|
5
|
-
"mappings": ";;AAAA,SAAmB,aAAoD;AACvE,OAAO,UAAU;AAIjB,SAAS,cAAc;AACvB,OAAO,iBAAiB;AAExB,SAAS,MAAM,QAAQ,QAAQ,YAAY;AAgB3C,MAAO,aAA2B;AAAA,EAxBlC,OAwBkC;AAAA;AAAA;AAAA,EACxB,SAAwB;AAAA,EAExB;AAAA,EAEA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,SAA6B,oBAAI,IAAI;AAAA,EAErC,gBAA4C,oBAAI,IAAI;AAAA,EAE5D,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAkC;AAEhC,QAAI,SAAS;AACX,WAAK,UAAU;AAAA,IACjB,OAAO;AAEL,WAAK,UAAU,EAAE,qBAAqB,GAAG;AAAA,IAC3C;AAEA,SAAK,oBAAoB;AAEzB,SAAK,gBAAgB;AACrB,SAAK,mBAAmB;AACxB,SAAK,eAAe;AAAA,EACtB;AAAA,EAEA,MAAa,eAAe,EAAE,OAAO,GAA2C;AAC9E,QAAI,CAAC,QAAQ;AACX;AAAA,IACF;AAGA,UAAM,4BAA4B,MAAM,KAAK,WAAW,KAAK,QAAQ,mBAAmB;AAExF,QAAI,CAAC,2BAA2B;AAC9B;AAAA,IACF;AAEA,QAAI;AACF,YAAM,sBAAsB,MAAM,OAAO,uBAA6C;AAAA,QACpF,WAAW,KAAK,QAAQ;AAAA,QACxB,YAAY,CAAC,OAAO,KAAK;AAAA,MAC3B,CAAC;AAED,iBAAW,SAAS,QAAQ;AAC1B,aAAK,cAAc,EAAE,OAAO,oBAAoB,CAAC;AAAA,MACnD;AAEA,UAAI,KAAK,kBAAkB,MAAM,KAAK,kBAAkB;AACtD,aAAK,IAAI,oBAAoB;AAAA,UAC3B,eAAe,OAAO;AAAA,UACtB,aAAa,KAAK,cAAc;AAAA,QAClC,CAAC;AAAA,MACH;AAAA,IACF,SAAS,OAAO;AACd,aAAO,MAAM,EAAE,MAAM,CAAC;AAAA,IACxB;AAAA,EACF;AAAA,EAEQ,cAAc;AAAA,IACpB;AAAA,IACA;AAAA,EACF,GAGS;AACP,QAAI,CAAC,MAAM,MAAM;AACf,aAAO,KAAK;AAAA,QACV,SAAS;AAAA,QACT,MAAM;AAAA,UACJ,MAAM,MAAM;AAAA,QACd;AAAA,MACF,CAAC;AAED;AAAA,IACF;AAGA,UAAM,eAA6B;AAAA,MACjC,YAAY,KAAK,cAAc;AAAA,MAC/B,mBAAmB;AAAA,QACjB,kBAAkB;AAAA,QAClB,cAAc;AAAA,QACd,GAAI,MAAM,qBAAqB,CAAC;AAAA,MAClC;AAAA,IACF;AAEA,UAAM,gBAAgB,IAAI,MAAM,MAAM,MAAM,YAAY;AAExD,kBAAc,GAAG,SAAS,KAAK,YAAY;AAC3C,kBAAc,GAAG,WAAW,KAAK,cAAc;AAC/C,kBAAc,GAAG,YAAY,KAAK,eAAe;AACjD,kBAAc,GAAG,WAAW,KAAK,cAAc;AAE/C,QAAI,CAAC,MAAM,YAAY;AAErB,YAAM,gBAA+B;AAAA,QACnC,YAAY,KAAK,cAAc;AAAA,QAC/B,SAAS;AAAA,QACT,GAAI,MAAM,YAAY,CAAC;AAAA,MACzB;AAEA,
|
|
4
|
+
"sourcesContent": ["import { type Job, Queue, type QueueOptions, type WorkerOptions } from 'bullmq';\nimport path from 'path';\nimport type { QueueManagerConstructorParams, QueueManagerOptions } from './manager.interface.js';\nimport type { RedisInstance } from '../redis/index.js';\nimport type { DatabaseInstance } from '../database/index.js';\nimport { Logger } from '../logger/index.js';\nimport QueueWorker from './worker.js';\nimport type BaseProcessor from './processor/base.js';\nimport { File, Helper, Loader, Time } from '../util/index.js';\nimport type { QueueJob, QueueJobData, QueueJobPayload } from './job.interface.js';\nimport type { ProcessorConstructor } from './processor/processor.interface.js';\nimport type { QueueItem } from './index.interface.js';\nimport type { ApplicationConfig } from '../application/base-application.interface.js';\nimport type EventManager from '../event/manager.js';\n\nexport interface JobSummary {\n id: string;\n name: string;\n queueName: string;\n state: 'active' | 'waiting' | 'completed' | 'failed' | 'delayed' | 'paused';\n attemptsMade: number;\n failedReason?: string;\n}\n\nexport default class QueueManager {\n private logger: typeof Logger = Logger;\n\n private applicationConfig: ApplicationConfig;\n\n private options: QueueManagerOptions;\n\n private redisInstance: RedisInstance;\n private databaseInstance: DatabaseInstance | null;\n private eventManager?: EventManager;\n\n private queues: Map<string, Queue> = new Map();\n\n private workers: Map<string, QueueWorker> = new Map();\n\n private jobProcessors: Map<string, BaseProcessor> = new Map();\n\n constructor({\n applicationConfig,\n options,\n queues: _queues,\n redisInstance,\n databaseInstance,\n eventManager,\n }: QueueManagerConstructorParams) {\n // Merge options with defaults if provided\n if (options) {\n this.options = options;\n } else {\n // This shouldn't happen, but handle the edge case\n this.options = { processorsDirectory: '' };\n }\n\n this.applicationConfig = applicationConfig;\n\n this.redisInstance = redisInstance;\n this.databaseInstance = databaseInstance;\n this.eventManager = eventManager;\n }\n\n public async registerQueues({ queues }: { queues: QueueItem[] }): Promise<void> {\n if (!queues) {\n return;\n }\n\n // Check if processors directory exists\n const processorsDirectoryExists = await File.pathExists(this.options.processorsDirectory);\n\n if (!processorsDirectoryExists) {\n return;\n }\n\n try {\n const jobProcessorClasses = await Loader.loadModulesInDirectory<ProcessorConstructor>({\n directory: this.options.processorsDirectory,\n extensions: ['.ts', '.js'],\n });\n\n for (const queue of queues) {\n this.registerQueue({ queue, jobProcessorClasses });\n }\n\n if (this.applicationConfig.queue.log?.queuesRegistered) {\n this.log('Registered queue', {\n 'Queue Count': queues.length,\n 'Job Count': this.jobProcessors.size,\n });\n }\n } catch (error) {\n Logger.error({ error });\n }\n }\n\n private registerQueue({\n queue,\n jobProcessorClasses,\n }: {\n queue: QueueItem;\n jobProcessorClasses: Record<string, ProcessorConstructor>;\n }): void {\n if (!queue.jobs) {\n Logger.warn({\n message: 'No jobs found for queue, skip register',\n meta: {\n Name: queue.name,\n },\n });\n\n return;\n }\n\n // Merge framework defaults with queue-specific default job options\n const queueOptions: QueueOptions = {\n connection: this.redisInstance.client,\n defaultJobOptions: {\n removeOnComplete: true,\n removeOnFail: true,\n ...(queue.defaultJobOptions ?? {}),\n },\n };\n\n const queueInstance = new Queue(queue.name, queueOptions);\n\n queueInstance.on('error', this.onQueueError);\n queueInstance.on('waiting', this.onQueueWaiting);\n queueInstance.on('progress', this.onQueueProgress);\n queueInstance.on('removed', this.onQueueRemoved);\n\n if (!queue.isExternal) {\n // Build worker options, applying per-queue runtime settings\n const workerOptions: WorkerOptions = {\n connection: this.redisInstance.client,\n autorun: true,\n ...(queue.settings ?? {}),\n };\n\n const worker = new QueueWorker({\n applicationConfig: this.applicationConfig,\n queueManager: this,\n name: queue.name,\n processor: this.workerProcessor,\n options: workerOptions,\n redisInstance: this.redisInstance,\n });\n\n this.workers.set(queue.name, worker);\n }\n\n this.queues.set(queue.name, queueInstance);\n\n if (this.applicationConfig.queue.log?.queueRegistered) {\n this.log('Registered queue', {\n Name: queue.name,\n Settings: queue.settings ? JSON.stringify(queue.settings) : 'default',\n });\n }\n\n // Register job processors\n this.registerJobProcessors({\n queue,\n jobs: queue.jobs,\n jobProcessorClasses,\n });\n }\n\n private registerJobProcessors({\n queue,\n jobs,\n jobProcessorClasses,\n }: {\n queue: QueueItem;\n jobs: QueueJob[];\n jobProcessorClasses: Record<string, ProcessorConstructor>;\n }): void {\n if (!jobs) {\n return;\n }\n\n const scriptFileExtension = Helper.getScriptFileExtension();\n\n for (const job of jobs) {\n if (!queue.isExternal) {\n const ProcessorClass = jobProcessorClasses[job.id];\n\n if (!ProcessorClass) {\n const jobPath = path.join(this.options.processorsDirectory, `${job.id}.${scriptFileExtension}`);\n\n throw new Error(`Processor class not found (Job ID: ${job.id} | Path: ${jobPath})`);\n }\n\n const processorInstance = new ProcessorClass(\n this,\n this.applicationConfig,\n this.redisInstance,\n this.databaseInstance,\n this.eventManager,\n );\n\n this.jobProcessors.set(job.id, processorInstance);\n }\n\n if (this.applicationConfig.queue.log?.jobRegistered) {\n this.log('Job registered', { ID: job.id });\n }\n }\n }\n\n private onQueueError = (error: Error): void => {\n Logger.error({ error });\n };\n\n private onQueueWaiting = (job: Job): void => {\n if (this.applicationConfig.queue.log?.queueWaiting) {\n this.log('Waiting...', { Queue: job.queueName, Job: job.id });\n }\n };\n\n private onQueueProgress = (jobId: string, progress: unknown): void => {\n this.log('Progress update', {\n 'Job ID': jobId,\n Progress: progress,\n });\n };\n\n private onQueueRemoved = (jobId: string): void => {\n this.log('Removed queue', { Job: jobId });\n };\n\n public addJobToQueue = async <\n TPayload extends QueueJobPayload = QueueJobPayload,\n TMetadata extends Record<string, unknown> = Record<string, unknown>,\n TResult = unknown,\n TName extends string = string,\n >({\n queueId,\n jobId,\n data,\n }: {\n queueId: string;\n jobId: TName;\n data: QueueJobData<TPayload, TMetadata>;\n }): Promise<Job<QueueJobData<TPayload, TMetadata>, TResult, TName> | undefined> => {\n const queue = this.queues.get(queueId);\n\n if (!queue) {\n this.log('Queue not found', { 'Queue ID': queueId });\n\n return;\n }\n\n const job = (await queue.add(jobId, data)) as Job<QueueJobData<TPayload, TMetadata>, TResult, TName>;\n\n if (this.applicationConfig.queue.log?.jobAdded) {\n const dataStr = JSON.stringify(data);\n const maxLogDataStrLength = 50;\n const truncatedLogDataStr =\n dataStr.length > maxLogDataStrLength ? `${dataStr.substring(0, maxLogDataStrLength)}...` : dataStr;\n\n this.log('Job added', {\n Queue: queueId,\n 'Job ID': jobId,\n Data: truncatedLogDataStr,\n });\n }\n\n return job;\n };\n\n private workerProcessor = async (job: Job): Promise<unknown> => {\n if (!job) {\n return;\n }\n\n const startTime = Time.now();\n\n // Add start time to job data\n if (typeof job.updateData === 'function') {\n try {\n await job.updateData({ ...job.data, startTime });\n } catch (error) {\n Logger.warn({\n message: 'Failed to persist job metadata before processing',\n meta: {\n Queue: job.queueName,\n 'Job Name': job.name,\n 'Job ID': job.id,\n Error: error instanceof Error ? error.message : String(error),\n },\n });\n }\n }\n\n this.log('Worker processing...', {\n Queue: job.queueName,\n 'Job Name': job.name,\n 'Job ID': job.id,\n });\n\n const processor = this.jobProcessors.get(job.name);\n\n if (!processor) {\n throw new Error(`No processor registered for job (Name: ${job.name})`);\n }\n\n let result: unknown;\n let error: Error | undefined;\n\n try {\n // Call beforeProcess hook\n await processor.beforeProcess({ job });\n\n // Execute main processing\n result = await processor.process({ job });\n\n return result;\n } catch (err) {\n error = err as Error;\n\n Logger.warn({\n message: 'Queue worker processing error',\n meta: {\n Queue: job.queueName,\n 'Job Name': job.name,\n 'Job ID': job.id,\n Error: error.message,\n },\n });\n\n Logger.error({ error });\n\n throw error; // Re-throw to mark job as failed\n } finally {\n // ALWAYS call afterProcess for cleanup (even on error)\n try {\n await processor.afterProcess({ job, result, error });\n } catch (cleanupError) {\n // Log but don't throw - cleanup errors shouldn't fail the job\n Logger.error({\n error: cleanupError,\n message: 'Error in processor afterProcess cleanup',\n });\n }\n }\n };\n\n public async listAllJobsWithStatus(): Promise<JobSummary[]> {\n const jobsSummary: JobSummary[] = [];\n\n for (const [queueName, queue] of this.queues) {\n const jobStates = ['active', 'waiting', 'completed', 'failed', 'delayed', 'paused'] as const;\n\n const jobsDetailsPromises = jobStates.map(async state => {\n const jobs = await queue.getJobs([state]);\n return jobs.map(\n (job): JobSummary => ({\n id: job.id ?? 'unknown',\n name: job.name ?? 'unknown',\n queueName,\n state,\n attemptsMade: job.attemptsMade,\n failedReason: job.failedReason,\n }),\n );\n });\n\n const results = await Promise.all(jobsDetailsPromises);\n const flattenedResults = results.flat();\n\n jobsSummary.push(...flattenedResults);\n }\n\n return jobsSummary;\n }\n\n /**\n * Disconnect all queues and workers, cleanup resources.\n * Should be called during application shutdown.\n */\n public async disconnect(): Promise<void> {\n // First, close all workers (they process jobs)\n for (const [name, worker] of this.workers) {\n try {\n await worker.cleanup();\n this.log('Worker closed', { Name: name });\n } catch (error) {\n Logger.error({\n error,\n message: `Failed to close worker: ${name}`,\n });\n }\n }\n\n // Then, close all queues (they manage job state)\n for (const [name, queue] of this.queues) {\n try {\n queue.removeAllListeners();\n await queue.close();\n this.log('Queue closed', { Name: name });\n } catch (error) {\n Logger.error({\n error,\n message: `Failed to close queue: ${name}`,\n });\n }\n }\n\n // Clear all maps\n this.workers.clear();\n this.queues.clear();\n this.jobProcessors.clear();\n\n this.log('Queue manager disconnected');\n }\n\n /**\n * Log queue message\n */\n public log(message: string, meta?: Record<string, unknown>): void {\n this.logger.custom({ level: 'queue', message, meta });\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["error"]
|
|
7
7
|
}
|
package/dist/queue/worker.d.ts
CHANGED
|
@@ -10,5 +10,10 @@ export default class QueueWorker extends Worker {
|
|
|
10
10
|
private onWorkerFailed;
|
|
11
11
|
private onWorkerStalled;
|
|
12
12
|
private onWorkerCompleted;
|
|
13
|
+
/**
|
|
14
|
+
* Cleanup worker resources before shutdown.
|
|
15
|
+
* Removes all event listeners and closes the worker connection.
|
|
16
|
+
*/
|
|
17
|
+
cleanup(): Promise<void>;
|
|
13
18
|
}
|
|
14
19
|
//# sourceMappingURL=worker.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/queue/worker.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC1D,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,uBAAuB,CAAC;AAQ1E,MAAM,CAAC,OAAO,OAAO,WAAY,SAAQ,MAAM;IAC7C,OAAO,CAAC,iBAAiB,CAAoB;IAE7C,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,aAAa,CAAgB;gBAEzB,EACV,iBAAiB,EACjB,YAAY,EACZ,IAAI,EACJ,SAAS,EACT,OAAO,EACP,aAAa,GACd,EAAE,4BAA4B;IAe/B,OAAO,CAAC,cAAc,CAMpB;IAEF,OAAO,CAAC,aAAa,CAEnB;IAEF,OAAO,CAAC,cAAc,CAcpB;IAEF,OAAO,CAAC,eAAe,CAErB;IAEF,OAAO,CAAC,iBAAiB,CAwBvB;
|
|
1
|
+
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/queue/worker.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC1D,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,uBAAuB,CAAC;AAQ1E,MAAM,CAAC,OAAO,OAAO,WAAY,SAAQ,MAAM;IAC7C,OAAO,CAAC,iBAAiB,CAAoB;IAE7C,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,aAAa,CAAgB;gBAEzB,EACV,iBAAiB,EACjB,YAAY,EACZ,IAAI,EACJ,SAAS,EACT,OAAO,EACP,aAAa,GACd,EAAE,4BAA4B;IAe/B,OAAO,CAAC,cAAc,CAMpB;IAEF,OAAO,CAAC,aAAa,CAEnB;IAEF,OAAO,CAAC,cAAc,CAcpB;IAEF,OAAO,CAAC,eAAe,CAErB;IAEF,OAAO,CAAC,iBAAiB,CAwBvB;IAEF;;;OAGG;IACU,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAItC"}
|
package/dist/queue/worker.js
CHANGED
|
@@ -65,6 +65,14 @@ class QueueWorker extends Worker {
|
|
|
65
65
|
});
|
|
66
66
|
}
|
|
67
67
|
}, "onWorkerCompleted");
|
|
68
|
+
/**
|
|
69
|
+
* Cleanup worker resources before shutdown.
|
|
70
|
+
* Removes all event listeners and closes the worker connection.
|
|
71
|
+
*/
|
|
72
|
+
async cleanup() {
|
|
73
|
+
this.removeAllListeners();
|
|
74
|
+
await this.close();
|
|
75
|
+
}
|
|
68
76
|
}
|
|
69
77
|
export {
|
|
70
78
|
QueueWorker as default
|
package/dist/queue/worker.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/queue/worker.ts"],
|
|
4
|
-
"sourcesContent": ["import { type Job, type Processor, Worker } from 'bullmq';\nimport type { QueueWorkerConstructorParams } from './worker.interface.js';\nimport type { RedisInstance } from '../redis/index.js';\nimport { Logger } from '../logger/index.js';\nimport { Time } from '../util/index.js';\nimport { WebSocketRedisSubscriberEvent } from '../websocket/websocket.interface.js';\nimport type { ApplicationConfig } from '../application/base-application.interface.js';\nimport type QueueManager from './manager.js';\n\nexport default class QueueWorker extends Worker {\n private applicationConfig: ApplicationConfig;\n\n private queueManager: QueueManager;\n private redisInstance: RedisInstance;\n\n constructor({\n applicationConfig,\n queueManager,\n name,\n processor,\n options,\n redisInstance,\n }: QueueWorkerConstructorParams) {\n super(name, processor, options);\n\n this.applicationConfig = applicationConfig;\n\n this.queueManager = queueManager;\n this.redisInstance = redisInstance;\n\n this.on('active', this.onWorkerActive);\n this.on('error', this.onWorkerError);\n this.on('failed', this.onWorkerFailed);\n this.on('stalled', this.onWorkerStalled);\n this.on('completed', this.onWorkerCompleted);\n }\n\n private onWorkerActive = (job: Job): void => {\n this.queueManager.log('Worker active', {\n Queue: job.queueName,\n 'Job Name': job.name,\n 'Job ID': job.id,\n });\n };\n\n private onWorkerError = (error: Error): void => {\n Logger.error({ error });\n };\n\n private onWorkerFailed = (job: Job<any, Processor<any, any, string>, string> | undefined, error: Error): void => {\n // // Send job failed message to client\n // if (job && job.data.webSocketClientId) {\n // const errorMessage = {\n // webSocketClientId: job.data.webSocketClientId,\n // action: job.name,\n // error: error.message,\n // };\n\n // // Send error message to client\n // this.redisInstance.publisherClient.publish('queueJobError', JSON.stringify(errorMessage));\n // }\n\n Logger.error({ error });\n };\n\n private onWorkerStalled = (jobId: string): void => {\n this.queueManager.log('Worker stalled', { Job: jobId });\n };\n\n private onWorkerCompleted = (job: Job): void => {\n const jobData = job.data;\n\n if (job.returnvalue?.webSocketClientId) {\n // Send job completed message to client\n this.redisInstance.publisherClient.publish(\n WebSocketRedisSubscriberEvent.QueueJobCompleted,\n JSON.stringify(job.returnvalue),\n );\n }\n\n const startTime = jobData.startTime;\n\n const executionTimeMs = Time.calculateElapsedTimeMs({ startTime });\n const formattedExecutionTime = executionTimeMs.toFixed(2);\n\n if (this.applicationConfig.queue.log?.jobCompleted) {\n this.queueManager.log('Job completed', {\n Queue: job.queueName,\n 'Job Name': job.name,\n 'Job ID': job.id,\n Time: `${formattedExecutionTime}ms`,\n });\n }\n };\n}\n"],
|
|
5
|
-
"mappings": ";;AAAA,SAAmC,cAAc;AAGjD,SAAS,cAAc;AACvB,SAAS,YAAY;AACrB,SAAS,qCAAqC;AAI9C,MAAO,oBAAkC,OAAO;AAAA,EAThD,OASgD;AAAA;AAAA;AAAA,EACtC;AAAA,EAEA;AAAA,EACA;AAAA,EAER,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAiC;AAC/B,UAAM,MAAM,WAAW,OAAO;AAE9B,SAAK,oBAAoB;AAEzB,SAAK,eAAe;AACpB,SAAK,gBAAgB;AAErB,SAAK,GAAG,UAAU,KAAK,cAAc;AACrC,SAAK,GAAG,SAAS,KAAK,aAAa;AACnC,SAAK,GAAG,UAAU,KAAK,cAAc;AACrC,SAAK,GAAG,WAAW,KAAK,eAAe;AACvC,SAAK,GAAG,aAAa,KAAK,iBAAiB;AAAA,EAC7C;AAAA,EAEQ,iBAAiB,wBAAC,QAAmB;AAC3C,SAAK,aAAa,IAAI,iBAAiB;AAAA,MACrC,OAAO,IAAI;AAAA,MACX,YAAY,IAAI;AAAA,MAChB,UAAU,IAAI;AAAA,IAChB,CAAC;AAAA,EACH,GANyB;AAAA,EAQjB,gBAAgB,wBAAC,UAAuB;AAC9C,WAAO,MAAM,EAAE,MAAM,CAAC;AAAA,EACxB,GAFwB;AAAA,EAIhB,iBAAiB,wBAAC,KAAgE,UAAuB;AAa/G,WAAO,MAAM,EAAE,MAAM,CAAC;AAAA,EACxB,GAdyB;AAAA,EAgBjB,kBAAkB,wBAAC,UAAwB;AACjD,SAAK,aAAa,IAAI,kBAAkB,EAAE,KAAK,MAAM,CAAC;AAAA,EACxD,GAF0B;AAAA,EAIlB,oBAAoB,wBAAC,QAAmB;AAC9C,UAAM,UAAU,IAAI;AAEpB,QAAI,IAAI,aAAa,mBAAmB;AAEtC,WAAK,cAAc,gBAAgB;AAAA,QACjC,8BAA8B;AAAA,QAC9B,KAAK,UAAU,IAAI,WAAW;AAAA,MAChC;AAAA,IACF;AAEA,UAAM,YAAY,QAAQ;AAE1B,UAAM,kBAAkB,KAAK,uBAAuB,EAAE,UAAU,CAAC;AACjE,UAAM,yBAAyB,gBAAgB,QAAQ,CAAC;AAExD,QAAI,KAAK,kBAAkB,MAAM,KAAK,cAAc;AAClD,WAAK,aAAa,IAAI,iBAAiB;AAAA,QACrC,OAAO,IAAI;AAAA,QACX,YAAY,IAAI;AAAA,QAChB,UAAU,IAAI;AAAA,QACd,MAAM,GAAG,sBAAsB;AAAA,MACjC,CAAC;AAAA,IACH;AAAA,EACF,GAxB4B;
|
|
4
|
+
"sourcesContent": ["import { type Job, type Processor, Worker } from 'bullmq';\nimport type { QueueWorkerConstructorParams } from './worker.interface.js';\nimport type { RedisInstance } from '../redis/index.js';\nimport { Logger } from '../logger/index.js';\nimport { Time } from '../util/index.js';\nimport { WebSocketRedisSubscriberEvent } from '../websocket/websocket.interface.js';\nimport type { ApplicationConfig } from '../application/base-application.interface.js';\nimport type QueueManager from './manager.js';\n\nexport default class QueueWorker extends Worker {\n private applicationConfig: ApplicationConfig;\n\n private queueManager: QueueManager;\n private redisInstance: RedisInstance;\n\n constructor({\n applicationConfig,\n queueManager,\n name,\n processor,\n options,\n redisInstance,\n }: QueueWorkerConstructorParams) {\n super(name, processor, options);\n\n this.applicationConfig = applicationConfig;\n\n this.queueManager = queueManager;\n this.redisInstance = redisInstance;\n\n this.on('active', this.onWorkerActive);\n this.on('error', this.onWorkerError);\n this.on('failed', this.onWorkerFailed);\n this.on('stalled', this.onWorkerStalled);\n this.on('completed', this.onWorkerCompleted);\n }\n\n private onWorkerActive = (job: Job): void => {\n this.queueManager.log('Worker active', {\n Queue: job.queueName,\n 'Job Name': job.name,\n 'Job ID': job.id,\n });\n };\n\n private onWorkerError = (error: Error): void => {\n Logger.error({ error });\n };\n\n private onWorkerFailed = (job: Job<any, Processor<any, any, string>, string> | undefined, error: Error): void => {\n // // Send job failed message to client\n // if (job && job.data.webSocketClientId) {\n // const errorMessage = {\n // webSocketClientId: job.data.webSocketClientId,\n // action: job.name,\n // error: error.message,\n // };\n\n // // Send error message to client\n // this.redisInstance.publisherClient.publish('queueJobError', JSON.stringify(errorMessage));\n // }\n\n Logger.error({ error });\n };\n\n private onWorkerStalled = (jobId: string): void => {\n this.queueManager.log('Worker stalled', { Job: jobId });\n };\n\n private onWorkerCompleted = (job: Job): void => {\n const jobData = job.data;\n\n if (job.returnvalue?.webSocketClientId) {\n // Send job completed message to client\n this.redisInstance.publisherClient.publish(\n WebSocketRedisSubscriberEvent.QueueJobCompleted,\n JSON.stringify(job.returnvalue),\n );\n }\n\n const startTime = jobData.startTime;\n\n const executionTimeMs = Time.calculateElapsedTimeMs({ startTime });\n const formattedExecutionTime = executionTimeMs.toFixed(2);\n\n if (this.applicationConfig.queue.log?.jobCompleted) {\n this.queueManager.log('Job completed', {\n Queue: job.queueName,\n 'Job Name': job.name,\n 'Job ID': job.id,\n Time: `${formattedExecutionTime}ms`,\n });\n }\n };\n\n /**\n * Cleanup worker resources before shutdown.\n * Removes all event listeners and closes the worker connection.\n */\n public async cleanup(): Promise<void> {\n this.removeAllListeners();\n await this.close();\n }\n}\n"],
|
|
5
|
+
"mappings": ";;AAAA,SAAmC,cAAc;AAGjD,SAAS,cAAc;AACvB,SAAS,YAAY;AACrB,SAAS,qCAAqC;AAI9C,MAAO,oBAAkC,OAAO;AAAA,EAThD,OASgD;AAAA;AAAA;AAAA,EACtC;AAAA,EAEA;AAAA,EACA;AAAA,EAER,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAiC;AAC/B,UAAM,MAAM,WAAW,OAAO;AAE9B,SAAK,oBAAoB;AAEzB,SAAK,eAAe;AACpB,SAAK,gBAAgB;AAErB,SAAK,GAAG,UAAU,KAAK,cAAc;AACrC,SAAK,GAAG,SAAS,KAAK,aAAa;AACnC,SAAK,GAAG,UAAU,KAAK,cAAc;AACrC,SAAK,GAAG,WAAW,KAAK,eAAe;AACvC,SAAK,GAAG,aAAa,KAAK,iBAAiB;AAAA,EAC7C;AAAA,EAEQ,iBAAiB,wBAAC,QAAmB;AAC3C,SAAK,aAAa,IAAI,iBAAiB;AAAA,MACrC,OAAO,IAAI;AAAA,MACX,YAAY,IAAI;AAAA,MAChB,UAAU,IAAI;AAAA,IAChB,CAAC;AAAA,EACH,GANyB;AAAA,EAQjB,gBAAgB,wBAAC,UAAuB;AAC9C,WAAO,MAAM,EAAE,MAAM,CAAC;AAAA,EACxB,GAFwB;AAAA,EAIhB,iBAAiB,wBAAC,KAAgE,UAAuB;AAa/G,WAAO,MAAM,EAAE,MAAM,CAAC;AAAA,EACxB,GAdyB;AAAA,EAgBjB,kBAAkB,wBAAC,UAAwB;AACjD,SAAK,aAAa,IAAI,kBAAkB,EAAE,KAAK,MAAM,CAAC;AAAA,EACxD,GAF0B;AAAA,EAIlB,oBAAoB,wBAAC,QAAmB;AAC9C,UAAM,UAAU,IAAI;AAEpB,QAAI,IAAI,aAAa,mBAAmB;AAEtC,WAAK,cAAc,gBAAgB;AAAA,QACjC,8BAA8B;AAAA,QAC9B,KAAK,UAAU,IAAI,WAAW;AAAA,MAChC;AAAA,IACF;AAEA,UAAM,YAAY,QAAQ;AAE1B,UAAM,kBAAkB,KAAK,uBAAuB,EAAE,UAAU,CAAC;AACjE,UAAM,yBAAyB,gBAAgB,QAAQ,CAAC;AAExD,QAAI,KAAK,kBAAkB,MAAM,KAAK,cAAc;AAClD,WAAK,aAAa,IAAI,iBAAiB;AAAA,QACrC,OAAO,IAAI;AAAA,QACX,YAAY,IAAI;AAAA,QAChB,UAAU,IAAI;AAAA,QACd,MAAM,GAAG,sBAAsB;AAAA,MACjC,CAAC;AAAA,IACH;AAAA,EACF,GAxB4B;AAAA;AAAA;AAAA;AAAA;AAAA,EA8B5B,MAAa,UAAyB;AACpC,SAAK,mBAAmB;AACxB,UAAM,KAAK,MAAM;AAAA,EACnB;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/redis/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/redis/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/redis/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,6BAA6B,EAAE,MAAM,cAAc,CAAC;AACtF,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/redis/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { default as default2 } from "./manager.js";
|
|
1
|
+
import { default as default2, clearGlobalInMemoryRedisState } from "./manager.js";
|
|
2
2
|
import { default as default3 } from "./instance.js";
|
|
3
3
|
export {
|
|
4
4
|
default3 as RedisInstance,
|
|
5
|
-
default2 as RedisManager
|
|
5
|
+
default2 as RedisManager,
|
|
6
|
+
clearGlobalInMemoryRedisState
|
|
6
7
|
};
|
|
7
8
|
//# sourceMappingURL=index.js.map
|
package/dist/redis/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/redis/index.ts"],
|
|
4
|
-
"sourcesContent": ["export { default as RedisManager } from './manager.js';\nexport { default as RedisInstance } from './instance.js';\n"],
|
|
5
|
-
"mappings": "AAAA,SAAoB,WAAXA,
|
|
4
|
+
"sourcesContent": ["export { default as RedisManager, clearGlobalInMemoryRedisState } from './manager.js';\nexport { default as RedisInstance } from './instance.js';\n"],
|
|
5
|
+
"mappings": "AAAA,SAAoB,WAAXA,UAAyB,qCAAqC;AACvE,SAAoB,WAAXA,gBAAgC;",
|
|
6
6
|
"names": ["default"]
|
|
7
7
|
}
|
package/dist/redis/instance.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/redis/instance.ts"],
|
|
4
|
-
"sourcesContent": ["import type { Redis } from 'ioredis';\nimport { Logger } from '../logger/index.js';\nimport type { RedisInstanceProps } from './instance.interface.js';\nimport type RedisManager from './manager.js';\n\nexport default class RedisInstance {\n private redisManager: RedisManager;\n\n public client: Redis;\n public publisherClient: Redis;\n public subscriberClient: Redis;\n\n constructor({ redisManager, client, publisherClient, subscriberClient }: RedisInstanceProps) {\n this.redisManager = redisManager;\n\n this.client = client;\n this.publisherClient = publisherClient;\n this.subscriberClient = subscriberClient;\n }\n\n public async disconnect(): Promise<void> {\n try {\n this.subscriberClient.disconnect();\n } catch (error) {\n Logger.error({ error, message: 'Could not disconnect Redis subscriber client' });\n }\n\n try {\n this.publisherClient.disconnect();\n } catch (error) {\n Logger.error({ error, message: 'Could not disconnect Redis publisherClient' });\n }\n\n try {\n this.client.disconnect();\n } catch (error) {\n Logger.error({ error, message: 'Could not disconnect Redis client' });\n }\n\n this.redisManager.log('Disconnected');\n }\n\n public isConnected(): Promise<boolean> {\n return new Promise((resolve, reject) => {\n if (this.client) {\n this.client.ping(error => {\n if (error) {\n reject(error);\n } else {\n resolve(true);\n }\n });\n } else {\n resolve(false);\n }\n });\n }\n\n /**\n * Sets a value in the cache with an optional expiration time.\n *\n * @param key - The key to set in the cache.\n * @param value - The value to set in the cache.\n * @param expiration - The expiration time in seconds (optional).\n * @throws Error if the value type is not supported.\n * @returns A Promise that resolves when the value is set in the cache.\n */\n public async setCache({\n key,\n value,\n expiration,\n }: {\n key: string;\n value: unknown;\n expiration?: number;\n }): Promise<void> {\n let formattedValue: string | number | Buffer;\n\n if (Buffer.isBuffer(value)) {\n formattedValue = value;\n } else if (value === null) {\n formattedValue = 'null';\n } else if (typeof value === 'object') {\n formattedValue = JSON.stringify(value);\n } else if (typeof value === 'number') {\n formattedValue = value;\n } else if (typeof value === 'string') {\n formattedValue = value;\n } else if (typeof value === 'boolean') {\n formattedValue = value ? 'true' : 'false';\n } else if (typeof value === 'bigint') {\n formattedValue = value.toString();\n } else {\n throw new Error('Unsupported value type');\n }\n\n if (expiration) {\n await this.client.set(key, formattedValue, 'EX', expiration);\n } else {\n await this.client.set(key, formattedValue);\n }\n }\n\n public async getCache({ key }: { key: string }): Promise<string | null> {\n const cacheValue = this.client.get(key);\n\n return cacheValue;\n }\n\n public async deleteCache({ key }: { key: string }): Promise<void> {\n await this.client.del(key);\n }\n}\n"],
|
|
5
|
-
"mappings": ";;AACA,SAAS,cAAc;AAIvB,MAAO,cAA4B;AAAA,EALnC,OAKmC;AAAA;AAAA;AAAA,EACzB;AAAA,EAED;AAAA,EACA;AAAA,EACA;AAAA,EAEP,YAAY,EAAE,cAAc,QAAQ,iBAAiB,iBAAiB,GAAuB;AAC3F,SAAK,eAAe;AAEpB,SAAK,SAAS;AACd,SAAK,kBAAkB;AACvB,SAAK,mBAAmB;AAAA,EAC1B;AAAA,EAEA,MAAa,aAA4B;AACvC,QAAI;AACF,WAAK,iBAAiB,WAAW;AAAA,IACnC,SAAS,OAAO;AACd,aAAO,MAAM,EAAE,OAAO,SAAS,+CAA+C,CAAC;AAAA,IACjF;AAEA,QAAI;AACF,WAAK,gBAAgB,WAAW;AAAA,IAClC,SAAS,OAAO;AACd,aAAO,MAAM,EAAE,OAAO,SAAS,6CAA6C,CAAC;AAAA,IAC/E;AAEA,QAAI;AACF,WAAK,OAAO,WAAW;AAAA,IACzB,SAAS,OAAO;AACd,aAAO,MAAM,EAAE,OAAO,SAAS,oCAAoC,CAAC;AAAA,IACtE;AAEA,SAAK,aAAa,IAAI,cAAc;AAAA,EACtC;AAAA,EAEO,cAAgC;AACrC,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAI,KAAK,QAAQ;AACf,aAAK,OAAO,KAAK,WAAS;AACxB,cAAI,OAAO;AACT,mBAAO,KAAK;AAAA,UACd,OAAO;AACL,oBAAQ,IAAI;AAAA,UACd;AAAA,QACF,CAAC;AAAA,MACH,OAAO;AACL,gBAAQ,KAAK;AAAA,MACf;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAa,SAAS;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAIkB;AAChB,QAAI;AAEJ,QAAI,OAAO,SAAS,KAAK,GAAG;AAC1B,uBAAiB;AAAA,IACnB,WAAW,UAAU,MAAM;AACzB,uBAAiB;AAAA,IACnB,WAAW,OAAO,UAAU,UAAU;AACpC,uBAAiB,KAAK,UAAU,KAAK;AAAA,IACvC,WAAW,OAAO,UAAU,UAAU;AACpC,uBAAiB;AAAA,IACnB,WAAW,OAAO,UAAU,UAAU;AACpC,uBAAiB;AAAA,IACnB,WAAW,OAAO,UAAU,WAAW;AACrC,uBAAiB,QAAQ,SAAS;AAAA,IACpC,WAAW,OAAO,UAAU,UAAU;AACpC,uBAAiB,MAAM,SAAS;AAAA,IAClC,OAAO;AACL,YAAM,IAAI,MAAM,wBAAwB;AAAA,IAC1C;AAEA,QAAI,YAAY;AACd,YAAM,KAAK,OAAO,IAAI,KAAK,gBAAgB,MAAM,UAAU;AAAA,IAC7D,OAAO;AACL,YAAM,KAAK,OAAO,IAAI,KAAK,cAAc;AAAA,IAC3C;AAAA,EACF;AAAA,EAEA,MAAa,SAAS,EAAE,IAAI,GAA4C;AACtE,UAAM,aAAa,KAAK,OAAO,IAAI,GAAG;
|
|
4
|
+
"sourcesContent": ["import type { Redis } from 'ioredis';\nimport { Logger } from '../logger/index.js';\nimport type { RedisInstanceProps } from './instance.interface.js';\nimport type RedisManager from './manager.js';\n\nexport default class RedisInstance {\n private redisManager: RedisManager;\n\n public client: Redis;\n public publisherClient: Redis;\n public subscriberClient: Redis;\n\n constructor({ redisManager, client, publisherClient, subscriberClient }: RedisInstanceProps) {\n this.redisManager = redisManager;\n\n this.client = client;\n this.publisherClient = publisherClient;\n this.subscriberClient = subscriberClient;\n }\n\n public async disconnect(): Promise<void> {\n try {\n this.subscriberClient.disconnect();\n } catch (error) {\n Logger.error({ error, message: 'Could not disconnect Redis subscriber client' });\n }\n\n try {\n this.publisherClient.disconnect();\n } catch (error) {\n Logger.error({ error, message: 'Could not disconnect Redis publisherClient' });\n }\n\n try {\n this.client.disconnect();\n } catch (error) {\n Logger.error({ error, message: 'Could not disconnect Redis client' });\n }\n\n this.redisManager.log('Disconnected');\n }\n\n public isConnected(): Promise<boolean> {\n return new Promise((resolve, reject) => {\n if (this.client) {\n this.client.ping(error => {\n if (error) {\n reject(error);\n } else {\n resolve(true);\n }\n });\n } else {\n resolve(false);\n }\n });\n }\n\n /**\n * Sets a value in the cache with an optional expiration time.\n *\n * @param key - The key to set in the cache.\n * @param value - The value to set in the cache.\n * @param expiration - The expiration time in seconds (optional).\n * @throws Error if the value type is not supported.\n * @returns A Promise that resolves when the value is set in the cache.\n */\n public async setCache({\n key,\n value,\n expiration,\n }: {\n key: string;\n value: unknown;\n expiration?: number;\n }): Promise<void> {\n let formattedValue: string | number | Buffer;\n\n if (Buffer.isBuffer(value)) {\n formattedValue = value;\n } else if (value === null) {\n formattedValue = 'null';\n } else if (typeof value === 'object') {\n formattedValue = JSON.stringify(value);\n } else if (typeof value === 'number') {\n formattedValue = value;\n } else if (typeof value === 'string') {\n formattedValue = value;\n } else if (typeof value === 'boolean') {\n formattedValue = value ? 'true' : 'false';\n } else if (typeof value === 'bigint') {\n formattedValue = value.toString();\n } else {\n throw new Error('Unsupported value type');\n }\n\n if (expiration) {\n await this.client.set(key, formattedValue, 'EX', expiration);\n } else {\n await this.client.set(key, formattedValue);\n }\n }\n\n public async getCache({ key }: { key: string }): Promise<string | null> {\n const cacheValue = await this.client.get(key);\n\n return cacheValue;\n }\n\n public async deleteCache({ key }: { key: string }): Promise<void> {\n await this.client.del(key);\n }\n}\n"],
|
|
5
|
+
"mappings": ";;AACA,SAAS,cAAc;AAIvB,MAAO,cAA4B;AAAA,EALnC,OAKmC;AAAA;AAAA;AAAA,EACzB;AAAA,EAED;AAAA,EACA;AAAA,EACA;AAAA,EAEP,YAAY,EAAE,cAAc,QAAQ,iBAAiB,iBAAiB,GAAuB;AAC3F,SAAK,eAAe;AAEpB,SAAK,SAAS;AACd,SAAK,kBAAkB;AACvB,SAAK,mBAAmB;AAAA,EAC1B;AAAA,EAEA,MAAa,aAA4B;AACvC,QAAI;AACF,WAAK,iBAAiB,WAAW;AAAA,IACnC,SAAS,OAAO;AACd,aAAO,MAAM,EAAE,OAAO,SAAS,+CAA+C,CAAC;AAAA,IACjF;AAEA,QAAI;AACF,WAAK,gBAAgB,WAAW;AAAA,IAClC,SAAS,OAAO;AACd,aAAO,MAAM,EAAE,OAAO,SAAS,6CAA6C,CAAC;AAAA,IAC/E;AAEA,QAAI;AACF,WAAK,OAAO,WAAW;AAAA,IACzB,SAAS,OAAO;AACd,aAAO,MAAM,EAAE,OAAO,SAAS,oCAAoC,CAAC;AAAA,IACtE;AAEA,SAAK,aAAa,IAAI,cAAc;AAAA,EACtC;AAAA,EAEO,cAAgC;AACrC,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAI,KAAK,QAAQ;AACf,aAAK,OAAO,KAAK,WAAS;AACxB,cAAI,OAAO;AACT,mBAAO,KAAK;AAAA,UACd,OAAO;AACL,oBAAQ,IAAI;AAAA,UACd;AAAA,QACF,CAAC;AAAA,MACH,OAAO;AACL,gBAAQ,KAAK;AAAA,MACf;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAa,SAAS;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAIkB;AAChB,QAAI;AAEJ,QAAI,OAAO,SAAS,KAAK,GAAG;AAC1B,uBAAiB;AAAA,IACnB,WAAW,UAAU,MAAM;AACzB,uBAAiB;AAAA,IACnB,WAAW,OAAO,UAAU,UAAU;AACpC,uBAAiB,KAAK,UAAU,KAAK;AAAA,IACvC,WAAW,OAAO,UAAU,UAAU;AACpC,uBAAiB;AAAA,IACnB,WAAW,OAAO,UAAU,UAAU;AACpC,uBAAiB;AAAA,IACnB,WAAW,OAAO,UAAU,WAAW;AACrC,uBAAiB,QAAQ,SAAS;AAAA,IACpC,WAAW,OAAO,UAAU,UAAU;AACpC,uBAAiB,MAAM,SAAS;AAAA,IAClC,OAAO;AACL,YAAM,IAAI,MAAM,wBAAwB;AAAA,IAC1C;AAEA,QAAI,YAAY;AACd,YAAM,KAAK,OAAO,IAAI,KAAK,gBAAgB,MAAM,UAAU;AAAA,IAC7D,OAAO;AACL,YAAM,KAAK,OAAO,IAAI,KAAK,cAAc;AAAA,IAC3C;AAAA,EACF;AAAA,EAEA,MAAa,SAAS,EAAE,IAAI,GAA4C;AACtE,UAAM,aAAa,MAAM,KAAK,OAAO,IAAI,GAAG;AAE5C,WAAO;AAAA,EACT;AAAA,EAEA,MAAa,YAAY,EAAE,IAAI,GAAmC;AAChE,UAAM,KAAK,OAAO,IAAI,GAAG;AAAA,EAC3B;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/redis/manager.d.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { RedisManagerConfig as RedisManagerOptions } from './manager.interface.js';
|
|
2
2
|
import RedisInstance from './instance.js';
|
|
3
|
+
/**
|
|
4
|
+
* Clears the global in-memory Redis state including all timers.
|
|
5
|
+
* Useful for test cleanup to prevent timer leaks between tests.
|
|
6
|
+
*/
|
|
7
|
+
export declare function clearGlobalInMemoryRedisState(): void;
|
|
3
8
|
export default class RedisManager {
|
|
4
9
|
private logger;
|
|
5
10
|
private options;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/redis/manager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,IAAI,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AACxF,OAAO,aAAa,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/redis/manager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,IAAI,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AACxF,OAAO,aAAa,MAAM,eAAe,CAAC;AAiC1C;;;GAGG;AACH,wBAAgB,6BAA6B,IAAI,IAAI,CAWpD;AAyHD,MAAM,CAAC,OAAO,OAAO,YAAY;IAC/B,OAAO,CAAC,MAAM,CAAyB;IAEvC,OAAO,CAAC,OAAO,CAAsB;IAE9B,SAAS,EAAE,aAAa,EAAE,CAAM;gBAE3B,MAAM,EAAE,mBAAmB;IAI1B,OAAO,IAAI,OAAO,CAAC,aAAa,CAAC;IA8GjC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAiDxC;;OAEG;IACI,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAGlE"}
|
package/dist/redis/manager.js
CHANGED
|
@@ -20,6 +20,18 @@ function getGlobalInMemoryRedisState() {
|
|
|
20
20
|
return globalInMemoryRedisState;
|
|
21
21
|
}
|
|
22
22
|
__name(getGlobalInMemoryRedisState, "getGlobalInMemoryRedisState");
|
|
23
|
+
function clearGlobalInMemoryRedisState() {
|
|
24
|
+
if (globalInMemoryRedisState) {
|
|
25
|
+
for (const timer of globalInMemoryRedisState.expirations.values()) {
|
|
26
|
+
clearTimeout(timer);
|
|
27
|
+
}
|
|
28
|
+
globalInMemoryRedisState.expirations.clear();
|
|
29
|
+
globalInMemoryRedisState.store.clear();
|
|
30
|
+
globalInMemoryRedisState.subscriptions.clear();
|
|
31
|
+
}
|
|
32
|
+
globalInMemoryRedisState = null;
|
|
33
|
+
}
|
|
34
|
+
__name(clearGlobalInMemoryRedisState, "clearGlobalInMemoryRedisState");
|
|
23
35
|
class InMemoryRedisClient extends EventEmitter {
|
|
24
36
|
static {
|
|
25
37
|
__name(this, "InMemoryRedisClient");
|
|
@@ -265,6 +277,7 @@ class RedisManager {
|
|
|
265
277
|
}
|
|
266
278
|
}
|
|
267
279
|
export {
|
|
280
|
+
clearGlobalInMemoryRedisState,
|
|
268
281
|
RedisManager as default
|
|
269
282
|
};
|
|
270
283
|
//# sourceMappingURL=manager.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/redis/manager.ts"],
|
|
4
|
-
"sourcesContent": ["import { Redis, type RedisOptions } from 'ioredis';\nimport { EventEmitter } from 'node:events';\nimport type { RedisManagerConfig as RedisManagerOptions } from './manager.interface.js';\nimport RedisInstance from './instance.js';\nimport { Logger } from '../logger/index.js';\nimport { CachePerformanceWrapper } from '../performance/index.js';\nimport { safeSerializeError } from '../error/error-reporter.js';\n\nconst truthyPattern = /^(1|true|yes|on)$/i;\nconst scheduleMicrotask =\n typeof (globalThis as any).queueMicrotask === 'function'\n ? (globalThis as any).queueMicrotask.bind(globalThis)\n : (callback: () => void) => {\n void Promise.resolve().then(callback);\n };\n\ntype RedisCallback = (error: Error | null, result?: string) => void;\n\ninterface InMemoryRedisSharedState {\n store: Map<string, string | Buffer>;\n expirations: Map<string, NodeJS.Timeout>;\n subscriptions: Map<string, Set<InMemoryRedisClient>>;\n}\n\n// Global singleton shared state for in-memory Redis\nlet globalInMemoryRedisState: InMemoryRedisSharedState | null = null;\n\nfunction getGlobalInMemoryRedisState(): InMemoryRedisSharedState {\n globalInMemoryRedisState ??= {\n store: new Map<string, string | Buffer>(),\n expirations: new Map<string, NodeJS.Timeout>(),\n subscriptions: new Map<string, Set<InMemoryRedisClient>>(),\n };\n return globalInMemoryRedisState;\n}\n\nclass InMemoryRedisClient extends EventEmitter {\n private shared: InMemoryRedisSharedState;\n\n constructor(shared: InMemoryRedisSharedState) {\n super();\n this.shared = shared;\n\n scheduleMicrotask(() => {\n this.emit('ready');\n });\n }\n\n private cleanupSubscriptions(): void {\n for (const subscribers of this.shared.subscriptions.values()) {\n subscribers.delete(this);\n }\n }\n\n private clearExpirationForKey(key: string): void {\n const timer = this.shared.expirations.get(key);\n if (timer) {\n clearTimeout(timer);\n this.shared.expirations.delete(key);\n }\n }\n\n public ping(callback?: RedisCallback): Promise<string> {\n if (callback) {\n callback(null, 'PONG');\n return Promise.resolve('PONG');\n }\n\n return Promise.resolve('PONG');\n }\n\n public async set(...args: any[]): Promise<'OK'> {\n const [key, value, mode, expiration] = args;\n const serializedValue: string | Buffer = value instanceof Buffer ? value : String(value);\n\n this.shared.store.set(key, serializedValue);\n this.clearExpirationForKey(key);\n\n if (typeof mode === 'string' && mode.toUpperCase() === 'EX' && typeof expiration === 'number') {\n const timer = setTimeout(() => {\n this.shared.store.delete(key);\n this.shared.expirations.delete(key);\n }, expiration * 1000);\n\n if (typeof timer.unref === 'function') {\n timer.unref();\n }\n\n this.shared.expirations.set(key, timer);\n }\n\n return 'OK';\n }\n\n public async get(key: string): Promise<string | null> {\n return (this.shared.store.get(key) as string | undefined) ?? null;\n }\n\n public async del(key: string): Promise<number> {\n const existed = this.shared.store.delete(key);\n this.clearExpirationForKey(key);\n return existed ? 1 : 0;\n }\n\n public async publish(channel: string, message: string): Promise<number> {\n const subscribers = this.shared.subscriptions.get(channel);\n\n if (!subscribers || subscribers.size === 0) {\n return 0;\n }\n\n for (const subscriber of subscribers) {\n scheduleMicrotask(() => {\n subscriber.emit('message', channel, message);\n });\n }\n\n return subscribers.size;\n }\n\n public async subscribe(channel: string): Promise<number> {\n let subscribers = this.shared.subscriptions.get(channel);\n if (!subscribers) {\n subscribers = new Set<InMemoryRedisClient>();\n this.shared.subscriptions.set(channel, subscribers);\n }\n subscribers.add(this);\n return subscribers.size;\n }\n\n public async unsubscribe(channel: string): Promise<number> {\n const subscribers = this.shared.subscriptions.get(channel);\n\n if (!subscribers) {\n return 0;\n }\n\n subscribers.delete(this);\n return subscribers.size;\n }\n\n public async quit(): Promise<'OK'> {\n this.cleanupSubscriptions();\n this.emit('end');\n this.removeAllListeners();\n return 'OK';\n }\n\n public disconnect(): void {\n this.cleanupSubscriptions();\n this.emit('end');\n this.removeAllListeners();\n }\n}\n\nexport default class RedisManager {\n private logger: typeof Logger = Logger;\n\n private options: RedisManagerOptions;\n\n public instances: RedisInstance[] = [];\n\n constructor(config: RedisManagerOptions) {\n this.options = config;\n }\n\n public async connect(): Promise<RedisInstance> {\n return CachePerformanceWrapper.monitorConnection(\n 'connect',\n async () => {\n const startTime = performance.now();\n\n const redisOptions: RedisOptions = {\n host: this.options.host,\n port: this.options.port,\n password: this.options.password,\n maxRetriesPerRequest: null, // Needed for bullmq\n lazyConnect: true, // Prevent automatic connection to avoid unhandled errors\n };\n\n const useInMemoryRedis =\n truthyPattern.test(process.env.PXL_REDIS_IN_MEMORY ?? '') ||\n truthyPattern.test(process.env.REDIS_IN_MEMORY ?? '');\n\n const createClient = (): Redis => {\n if (useInMemoryRedis) {\n return new InMemoryRedisClient(getGlobalInMemoryRedisState()) as unknown as Redis;\n }\n\n const client = new Redis(redisOptions);\n // Attach a temporary error handler to prevent unhandled errors during connection\n const errorHandler = (error: Error) => {\n // Error will be handled by the promise rejection below\n };\n client.once('error', errorHandler);\n return client;\n };\n\n const client = createClient();\n const publisherClient = createClient();\n const subscriberClient = createClient();\n\n try {\n // For non-in-memory clients, explicitly connect since we use lazyConnect\n if (!useInMemoryRedis) {\n await Promise.all([client.connect(), publisherClient.connect(), subscriberClient.connect()]);\n } else {\n // Wait for in-memory clients to be ready\n await Promise.all([\n new Promise<void>((resolve, reject) => {\n client.once('ready', () => resolve());\n client.once('error', (error: Error) => reject(error));\n }),\n new Promise<void>((resolve, reject) => {\n publisherClient.once('ready', () => resolve());\n publisherClient.once('error', (error: Error) => reject(error));\n }),\n new Promise<void>((resolve, reject) => {\n subscriberClient.once('ready', () => resolve());\n subscriberClient.once('error', (error: Error) => reject(error));\n }),\n ]);\n }\n\n const redisInstance = new RedisInstance({\n redisManager: this,\n client,\n publisherClient,\n subscriberClient,\n });\n\n this.instances.push(redisInstance);\n\n const duration = performance.now() - startTime;\n const meta = {\n Host: this.options.host,\n Port: this.options.port,\n Duration: `${duration.toFixed(2)}ms`,\n Mode: useInMemoryRedis ? 'in-memory' : 'network',\n };\n\n if (this.options.applicationConfig.log?.startUp) {\n this.log('Connected', meta);\n } else {\n this.logger.debug({ message: 'Redis connected', meta });\n }\n\n if (useInMemoryRedis) {\n this.logger.debug({ message: 'Using in-memory Redis stub' });\n }\n\n return redisInstance;\n } catch (error) {\n const duration = performance.now() - startTime;\n\n // Clean up clients on error\n await Promise.allSettled([client.quit(), publisherClient.quit(), subscriberClient.quit()]);\n\n this.logger.error({\n error: error instanceof Error ? error : new Error(safeSerializeError(error)),\n message: 'Redis connection failed',\n meta: {\n Host: this.options.host,\n Port: this.options.port,\n Duration: `${duration.toFixed(2)}ms`,\n Mode: useInMemoryRedis ? 'in-memory' : 'network',\n },\n });\n\n throw error;\n }\n },\n { host: this.options.host, port: this.options.port },\n );\n }\n\n public async disconnect(): Promise<void> {\n await CachePerformanceWrapper.monitorConnection(\n 'disconnect',\n async () => {\n const startTime = performance.now();\n const instanceCount = this.instances.length;\n\n try {\n await Promise.all(this.instances.map(instance => instance.disconnect()));\n\n const duration = performance.now() - startTime;\n\n if (instanceCount > 0) {\n const meta = {\n Instances: instanceCount,\n Host: this.options.host,\n Port: this.options.port,\n Duration: `${duration.toFixed(2)}ms`,\n };\n\n if (this.options.applicationConfig.log?.startUp) {\n this.log('Disconnected all Redis instances', meta);\n } else {\n this.logger.debug({ message: 'Redis instances disconnected', meta });\n }\n }\n\n this.instances = [];\n } catch (error) {\n const duration = performance.now() - startTime;\n\n this.logger.error({\n error: error instanceof Error ? error : new Error(safeSerializeError(error)),\n message: 'Redis disconnection failed',\n meta: {\n Host: this.options.host,\n Port: this.options.port,\n Instances: instanceCount,\n Duration: `${duration.toFixed(2)}ms`,\n },\n });\n\n throw error;\n }\n },\n { host: this.options.host, port: this.options.port },\n );\n }\n\n /**\n * Log Redis message\n */\n public log(message: string, meta?: Record<string, unknown>): void {\n this.logger.custom({ level: 'redis', message, meta });\n }\n}\n"],
|
|
5
|
-
"mappings": ";;AAAA,SAAS,aAAgC;AACzC,SAAS,oBAAoB;AAE7B,OAAO,mBAAmB;AAC1B,SAAS,cAAc;AACvB,SAAS,+BAA+B;AACxC,SAAS,0BAA0B;AAEnC,MAAM,gBAAgB;AACtB,MAAM,oBACJ,OAAQ,WAAmB,mBAAmB,aACzC,WAAmB,eAAe,KAAK,UAAU,IAClD,CAAC,aAAyB;AACxB,OAAK,QAAQ,QAAQ,EAAE,KAAK,QAAQ;AACtC;AAWN,IAAI,2BAA4D;AAEhE,SAAS,8BAAwD;AAC/D,+BAA6B;AAAA,IAC3B,OAAO,oBAAI,IAA6B;AAAA,IACxC,aAAa,oBAAI,IAA4B;AAAA,IAC7C,eAAe,oBAAI,IAAsC;AAAA,EAC3D;AACA,SAAO;AACT;AAPS;
|
|
4
|
+
"sourcesContent": ["import { Redis, type RedisOptions } from 'ioredis';\nimport { EventEmitter } from 'node:events';\nimport type { RedisManagerConfig as RedisManagerOptions } from './manager.interface.js';\nimport RedisInstance from './instance.js';\nimport { Logger } from '../logger/index.js';\nimport { CachePerformanceWrapper } from '../performance/index.js';\nimport { safeSerializeError } from '../error/error-reporter.js';\n\nconst truthyPattern = /^(1|true|yes|on)$/i;\nconst scheduleMicrotask =\n typeof (globalThis as any).queueMicrotask === 'function'\n ? (globalThis as any).queueMicrotask.bind(globalThis)\n : (callback: () => void) => {\n void Promise.resolve().then(callback);\n };\n\ntype RedisCallback = (error: Error | null, result?: string) => void;\n\ninterface InMemoryRedisSharedState {\n store: Map<string, string | Buffer>;\n expirations: Map<string, NodeJS.Timeout>;\n subscriptions: Map<string, Set<InMemoryRedisClient>>;\n}\n\n// Global singleton shared state for in-memory Redis\nlet globalInMemoryRedisState: InMemoryRedisSharedState | null = null;\n\nfunction getGlobalInMemoryRedisState(): InMemoryRedisSharedState {\n globalInMemoryRedisState ??= {\n store: new Map<string, string | Buffer>(),\n expirations: new Map<string, NodeJS.Timeout>(),\n subscriptions: new Map<string, Set<InMemoryRedisClient>>(),\n };\n return globalInMemoryRedisState;\n}\n\n/**\n * Clears the global in-memory Redis state including all timers.\n * Useful for test cleanup to prevent timer leaks between tests.\n */\nexport function clearGlobalInMemoryRedisState(): void {\n if (globalInMemoryRedisState) {\n // Clear all expiration timers to prevent memory leaks\n for (const timer of globalInMemoryRedisState.expirations.values()) {\n clearTimeout(timer);\n }\n globalInMemoryRedisState.expirations.clear();\n globalInMemoryRedisState.store.clear();\n globalInMemoryRedisState.subscriptions.clear();\n }\n globalInMemoryRedisState = null;\n}\n\nclass InMemoryRedisClient extends EventEmitter {\n private shared: InMemoryRedisSharedState;\n\n constructor(shared: InMemoryRedisSharedState) {\n super();\n this.shared = shared;\n\n scheduleMicrotask(() => {\n this.emit('ready');\n });\n }\n\n private cleanupSubscriptions(): void {\n for (const subscribers of this.shared.subscriptions.values()) {\n subscribers.delete(this);\n }\n }\n\n private clearExpirationForKey(key: string): void {\n const timer = this.shared.expirations.get(key);\n if (timer) {\n clearTimeout(timer);\n this.shared.expirations.delete(key);\n }\n }\n\n public ping(callback?: RedisCallback): Promise<string> {\n if (callback) {\n callback(null, 'PONG');\n return Promise.resolve('PONG');\n }\n\n return Promise.resolve('PONG');\n }\n\n public async set(...args: any[]): Promise<'OK'> {\n const [key, value, mode, expiration] = args;\n const serializedValue: string | Buffer = value instanceof Buffer ? value : String(value);\n\n this.shared.store.set(key, serializedValue);\n this.clearExpirationForKey(key);\n\n if (typeof mode === 'string' && mode.toUpperCase() === 'EX' && typeof expiration === 'number') {\n const timer = setTimeout(() => {\n this.shared.store.delete(key);\n this.shared.expirations.delete(key);\n }, expiration * 1000);\n\n if (typeof timer.unref === 'function') {\n timer.unref();\n }\n\n this.shared.expirations.set(key, timer);\n }\n\n return 'OK';\n }\n\n public async get(key: string): Promise<string | null> {\n return (this.shared.store.get(key) as string | undefined) ?? null;\n }\n\n public async del(key: string): Promise<number> {\n const existed = this.shared.store.delete(key);\n this.clearExpirationForKey(key);\n return existed ? 1 : 0;\n }\n\n public async publish(channel: string, message: string): Promise<number> {\n const subscribers = this.shared.subscriptions.get(channel);\n\n if (!subscribers || subscribers.size === 0) {\n return 0;\n }\n\n for (const subscriber of subscribers) {\n scheduleMicrotask(() => {\n subscriber.emit('message', channel, message);\n });\n }\n\n return subscribers.size;\n }\n\n public async subscribe(channel: string): Promise<number> {\n let subscribers = this.shared.subscriptions.get(channel);\n if (!subscribers) {\n subscribers = new Set<InMemoryRedisClient>();\n this.shared.subscriptions.set(channel, subscribers);\n }\n subscribers.add(this);\n return subscribers.size;\n }\n\n public async unsubscribe(channel: string): Promise<number> {\n const subscribers = this.shared.subscriptions.get(channel);\n\n if (!subscribers) {\n return 0;\n }\n\n subscribers.delete(this);\n return subscribers.size;\n }\n\n public async quit(): Promise<'OK'> {\n this.cleanupSubscriptions();\n this.emit('end');\n this.removeAllListeners();\n return 'OK';\n }\n\n public disconnect(): void {\n this.cleanupSubscriptions();\n this.emit('end');\n this.removeAllListeners();\n }\n}\n\nexport default class RedisManager {\n private logger: typeof Logger = Logger;\n\n private options: RedisManagerOptions;\n\n public instances: RedisInstance[] = [];\n\n constructor(config: RedisManagerOptions) {\n this.options = config;\n }\n\n public async connect(): Promise<RedisInstance> {\n return CachePerformanceWrapper.monitorConnection(\n 'connect',\n async () => {\n const startTime = performance.now();\n\n const redisOptions: RedisOptions = {\n host: this.options.host,\n port: this.options.port,\n password: this.options.password,\n maxRetriesPerRequest: null, // Needed for bullmq\n lazyConnect: true, // Prevent automatic connection to avoid unhandled errors\n };\n\n const useInMemoryRedis =\n truthyPattern.test(process.env.PXL_REDIS_IN_MEMORY ?? '') ||\n truthyPattern.test(process.env.REDIS_IN_MEMORY ?? '');\n\n const createClient = (): Redis => {\n if (useInMemoryRedis) {\n return new InMemoryRedisClient(getGlobalInMemoryRedisState()) as unknown as Redis;\n }\n\n const client = new Redis(redisOptions);\n // Attach a temporary error handler to prevent unhandled errors during connection\n const errorHandler = (error: Error) => {\n // Error will be handled by the promise rejection below\n };\n client.once('error', errorHandler);\n return client;\n };\n\n const client = createClient();\n const publisherClient = createClient();\n const subscriberClient = createClient();\n\n try {\n // For non-in-memory clients, explicitly connect since we use lazyConnect\n if (!useInMemoryRedis) {\n await Promise.all([client.connect(), publisherClient.connect(), subscriberClient.connect()]);\n } else {\n // Wait for in-memory clients to be ready\n await Promise.all([\n new Promise<void>((resolve, reject) => {\n client.once('ready', () => resolve());\n client.once('error', (error: Error) => reject(error));\n }),\n new Promise<void>((resolve, reject) => {\n publisherClient.once('ready', () => resolve());\n publisherClient.once('error', (error: Error) => reject(error));\n }),\n new Promise<void>((resolve, reject) => {\n subscriberClient.once('ready', () => resolve());\n subscriberClient.once('error', (error: Error) => reject(error));\n }),\n ]);\n }\n\n const redisInstance = new RedisInstance({\n redisManager: this,\n client,\n publisherClient,\n subscriberClient,\n });\n\n this.instances.push(redisInstance);\n\n const duration = performance.now() - startTime;\n const meta = {\n Host: this.options.host,\n Port: this.options.port,\n Duration: `${duration.toFixed(2)}ms`,\n Mode: useInMemoryRedis ? 'in-memory' : 'network',\n };\n\n if (this.options.applicationConfig.log?.startUp) {\n this.log('Connected', meta);\n } else {\n this.logger.debug({ message: 'Redis connected', meta });\n }\n\n if (useInMemoryRedis) {\n this.logger.debug({ message: 'Using in-memory Redis stub' });\n }\n\n return redisInstance;\n } catch (error) {\n const duration = performance.now() - startTime;\n\n // Clean up clients on error\n await Promise.allSettled([client.quit(), publisherClient.quit(), subscriberClient.quit()]);\n\n this.logger.error({\n error: error instanceof Error ? error : new Error(safeSerializeError(error)),\n message: 'Redis connection failed',\n meta: {\n Host: this.options.host,\n Port: this.options.port,\n Duration: `${duration.toFixed(2)}ms`,\n Mode: useInMemoryRedis ? 'in-memory' : 'network',\n },\n });\n\n throw error;\n }\n },\n { host: this.options.host, port: this.options.port },\n );\n }\n\n public async disconnect(): Promise<void> {\n await CachePerformanceWrapper.monitorConnection(\n 'disconnect',\n async () => {\n const startTime = performance.now();\n const instanceCount = this.instances.length;\n\n try {\n await Promise.all(this.instances.map(instance => instance.disconnect()));\n\n const duration = performance.now() - startTime;\n\n if (instanceCount > 0) {\n const meta = {\n Instances: instanceCount,\n Host: this.options.host,\n Port: this.options.port,\n Duration: `${duration.toFixed(2)}ms`,\n };\n\n if (this.options.applicationConfig.log?.startUp) {\n this.log('Disconnected all Redis instances', meta);\n } else {\n this.logger.debug({ message: 'Redis instances disconnected', meta });\n }\n }\n\n this.instances = [];\n } catch (error) {\n const duration = performance.now() - startTime;\n\n this.logger.error({\n error: error instanceof Error ? error : new Error(safeSerializeError(error)),\n message: 'Redis disconnection failed',\n meta: {\n Host: this.options.host,\n Port: this.options.port,\n Instances: instanceCount,\n Duration: `${duration.toFixed(2)}ms`,\n },\n });\n\n throw error;\n }\n },\n { host: this.options.host, port: this.options.port },\n );\n }\n\n /**\n * Log Redis message\n */\n public log(message: string, meta?: Record<string, unknown>): void {\n this.logger.custom({ level: 'redis', message, meta });\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["client"]
|
|
7
7
|
}
|
package/dist/util/file.d.ts
CHANGED
|
@@ -15,7 +15,12 @@ declare function convertFile({ inputFilePath, outputFilePath, format, }: {
|
|
|
15
15
|
format: string;
|
|
16
16
|
}): Promise<void>;
|
|
17
17
|
/**
|
|
18
|
-
* Copy a file or directory synchronously
|
|
18
|
+
* Copy a file or directory synchronously.
|
|
19
|
+
*
|
|
20
|
+
* **Note**: This function uses synchronous file system operations which block
|
|
21
|
+
* the event loop. It is intended for use during application initialization,
|
|
22
|
+
* build scripts, or CLI tools where blocking is acceptable.
|
|
23
|
+
* For production runtime code with high concurrency, consider using async alternatives.
|
|
19
24
|
*
|
|
20
25
|
* @param src The source path
|
|
21
26
|
* @param dest The destination path
|
|
@@ -40,7 +45,13 @@ declare function formatFileSize({ bytes }: {
|
|
|
40
45
|
bytes: number;
|
|
41
46
|
}): string;
|
|
42
47
|
/**
|
|
43
|
-
* Remove a file or directory synchronously
|
|
48
|
+
* Remove a file or directory synchronously.
|
|
49
|
+
*
|
|
50
|
+
* **Note**: This function uses synchronous file system operations which block
|
|
51
|
+
* the event loop. It is intended for use during application cleanup, build scripts,
|
|
52
|
+
* or CLI tools where blocking is acceptable.
|
|
53
|
+
* For production runtime code with high concurrency, consider using async alternatives
|
|
54
|
+
* like `fs.promises.rm(target, { recursive: true, force: true })`.
|
|
44
55
|
*
|
|
45
56
|
* @param target The path to the file or directory to remove
|
|
46
57
|
*/
|
package/dist/util/file.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../src/util/file.ts"],"names":[],"mappings":"AAUA;;;;GAIG;AACH,iBAAe,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO/D;AAED;;;GAGG;AACH,iBAAe,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMvD;AAED,iBAAe,WAAW,CAAC,EACzB,aAAa,EACb,cAAc,EACd,MAAM,GACP,EAAE;IACD,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBhB;AAED
|
|
1
|
+
{"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../src/util/file.ts"],"names":[],"mappings":"AAUA;;;;GAIG;AACH,iBAAe,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO/D;AAED;;;GAGG;AACH,iBAAe,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMvD;AAED,iBAAe,WAAW,CAAC,EACzB,aAAa,EACb,cAAc,EACd,MAAM,GACP,EAAE;IACD,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBhB;AAED;;;;;;;;;;GAUG;AACH,iBAAS,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAmBjD;AAED;;;;;GAKG;AACH,iBAAe,YAAY,CAAC,EAAE,GAAG,EAAE,eAAe,EAAE,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA4B7G;AAED;;;;GAIG;AACH,iBAAS,cAAc,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAyB5D;AAED;;;;;;;;;;GAUG;AACH,iBAAS,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAoBxC;;;;;;;;;;AAED,wBAQE"}
|