@m16khb/nestjs-sidequest 0.1.0 → 0.1.2
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/LICENSE +92 -0
- package/README.ko.md +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
GNU LESSER GENERAL PUBLIC LICENSE
|
|
2
|
+
Version 3, 29 June 2007
|
|
3
|
+
|
|
4
|
+
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
|
5
|
+
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
|
|
6
|
+
|
|
7
|
+
This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below.
|
|
8
|
+
|
|
9
|
+
0. Additional Definitions.
|
|
10
|
+
|
|
11
|
+
As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License.
|
|
12
|
+
|
|
13
|
+
"The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below.
|
|
14
|
+
|
|
15
|
+
An "Application" is any work that makes use of an interface provided by the Library, but which is not based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library.
|
|
16
|
+
|
|
17
|
+
A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version".
|
|
18
|
+
|
|
19
|
+
The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version.
|
|
20
|
+
|
|
21
|
+
The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, excluding any System Libraries, and excluding any portion of the Combined Work that is based on the Library but is not part of the Linked Version.
|
|
22
|
+
|
|
23
|
+
The "Corresponding Source" for a Combined Work means the object code and/or source code for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version.
|
|
24
|
+
|
|
25
|
+
1. Exception to Section 3 of the GNU GPL.
|
|
26
|
+
|
|
27
|
+
You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL.
|
|
28
|
+
|
|
29
|
+
2. Conveying Modified Versions.
|
|
30
|
+
|
|
31
|
+
If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version:
|
|
32
|
+
|
|
33
|
+
a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or
|
|
34
|
+
|
|
35
|
+
b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy.
|
|
36
|
+
|
|
37
|
+
3. Object Code Incorporating Material from Library Header Files.
|
|
38
|
+
|
|
39
|
+
The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following:
|
|
40
|
+
|
|
41
|
+
a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License.
|
|
42
|
+
|
|
43
|
+
b) Accompany the object code with a copy of the GNU GPL and this license document.
|
|
44
|
+
|
|
45
|
+
4. Combined Works.
|
|
46
|
+
|
|
47
|
+
You may convey a Combined Work under terms of your choice that, if applied to the Combined Work, would make the Combined Work a "Conveying Modified Versions" of the Library, provided you also do each of the following:
|
|
48
|
+
|
|
49
|
+
a) Make prominent notice in the Combined Work that the Library is used in it and that the Library and its use are covered by this License.
|
|
50
|
+
|
|
51
|
+
b) Acknowledge the part of the Library that is used in the Combined Work, and how the Library is used in the Combined Work.
|
|
52
|
+
|
|
53
|
+
c) Accompany the Combined Work with a copy of the GNU GPL and this license document.
|
|
54
|
+
|
|
55
|
+
5. Combined Works with Library Independent of Library.
|
|
56
|
+
|
|
57
|
+
If you modify a copy of the Library and use it in a Combined Work, but the Combined Work is not a "Conveying Modified Version" of the Library, then you must, if the Combined Work is a "Combined Work with Library Independent of Library", comply with the terms of section 4.
|
|
58
|
+
|
|
59
|
+
A "Combined Work with Library Independent of Library" means a Combined Work that is not a "Conveying Modified Version" of the Library, and that includes a Library that is independent of the Linked Version.
|
|
60
|
+
|
|
61
|
+
6. Revised Versions of the GNU Lesser General Public License.
|
|
62
|
+
|
|
63
|
+
The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
|
|
64
|
+
|
|
65
|
+
Each version is given a distinguishing version number. If the Library as you received it specifies that a proxy or a decision of the Free Software Foundation, the version that the Library specifies as the version number of this License, or any later version that has been published (not as a draft) by the Free Software Foundation. If the Library as you received it does not specify a version number of this License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation.
|
|
66
|
+
|
|
67
|
+
If the Library as you received it specifies that a proxy can decide or can be elected to the Free Software Foundation's public statement of acceptance of a version, you may choose any version published by the Free Software Foundation.
|
|
68
|
+
|
|
69
|
+
If the Library specifies that a proxy can decide or can be elected to the Free Software Foundation's public statement of acceptance of a version, then any later version of the GNU Lesser General Public License will apply to the Combined Work.
|
|
70
|
+
|
|
71
|
+
END OF TERMS AND CONDITIONS
|
|
72
|
+
|
|
73
|
+
How to Apply These Terms to Your New Libraries
|
|
74
|
+
|
|
75
|
+
If you develop a new Library, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License).
|
|
76
|
+
|
|
77
|
+
To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.
|
|
78
|
+
|
|
79
|
+
<one line to give the library's name and a brief idea of what it does.>
|
|
80
|
+
Copyright (C) <year> <name of author>
|
|
81
|
+
|
|
82
|
+
This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
|
|
83
|
+
|
|
84
|
+
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
|
85
|
+
|
|
86
|
+
You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
87
|
+
|
|
88
|
+
Also add information on how to contact you by electronic and paper mail.
|
|
89
|
+
|
|
90
|
+
You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the library, if necessary. For more information on this, and how to apply and follow the GNU GPL, see <https://www.gnu.org/licenses/>.
|
|
91
|
+
|
|
92
|
+
The GNU Lesser General Public License is also available in plain text format.
|
package/README.ko.md
CHANGED
|
@@ -240,7 +240,7 @@ SidequestModule.forRootAsync({
|
|
|
240
240
|
|
|
241
241
|
### @Processor(queueName, options?)
|
|
242
242
|
|
|
243
|
-
클래스를 지정된 큐의 Job
|
|
243
|
+
클래스를 지정된 큐의 Job 프로세서로 표시합니다.
|
|
244
244
|
|
|
245
245
|
```typescript
|
|
246
246
|
@Processor('email', { concurrency: 10 })
|
|
@@ -249,7 +249,7 @@ export class EmailProcessor {}
|
|
|
249
249
|
|
|
250
250
|
### @OnJob(JobClass, options?)
|
|
251
251
|
|
|
252
|
-
메서드를 지정된 Job 타입의
|
|
252
|
+
메서드를 지정된 Job 타입의 핸들러로 표시합니다.
|
|
253
253
|
|
|
254
254
|
```typescript
|
|
255
255
|
@OnJob(SendEmailJob, { timeout: 30000 })
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/constants.ts","../src/core/sidequest.adapter.ts","../src/services/sidequest-engine.service.ts","../src/services/queue-registry.service.ts","../src/services/cls-integration.service.ts","../src/services/processor-registry.service.ts","../src/explorers/processor.explorer.ts","../src/modules/sidequest.module.ts","../src/decorators/processor.decorator.ts","../src/decorators/on-job.decorator.ts","../src/decorators/retry.decorator.ts","../src/decorators/inject-queue.decorator.ts","../src/decorators/on-job-complete.decorator.ts","../src/decorators/on-job-failed.decorator.ts"],"names":["SIDEQUEST_MODULE_OPTIONS","Symbol","SIDEQUEST_ENGINE","PROCESSOR_METADATA_KEY","ON_JOB_METADATA_KEY","RETRY_OPTIONS_METADATA_KEY","ON_JOB_COMPLETE_METADATA_KEY","ON_JOB_FAILED_METADATA_KEY","QUEUE_TOKEN_PREFIX","getQueueToken","queueName","DEFAULT_QUEUE_NAME","DEFAULT_MAX_ATTEMPTS","DEFAULT_TIMEOUT","DEFAULT_CONCURRENCY","SidequestAdapter","logger","Logger","name","isStarted","registeredJobs","Map","start","options","warn","log","config","backend","driver","queues","map","q","concurrency","priority","state","maxConcurrentJobs","undefined","minThreads","maxThreads","jobPollingInterval","releaseStaleJobsIntervalMin","cleanupFinishedJobsIntervalMin","level","json","dashboard","Sidequest","error","shutdown","stop","registerJob","jobName","JobClass","set","debug","addJob","args","get","Error","builder","build","queue","maxAttempts","timeout","scheduledAt","availableAt","retryDelay","backoffStrategy","uniqueKey","unique","jobData","enqueue","jobId","String","id","Date","now","addBulkJobs","jobs","jobIds","push","getJob","numericId","parseInt","isNaN","job","attempt","max_attempts","insertedAt","inserted_at","attemptedAt","attempted_at","completedAt","completed_at","result","errors","started","getRegisteredJob","getAllRegisteredJobs","SidequestEngineService","adapter","onModuleInit","onModuleDestroy","gracefulShutdown","enabled","getAdapter","QueueRegistryService","queueServices","initializeQueues","queueConfig","registerQueue","has","queueService","createQueueService","getQueue","getQueueOrThrow","getAllQueues","add","addWithOptions","addScheduled","addBulk","bulkJobs","ClsIntegrationService","clsService","enableCls","runInContext","metadata","callback","Promise","resolve","reject","run","key","value","Object","entries","then","catch","getTraceId","setTraceId","traceId","isEnabled","ProcessorRegistryService","processors","register","processor","metatype","getProcessor","getAllProcessors","getJobHandler","handlers","getCompleteHandler","completeHandlers","getFailedHandler","failedHandlers","dispatch","handler","instance","method","methodName","executeJob","apply","completeHandlerName","completeHandler","failedHandlerName","failedHandler","ProcessorExplorer","discoveryService","metadataScanner","reflector","processorRegistry","explore","providers","getProviders","wrapper","processWrapper","processorMetadata","scanHandlers","scanCompleteHandlers","scanFailedHandlers","registeredProcessor","size","_metatype","prototype","getPrototypeOf","methodNames","getAllMethodNames","methodRef","onJobMetadata","retryOptions","SidequestModule","forRoot","isGlobal","queueProviders","createQueueProviders","module","global","imports","DiscoveryModule","provide","useValue","exports","p","forRootAsync","asyncOptions","createAsyncProviders","useFactory","inject","registry","useClass","optionsFactory","createSidequestOptions","useExisting","Processor","target","SetMetadata","Injectable","OnJob","propertyKey","descriptor","Retry","InjectQueue","Inject","OnJobComplete","OnJobFailed"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * SidequestModule 상수\n */\n\n// DI 토큰\nexport const SIDEQUEST_MODULE_OPTIONS = Symbol('SIDEQUEST_MODULE_OPTIONS');\nexport const SIDEQUEST_ENGINE = Symbol('SIDEQUEST_ENGINE');\n\n// 메타데이터 키\nexport const PROCESSOR_METADATA_KEY = Symbol('sidequest:processor');\nexport const ON_JOB_METADATA_KEY = Symbol('sidequest:on-job');\nexport const RETRY_OPTIONS_METADATA_KEY = Symbol('sidequest:retry');\nexport const ON_JOB_COMPLETE_METADATA_KEY = Symbol('sidequest:on-job-complete');\nexport const ON_JOB_FAILED_METADATA_KEY = Symbol('sidequest:on-job-failed');\n\n// Queue 토큰 프리픽스\nexport const QUEUE_TOKEN_PREFIX = 'SIDEQUEST_QUEUE_';\n\n/**\n * Queue DI 토큰 생성\n */\nexport function getQueueToken(queueName: string): string {\n return `${QUEUE_TOKEN_PREFIX}${queueName}`;\n}\n\n// 기본값\nexport const DEFAULT_QUEUE_NAME = 'default';\nexport const DEFAULT_MAX_ATTEMPTS = 3;\nexport const DEFAULT_TIMEOUT = 30000;\nexport const DEFAULT_CONCURRENCY = 10;\n\n// Log messages\nexport const LOG_MESSAGES = {\n ENGINE_STARTING: 'Starting Sidequest engine...',\n ENGINE_STARTED: 'Sidequest engine started',\n ENGINE_STOPPING: 'Stopping Sidequest engine...',\n ENGINE_STOPPED: 'Sidequest engine stopped',\n QUEUE_REGISTERED: (name: string) => `Queue '${name}' registered`,\n PROCESSOR_REGISTERED: (name: string) => `Processor '${name}' registered`,\n JOB_HANDLER_REGISTERED: (jobName: string, queueName: string) =>\n `Job handler '${jobName}' (Queue: ${queueName}) registered`,\n} as const;\n","import {Injectable, Logger} from '@nestjs/common';\nimport {Sidequest, Job, JobBuilder} from 'sidequest';\nimport type {SidequestModuleOptions} from '../interfaces/module-options.interface.js';\nimport type {JobAddOptions, JobInfo, JobState, ErrorData} from '../interfaces/queue.interface.js';\n\n// Job 클래스 타입\ntype JobClassType = new (...args: unknown[]) => Job;\n\n/**\n * Sidequest.js API Adapter\n *\n * Sidequest.js의 API를 NestJS와 통합합니다.\n * 실제 sidequest 패키지를 사용하여 Job 처리를 수행합니다.\n */\n@Injectable()\nexport class SidequestAdapter {\n private readonly logger = new Logger(SidequestAdapter.name);\n private isStarted = false;\n private readonly registeredJobs = new Map<string, JobClassType>();\n\n /**\n * Sidequest 엔진 시작\n */\n async start(options: SidequestModuleOptions): Promise<void> {\n if (this.isStarted) {\n this.logger.warn('Sidequest engine is already started');\n return;\n }\n\n this.logger.log('Starting Sidequest engine...');\n\n try {\n // Sidequest 설정 구성\n const config: Record<string, unknown> = {\n backend: {\n driver: options.backend.driver,\n config: options.backend.config,\n },\n };\n\n // 큐 설정\n if (options.queues) {\n config.queues = options.queues.map(q => ({\n name: q.name,\n concurrency: q.concurrency,\n priority: q.priority,\n state: q.state,\n }));\n }\n\n // 엔진 설정\n if (options.maxConcurrentJobs !== undefined) {\n config.maxConcurrentJobs = options.maxConcurrentJobs;\n }\n if (options.minThreads !== undefined) {\n config.minThreads = options.minThreads;\n }\n if (options.maxThreads !== undefined) {\n config.maxThreads = options.maxThreads;\n }\n if (options.jobPollingInterval !== undefined) {\n config.jobPollingInterval = options.jobPollingInterval;\n }\n if (options.releaseStaleJobsIntervalMin !== undefined) {\n config.releaseStaleJobsIntervalMin = options.releaseStaleJobsIntervalMin;\n }\n if (options.cleanupFinishedJobsIntervalMin !== undefined) {\n config.cleanupFinishedJobsIntervalMin = options.cleanupFinishedJobsIntervalMin;\n }\n\n // 로거 설정\n if (options.logger) {\n config.logger = {\n level: options.logger.level ?? 'info',\n json: options.logger.json ?? false,\n };\n }\n\n // 대시보드 설정\n if (options.dashboard) {\n config.dashboard = options.dashboard;\n }\n\n // Sidequest 엔진 시작\n await Sidequest.start(config as Parameters<typeof Sidequest.start>[0]);\n\n this.isStarted = true;\n this.logger.log('Sidequest engine started');\n } catch (error) {\n this.logger.error('Failed to start Sidequest engine', error);\n throw error;\n }\n }\n\n /**\n * Sidequest 엔진 종료\n */\n async shutdown(): Promise<void> {\n if (!this.isStarted) {\n return;\n }\n\n this.logger.log('Stopping Sidequest engine...');\n\n try {\n await Sidequest.stop();\n this.isStarted = false;\n this.logger.log('Sidequest engine stopped');\n } catch (error) {\n this.logger.error('Failed to stop Sidequest engine', error);\n throw error;\n }\n }\n\n /**\n * Job 클래스 등록\n */\n registerJob(jobName: string, JobClass: JobClassType): void {\n this.registeredJobs.set(jobName, JobClass);\n this.logger.debug(`Job '${jobName}' registered`);\n }\n\n /**\n * Job 추가\n */\n async addJob(\n queueName: string,\n jobName: string,\n args: unknown[],\n options?: JobAddOptions,\n ): Promise<string> {\n const JobClass = this.registeredJobs.get(jobName);\n if (!JobClass) {\n throw new Error(`Job class '${jobName}' not found. Make sure it's registered.`);\n }\n\n let builder: JobBuilder<JobClassType> = Sidequest.build(JobClass)\n .queue(queueName);\n\n // 옵션 적용\n if (options?.maxAttempts !== undefined) {\n builder = builder.maxAttempts(options.maxAttempts);\n }\n if (options?.timeout !== undefined) {\n builder = builder.timeout(options.timeout);\n }\n if (options?.priority !== undefined) {\n // priority는 queue 레벨에서 설정됨\n }\n if (options?.scheduledAt !== undefined) {\n builder = builder.availableAt(options.scheduledAt);\n }\n if (options?.retryDelay !== undefined) {\n builder = builder.retryDelay(options.retryDelay);\n }\n if (options?.backoffStrategy !== undefined) {\n builder = builder.backoffStrategy(options.backoffStrategy);\n }\n if (options?.uniqueKey !== undefined) {\n builder = builder.unique(true);\n }\n\n // Job 실행 (enqueue)\n const jobData = await builder.enqueue(...args);\n const jobId = String(jobData?.id ?? `job_${Date.now()}`);\n\n this.logger.debug(`Job '${jobName}' (ID: ${jobId}) added to Queue '${queueName}'`);\n\n return jobId;\n }\n\n /**\n * Bulk Job 추가\n */\n async addBulkJobs(\n queueName: string,\n jobs: Array<{jobName: string; args: unknown[]; options?: JobAddOptions}>,\n ): Promise<string[]> {\n const jobIds: string[] = [];\n\n for (const {jobName, args, options} of jobs) {\n const jobId = await this.addJob(queueName, jobName, args, options);\n jobIds.push(jobId);\n }\n\n return jobIds;\n }\n\n /**\n * Job 조회\n */\n async getJob(jobId: string | number): Promise<JobInfo | undefined> {\n try {\n const numericId = typeof jobId === 'string' ? parseInt(jobId, 10) : jobId;\n if (isNaN(numericId)) {\n return undefined;\n }\n\n const job = await Sidequest.job.get(numericId);\n if (!job) {\n return undefined;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const jobData = job as any;\n\n return {\n id: String(job.id),\n name: jobData.name as string | undefined,\n queue: job.queue,\n state: job.state as JobState,\n attempt: job.attempt,\n maxAttempts: job.max_attempts,\n insertedAt: job.inserted_at,\n attemptedAt: job.attempted_at ?? undefined,\n completedAt: job.completed_at ?? undefined,\n result: job.result,\n errors: job.errors as ErrorData[] | null | undefined,\n };\n } catch {\n return undefined;\n }\n }\n\n /**\n * 엔진 시작 여부\n */\n get started(): boolean {\n return this.isStarted;\n }\n\n /**\n * 등록된 Job 클래스 반환\n */\n getRegisteredJob(jobName: string): JobClassType | undefined {\n return this.registeredJobs.get(jobName);\n }\n\n /**\n * 모든 등록된 Job 클래스 반환\n */\n getAllRegisteredJobs(): Map<string, JobClassType> {\n return this.registeredJobs;\n }\n}\n\n// Job 베이스 클래스 re-export\nexport {Job} from 'sidequest';\n","import {Inject, Injectable, Logger, OnModuleDestroy, OnModuleInit} from '@nestjs/common';\nimport {SIDEQUEST_MODULE_OPTIONS} from '../constants.js';\nimport {SidequestAdapter} from '../core/sidequest.adapter.js';\nimport type {SidequestModuleOptions} from '../interfaces/module-options.interface.js';\n\n/**\n * Sidequest 엔진 관리 서비스\n *\n * Sidequest.js 엔진의 라이프사이클을 관리합니다.\n * 모듈 초기화 시 엔진을 시작하고, 종료 시 graceful shutdown을 수행합니다.\n */\n@Injectable()\nexport class SidequestEngineService implements OnModuleInit, OnModuleDestroy {\n private readonly logger = new Logger(SidequestEngineService.name);\n\n constructor(\n @Inject(SIDEQUEST_MODULE_OPTIONS)\n private readonly options: SidequestModuleOptions,\n private readonly adapter: SidequestAdapter,\n ) {}\n\n /**\n * 모듈 초기화 시 엔진 시작\n */\n async onModuleInit(): Promise<void> {\n this.logger.log('Initializing Sidequest engine...');\n await this.adapter.start(this.options);\n this.logger.log('Sidequest engine initialized');\n }\n\n /**\n * 모듈 종료 시 엔진 종료\n */\n async onModuleDestroy(): Promise<void> {\n const gracefulShutdown = this.options.gracefulShutdown ?? {enabled: true, timeout: 30000};\n\n if (gracefulShutdown.enabled) {\n this.logger.log(\n `Sidequest engine graceful shutdown (timeout: ${gracefulShutdown.timeout}ms)`,\n );\n }\n\n await this.adapter.shutdown();\n this.logger.log('Sidequest engine stopped');\n }\n\n /**\n * 엔진 시작 여부\n */\n get isStarted(): boolean {\n return this.adapter.started;\n }\n\n /**\n * Adapter 인스턴스 반환\n */\n getAdapter(): SidequestAdapter {\n return this.adapter;\n }\n}\n","import {Inject, Injectable, Logger} from '@nestjs/common';\nimport {SIDEQUEST_MODULE_OPTIONS} from '../constants.js';\nimport {SidequestAdapter} from '../core/sidequest.adapter.js';\nimport type {SidequestModuleOptions, QueueConfig} from '../interfaces/module-options.interface.js';\nimport type {IQueueService, JobAddOptions} from '../interfaces/queue.interface.js';\n\n/**\n * Queue 레지스트리 서비스\n *\n * 큐 인스턴스를 관리하고 @InjectQueue()를 위한 DI 프로바이더를 제공합니다.\n */\n@Injectable()\nexport class QueueRegistryService {\n private readonly logger = new Logger(QueueRegistryService.name);\n private readonly queueServices = new Map<string, IQueueService>();\n\n constructor(\n @Inject(SIDEQUEST_MODULE_OPTIONS)\n private readonly options: SidequestModuleOptions,\n private readonly adapter: SidequestAdapter,\n ) {\n this.initializeQueues();\n }\n\n /**\n * 설정된 큐 초기화\n */\n private initializeQueues(): void {\n const queues = this.options.queues ?? [];\n\n for (const queueConfig of queues) {\n this.registerQueue(queueConfig);\n }\n\n // 기본 큐가 없으면 생성\n if (!this.queueServices.has('default')) {\n this.registerQueue({name: 'default'});\n }\n }\n\n /**\n * 큐 등록\n */\n registerQueue(config: QueueConfig): void {\n const queueService = this.createQueueService(config.name);\n this.queueServices.set(config.name, queueService);\n this.logger.log(`Queue '${config.name}' registered`);\n }\n\n /**\n * 큐 서비스 조회\n */\n getQueue(name: string): IQueueService | undefined {\n return this.queueServices.get(name);\n }\n\n /**\n * 큐 서비스 조회 (없으면 에러)\n */\n getQueueOrThrow(name: string): IQueueService {\n const queue = this.getQueue(name);\n if (!queue) {\n throw new Error(\n `Queue '${name}' not found. Make sure it is registered in SidequestModule.forRoot().`,\n );\n }\n return queue;\n }\n\n /**\n * 모든 큐 조회\n */\n getAllQueues(): Map<string, IQueueService> {\n return this.queueServices;\n }\n\n /**\n * 큐 서비스 인스턴스 생성\n */\n private createQueueService(queueName: string): IQueueService {\n const adapter = this.adapter;\n\n return {\n name: queueName,\n\n async add<T>(JobClass: new (...args: unknown[]) => T, ...args: unknown[]): Promise<string> {\n const jobName = JobClass.name;\n return adapter.addJob(queueName, jobName, args);\n },\n\n async addWithOptions<T>(\n JobClass: new (...args: unknown[]) => T,\n options: JobAddOptions,\n ...args: unknown[]\n ): Promise<string> {\n const jobName = JobClass.name;\n return adapter.addJob(queueName, jobName, args, options);\n },\n\n async addScheduled<T>(\n JobClass: new (...args: unknown[]) => T,\n scheduledAt: Date,\n ...args: unknown[]\n ): Promise<string> {\n const jobName = JobClass.name;\n return adapter.addJob(queueName, jobName, args, {scheduledAt});\n },\n\n async addBulk<T>(\n jobs: Array<{\n JobClass: new (...args: unknown[]) => T;\n args: unknown[];\n options?: JobAddOptions;\n }>,\n ): Promise<string[]> {\n const bulkJobs = jobs.map(job => {\n const result: {jobName: string; args: unknown[]; options?: JobAddOptions} = {\n jobName: job.JobClass.name,\n args: job.args,\n };\n if (job.options !== undefined) {\n result.options = job.options;\n }\n return result;\n });\n return adapter.addBulkJobs(queueName, bulkJobs);\n },\n };\n }\n}\n","import {Injectable, Logger, Optional, Inject} from '@nestjs/common';\nimport {SIDEQUEST_MODULE_OPTIONS} from '../constants.js';\nimport type {SidequestModuleOptions} from '../interfaces/module-options.interface.js';\n\n// nestjs-cls 타입 (optional dependency)\ninterface ClsService {\n getId(): string | undefined;\n get<T>(key: string): T | undefined;\n set<T>(key: string, value: T): void;\n run<T>(callback: () => T): T;\n}\n\n/**\n * CLS(Continuation Local Storage) 통합 서비스\n *\n * nestjs-cls가 설치되어 있을 경우 Job 실행 시 context를 전파합니다.\n * nestjs-cls가 없으면 no-op으로 동작합니다.\n */\n@Injectable()\nexport class ClsIntegrationService {\n private readonly logger = new Logger(ClsIntegrationService.name);\n private readonly enabled: boolean;\n private clsService: ClsService | null = null;\n\n constructor(\n @Inject(SIDEQUEST_MODULE_OPTIONS)\n options: SidequestModuleOptions,\n @Optional() @Inject('ClsService') clsService?: ClsService,\n ) {\n this.enabled = options.enableCls ?? false;\n this.clsService = clsService ?? null;\n\n if (this.enabled && !this.clsService) {\n this.logger.warn(\n 'CLS integration is enabled but nestjs-cls is not installed. ' +\n 'Install nestjs-cls to enable context propagation.',\n );\n }\n }\n\n /**\n * CLS context 내에서 콜백 실행\n */\n async runInContext<T>(\n metadata: Record<string, unknown>,\n callback: () => Promise<T>,\n ): Promise<T> {\n if (!this.enabled || !this.clsService) {\n return callback();\n }\n\n // nestjs-cls의 run 메서드를 사용하여 새 context에서 실행\n return new Promise((resolve, reject) => {\n try {\n this.clsService!.run(() => {\n // 메타데이터를 CLS에 설정\n for (const [key, value] of Object.entries(metadata)) {\n this.clsService!.set(key, value);\n }\n\n callback().then(resolve).catch(reject);\n });\n } catch (error) {\n reject(error);\n }\n });\n }\n\n /**\n * 현재 traceId 조회\n */\n getTraceId(): string | undefined {\n if (!this.enabled || !this.clsService) {\n return undefined;\n }\n\n return this.clsService.get<string>('traceId');\n }\n\n /**\n * traceId 설정\n */\n setTraceId(traceId: string): void {\n if (!this.enabled || !this.clsService) {\n return;\n }\n\n this.clsService.set('traceId', traceId);\n }\n\n /**\n * CLS에서 값 조회\n */\n get<T>(key: string): T | undefined {\n if (!this.enabled || !this.clsService) {\n return undefined;\n }\n\n return this.clsService.get<T>(key);\n }\n\n /**\n * CLS에 값 설정\n */\n set<T>(key: string, value: T): void {\n if (!this.enabled || !this.clsService) {\n return;\n }\n\n this.clsService.set(key, value);\n }\n\n /**\n * CLS 통합 활성화 여부\n */\n isEnabled(): boolean {\n return this.enabled && this.clsService !== null;\n }\n}\n","import {Injectable, Logger, Optional} from '@nestjs/common';\nimport type {RegisteredProcessor, RegisteredHandler} from '../interfaces/processor.interface.js';\nimport {ClsIntegrationService} from './cls-integration.service.js';\n\n/**\n * Processor 레지스트리 서비스\n *\n * @Processor 데코레이터로 등록된 프로세서와 핸들러를 관리합니다.\n */\n@Injectable()\nexport class ProcessorRegistryService {\n private readonly logger = new Logger(ProcessorRegistryService.name);\n private readonly processors = new Map<string, RegisteredProcessor>();\n\n constructor(\n @Optional() private readonly clsService?: ClsIntegrationService,\n ) {}\n\n /**\n * 프로세서 등록\n */\n register(processor: RegisteredProcessor): void {\n this.processors.set(processor.queueName, processor);\n this.logger.log(\n `Processor '${processor.metatype.name}' (Queue: ${processor.queueName}) registered`,\n );\n }\n\n /**\n * 프로세서 조회\n */\n getProcessor(queueName: string): RegisteredProcessor | undefined {\n return this.processors.get(queueName);\n }\n\n /**\n * 모든 프로세서 조회\n */\n getAllProcessors(): Map<string, RegisteredProcessor> {\n return this.processors;\n }\n\n /**\n * Job 핸들러 조회\n */\n getJobHandler(queueName: string, jobName: string): RegisteredHandler | undefined {\n const processor = this.processors.get(queueName);\n if (!processor) {\n return undefined;\n }\n return processor.handlers.get(jobName);\n }\n\n /**\n * Job 완료 핸들러 조회\n */\n getCompleteHandler(queueName: string, jobName: string): string | undefined {\n const processor = this.processors.get(queueName);\n if (!processor) {\n return undefined;\n }\n return processor.completeHandlers.get(jobName) ?? processor.completeHandlers.get('*');\n }\n\n /**\n * Job 실패 핸들러 조회\n */\n getFailedHandler(queueName: string, jobName: string): string | undefined {\n const processor = this.processors.get(queueName);\n if (!processor) {\n return undefined;\n }\n return processor.failedHandlers.get(jobName) ?? processor.failedHandlers.get('*');\n }\n\n /**\n * Job 디스패치 (실행)\n *\n * @param queueName - 큐 이름\n * @param jobName - Job 이름\n * @param args - Job 인자\n * @param metadata - Job 메타데이터 (traceId 등)\n */\n async dispatch(\n queueName: string,\n jobName: string,\n args: unknown[],\n metadata?: Record<string, unknown>,\n ): Promise<unknown> {\n const processor = this.processors.get(queueName);\n if (!processor) {\n throw new Error(`Processor not found for Queue '${queueName}'`);\n }\n\n const handler = processor.handlers.get(jobName);\n if (!handler) {\n throw new Error(`Handler not found for Job '${jobName}' (Queue: ${queueName})`);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n const instance = processor.instance as Record<string, Function>;\n const method = instance[handler.methodName];\n\n if (typeof method !== 'function') {\n throw new Error(`Handler method '${handler.methodName}' not found`);\n }\n\n // CLS context에서 실행\n const executeJob = async (): Promise<unknown> => {\n try {\n const result = await method.apply(processor.instance, args);\n\n // 완료 핸들러 호출\n const completeHandlerName = this.getCompleteHandler(queueName, jobName);\n if (completeHandlerName) {\n const completeHandler = instance[completeHandlerName];\n if (typeof completeHandler === 'function') {\n await completeHandler.apply(processor.instance, [{jobName, args, result}]);\n }\n }\n\n return result;\n } catch (error) {\n // 실패 핸들러 호출\n const failedHandlerName = this.getFailedHandler(queueName, jobName);\n if (failedHandlerName) {\n const failedHandler = instance[failedHandlerName];\n if (typeof failedHandler === 'function') {\n await failedHandler.apply(processor.instance, [{jobName, args, error}]);\n }\n }\n\n throw error;\n }\n };\n\n // CLS 통합이 활성화되어 있으면 context 내에서 실행\n if (this.clsService?.isEnabled() && metadata) {\n return this.clsService.runInContext(metadata, executeJob);\n }\n\n return executeJob();\n }\n}\n","import {Injectable, Logger, OnModuleInit} from '@nestjs/common';\nimport {DiscoveryService, MetadataScanner, Reflector} from '@nestjs/core';\nimport {InstanceWrapper} from '@nestjs/core/injector/instance-wrapper';\nimport {\n PROCESSOR_METADATA_KEY,\n ON_JOB_METADATA_KEY,\n RETRY_OPTIONS_METADATA_KEY,\n ON_JOB_COMPLETE_METADATA_KEY,\n ON_JOB_FAILED_METADATA_KEY,\n} from '../constants.js';\nimport {ProcessorRegistryService} from '../services/processor-registry.service.js';\nimport type {\n ProcessorMetadata,\n OnJobMetadata,\n RetryOptions,\n RegisteredHandler,\n RegisteredProcessor,\n} from '../interfaces/processor.interface.js';\n\n/**\n * Processor Explorer\n *\n * 애플리케이션 시작 시 @Processor 데코레이터가 붙은 클래스를 스캔하고,\n * @OnJob, @Retry, @OnJobComplete, @OnJobFailed 메타데이터를 수집하여\n * ProcessorRegistry에 등록합니다.\n */\n@Injectable()\nexport class ProcessorExplorer implements OnModuleInit {\n private readonly logger = new Logger(ProcessorExplorer.name);\n\n constructor(\n private readonly discoveryService: DiscoveryService,\n private readonly metadataScanner: MetadataScanner,\n private readonly reflector: Reflector,\n private readonly processorRegistry: ProcessorRegistryService,\n ) {}\n\n /**\n * 모듈 초기화 시 프로세서 스캔\n */\n async onModuleInit(): Promise<void> {\n this.logger.log('Scanning for processors...');\n await this.explore();\n this.logger.log('Processor scan completed');\n }\n\n /**\n * 모든 프로바이더를 스캔하여 @Processor 클래스 찾기\n */\n async explore(): Promise<void> {\n const providers = this.discoveryService.getProviders();\n\n for (const wrapper of providers) {\n await this.processWrapper(wrapper);\n }\n }\n\n /**\n * 프로바이더 래퍼 처리\n */\n private async processWrapper(wrapper: InstanceWrapper): Promise<void> {\n const {instance, metatype} = wrapper;\n\n // 인스턴스와 메타타입이 없으면 스킵\n if (!instance || !metatype) {\n return;\n }\n\n // @Processor 메타데이터 확인\n const processorMetadata = this.reflector.get<ProcessorMetadata>(\n PROCESSOR_METADATA_KEY,\n metatype,\n );\n\n if (!processorMetadata) {\n return;\n }\n\n // 핸들러 스캔\n const handlers = this.scanHandlers(instance, metatype);\n const completeHandlers = this.scanCompleteHandlers(instance, metatype);\n const failedHandlers = this.scanFailedHandlers(instance, metatype);\n\n // 프로세서 등록\n const registeredProcessor: RegisteredProcessor = {\n queueName: processorMetadata.queueName,\n instance,\n metatype,\n handlers,\n completeHandlers,\n failedHandlers,\n };\n\n this.processorRegistry.register(registeredProcessor);\n\n this.logger.log(\n `Processor '${metatype.name}' registered (Queue: ${processorMetadata.queueName}, Handlers: ${handlers.size})`,\n );\n }\n\n /**\n * @OnJob 메서드 스캔\n */\n private scanHandlers(instance: unknown, _metatype: object): Map<string, RegisteredHandler> {\n const handlers = new Map<string, RegisteredHandler>();\n const prototype = Object.getPrototypeOf(instance);\n const methodNames = this.metadataScanner.getAllMethodNames(prototype);\n\n for (const methodName of methodNames) {\n const methodRef = prototype[methodName];\n\n // @OnJob 메타데이터 확인\n const onJobMetadata = this.reflector.get<OnJobMetadata>(ON_JOB_METADATA_KEY, methodRef);\n\n if (!onJobMetadata) {\n continue;\n }\n\n // @Retry 메타데이터 확인\n const retryOptions = this.reflector.get<RetryOptions>(RETRY_OPTIONS_METADATA_KEY, methodRef);\n\n const handler: RegisteredHandler = {\n methodName,\n jobName: onJobMetadata.jobName,\n options: onJobMetadata.options,\n retryOptions,\n };\n\n handlers.set(onJobMetadata.jobName, handler);\n\n this.logger.debug(` - Job '${onJobMetadata.jobName}' -> ${methodName}()`);\n }\n\n return handlers;\n }\n\n /**\n * @OnJobComplete 메서드 스캔\n */\n private scanCompleteHandlers(instance: unknown, _metatype: object): Map<string, string> {\n const handlers = new Map<string, string>();\n const prototype = Object.getPrototypeOf(instance);\n const methodNames = this.metadataScanner.getAllMethodNames(prototype);\n\n for (const methodName of methodNames) {\n const methodRef = prototype[methodName];\n\n // @OnJobComplete 메타데이터 확인\n const jobName = this.reflector.get<string | undefined>(\n ON_JOB_COMPLETE_METADATA_KEY,\n methodRef,\n );\n\n if (jobName !== undefined) {\n // jobName이 빈 문자열이면 모든 Job에 대해 호출 ('*')\n const key = jobName || '*';\n handlers.set(key, methodName);\n this.logger.debug(` - OnJobComplete '${key}' -> ${methodName}()`);\n }\n }\n\n return handlers;\n }\n\n /**\n * @OnJobFailed 메서드 스캔\n */\n private scanFailedHandlers(instance: unknown, _metatype: object): Map<string, string> {\n const handlers = new Map<string, string>();\n const prototype = Object.getPrototypeOf(instance);\n const methodNames = this.metadataScanner.getAllMethodNames(prototype);\n\n for (const methodName of methodNames) {\n const methodRef = prototype[methodName];\n\n // @OnJobFailed 메타데이터 확인\n const jobName = this.reflector.get<string | undefined>(ON_JOB_FAILED_METADATA_KEY, methodRef);\n\n if (jobName !== undefined) {\n // jobName이 빈 문자열이면 모든 Job에 대해 호출 ('*')\n const key = jobName || '*';\n handlers.set(key, methodName);\n this.logger.debug(` - OnJobFailed '${key}' -> ${methodName}()`);\n }\n }\n\n return handlers;\n }\n}\n","import {DynamicModule, Global, Module, Provider} from '@nestjs/common';\nimport {DiscoveryModule} from '@nestjs/core';\nimport {SIDEQUEST_MODULE_OPTIONS, getQueueToken} from '../constants.js';\nimport {SidequestAdapter} from '../core/sidequest.adapter.js';\nimport type {\n SidequestModuleOptions,\n SidequestModuleAsyncOptions,\n SidequestOptionsFactory,\n} from '../interfaces/module-options.interface.js';\nimport {SidequestEngineService} from '../services/sidequest-engine.service.js';\nimport {QueueRegistryService} from '../services/queue-registry.service.js';\nimport {ProcessorRegistryService} from '../services/processor-registry.service.js';\nimport {ClsIntegrationService} from '../services/cls-integration.service.js';\nimport {ProcessorExplorer} from '../explorers/processor.explorer.js';\n\n/**\n * SidequestModule\n *\n * NestJS에서 Sidequest.js를 사용하기 위한 메인 모듈입니다.\n *\n * @example\n * ```typescript\n * // 동기 설정\n * @Module({\n * imports: [\n * SidequestModule.forRoot({\n * backend: {\n * driver: '@sidequest/postgres-backend',\n * config: process.env.DATABASE_URL,\n * },\n * queues: [\n * { name: 'email', concurrency: 5 },\n * { name: 'report', concurrency: 2 },\n * ],\n * }),\n * ],\n * })\n * export class AppModule {}\n *\n * // 비동기 설정 (ConfigService 사용)\n * @Module({\n * imports: [\n * SidequestModule.forRootAsync({\n * imports: [ConfigModule],\n * useFactory: (config: ConfigService) => ({\n * backend: {\n * driver: '@sidequest/postgres-backend',\n * config: config.get('DATABASE_URL'),\n * },\n * queues: [{ name: 'default' }],\n * }),\n * inject: [ConfigService],\n * }),\n * ],\n * })\n * export class AppModule {}\n * ```\n */\n@Global()\n@Module({})\nexport class SidequestModule {\n /**\n * 동기 설정으로 모듈 등록\n */\n static forRoot(options: SidequestModuleOptions): DynamicModule {\n const isGlobal = options.isGlobal ?? true;\n const queueProviders = this.createQueueProviders(options);\n\n return {\n module: SidequestModule,\n global: isGlobal,\n imports: [DiscoveryModule],\n providers: [\n {\n provide: SIDEQUEST_MODULE_OPTIONS,\n useValue: options,\n },\n SidequestAdapter,\n SidequestEngineService,\n QueueRegistryService,\n ProcessorRegistryService,\n ClsIntegrationService,\n ProcessorExplorer,\n ...queueProviders,\n ],\n exports: [\n SIDEQUEST_MODULE_OPTIONS,\n SidequestAdapter,\n SidequestEngineService,\n QueueRegistryService,\n ProcessorRegistryService,\n ClsIntegrationService,\n ...queueProviders.map(p => (p as {provide: symbol | string}).provide),\n ],\n };\n }\n\n /**\n * 비동기 설정으로 모듈 등록\n */\n static forRootAsync(asyncOptions: SidequestModuleAsyncOptions): DynamicModule {\n const isGlobal = asyncOptions.isGlobal ?? true;\n\n return {\n module: SidequestModule,\n global: isGlobal,\n imports: [DiscoveryModule, ...(asyncOptions.imports || [])],\n providers: [\n ...this.createAsyncProviders(asyncOptions),\n SidequestAdapter,\n SidequestEngineService,\n QueueRegistryService,\n ProcessorRegistryService,\n ClsIntegrationService,\n ProcessorExplorer,\n // 동적 큐 프로바이더 - options에서 queues를 읽어 생성\n {\n provide: 'SIDEQUEST_QUEUE_PROVIDERS_INIT',\n useFactory: () => {\n // QueueRegistryService가 자동으로 큐를 초기화하므로 별도 처리 불필요\n return true;\n },\n inject: [QueueRegistryService],\n },\n ],\n exports: [\n SIDEQUEST_MODULE_OPTIONS,\n SidequestAdapter,\n SidequestEngineService,\n QueueRegistryService,\n ProcessorRegistryService,\n ClsIntegrationService,\n ],\n };\n }\n\n /**\n * 큐별 DI 프로바이더 생성\n */\n private static createQueueProviders(options: SidequestModuleOptions): Provider[] {\n const queues = options.queues ?? [{name: 'default'}];\n\n return queues.map(queue => ({\n provide: getQueueToken(queue.name),\n useFactory: (registry: QueueRegistryService) => registry.getQueueOrThrow(queue.name),\n inject: [QueueRegistryService],\n }));\n }\n\n /**\n * 비동기 프로바이더 생성\n */\n private static createAsyncProviders(asyncOptions: SidequestModuleAsyncOptions): Provider[] {\n if (asyncOptions.useFactory) {\n return [\n {\n provide: SIDEQUEST_MODULE_OPTIONS,\n useFactory: asyncOptions.useFactory,\n inject: asyncOptions.inject || [],\n },\n ];\n }\n\n if (asyncOptions.useClass) {\n return [\n {\n provide: asyncOptions.useClass,\n useClass: asyncOptions.useClass,\n },\n {\n provide: SIDEQUEST_MODULE_OPTIONS,\n useFactory: async (optionsFactory: SidequestOptionsFactory) =>\n optionsFactory.createSidequestOptions(),\n inject: [asyncOptions.useClass],\n },\n ];\n }\n\n if (asyncOptions.useExisting) {\n return [\n {\n provide: SIDEQUEST_MODULE_OPTIONS,\n useFactory: async (optionsFactory: SidequestOptionsFactory) =>\n optionsFactory.createSidequestOptions(),\n inject: [asyncOptions.useExisting],\n },\n ];\n }\n\n return [\n {\n provide: SIDEQUEST_MODULE_OPTIONS,\n useValue: {},\n },\n ];\n }\n}\n","import {Injectable, SetMetadata} from '@nestjs/common';\nimport {PROCESSOR_METADATA_KEY} from '../constants.js';\nimport type {ProcessorOptions, ProcessorMetadata} from '../interfaces/processor.interface.js';\n\n/**\n * 클래스를 Sidequest Job Processor로 지정합니다.\n *\n * @Processor 데코레이터가 붙은 클래스는 모듈 초기화 시 자동으로 스캔되어\n * 해당 큐의 Job 핸들러로 등록됩니다.\n *\n * @param queueName - 처리할 큐 이름\n * @param options - 프로세서 옵션\n *\n * @example\n * ```typescript\n * @Processor('email')\n * export class EmailProcessor {\n * @OnJob('send-welcome-email')\n * async handleWelcomeEmail(job: JobContext) {\n * const { to, subject, body } = job.data;\n * await this.mailer.send({ to, subject, body });\n * }\n * }\n *\n * // 동시성 설정과 함께\n * @Processor('report', { concurrency: 2 })\n * export class ReportProcessor {\n * @OnJob('generate-daily-report')\n * async handleDailyReport(job: JobContext) {\n * // 리포트 생성 로직\n * }\n * }\n * ```\n */\nexport function Processor(queueName: string, options?: ProcessorOptions): ClassDecorator {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n return (target: Function): void => {\n const metadata: ProcessorMetadata = {\n queueName,\n options,\n };\n\n // 메타데이터 설정\n SetMetadata(PROCESSOR_METADATA_KEY, metadata)(target);\n\n // @Injectable() 자동 적용\n Injectable()(target);\n };\n}\n","import {SetMetadata} from '@nestjs/common';\nimport {ON_JOB_METADATA_KEY} from '../constants.js';\nimport type {OnJobOptions, OnJobMetadata} from '../interfaces/processor.interface.js';\n\n/**\n * 메서드를 특정 Job 타입의 핸들러로 지정합니다.\n *\n * @Processor 데코레이터가 붙은 클래스 내부에서 사용합니다.\n * 해당 Job이 큐에서 처리될 때 이 메서드가 호출됩니다.\n *\n * @param jobName - Job 이름 (일반적으로 Job 클래스명)\n * @param options - Job 실행 옵션 (우선순위, 타임아웃 등)\n *\n * @example\n * ```typescript\n * @Processor('email')\n * export class EmailProcessor {\n * @OnJob('SendWelcomeEmailJob')\n * async handleWelcomeEmail(job: JobContext) {\n * const { to, subject, body } = job.data;\n * await this.mailer.send({ to, subject, body });\n * }\n *\n * // 우선순위와 타임아웃 설정\n * @OnJob('SendPriorityEmailJob', { priority: 100, timeout: 5000 })\n * async handlePriorityEmail(job: JobContext) {\n * // 우선순위가 높은 이메일 처리\n * }\n * }\n * ```\n */\nexport function OnJob(jobName: string, options?: OnJobOptions): MethodDecorator {\n return (\n target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor,\n ): PropertyDescriptor => {\n const metadata: OnJobMetadata = {\n jobName,\n options,\n };\n\n SetMetadata(ON_JOB_METADATA_KEY, metadata)(target, propertyKey, descriptor);\n\n return descriptor;\n };\n}\n","import {SetMetadata} from '@nestjs/common';\nimport {RETRY_OPTIONS_METADATA_KEY} from '../constants.js';\nimport type {RetryOptions} from '../interfaces/processor.interface.js';\n\n/**\n * Job 재시도 정책을 설정합니다.\n *\n * @OnJob 데코레이터와 함께 사용하여 Job 실패 시 재시도 동작을 정의합니다.\n *\n * @param options - 재시도 옵션\n *\n * @example\n * ```typescript\n * @Processor('payment')\n * export class PaymentProcessor {\n * // 고정 지연 재시도\n * @OnJob('ProcessPaymentJob')\n * @Retry({ maxAttempts: 3, delay: 1000 })\n * async handlePayment(job: JobContext) {\n * // 결제 처리 로직\n * }\n *\n * // 지수 백오프 재시도\n * @OnJob('RefundJob')\n * @Retry({ maxAttempts: 5, delay: 500, backoff: 'exponential' })\n * async handleRefund(job: JobContext) {\n * // 환불 처리 로직\n * }\n * }\n * ```\n */\nexport function Retry(options: RetryOptions): MethodDecorator {\n return (\n target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor,\n ): PropertyDescriptor => {\n SetMetadata(RETRY_OPTIONS_METADATA_KEY, options)(target, propertyKey, descriptor);\n return descriptor;\n };\n}\n","import {Inject} from '@nestjs/common';\nimport {getQueueToken} from '../constants.js';\n\n/**\n * Queue 인스턴스를 주입합니다.\n *\n * SidequestModule.forRoot()에서 등록된 큐를 서비스에 주입받아 사용할 수 있습니다.\n *\n * @param queueName - 주입받을 큐 이름\n *\n * @example\n * ```typescript\n * @Injectable()\n * export class UserService {\n * constructor(\n * @InjectQueue('email') private emailQueue: IQueueService,\n * @InjectQueue('notification') private notificationQueue: IQueueService,\n * ) {}\n *\n * async createUser(email: string, name: string) {\n * // 사용자 생성 로직...\n *\n * // 환영 이메일 발송\n * await this.emailQueue.add(SendWelcomeEmailJob, email, `Welcome, ${name}!`);\n *\n * // 알림 발송\n * await this.notificationQueue.add(SendNotificationJob, email, 'new-user');\n * }\n * }\n * ```\n */\nexport function InjectQueue(queueName: string): ParameterDecorator {\n return Inject(getQueueToken(queueName));\n}\n","import {SetMetadata} from '@nestjs/common';\nimport {ON_JOB_COMPLETE_METADATA_KEY} from '../constants.js';\n\n/**\n * Job 완료 이벤트 핸들러를 지정합니다.\n *\n * @Processor 클래스 내부에서 사용하며, Job이 성공적으로 완료되면 호출됩니다.\n *\n * @param jobName - 대상 Job 이름 (생략 시 모든 Job에 대해 호출)\n *\n * @example\n * ```typescript\n * @Processor('email')\n * export class EmailProcessor {\n * @OnJob('SendWelcomeEmailJob')\n * async handleWelcomeEmail(job: JobContext) {\n * await this.mailer.send(job.data);\n * }\n *\n * // 특정 Job 완료 이벤트\n * @OnJobComplete('SendWelcomeEmailJob')\n * async onWelcomeEmailComplete(event: JobCompleteEvent) {\n * this.logger.log(`환영 이메일 발송 완료: ${event.result}`);\n * await this.analytics.track('email_sent', { type: 'welcome' });\n * }\n *\n * // 모든 Job 완료 이벤트 (jobName 생략)\n * @OnJobComplete()\n * async onAnyJobComplete(event: JobCompleteEvent) {\n * this.logger.log(`Job 완료: ${event.jobName}`);\n * }\n * }\n * ```\n */\nexport function OnJobComplete(jobName?: string): MethodDecorator {\n return (\n target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor,\n ): PropertyDescriptor => {\n // jobName이 undefined면 빈 문자열로 저장 (모든 Job에 대해 호출)\n SetMetadata(ON_JOB_COMPLETE_METADATA_KEY, jobName ?? '')(target, propertyKey, descriptor);\n return descriptor;\n };\n}\n\n/**\n * Job 완료 이벤트 데이터\n */\nexport interface JobCompleteEvent {\n /** Job 이름 */\n jobName: string;\n\n /** Job 실행 인자 */\n args: unknown[];\n\n /** Job 실행 결과 */\n result: unknown;\n}\n","import {SetMetadata} from '@nestjs/common';\nimport {ON_JOB_FAILED_METADATA_KEY} from '../constants.js';\n\n/**\n * Job 실패 이벤트 핸들러를 지정합니다.\n *\n * @Processor 클래스 내부에서 사용하며, Job 실행이 실패하면 호출됩니다.\n * 재시도 횟수를 모두 소진한 후 최종 실패 시에만 호출됩니다.\n *\n * @param jobName - 대상 Job 이름 (생략 시 모든 Job에 대해 호출)\n *\n * @example\n * ```typescript\n * @Processor('payment')\n * export class PaymentProcessor {\n * @OnJob('ProcessPaymentJob')\n * @Retry({ maxAttempts: 3 })\n * async handlePayment(job: JobContext) {\n * await this.paymentService.process(job.data);\n * }\n *\n * // 특정 Job 실패 이벤트\n * @OnJobFailed('ProcessPaymentJob')\n * async onPaymentFailed(event: JobFailedEvent) {\n * this.logger.error(`결제 처리 실패: ${event.error.message}`);\n * await this.alertService.notify('payment-failure', {\n * orderId: event.args[0],\n * error: event.error.message,\n * });\n * }\n *\n * // 모든 Job 실패 이벤트 (jobName 생략)\n * @OnJobFailed()\n * async onAnyJobFailed(event: JobFailedEvent) {\n * this.logger.error(`Job 실패: ${event.jobName}`, event.error);\n * }\n * }\n * ```\n */\nexport function OnJobFailed(jobName?: string): MethodDecorator {\n return (\n target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor,\n ): PropertyDescriptor => {\n // jobName이 undefined면 빈 문자열로 저장 (모든 Job에 대해 호출)\n SetMetadata(ON_JOB_FAILED_METADATA_KEY, jobName ?? '')(target, propertyKey, descriptor);\n return descriptor;\n };\n}\n\n/**\n * Job 실패 이벤트 데이터\n */\nexport interface JobFailedEvent {\n /** Job 이름 */\n jobName: string;\n\n /** Job 실행 인자 */\n args: unknown[];\n\n /** 발생한 에러 */\n error: Error;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/constants.ts","../src/core/sidequest.adapter.ts","../src/services/sidequest-engine.service.ts","../src/services/queue-registry.service.ts","../src/services/cls-integration.service.ts","../src/services/processor-registry.service.ts","../src/explorers/processor.explorer.ts","../src/modules/sidequest.module.ts","../src/decorators/processor.decorator.ts","../src/decorators/on-job.decorator.ts","../src/decorators/retry.decorator.ts","../src/decorators/inject-queue.decorator.ts","../src/decorators/on-job-complete.decorator.ts","../src/decorators/on-job-failed.decorator.ts"],"names":["SIDEQUEST_MODULE_OPTIONS","Symbol","SIDEQUEST_ENGINE","PROCESSOR_METADATA_KEY","ON_JOB_METADATA_KEY","RETRY_OPTIONS_METADATA_KEY","ON_JOB_COMPLETE_METADATA_KEY","ON_JOB_FAILED_METADATA_KEY","QUEUE_TOKEN_PREFIX","getQueueToken","queueName","DEFAULT_QUEUE_NAME","DEFAULT_MAX_ATTEMPTS","DEFAULT_TIMEOUT","DEFAULT_CONCURRENCY","SidequestAdapter","logger","Logger","name","isStarted","registeredJobs","Map","start","options","warn","log","config","backend","driver","queues","map","q","concurrency","priority","state","maxConcurrentJobs","undefined","minThreads","maxThreads","jobPollingInterval","releaseStaleJobsIntervalMin","cleanupFinishedJobsIntervalMin","level","json","dashboard","Sidequest","error","shutdown","stop","registerJob","jobName","JobClass","set","debug","addJob","args","get","Error","builder","build","queue","maxAttempts","timeout","scheduledAt","availableAt","retryDelay","backoffStrategy","uniqueKey","unique","jobData","enqueue","jobId","String","id","Date","now","addBulkJobs","jobs","jobIds","push","getJob","numericId","parseInt","isNaN","job","attempt","max_attempts","insertedAt","inserted_at","attemptedAt","attempted_at","completedAt","completed_at","result","errors","started","getRegisteredJob","getAllRegisteredJobs","SidequestEngineService","adapter","onModuleInit","onModuleDestroy","gracefulShutdown","enabled","getAdapter","QueueRegistryService","queueServices","initializeQueues","queueConfig","registerQueue","has","queueService","createQueueService","getQueue","getQueueOrThrow","getAllQueues","add","addWithOptions","addScheduled","addBulk","bulkJobs","ClsIntegrationService","clsService","enableCls","runInContext","metadata","callback","Promise","resolve","reject","run","key","value","Object","entries","then","catch","getTraceId","setTraceId","traceId","isEnabled","ProcessorRegistryService","processors","register","processor","metatype","getProcessor","getAllProcessors","getJobHandler","handlers","getCompleteHandler","completeHandlers","getFailedHandler","failedHandlers","dispatch","handler","instance","method","methodName","executeJob","apply","completeHandlerName","completeHandler","failedHandlerName","failedHandler","ProcessorExplorer","discoveryService","metadataScanner","reflector","processorRegistry","explore","providers","getProviders","wrapper","processWrapper","processorMetadata","scanHandlers","scanCompleteHandlers","scanFailedHandlers","registeredProcessor","size","_metatype","prototype","getPrototypeOf","methodNames","getAllMethodNames","methodRef","onJobMetadata","retryOptions","SidequestModule","forRoot","isGlobal","queueProviders","createQueueProviders","module","global","imports","DiscoveryModule","provide","useValue","exports","p","forRootAsync","asyncOptions","createAsyncProviders","useFactory","inject","registry","useClass","optionsFactory","createSidequestOptions","useExisting","Processor","target","SetMetadata","Injectable","OnJob","propertyKey","descriptor","Retry","InjectQueue","Inject","OnJobComplete","OnJobFailed"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * SidequestModule 상수\n */\n\n// DI 토큰\nexport const SIDEQUEST_MODULE_OPTIONS = Symbol('SIDEQUEST_MODULE_OPTIONS');\nexport const SIDEQUEST_ENGINE = Symbol('SIDEQUEST_ENGINE');\n\n// 메타데이터 키\nexport const PROCESSOR_METADATA_KEY = Symbol('sidequest:processor');\nexport const ON_JOB_METADATA_KEY = Symbol('sidequest:on-job');\nexport const RETRY_OPTIONS_METADATA_KEY = Symbol('sidequest:retry');\nexport const ON_JOB_COMPLETE_METADATA_KEY = Symbol('sidequest:on-job-complete');\nexport const ON_JOB_FAILED_METADATA_KEY = Symbol('sidequest:on-job-failed');\n\n// Queue 토큰 프리픽스\nexport const QUEUE_TOKEN_PREFIX = 'SIDEQUEST_QUEUE_';\n\n/**\n * Queue DI 토큰 생성\n */\nexport function getQueueToken(queueName: string): string {\n return `${QUEUE_TOKEN_PREFIX}${queueName}`;\n}\n\n// 기본값\nexport const DEFAULT_QUEUE_NAME = 'default';\nexport const DEFAULT_MAX_ATTEMPTS = 3;\nexport const DEFAULT_TIMEOUT = 30000;\nexport const DEFAULT_CONCURRENCY = 10;\n\n// Log messages\nexport const LOG_MESSAGES = {\n ENGINE_STARTING: 'Starting Sidequest engine...',\n ENGINE_STARTED: 'Sidequest engine started',\n ENGINE_STOPPING: 'Stopping Sidequest engine...',\n ENGINE_STOPPED: 'Sidequest engine stopped',\n QUEUE_REGISTERED: (name: string) => `Queue '${name}' registered`,\n PROCESSOR_REGISTERED: (name: string) => `Processor '${name}' registered`,\n JOB_HANDLER_REGISTERED: (jobName: string, queueName: string) =>\n `Job handler '${jobName}' (Queue: ${queueName}) registered`,\n} as const;\n","import {Injectable, Logger} from '@nestjs/common';\nimport {Sidequest, Job, JobBuilder} from 'sidequest';\nimport type {SidequestModuleOptions} from '../interfaces/module-options.interface.js';\nimport type {JobAddOptions, JobInfo, JobState, ErrorData} from '../interfaces/queue.interface.js';\n\n// Job 클래스 타입\ntype JobClassType = new (...args: unknown[]) => Job;\n\n/**\n * Sidequest.js API Adapter\n *\n * Sidequest.js의 API를 NestJS와 통합합니다.\n * 실제 sidequest 패키지를 사용하여 Job 처리를 수행합니다.\n */\n@Injectable()\nexport class SidequestAdapter {\n private readonly logger = new Logger(SidequestAdapter.name);\n private isStarted = false;\n private readonly registeredJobs = new Map<string, JobClassType>();\n\n /**\n * Sidequest 엔진 시작\n */\n async start(options: SidequestModuleOptions): Promise<void> {\n if (this.isStarted) {\n this.logger.warn('Sidequest engine is already started');\n return;\n }\n\n this.logger.log('Starting Sidequest engine...');\n\n try {\n // Sidequest 설정 구성\n const config: Record<string, unknown> = {\n backend: {\n driver: options.backend.driver,\n config: options.backend.config,\n },\n };\n\n // 큐 설정\n if (options.queues) {\n config.queues = options.queues.map(q => ({\n name: q.name,\n concurrency: q.concurrency,\n priority: q.priority,\n state: q.state,\n }));\n }\n\n // 엔진 설정\n if (options.maxConcurrentJobs !== undefined) {\n config.maxConcurrentJobs = options.maxConcurrentJobs;\n }\n if (options.minThreads !== undefined) {\n config.minThreads = options.minThreads;\n }\n if (options.maxThreads !== undefined) {\n config.maxThreads = options.maxThreads;\n }\n if (options.jobPollingInterval !== undefined) {\n config.jobPollingInterval = options.jobPollingInterval;\n }\n if (options.releaseStaleJobsIntervalMin !== undefined) {\n config.releaseStaleJobsIntervalMin = options.releaseStaleJobsIntervalMin;\n }\n if (options.cleanupFinishedJobsIntervalMin !== undefined) {\n config.cleanupFinishedJobsIntervalMin = options.cleanupFinishedJobsIntervalMin;\n }\n\n // 로거 설정\n if (options.logger) {\n config.logger = {\n level: options.logger.level ?? 'info',\n json: options.logger.json ?? false,\n };\n }\n\n // 대시보드 설정\n if (options.dashboard) {\n config.dashboard = options.dashboard;\n }\n\n // Sidequest 엔진 시작\n await Sidequest.start(config as Parameters<typeof Sidequest.start>[0]);\n\n this.isStarted = true;\n this.logger.log('Sidequest engine started');\n } catch (error) {\n this.logger.error('Failed to start Sidequest engine', error);\n throw error;\n }\n }\n\n /**\n * Sidequest 엔진 종료\n */\n async shutdown(): Promise<void> {\n if (!this.isStarted) {\n return;\n }\n\n this.logger.log('Stopping Sidequest engine...');\n\n try {\n await Sidequest.stop();\n this.isStarted = false;\n this.logger.log('Sidequest engine stopped');\n } catch (error) {\n this.logger.error('Failed to stop Sidequest engine', error);\n throw error;\n }\n }\n\n /**\n * Job 클래스 등록\n */\n registerJob(jobName: string, JobClass: JobClassType): void {\n this.registeredJobs.set(jobName, JobClass);\n this.logger.debug(`Job '${jobName}' registered`);\n }\n\n /**\n * Job 추가\n */\n async addJob(\n queueName: string,\n jobName: string,\n args: unknown[],\n options?: JobAddOptions,\n ): Promise<string> {\n const JobClass = this.registeredJobs.get(jobName);\n if (!JobClass) {\n throw new Error(`Job class '${jobName}' not found. Make sure it's registered.`);\n }\n\n let builder: JobBuilder<JobClassType> = Sidequest.build(JobClass).queue(queueName);\n\n // 옵션 적용\n if (options?.maxAttempts !== undefined) {\n builder = builder.maxAttempts(options.maxAttempts);\n }\n if (options?.timeout !== undefined) {\n builder = builder.timeout(options.timeout);\n }\n if (options?.priority !== undefined) {\n // priority는 queue 레벨에서 설정됨\n }\n if (options?.scheduledAt !== undefined) {\n builder = builder.availableAt(options.scheduledAt);\n }\n if (options?.retryDelay !== undefined) {\n builder = builder.retryDelay(options.retryDelay);\n }\n if (options?.backoffStrategy !== undefined) {\n builder = builder.backoffStrategy(options.backoffStrategy);\n }\n if (options?.uniqueKey !== undefined) {\n builder = builder.unique(true);\n }\n\n // Job 실행 (enqueue)\n const jobData = await builder.enqueue(...args);\n const jobId = String(jobData?.id ?? `job_${Date.now()}`);\n\n this.logger.debug(`Job '${jobName}' (ID: ${jobId}) added to Queue '${queueName}'`);\n\n return jobId;\n }\n\n /**\n * Bulk Job 추가\n */\n async addBulkJobs(\n queueName: string,\n jobs: Array<{jobName: string; args: unknown[]; options?: JobAddOptions}>,\n ): Promise<string[]> {\n const jobIds: string[] = [];\n\n for (const {jobName, args, options} of jobs) {\n const jobId = await this.addJob(queueName, jobName, args, options);\n jobIds.push(jobId);\n }\n\n return jobIds;\n }\n\n /**\n * Job 조회\n */\n async getJob(jobId: string | number): Promise<JobInfo | undefined> {\n try {\n const numericId = typeof jobId === 'string' ? parseInt(jobId, 10) : jobId;\n if (isNaN(numericId)) {\n return undefined;\n }\n\n const job = await Sidequest.job.get(numericId);\n if (!job) {\n return undefined;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const jobData = job as any;\n\n return {\n id: String(job.id),\n name: jobData.name as string | undefined,\n queue: job.queue,\n state: job.state as JobState,\n attempt: job.attempt,\n maxAttempts: job.max_attempts,\n insertedAt: job.inserted_at,\n attemptedAt: job.attempted_at ?? undefined,\n completedAt: job.completed_at ?? undefined,\n result: job.result,\n errors: job.errors as ErrorData[] | null | undefined,\n };\n } catch {\n return undefined;\n }\n }\n\n /**\n * 엔진 시작 여부\n */\n get started(): boolean {\n return this.isStarted;\n }\n\n /**\n * 등록된 Job 클래스 반환\n */\n getRegisteredJob(jobName: string): JobClassType | undefined {\n return this.registeredJobs.get(jobName);\n }\n\n /**\n * 모든 등록된 Job 클래스 반환\n */\n getAllRegisteredJobs(): Map<string, JobClassType> {\n return this.registeredJobs;\n }\n}\n\n// Job 베이스 클래스 re-export\nexport {Job} from 'sidequest';\n","import {Inject, Injectable, Logger, OnModuleDestroy, OnModuleInit} from '@nestjs/common';\nimport {SIDEQUEST_MODULE_OPTIONS} from '../constants.js';\nimport {SidequestAdapter} from '../core/sidequest.adapter.js';\nimport type {SidequestModuleOptions} from '../interfaces/module-options.interface.js';\n\n/**\n * Sidequest 엔진 관리 서비스\n *\n * Sidequest.js 엔진의 라이프사이클을 관리합니다.\n * 모듈 초기화 시 엔진을 시작하고, 종료 시 graceful shutdown을 수행합니다.\n */\n@Injectable()\nexport class SidequestEngineService implements OnModuleInit, OnModuleDestroy {\n private readonly logger = new Logger(SidequestEngineService.name);\n\n constructor(\n @Inject(SIDEQUEST_MODULE_OPTIONS)\n private readonly options: SidequestModuleOptions,\n private readonly adapter: SidequestAdapter,\n ) {}\n\n /**\n * 모듈 초기화 시 엔진 시작\n */\n async onModuleInit(): Promise<void> {\n this.logger.log('Initializing Sidequest engine...');\n await this.adapter.start(this.options);\n this.logger.log('Sidequest engine initialized');\n }\n\n /**\n * 모듈 종료 시 엔진 종료\n */\n async onModuleDestroy(): Promise<void> {\n const gracefulShutdown = this.options.gracefulShutdown ?? {enabled: true, timeout: 30000};\n\n if (gracefulShutdown.enabled) {\n this.logger.log(\n `Sidequest engine graceful shutdown (timeout: ${gracefulShutdown.timeout}ms)`,\n );\n }\n\n await this.adapter.shutdown();\n this.logger.log('Sidequest engine stopped');\n }\n\n /**\n * 엔진 시작 여부\n */\n get isStarted(): boolean {\n return this.adapter.started;\n }\n\n /**\n * Adapter 인스턴스 반환\n */\n getAdapter(): SidequestAdapter {\n return this.adapter;\n }\n}\n","import {Inject, Injectable, Logger} from '@nestjs/common';\nimport {SIDEQUEST_MODULE_OPTIONS} from '../constants.js';\nimport {SidequestAdapter} from '../core/sidequest.adapter.js';\nimport type {SidequestModuleOptions, QueueConfig} from '../interfaces/module-options.interface.js';\nimport type {IQueueService, JobAddOptions} from '../interfaces/queue.interface.js';\n\n/**\n * Queue 레지스트리 서비스\n *\n * 큐 인스턴스를 관리하고 @InjectQueue()를 위한 DI 프로바이더를 제공합니다.\n */\n@Injectable()\nexport class QueueRegistryService {\n private readonly logger = new Logger(QueueRegistryService.name);\n private readonly queueServices = new Map<string, IQueueService>();\n\n constructor(\n @Inject(SIDEQUEST_MODULE_OPTIONS)\n private readonly options: SidequestModuleOptions,\n private readonly adapter: SidequestAdapter,\n ) {\n this.initializeQueues();\n }\n\n /**\n * 설정된 큐 초기화\n */\n private initializeQueues(): void {\n const queues = this.options.queues ?? [];\n\n for (const queueConfig of queues) {\n this.registerQueue(queueConfig);\n }\n\n // 기본 큐가 없으면 생성\n if (!this.queueServices.has('default')) {\n this.registerQueue({name: 'default'});\n }\n }\n\n /**\n * 큐 등록\n */\n registerQueue(config: QueueConfig): void {\n const queueService = this.createQueueService(config.name);\n this.queueServices.set(config.name, queueService);\n this.logger.log(`Queue '${config.name}' registered`);\n }\n\n /**\n * 큐 서비스 조회\n */\n getQueue(name: string): IQueueService | undefined {\n return this.queueServices.get(name);\n }\n\n /**\n * 큐 서비스 조회 (없으면 에러)\n */\n getQueueOrThrow(name: string): IQueueService {\n const queue = this.getQueue(name);\n if (!queue) {\n throw new Error(\n `Queue '${name}' not found. Make sure it is registered in SidequestModule.forRoot().`,\n );\n }\n return queue;\n }\n\n /**\n * 모든 큐 조회\n */\n getAllQueues(): Map<string, IQueueService> {\n return this.queueServices;\n }\n\n /**\n * 큐 서비스 인스턴스 생성\n */\n private createQueueService(queueName: string): IQueueService {\n const adapter = this.adapter;\n\n return {\n name: queueName,\n\n async add<T>(JobClass: new (...args: unknown[]) => T, ...args: unknown[]): Promise<string> {\n const jobName = JobClass.name;\n return adapter.addJob(queueName, jobName, args);\n },\n\n async addWithOptions<T>(\n JobClass: new (...args: unknown[]) => T,\n options: JobAddOptions,\n ...args: unknown[]\n ): Promise<string> {\n const jobName = JobClass.name;\n return adapter.addJob(queueName, jobName, args, options);\n },\n\n async addScheduled<T>(\n JobClass: new (...args: unknown[]) => T,\n scheduledAt: Date,\n ...args: unknown[]\n ): Promise<string> {\n const jobName = JobClass.name;\n return adapter.addJob(queueName, jobName, args, {scheduledAt});\n },\n\n async addBulk<T>(\n jobs: Array<{\n JobClass: new (...args: unknown[]) => T;\n args: unknown[];\n options?: JobAddOptions;\n }>,\n ): Promise<string[]> {\n const bulkJobs = jobs.map(job => {\n const result: {jobName: string; args: unknown[]; options?: JobAddOptions} = {\n jobName: job.JobClass.name,\n args: job.args,\n };\n if (job.options !== undefined) {\n result.options = job.options;\n }\n return result;\n });\n return adapter.addBulkJobs(queueName, bulkJobs);\n },\n };\n }\n}\n","import {Injectable, Logger, Optional, Inject} from '@nestjs/common';\nimport {SIDEQUEST_MODULE_OPTIONS} from '../constants.js';\nimport type {SidequestModuleOptions} from '../interfaces/module-options.interface.js';\n\n// nestjs-cls 타입 (optional dependency)\ninterface ClsService {\n getId(): string | undefined;\n get<T>(key: string): T | undefined;\n set<T>(key: string, value: T): void;\n run<T>(callback: () => T): T;\n}\n\n/**\n * CLS(Continuation Local Storage) 통합 서비스\n *\n * nestjs-cls가 설치되어 있을 경우 Job 실행 시 context를 전파합니다.\n * nestjs-cls가 없으면 no-op으로 동작합니다.\n */\n@Injectable()\nexport class ClsIntegrationService {\n private readonly logger = new Logger(ClsIntegrationService.name);\n private readonly enabled: boolean;\n private clsService: ClsService | null = null;\n\n constructor(\n @Inject(SIDEQUEST_MODULE_OPTIONS)\n options: SidequestModuleOptions,\n @Optional() @Inject('ClsService') clsService?: ClsService,\n ) {\n this.enabled = options.enableCls ?? false;\n this.clsService = clsService ?? null;\n\n if (this.enabled && !this.clsService) {\n this.logger.warn(\n 'CLS integration is enabled but nestjs-cls is not installed. ' +\n 'Install nestjs-cls to enable context propagation.',\n );\n }\n }\n\n /**\n * CLS context 내에서 콜백 실행\n */\n async runInContext<T>(metadata: Record<string, unknown>, callback: () => Promise<T>): Promise<T> {\n if (!this.enabled || !this.clsService) {\n return callback();\n }\n\n // nestjs-cls의 run 메서드를 사용하여 새 context에서 실행\n return new Promise((resolve, reject) => {\n try {\n this.clsService!.run(() => {\n // 메타데이터를 CLS에 설정\n for (const [key, value] of Object.entries(metadata)) {\n this.clsService!.set(key, value);\n }\n\n callback().then(resolve).catch(reject);\n });\n } catch (error) {\n reject(error);\n }\n });\n }\n\n /**\n * 현재 traceId 조회\n */\n getTraceId(): string | undefined {\n if (!this.enabled || !this.clsService) {\n return undefined;\n }\n\n return this.clsService.get<string>('traceId');\n }\n\n /**\n * traceId 설정\n */\n setTraceId(traceId: string): void {\n if (!this.enabled || !this.clsService) {\n return;\n }\n\n this.clsService.set('traceId', traceId);\n }\n\n /**\n * CLS에서 값 조회\n */\n get<T>(key: string): T | undefined {\n if (!this.enabled || !this.clsService) {\n return undefined;\n }\n\n return this.clsService.get<T>(key);\n }\n\n /**\n * CLS에 값 설정\n */\n set<T>(key: string, value: T): void {\n if (!this.enabled || !this.clsService) {\n return;\n }\n\n this.clsService.set(key, value);\n }\n\n /**\n * CLS 통합 활성화 여부\n */\n isEnabled(): boolean {\n return this.enabled && this.clsService !== null;\n }\n}\n","import {Injectable, Logger, Optional} from '@nestjs/common';\nimport type {RegisteredProcessor, RegisteredHandler} from '../interfaces/processor.interface.js';\nimport {ClsIntegrationService} from './cls-integration.service.js';\n\n/**\n * Processor 레지스트리 서비스\n *\n * @Processor 데코레이터로 등록된 프로세서와 핸들러를 관리합니다.\n */\n@Injectable()\nexport class ProcessorRegistryService {\n private readonly logger = new Logger(ProcessorRegistryService.name);\n private readonly processors = new Map<string, RegisteredProcessor>();\n\n constructor(@Optional() private readonly clsService?: ClsIntegrationService) {}\n\n /**\n * 프로세서 등록\n */\n register(processor: RegisteredProcessor): void {\n this.processors.set(processor.queueName, processor);\n this.logger.log(\n `Processor '${processor.metatype.name}' (Queue: ${processor.queueName}) registered`,\n );\n }\n\n /**\n * 프로세서 조회\n */\n getProcessor(queueName: string): RegisteredProcessor | undefined {\n return this.processors.get(queueName);\n }\n\n /**\n * 모든 프로세서 조회\n */\n getAllProcessors(): Map<string, RegisteredProcessor> {\n return this.processors;\n }\n\n /**\n * Job 핸들러 조회\n */\n getJobHandler(queueName: string, jobName: string): RegisteredHandler | undefined {\n const processor = this.processors.get(queueName);\n if (!processor) {\n return undefined;\n }\n return processor.handlers.get(jobName);\n }\n\n /**\n * Job 완료 핸들러 조회\n */\n getCompleteHandler(queueName: string, jobName: string): string | undefined {\n const processor = this.processors.get(queueName);\n if (!processor) {\n return undefined;\n }\n return processor.completeHandlers.get(jobName) ?? processor.completeHandlers.get('*');\n }\n\n /**\n * Job 실패 핸들러 조회\n */\n getFailedHandler(queueName: string, jobName: string): string | undefined {\n const processor = this.processors.get(queueName);\n if (!processor) {\n return undefined;\n }\n return processor.failedHandlers.get(jobName) ?? processor.failedHandlers.get('*');\n }\n\n /**\n * Job 디스패치 (실행)\n *\n * @param queueName - 큐 이름\n * @param jobName - Job 이름\n * @param args - Job 인자\n * @param metadata - Job 메타데이터 (traceId 등)\n */\n async dispatch(\n queueName: string,\n jobName: string,\n args: unknown[],\n metadata?: Record<string, unknown>,\n ): Promise<unknown> {\n const processor = this.processors.get(queueName);\n if (!processor) {\n throw new Error(`Processor not found for Queue '${queueName}'`);\n }\n\n const handler = processor.handlers.get(jobName);\n if (!handler) {\n throw new Error(`Handler not found for Job '${jobName}' (Queue: ${queueName})`);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n const instance = processor.instance as Record<string, Function>;\n const method = instance[handler.methodName];\n\n if (typeof method !== 'function') {\n throw new Error(`Handler method '${handler.methodName}' not found`);\n }\n\n // CLS context에서 실행\n const executeJob = async (): Promise<unknown> => {\n try {\n const result = await method.apply(processor.instance, args);\n\n // 완료 핸들러 호출\n const completeHandlerName = this.getCompleteHandler(queueName, jobName);\n if (completeHandlerName) {\n const completeHandler = instance[completeHandlerName];\n if (typeof completeHandler === 'function') {\n await completeHandler.apply(processor.instance, [{jobName, args, result}]);\n }\n }\n\n return result;\n } catch (error) {\n // 실패 핸들러 호출\n const failedHandlerName = this.getFailedHandler(queueName, jobName);\n if (failedHandlerName) {\n const failedHandler = instance[failedHandlerName];\n if (typeof failedHandler === 'function') {\n await failedHandler.apply(processor.instance, [{jobName, args, error}]);\n }\n }\n\n throw error;\n }\n };\n\n // CLS 통합이 활성화되어 있으면 context 내에서 실행\n if (this.clsService?.isEnabled() && metadata) {\n return this.clsService.runInContext(metadata, executeJob);\n }\n\n return executeJob();\n }\n}\n","import {Injectable, Logger, OnModuleInit} from '@nestjs/common';\nimport {DiscoveryService, MetadataScanner, Reflector} from '@nestjs/core';\nimport {InstanceWrapper} from '@nestjs/core/injector/instance-wrapper';\nimport {\n PROCESSOR_METADATA_KEY,\n ON_JOB_METADATA_KEY,\n RETRY_OPTIONS_METADATA_KEY,\n ON_JOB_COMPLETE_METADATA_KEY,\n ON_JOB_FAILED_METADATA_KEY,\n} from '../constants.js';\nimport {ProcessorRegistryService} from '../services/processor-registry.service.js';\nimport type {\n ProcessorMetadata,\n OnJobMetadata,\n RetryOptions,\n RegisteredHandler,\n RegisteredProcessor,\n} from '../interfaces/processor.interface.js';\n\n/**\n * Processor Explorer\n *\n * 애플리케이션 시작 시 @Processor 데코레이터가 붙은 클래스를 스캔하고,\n * @OnJob, @Retry, @OnJobComplete, @OnJobFailed 메타데이터를 수집하여\n * ProcessorRegistry에 등록합니다.\n */\n@Injectable()\nexport class ProcessorExplorer implements OnModuleInit {\n private readonly logger = new Logger(ProcessorExplorer.name);\n\n constructor(\n private readonly discoveryService: DiscoveryService,\n private readonly metadataScanner: MetadataScanner,\n private readonly reflector: Reflector,\n private readonly processorRegistry: ProcessorRegistryService,\n ) {}\n\n /**\n * 모듈 초기화 시 프로세서 스캔\n */\n async onModuleInit(): Promise<void> {\n this.logger.log('Scanning for processors...');\n await this.explore();\n this.logger.log('Processor scan completed');\n }\n\n /**\n * 모든 프로바이더를 스캔하여 @Processor 클래스 찾기\n */\n async explore(): Promise<void> {\n const providers = this.discoveryService.getProviders();\n\n for (const wrapper of providers) {\n await this.processWrapper(wrapper);\n }\n }\n\n /**\n * 프로바이더 래퍼 처리\n */\n private async processWrapper(wrapper: InstanceWrapper): Promise<void> {\n const {instance, metatype} = wrapper;\n\n // 인스턴스와 메타타입이 없으면 스킵\n if (!instance || !metatype) {\n return;\n }\n\n // @Processor 메타데이터 확인\n const processorMetadata = this.reflector.get<ProcessorMetadata>(\n PROCESSOR_METADATA_KEY,\n metatype,\n );\n\n if (!processorMetadata) {\n return;\n }\n\n // 핸들러 스캔\n const handlers = this.scanHandlers(instance, metatype);\n const completeHandlers = this.scanCompleteHandlers(instance, metatype);\n const failedHandlers = this.scanFailedHandlers(instance, metatype);\n\n // 프로세서 등록\n const registeredProcessor: RegisteredProcessor = {\n queueName: processorMetadata.queueName,\n instance,\n metatype,\n handlers,\n completeHandlers,\n failedHandlers,\n };\n\n this.processorRegistry.register(registeredProcessor);\n\n this.logger.log(\n `Processor '${metatype.name}' registered (Queue: ${processorMetadata.queueName}, Handlers: ${handlers.size})`,\n );\n }\n\n /**\n * @OnJob 메서드 스캔\n */\n private scanHandlers(instance: unknown, _metatype: object): Map<string, RegisteredHandler> {\n const handlers = new Map<string, RegisteredHandler>();\n const prototype = Object.getPrototypeOf(instance);\n const methodNames = this.metadataScanner.getAllMethodNames(prototype);\n\n for (const methodName of methodNames) {\n const methodRef = prototype[methodName];\n\n // @OnJob 메타데이터 확인\n const onJobMetadata = this.reflector.get<OnJobMetadata>(ON_JOB_METADATA_KEY, methodRef);\n\n if (!onJobMetadata) {\n continue;\n }\n\n // @Retry 메타데이터 확인\n const retryOptions = this.reflector.get<RetryOptions>(RETRY_OPTIONS_METADATA_KEY, methodRef);\n\n const handler: RegisteredHandler = {\n methodName,\n jobName: onJobMetadata.jobName,\n options: onJobMetadata.options,\n retryOptions,\n };\n\n handlers.set(onJobMetadata.jobName, handler);\n\n this.logger.debug(` - Job '${onJobMetadata.jobName}' -> ${methodName}()`);\n }\n\n return handlers;\n }\n\n /**\n * @OnJobComplete 메서드 스캔\n */\n private scanCompleteHandlers(instance: unknown, _metatype: object): Map<string, string> {\n const handlers = new Map<string, string>();\n const prototype = Object.getPrototypeOf(instance);\n const methodNames = this.metadataScanner.getAllMethodNames(prototype);\n\n for (const methodName of methodNames) {\n const methodRef = prototype[methodName];\n\n // @OnJobComplete 메타데이터 확인\n const jobName = this.reflector.get<string | undefined>(\n ON_JOB_COMPLETE_METADATA_KEY,\n methodRef,\n );\n\n if (jobName !== undefined) {\n // jobName이 빈 문자열이면 모든 Job에 대해 호출 ('*')\n const key = jobName || '*';\n handlers.set(key, methodName);\n this.logger.debug(` - OnJobComplete '${key}' -> ${methodName}()`);\n }\n }\n\n return handlers;\n }\n\n /**\n * @OnJobFailed 메서드 스캔\n */\n private scanFailedHandlers(instance: unknown, _metatype: object): Map<string, string> {\n const handlers = new Map<string, string>();\n const prototype = Object.getPrototypeOf(instance);\n const methodNames = this.metadataScanner.getAllMethodNames(prototype);\n\n for (const methodName of methodNames) {\n const methodRef = prototype[methodName];\n\n // @OnJobFailed 메타데이터 확인\n const jobName = this.reflector.get<string | undefined>(ON_JOB_FAILED_METADATA_KEY, methodRef);\n\n if (jobName !== undefined) {\n // jobName이 빈 문자열이면 모든 Job에 대해 호출 ('*')\n const key = jobName || '*';\n handlers.set(key, methodName);\n this.logger.debug(` - OnJobFailed '${key}' -> ${methodName}()`);\n }\n }\n\n return handlers;\n }\n}\n","import {DynamicModule, Global, Module, Provider} from '@nestjs/common';\nimport {DiscoveryModule} from '@nestjs/core';\nimport {SIDEQUEST_MODULE_OPTIONS, getQueueToken} from '../constants.js';\nimport {SidequestAdapter} from '../core/sidequest.adapter.js';\nimport type {\n SidequestModuleOptions,\n SidequestModuleAsyncOptions,\n SidequestOptionsFactory,\n} from '../interfaces/module-options.interface.js';\nimport {SidequestEngineService} from '../services/sidequest-engine.service.js';\nimport {QueueRegistryService} from '../services/queue-registry.service.js';\nimport {ProcessorRegistryService} from '../services/processor-registry.service.js';\nimport {ClsIntegrationService} from '../services/cls-integration.service.js';\nimport {ProcessorExplorer} from '../explorers/processor.explorer.js';\n\n/**\n * SidequestModule\n *\n * NestJS에서 Sidequest.js를 사용하기 위한 메인 모듈입니다.\n *\n * @example\n * ```typescript\n * // 동기 설정\n * @Module({\n * imports: [\n * SidequestModule.forRoot({\n * backend: {\n * driver: '@sidequest/postgres-backend',\n * config: process.env.DATABASE_URL,\n * },\n * queues: [\n * { name: 'email', concurrency: 5 },\n * { name: 'report', concurrency: 2 },\n * ],\n * }),\n * ],\n * })\n * export class AppModule {}\n *\n * // 비동기 설정 (ConfigService 사용)\n * @Module({\n * imports: [\n * SidequestModule.forRootAsync({\n * imports: [ConfigModule],\n * useFactory: (config: ConfigService) => ({\n * backend: {\n * driver: '@sidequest/postgres-backend',\n * config: config.get('DATABASE_URL'),\n * },\n * queues: [{ name: 'default' }],\n * }),\n * inject: [ConfigService],\n * }),\n * ],\n * })\n * export class AppModule {}\n * ```\n */\n@Global()\n@Module({})\nexport class SidequestModule {\n /**\n * 동기 설정으로 모듈 등록\n */\n static forRoot(options: SidequestModuleOptions): DynamicModule {\n const isGlobal = options.isGlobal ?? true;\n const queueProviders = this.createQueueProviders(options);\n\n return {\n module: SidequestModule,\n global: isGlobal,\n imports: [DiscoveryModule],\n providers: [\n {\n provide: SIDEQUEST_MODULE_OPTIONS,\n useValue: options,\n },\n SidequestAdapter,\n SidequestEngineService,\n QueueRegistryService,\n ProcessorRegistryService,\n ClsIntegrationService,\n ProcessorExplorer,\n ...queueProviders,\n ],\n exports: [\n SIDEQUEST_MODULE_OPTIONS,\n SidequestAdapter,\n SidequestEngineService,\n QueueRegistryService,\n ProcessorRegistryService,\n ClsIntegrationService,\n ...queueProviders.map(p => (p as {provide: symbol | string}).provide),\n ],\n };\n }\n\n /**\n * 비동기 설정으로 모듈 등록\n */\n static forRootAsync(asyncOptions: SidequestModuleAsyncOptions): DynamicModule {\n const isGlobal = asyncOptions.isGlobal ?? true;\n\n return {\n module: SidequestModule,\n global: isGlobal,\n imports: [DiscoveryModule, ...(asyncOptions.imports || [])],\n providers: [\n ...this.createAsyncProviders(asyncOptions),\n SidequestAdapter,\n SidequestEngineService,\n QueueRegistryService,\n ProcessorRegistryService,\n ClsIntegrationService,\n ProcessorExplorer,\n // 동적 큐 프로바이더 - options에서 queues를 읽어 생성\n {\n provide: 'SIDEQUEST_QUEUE_PROVIDERS_INIT',\n useFactory: () => {\n // QueueRegistryService가 자동으로 큐를 초기화하므로 별도 처리 불필요\n return true;\n },\n inject: [QueueRegistryService],\n },\n ],\n exports: [\n SIDEQUEST_MODULE_OPTIONS,\n SidequestAdapter,\n SidequestEngineService,\n QueueRegistryService,\n ProcessorRegistryService,\n ClsIntegrationService,\n ],\n };\n }\n\n /**\n * 큐별 DI 프로바이더 생성\n */\n private static createQueueProviders(options: SidequestModuleOptions): Provider[] {\n const queues = options.queues ?? [{name: 'default'}];\n\n return queues.map(queue => ({\n provide: getQueueToken(queue.name),\n useFactory: (registry: QueueRegistryService) => registry.getQueueOrThrow(queue.name),\n inject: [QueueRegistryService],\n }));\n }\n\n /**\n * 비동기 프로바이더 생성\n */\n private static createAsyncProviders(asyncOptions: SidequestModuleAsyncOptions): Provider[] {\n if (asyncOptions.useFactory) {\n return [\n {\n provide: SIDEQUEST_MODULE_OPTIONS,\n useFactory: asyncOptions.useFactory,\n inject: asyncOptions.inject || [],\n },\n ];\n }\n\n if (asyncOptions.useClass) {\n return [\n {\n provide: asyncOptions.useClass,\n useClass: asyncOptions.useClass,\n },\n {\n provide: SIDEQUEST_MODULE_OPTIONS,\n useFactory: async (optionsFactory: SidequestOptionsFactory) =>\n optionsFactory.createSidequestOptions(),\n inject: [asyncOptions.useClass],\n },\n ];\n }\n\n if (asyncOptions.useExisting) {\n return [\n {\n provide: SIDEQUEST_MODULE_OPTIONS,\n useFactory: async (optionsFactory: SidequestOptionsFactory) =>\n optionsFactory.createSidequestOptions(),\n inject: [asyncOptions.useExisting],\n },\n ];\n }\n\n return [\n {\n provide: SIDEQUEST_MODULE_OPTIONS,\n useValue: {},\n },\n ];\n }\n}\n","import {Injectable, SetMetadata} from '@nestjs/common';\nimport {PROCESSOR_METADATA_KEY} from '../constants.js';\nimport type {ProcessorOptions, ProcessorMetadata} from '../interfaces/processor.interface.js';\n\n/**\n * 클래스를 Sidequest Job Processor로 지정합니다.\n *\n * @Processor 데코레이터가 붙은 클래스는 모듈 초기화 시 자동으로 스캔되어\n * 해당 큐의 Job 핸들러로 등록됩니다.\n *\n * @param queueName - 처리할 큐 이름\n * @param options - 프로세서 옵션\n *\n * @example\n * ```typescript\n * @Processor('email')\n * export class EmailProcessor {\n * @OnJob('send-welcome-email')\n * async handleWelcomeEmail(job: JobContext) {\n * const { to, subject, body } = job.data;\n * await this.mailer.send({ to, subject, body });\n * }\n * }\n *\n * // 동시성 설정과 함께\n * @Processor('report', { concurrency: 2 })\n * export class ReportProcessor {\n * @OnJob('generate-daily-report')\n * async handleDailyReport(job: JobContext) {\n * // 리포트 생성 로직\n * }\n * }\n * ```\n */\nexport function Processor(queueName: string, options?: ProcessorOptions): ClassDecorator {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n return (target: Function): void => {\n const metadata: ProcessorMetadata = {\n queueName,\n options,\n };\n\n // 메타데이터 설정\n SetMetadata(PROCESSOR_METADATA_KEY, metadata)(target);\n\n // @Injectable() 자동 적용\n Injectable()(target);\n };\n}\n","import {SetMetadata} from '@nestjs/common';\nimport {ON_JOB_METADATA_KEY} from '../constants.js';\nimport type {OnJobOptions, OnJobMetadata} from '../interfaces/processor.interface.js';\n\n/**\n * 메서드를 특정 Job 타입의 핸들러로 지정합니다.\n *\n * @Processor 데코레이터가 붙은 클래스 내부에서 사용합니다.\n * 해당 Job이 큐에서 처리될 때 이 메서드가 호출됩니다.\n *\n * @param jobName - Job 이름 (일반적으로 Job 클래스명)\n * @param options - Job 실행 옵션 (우선순위, 타임아웃 등)\n *\n * @example\n * ```typescript\n * @Processor('email')\n * export class EmailProcessor {\n * @OnJob('SendWelcomeEmailJob')\n * async handleWelcomeEmail(job: JobContext) {\n * const { to, subject, body } = job.data;\n * await this.mailer.send({ to, subject, body });\n * }\n *\n * // 우선순위와 타임아웃 설정\n * @OnJob('SendPriorityEmailJob', { priority: 100, timeout: 5000 })\n * async handlePriorityEmail(job: JobContext) {\n * // 우선순위가 높은 이메일 처리\n * }\n * }\n * ```\n */\nexport function OnJob(jobName: string, options?: OnJobOptions): MethodDecorator {\n return (\n target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor,\n ): PropertyDescriptor => {\n const metadata: OnJobMetadata = {\n jobName,\n options,\n };\n\n SetMetadata(ON_JOB_METADATA_KEY, metadata)(target, propertyKey, descriptor);\n\n return descriptor;\n };\n}\n","import {SetMetadata} from '@nestjs/common';\nimport {RETRY_OPTIONS_METADATA_KEY} from '../constants.js';\nimport type {RetryOptions} from '../interfaces/processor.interface.js';\n\n/**\n * Job 재시도 정책을 설정합니다.\n *\n * @OnJob 데코레이터와 함께 사용하여 Job 실패 시 재시도 동작을 정의합니다.\n *\n * @param options - 재시도 옵션\n *\n * @example\n * ```typescript\n * @Processor('payment')\n * export class PaymentProcessor {\n * // 고정 지연 재시도\n * @OnJob('ProcessPaymentJob')\n * @Retry({ maxAttempts: 3, delay: 1000 })\n * async handlePayment(job: JobContext) {\n * // 결제 처리 로직\n * }\n *\n * // 지수 백오프 재시도\n * @OnJob('RefundJob')\n * @Retry({ maxAttempts: 5, delay: 500, backoff: 'exponential' })\n * async handleRefund(job: JobContext) {\n * // 환불 처리 로직\n * }\n * }\n * ```\n */\nexport function Retry(options: RetryOptions): MethodDecorator {\n return (\n target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor,\n ): PropertyDescriptor => {\n SetMetadata(RETRY_OPTIONS_METADATA_KEY, options)(target, propertyKey, descriptor);\n return descriptor;\n };\n}\n","import {Inject} from '@nestjs/common';\nimport {getQueueToken} from '../constants.js';\n\n/**\n * Queue 인스턴스를 주입합니다.\n *\n * SidequestModule.forRoot()에서 등록된 큐를 서비스에 주입받아 사용할 수 있습니다.\n *\n * @param queueName - 주입받을 큐 이름\n *\n * @example\n * ```typescript\n * @Injectable()\n * export class UserService {\n * constructor(\n * @InjectQueue('email') private emailQueue: IQueueService,\n * @InjectQueue('notification') private notificationQueue: IQueueService,\n * ) {}\n *\n * async createUser(email: string, name: string) {\n * // 사용자 생성 로직...\n *\n * // 환영 이메일 발송\n * await this.emailQueue.add(SendWelcomeEmailJob, email, `Welcome, ${name}!`);\n *\n * // 알림 발송\n * await this.notificationQueue.add(SendNotificationJob, email, 'new-user');\n * }\n * }\n * ```\n */\nexport function InjectQueue(queueName: string): ParameterDecorator {\n return Inject(getQueueToken(queueName));\n}\n","import {SetMetadata} from '@nestjs/common';\nimport {ON_JOB_COMPLETE_METADATA_KEY} from '../constants.js';\n\n/**\n * Job 완료 이벤트 핸들러를 지정합니다.\n *\n * @Processor 클래스 내부에서 사용하며, Job이 성공적으로 완료되면 호출됩니다.\n *\n * @param jobName - 대상 Job 이름 (생략 시 모든 Job에 대해 호출)\n *\n * @example\n * ```typescript\n * @Processor('email')\n * export class EmailProcessor {\n * @OnJob('SendWelcomeEmailJob')\n * async handleWelcomeEmail(job: JobContext) {\n * await this.mailer.send(job.data);\n * }\n *\n * // 특정 Job 완료 이벤트\n * @OnJobComplete('SendWelcomeEmailJob')\n * async onWelcomeEmailComplete(event: JobCompleteEvent) {\n * this.logger.log(`환영 이메일 발송 완료: ${event.result}`);\n * await this.analytics.track('email_sent', { type: 'welcome' });\n * }\n *\n * // 모든 Job 완료 이벤트 (jobName 생략)\n * @OnJobComplete()\n * async onAnyJobComplete(event: JobCompleteEvent) {\n * this.logger.log(`Job 완료: ${event.jobName}`);\n * }\n * }\n * ```\n */\nexport function OnJobComplete(jobName?: string): MethodDecorator {\n return (\n target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor,\n ): PropertyDescriptor => {\n // jobName이 undefined면 빈 문자열로 저장 (모든 Job에 대해 호출)\n SetMetadata(ON_JOB_COMPLETE_METADATA_KEY, jobName ?? '')(target, propertyKey, descriptor);\n return descriptor;\n };\n}\n\n/**\n * Job 완료 이벤트 데이터\n */\nexport interface JobCompleteEvent {\n /** Job 이름 */\n jobName: string;\n\n /** Job 실행 인자 */\n args: unknown[];\n\n /** Job 실행 결과 */\n result: unknown;\n}\n","import {SetMetadata} from '@nestjs/common';\nimport {ON_JOB_FAILED_METADATA_KEY} from '../constants.js';\n\n/**\n * Job 실패 이벤트 핸들러를 지정합니다.\n *\n * @Processor 클래스 내부에서 사용하며, Job 실행이 실패하면 호출됩니다.\n * 재시도 횟수를 모두 소진한 후 최종 실패 시에만 호출됩니다.\n *\n * @param jobName - 대상 Job 이름 (생략 시 모든 Job에 대해 호출)\n *\n * @example\n * ```typescript\n * @Processor('payment')\n * export class PaymentProcessor {\n * @OnJob('ProcessPaymentJob')\n * @Retry({ maxAttempts: 3 })\n * async handlePayment(job: JobContext) {\n * await this.paymentService.process(job.data);\n * }\n *\n * // 특정 Job 실패 이벤트\n * @OnJobFailed('ProcessPaymentJob')\n * async onPaymentFailed(event: JobFailedEvent) {\n * this.logger.error(`결제 처리 실패: ${event.error.message}`);\n * await this.alertService.notify('payment-failure', {\n * orderId: event.args[0],\n * error: event.error.message,\n * });\n * }\n *\n * // 모든 Job 실패 이벤트 (jobName 생략)\n * @OnJobFailed()\n * async onAnyJobFailed(event: JobFailedEvent) {\n * this.logger.error(`Job 실패: ${event.jobName}`, event.error);\n * }\n * }\n * ```\n */\nexport function OnJobFailed(jobName?: string): MethodDecorator {\n return (\n target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor,\n ): PropertyDescriptor => {\n // jobName이 undefined면 빈 문자열로 저장 (모든 Job에 대해 호출)\n SetMetadata(ON_JOB_FAILED_METADATA_KEY, jobName ?? '')(target, propertyKey, descriptor);\n return descriptor;\n };\n}\n\n/**\n * Job 실패 이벤트 데이터\n */\nexport interface JobFailedEvent {\n /** Job 이름 */\n jobName: string;\n\n /** Job 실행 인자 */\n args: unknown[];\n\n /** 발생한 에러 */\n error: Error;\n}\n"]}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/constants.ts","../src/core/sidequest.adapter.ts","../src/services/sidequest-engine.service.ts","../src/services/queue-registry.service.ts","../src/services/cls-integration.service.ts","../src/services/processor-registry.service.ts","../src/explorers/processor.explorer.ts","../src/modules/sidequest.module.ts","../src/decorators/processor.decorator.ts","../src/decorators/on-job.decorator.ts","../src/decorators/retry.decorator.ts","../src/decorators/inject-queue.decorator.ts","../src/decorators/on-job-complete.decorator.ts","../src/decorators/on-job-failed.decorator.ts"],"names":["SIDEQUEST_MODULE_OPTIONS","Symbol","SIDEQUEST_ENGINE","PROCESSOR_METADATA_KEY","ON_JOB_METADATA_KEY","RETRY_OPTIONS_METADATA_KEY","ON_JOB_COMPLETE_METADATA_KEY","ON_JOB_FAILED_METADATA_KEY","QUEUE_TOKEN_PREFIX","getQueueToken","queueName","DEFAULT_QUEUE_NAME","DEFAULT_MAX_ATTEMPTS","DEFAULT_TIMEOUT","DEFAULT_CONCURRENCY","SidequestAdapter","logger","Logger","name","isStarted","registeredJobs","Map","start","options","warn","log","config","backend","driver","queues","map","q","concurrency","priority","state","maxConcurrentJobs","undefined","minThreads","maxThreads","jobPollingInterval","releaseStaleJobsIntervalMin","cleanupFinishedJobsIntervalMin","level","json","dashboard","Sidequest","error","shutdown","stop","registerJob","jobName","JobClass","set","debug","addJob","args","get","Error","builder","build","queue","maxAttempts","timeout","scheduledAt","availableAt","retryDelay","backoffStrategy","uniqueKey","unique","jobData","enqueue","jobId","String","id","Date","now","addBulkJobs","jobs","jobIds","push","getJob","numericId","parseInt","isNaN","job","attempt","max_attempts","insertedAt","inserted_at","attemptedAt","attempted_at","completedAt","completed_at","result","errors","started","getRegisteredJob","getAllRegisteredJobs","SidequestEngineService","adapter","onModuleInit","onModuleDestroy","gracefulShutdown","enabled","getAdapter","QueueRegistryService","queueServices","initializeQueues","queueConfig","registerQueue","has","queueService","createQueueService","getQueue","getQueueOrThrow","getAllQueues","add","addWithOptions","addScheduled","addBulk","bulkJobs","ClsIntegrationService","clsService","enableCls","runInContext","metadata","callback","Promise","resolve","reject","run","key","value","Object","entries","then","catch","getTraceId","setTraceId","traceId","isEnabled","ProcessorRegistryService","processors","register","processor","metatype","getProcessor","getAllProcessors","getJobHandler","handlers","getCompleteHandler","completeHandlers","getFailedHandler","failedHandlers","dispatch","handler","instance","method","methodName","executeJob","apply","completeHandlerName","completeHandler","failedHandlerName","failedHandler","ProcessorExplorer","discoveryService","metadataScanner","reflector","processorRegistry","explore","providers","getProviders","wrapper","processWrapper","processorMetadata","scanHandlers","scanCompleteHandlers","scanFailedHandlers","registeredProcessor","size","_metatype","prototype","getPrototypeOf","methodNames","getAllMethodNames","methodRef","onJobMetadata","retryOptions","SidequestModule","forRoot","isGlobal","queueProviders","createQueueProviders","module","global","imports","DiscoveryModule","provide","useValue","exports","p","forRootAsync","asyncOptions","createAsyncProviders","useFactory","inject","registry","useClass","optionsFactory","createSidequestOptions","useExisting","Processor","target","SetMetadata","Injectable","OnJob","propertyKey","descriptor","Retry","InjectQueue","Inject","OnJobComplete","OnJobFailed"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * SidequestModule 상수\n */\n\n// DI 토큰\nexport const SIDEQUEST_MODULE_OPTIONS = Symbol('SIDEQUEST_MODULE_OPTIONS');\nexport const SIDEQUEST_ENGINE = Symbol('SIDEQUEST_ENGINE');\n\n// 메타데이터 키\nexport const PROCESSOR_METADATA_KEY = Symbol('sidequest:processor');\nexport const ON_JOB_METADATA_KEY = Symbol('sidequest:on-job');\nexport const RETRY_OPTIONS_METADATA_KEY = Symbol('sidequest:retry');\nexport const ON_JOB_COMPLETE_METADATA_KEY = Symbol('sidequest:on-job-complete');\nexport const ON_JOB_FAILED_METADATA_KEY = Symbol('sidequest:on-job-failed');\n\n// Queue 토큰 프리픽스\nexport const QUEUE_TOKEN_PREFIX = 'SIDEQUEST_QUEUE_';\n\n/**\n * Queue DI 토큰 생성\n */\nexport function getQueueToken(queueName: string): string {\n return `${QUEUE_TOKEN_PREFIX}${queueName}`;\n}\n\n// 기본값\nexport const DEFAULT_QUEUE_NAME = 'default';\nexport const DEFAULT_MAX_ATTEMPTS = 3;\nexport const DEFAULT_TIMEOUT = 30000;\nexport const DEFAULT_CONCURRENCY = 10;\n\n// Log messages\nexport const LOG_MESSAGES = {\n ENGINE_STARTING: 'Starting Sidequest engine...',\n ENGINE_STARTED: 'Sidequest engine started',\n ENGINE_STOPPING: 'Stopping Sidequest engine...',\n ENGINE_STOPPED: 'Sidequest engine stopped',\n QUEUE_REGISTERED: (name: string) => `Queue '${name}' registered`,\n PROCESSOR_REGISTERED: (name: string) => `Processor '${name}' registered`,\n JOB_HANDLER_REGISTERED: (jobName: string, queueName: string) =>\n `Job handler '${jobName}' (Queue: ${queueName}) registered`,\n} as const;\n","import {Injectable, Logger} from '@nestjs/common';\nimport {Sidequest, Job, JobBuilder} from 'sidequest';\nimport type {SidequestModuleOptions} from '../interfaces/module-options.interface.js';\nimport type {JobAddOptions, JobInfo, JobState, ErrorData} from '../interfaces/queue.interface.js';\n\n// Job 클래스 타입\ntype JobClassType = new (...args: unknown[]) => Job;\n\n/**\n * Sidequest.js API Adapter\n *\n * Sidequest.js의 API를 NestJS와 통합합니다.\n * 실제 sidequest 패키지를 사용하여 Job 처리를 수행합니다.\n */\n@Injectable()\nexport class SidequestAdapter {\n private readonly logger = new Logger(SidequestAdapter.name);\n private isStarted = false;\n private readonly registeredJobs = new Map<string, JobClassType>();\n\n /**\n * Sidequest 엔진 시작\n */\n async start(options: SidequestModuleOptions): Promise<void> {\n if (this.isStarted) {\n this.logger.warn('Sidequest engine is already started');\n return;\n }\n\n this.logger.log('Starting Sidequest engine...');\n\n try {\n // Sidequest 설정 구성\n const config: Record<string, unknown> = {\n backend: {\n driver: options.backend.driver,\n config: options.backend.config,\n },\n };\n\n // 큐 설정\n if (options.queues) {\n config.queues = options.queues.map(q => ({\n name: q.name,\n concurrency: q.concurrency,\n priority: q.priority,\n state: q.state,\n }));\n }\n\n // 엔진 설정\n if (options.maxConcurrentJobs !== undefined) {\n config.maxConcurrentJobs = options.maxConcurrentJobs;\n }\n if (options.minThreads !== undefined) {\n config.minThreads = options.minThreads;\n }\n if (options.maxThreads !== undefined) {\n config.maxThreads = options.maxThreads;\n }\n if (options.jobPollingInterval !== undefined) {\n config.jobPollingInterval = options.jobPollingInterval;\n }\n if (options.releaseStaleJobsIntervalMin !== undefined) {\n config.releaseStaleJobsIntervalMin = options.releaseStaleJobsIntervalMin;\n }\n if (options.cleanupFinishedJobsIntervalMin !== undefined) {\n config.cleanupFinishedJobsIntervalMin = options.cleanupFinishedJobsIntervalMin;\n }\n\n // 로거 설정\n if (options.logger) {\n config.logger = {\n level: options.logger.level ?? 'info',\n json: options.logger.json ?? false,\n };\n }\n\n // 대시보드 설정\n if (options.dashboard) {\n config.dashboard = options.dashboard;\n }\n\n // Sidequest 엔진 시작\n await Sidequest.start(config as Parameters<typeof Sidequest.start>[0]);\n\n this.isStarted = true;\n this.logger.log('Sidequest engine started');\n } catch (error) {\n this.logger.error('Failed to start Sidequest engine', error);\n throw error;\n }\n }\n\n /**\n * Sidequest 엔진 종료\n */\n async shutdown(): Promise<void> {\n if (!this.isStarted) {\n return;\n }\n\n this.logger.log('Stopping Sidequest engine...');\n\n try {\n await Sidequest.stop();\n this.isStarted = false;\n this.logger.log('Sidequest engine stopped');\n } catch (error) {\n this.logger.error('Failed to stop Sidequest engine', error);\n throw error;\n }\n }\n\n /**\n * Job 클래스 등록\n */\n registerJob(jobName: string, JobClass: JobClassType): void {\n this.registeredJobs.set(jobName, JobClass);\n this.logger.debug(`Job '${jobName}' registered`);\n }\n\n /**\n * Job 추가\n */\n async addJob(\n queueName: string,\n jobName: string,\n args: unknown[],\n options?: JobAddOptions,\n ): Promise<string> {\n const JobClass = this.registeredJobs.get(jobName);\n if (!JobClass) {\n throw new Error(`Job class '${jobName}' not found. Make sure it's registered.`);\n }\n\n let builder: JobBuilder<JobClassType> = Sidequest.build(JobClass)\n .queue(queueName);\n\n // 옵션 적용\n if (options?.maxAttempts !== undefined) {\n builder = builder.maxAttempts(options.maxAttempts);\n }\n if (options?.timeout !== undefined) {\n builder = builder.timeout(options.timeout);\n }\n if (options?.priority !== undefined) {\n // priority는 queue 레벨에서 설정됨\n }\n if (options?.scheduledAt !== undefined) {\n builder = builder.availableAt(options.scheduledAt);\n }\n if (options?.retryDelay !== undefined) {\n builder = builder.retryDelay(options.retryDelay);\n }\n if (options?.backoffStrategy !== undefined) {\n builder = builder.backoffStrategy(options.backoffStrategy);\n }\n if (options?.uniqueKey !== undefined) {\n builder = builder.unique(true);\n }\n\n // Job 실행 (enqueue)\n const jobData = await builder.enqueue(...args);\n const jobId = String(jobData?.id ?? `job_${Date.now()}`);\n\n this.logger.debug(`Job '${jobName}' (ID: ${jobId}) added to Queue '${queueName}'`);\n\n return jobId;\n }\n\n /**\n * Bulk Job 추가\n */\n async addBulkJobs(\n queueName: string,\n jobs: Array<{jobName: string; args: unknown[]; options?: JobAddOptions}>,\n ): Promise<string[]> {\n const jobIds: string[] = [];\n\n for (const {jobName, args, options} of jobs) {\n const jobId = await this.addJob(queueName, jobName, args, options);\n jobIds.push(jobId);\n }\n\n return jobIds;\n }\n\n /**\n * Job 조회\n */\n async getJob(jobId: string | number): Promise<JobInfo | undefined> {\n try {\n const numericId = typeof jobId === 'string' ? parseInt(jobId, 10) : jobId;\n if (isNaN(numericId)) {\n return undefined;\n }\n\n const job = await Sidequest.job.get(numericId);\n if (!job) {\n return undefined;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const jobData = job as any;\n\n return {\n id: String(job.id),\n name: jobData.name as string | undefined,\n queue: job.queue,\n state: job.state as JobState,\n attempt: job.attempt,\n maxAttempts: job.max_attempts,\n insertedAt: job.inserted_at,\n attemptedAt: job.attempted_at ?? undefined,\n completedAt: job.completed_at ?? undefined,\n result: job.result,\n errors: job.errors as ErrorData[] | null | undefined,\n };\n } catch {\n return undefined;\n }\n }\n\n /**\n * 엔진 시작 여부\n */\n get started(): boolean {\n return this.isStarted;\n }\n\n /**\n * 등록된 Job 클래스 반환\n */\n getRegisteredJob(jobName: string): JobClassType | undefined {\n return this.registeredJobs.get(jobName);\n }\n\n /**\n * 모든 등록된 Job 클래스 반환\n */\n getAllRegisteredJobs(): Map<string, JobClassType> {\n return this.registeredJobs;\n }\n}\n\n// Job 베이스 클래스 re-export\nexport {Job} from 'sidequest';\n","import {Inject, Injectable, Logger, OnModuleDestroy, OnModuleInit} from '@nestjs/common';\nimport {SIDEQUEST_MODULE_OPTIONS} from '../constants.js';\nimport {SidequestAdapter} from '../core/sidequest.adapter.js';\nimport type {SidequestModuleOptions} from '../interfaces/module-options.interface.js';\n\n/**\n * Sidequest 엔진 관리 서비스\n *\n * Sidequest.js 엔진의 라이프사이클을 관리합니다.\n * 모듈 초기화 시 엔진을 시작하고, 종료 시 graceful shutdown을 수행합니다.\n */\n@Injectable()\nexport class SidequestEngineService implements OnModuleInit, OnModuleDestroy {\n private readonly logger = new Logger(SidequestEngineService.name);\n\n constructor(\n @Inject(SIDEQUEST_MODULE_OPTIONS)\n private readonly options: SidequestModuleOptions,\n private readonly adapter: SidequestAdapter,\n ) {}\n\n /**\n * 모듈 초기화 시 엔진 시작\n */\n async onModuleInit(): Promise<void> {\n this.logger.log('Initializing Sidequest engine...');\n await this.adapter.start(this.options);\n this.logger.log('Sidequest engine initialized');\n }\n\n /**\n * 모듈 종료 시 엔진 종료\n */\n async onModuleDestroy(): Promise<void> {\n const gracefulShutdown = this.options.gracefulShutdown ?? {enabled: true, timeout: 30000};\n\n if (gracefulShutdown.enabled) {\n this.logger.log(\n `Sidequest engine graceful shutdown (timeout: ${gracefulShutdown.timeout}ms)`,\n );\n }\n\n await this.adapter.shutdown();\n this.logger.log('Sidequest engine stopped');\n }\n\n /**\n * 엔진 시작 여부\n */\n get isStarted(): boolean {\n return this.adapter.started;\n }\n\n /**\n * Adapter 인스턴스 반환\n */\n getAdapter(): SidequestAdapter {\n return this.adapter;\n }\n}\n","import {Inject, Injectable, Logger} from '@nestjs/common';\nimport {SIDEQUEST_MODULE_OPTIONS} from '../constants.js';\nimport {SidequestAdapter} from '../core/sidequest.adapter.js';\nimport type {SidequestModuleOptions, QueueConfig} from '../interfaces/module-options.interface.js';\nimport type {IQueueService, JobAddOptions} from '../interfaces/queue.interface.js';\n\n/**\n * Queue 레지스트리 서비스\n *\n * 큐 인스턴스를 관리하고 @InjectQueue()를 위한 DI 프로바이더를 제공합니다.\n */\n@Injectable()\nexport class QueueRegistryService {\n private readonly logger = new Logger(QueueRegistryService.name);\n private readonly queueServices = new Map<string, IQueueService>();\n\n constructor(\n @Inject(SIDEQUEST_MODULE_OPTIONS)\n private readonly options: SidequestModuleOptions,\n private readonly adapter: SidequestAdapter,\n ) {\n this.initializeQueues();\n }\n\n /**\n * 설정된 큐 초기화\n */\n private initializeQueues(): void {\n const queues = this.options.queues ?? [];\n\n for (const queueConfig of queues) {\n this.registerQueue(queueConfig);\n }\n\n // 기본 큐가 없으면 생성\n if (!this.queueServices.has('default')) {\n this.registerQueue({name: 'default'});\n }\n }\n\n /**\n * 큐 등록\n */\n registerQueue(config: QueueConfig): void {\n const queueService = this.createQueueService(config.name);\n this.queueServices.set(config.name, queueService);\n this.logger.log(`Queue '${config.name}' registered`);\n }\n\n /**\n * 큐 서비스 조회\n */\n getQueue(name: string): IQueueService | undefined {\n return this.queueServices.get(name);\n }\n\n /**\n * 큐 서비스 조회 (없으면 에러)\n */\n getQueueOrThrow(name: string): IQueueService {\n const queue = this.getQueue(name);\n if (!queue) {\n throw new Error(\n `Queue '${name}' not found. Make sure it is registered in SidequestModule.forRoot().`,\n );\n }\n return queue;\n }\n\n /**\n * 모든 큐 조회\n */\n getAllQueues(): Map<string, IQueueService> {\n return this.queueServices;\n }\n\n /**\n * 큐 서비스 인스턴스 생성\n */\n private createQueueService(queueName: string): IQueueService {\n const adapter = this.adapter;\n\n return {\n name: queueName,\n\n async add<T>(JobClass: new (...args: unknown[]) => T, ...args: unknown[]): Promise<string> {\n const jobName = JobClass.name;\n return adapter.addJob(queueName, jobName, args);\n },\n\n async addWithOptions<T>(\n JobClass: new (...args: unknown[]) => T,\n options: JobAddOptions,\n ...args: unknown[]\n ): Promise<string> {\n const jobName = JobClass.name;\n return adapter.addJob(queueName, jobName, args, options);\n },\n\n async addScheduled<T>(\n JobClass: new (...args: unknown[]) => T,\n scheduledAt: Date,\n ...args: unknown[]\n ): Promise<string> {\n const jobName = JobClass.name;\n return adapter.addJob(queueName, jobName, args, {scheduledAt});\n },\n\n async addBulk<T>(\n jobs: Array<{\n JobClass: new (...args: unknown[]) => T;\n args: unknown[];\n options?: JobAddOptions;\n }>,\n ): Promise<string[]> {\n const bulkJobs = jobs.map(job => {\n const result: {jobName: string; args: unknown[]; options?: JobAddOptions} = {\n jobName: job.JobClass.name,\n args: job.args,\n };\n if (job.options !== undefined) {\n result.options = job.options;\n }\n return result;\n });\n return adapter.addBulkJobs(queueName, bulkJobs);\n },\n };\n }\n}\n","import {Injectable, Logger, Optional, Inject} from '@nestjs/common';\nimport {SIDEQUEST_MODULE_OPTIONS} from '../constants.js';\nimport type {SidequestModuleOptions} from '../interfaces/module-options.interface.js';\n\n// nestjs-cls 타입 (optional dependency)\ninterface ClsService {\n getId(): string | undefined;\n get<T>(key: string): T | undefined;\n set<T>(key: string, value: T): void;\n run<T>(callback: () => T): T;\n}\n\n/**\n * CLS(Continuation Local Storage) 통합 서비스\n *\n * nestjs-cls가 설치되어 있을 경우 Job 실행 시 context를 전파합니다.\n * nestjs-cls가 없으면 no-op으로 동작합니다.\n */\n@Injectable()\nexport class ClsIntegrationService {\n private readonly logger = new Logger(ClsIntegrationService.name);\n private readonly enabled: boolean;\n private clsService: ClsService | null = null;\n\n constructor(\n @Inject(SIDEQUEST_MODULE_OPTIONS)\n options: SidequestModuleOptions,\n @Optional() @Inject('ClsService') clsService?: ClsService,\n ) {\n this.enabled = options.enableCls ?? false;\n this.clsService = clsService ?? null;\n\n if (this.enabled && !this.clsService) {\n this.logger.warn(\n 'CLS integration is enabled but nestjs-cls is not installed. ' +\n 'Install nestjs-cls to enable context propagation.',\n );\n }\n }\n\n /**\n * CLS context 내에서 콜백 실행\n */\n async runInContext<T>(\n metadata: Record<string, unknown>,\n callback: () => Promise<T>,\n ): Promise<T> {\n if (!this.enabled || !this.clsService) {\n return callback();\n }\n\n // nestjs-cls의 run 메서드를 사용하여 새 context에서 실행\n return new Promise((resolve, reject) => {\n try {\n this.clsService!.run(() => {\n // 메타데이터를 CLS에 설정\n for (const [key, value] of Object.entries(metadata)) {\n this.clsService!.set(key, value);\n }\n\n callback().then(resolve).catch(reject);\n });\n } catch (error) {\n reject(error);\n }\n });\n }\n\n /**\n * 현재 traceId 조회\n */\n getTraceId(): string | undefined {\n if (!this.enabled || !this.clsService) {\n return undefined;\n }\n\n return this.clsService.get<string>('traceId');\n }\n\n /**\n * traceId 설정\n */\n setTraceId(traceId: string): void {\n if (!this.enabled || !this.clsService) {\n return;\n }\n\n this.clsService.set('traceId', traceId);\n }\n\n /**\n * CLS에서 값 조회\n */\n get<T>(key: string): T | undefined {\n if (!this.enabled || !this.clsService) {\n return undefined;\n }\n\n return this.clsService.get<T>(key);\n }\n\n /**\n * CLS에 값 설정\n */\n set<T>(key: string, value: T): void {\n if (!this.enabled || !this.clsService) {\n return;\n }\n\n this.clsService.set(key, value);\n }\n\n /**\n * CLS 통합 활성화 여부\n */\n isEnabled(): boolean {\n return this.enabled && this.clsService !== null;\n }\n}\n","import {Injectable, Logger, Optional} from '@nestjs/common';\nimport type {RegisteredProcessor, RegisteredHandler} from '../interfaces/processor.interface.js';\nimport {ClsIntegrationService} from './cls-integration.service.js';\n\n/**\n * Processor 레지스트리 서비스\n *\n * @Processor 데코레이터로 등록된 프로세서와 핸들러를 관리합니다.\n */\n@Injectable()\nexport class ProcessorRegistryService {\n private readonly logger = new Logger(ProcessorRegistryService.name);\n private readonly processors = new Map<string, RegisteredProcessor>();\n\n constructor(\n @Optional() private readonly clsService?: ClsIntegrationService,\n ) {}\n\n /**\n * 프로세서 등록\n */\n register(processor: RegisteredProcessor): void {\n this.processors.set(processor.queueName, processor);\n this.logger.log(\n `Processor '${processor.metatype.name}' (Queue: ${processor.queueName}) registered`,\n );\n }\n\n /**\n * 프로세서 조회\n */\n getProcessor(queueName: string): RegisteredProcessor | undefined {\n return this.processors.get(queueName);\n }\n\n /**\n * 모든 프로세서 조회\n */\n getAllProcessors(): Map<string, RegisteredProcessor> {\n return this.processors;\n }\n\n /**\n * Job 핸들러 조회\n */\n getJobHandler(queueName: string, jobName: string): RegisteredHandler | undefined {\n const processor = this.processors.get(queueName);\n if (!processor) {\n return undefined;\n }\n return processor.handlers.get(jobName);\n }\n\n /**\n * Job 완료 핸들러 조회\n */\n getCompleteHandler(queueName: string, jobName: string): string | undefined {\n const processor = this.processors.get(queueName);\n if (!processor) {\n return undefined;\n }\n return processor.completeHandlers.get(jobName) ?? processor.completeHandlers.get('*');\n }\n\n /**\n * Job 실패 핸들러 조회\n */\n getFailedHandler(queueName: string, jobName: string): string | undefined {\n const processor = this.processors.get(queueName);\n if (!processor) {\n return undefined;\n }\n return processor.failedHandlers.get(jobName) ?? processor.failedHandlers.get('*');\n }\n\n /**\n * Job 디스패치 (실행)\n *\n * @param queueName - 큐 이름\n * @param jobName - Job 이름\n * @param args - Job 인자\n * @param metadata - Job 메타데이터 (traceId 등)\n */\n async dispatch(\n queueName: string,\n jobName: string,\n args: unknown[],\n metadata?: Record<string, unknown>,\n ): Promise<unknown> {\n const processor = this.processors.get(queueName);\n if (!processor) {\n throw new Error(`Processor not found for Queue '${queueName}'`);\n }\n\n const handler = processor.handlers.get(jobName);\n if (!handler) {\n throw new Error(`Handler not found for Job '${jobName}' (Queue: ${queueName})`);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n const instance = processor.instance as Record<string, Function>;\n const method = instance[handler.methodName];\n\n if (typeof method !== 'function') {\n throw new Error(`Handler method '${handler.methodName}' not found`);\n }\n\n // CLS context에서 실행\n const executeJob = async (): Promise<unknown> => {\n try {\n const result = await method.apply(processor.instance, args);\n\n // 완료 핸들러 호출\n const completeHandlerName = this.getCompleteHandler(queueName, jobName);\n if (completeHandlerName) {\n const completeHandler = instance[completeHandlerName];\n if (typeof completeHandler === 'function') {\n await completeHandler.apply(processor.instance, [{jobName, args, result}]);\n }\n }\n\n return result;\n } catch (error) {\n // 실패 핸들러 호출\n const failedHandlerName = this.getFailedHandler(queueName, jobName);\n if (failedHandlerName) {\n const failedHandler = instance[failedHandlerName];\n if (typeof failedHandler === 'function') {\n await failedHandler.apply(processor.instance, [{jobName, args, error}]);\n }\n }\n\n throw error;\n }\n };\n\n // CLS 통합이 활성화되어 있으면 context 내에서 실행\n if (this.clsService?.isEnabled() && metadata) {\n return this.clsService.runInContext(metadata, executeJob);\n }\n\n return executeJob();\n }\n}\n","import {Injectable, Logger, OnModuleInit} from '@nestjs/common';\nimport {DiscoveryService, MetadataScanner, Reflector} from '@nestjs/core';\nimport {InstanceWrapper} from '@nestjs/core/injector/instance-wrapper';\nimport {\n PROCESSOR_METADATA_KEY,\n ON_JOB_METADATA_KEY,\n RETRY_OPTIONS_METADATA_KEY,\n ON_JOB_COMPLETE_METADATA_KEY,\n ON_JOB_FAILED_METADATA_KEY,\n} from '../constants.js';\nimport {ProcessorRegistryService} from '../services/processor-registry.service.js';\nimport type {\n ProcessorMetadata,\n OnJobMetadata,\n RetryOptions,\n RegisteredHandler,\n RegisteredProcessor,\n} from '../interfaces/processor.interface.js';\n\n/**\n * Processor Explorer\n *\n * 애플리케이션 시작 시 @Processor 데코레이터가 붙은 클래스를 스캔하고,\n * @OnJob, @Retry, @OnJobComplete, @OnJobFailed 메타데이터를 수집하여\n * ProcessorRegistry에 등록합니다.\n */\n@Injectable()\nexport class ProcessorExplorer implements OnModuleInit {\n private readonly logger = new Logger(ProcessorExplorer.name);\n\n constructor(\n private readonly discoveryService: DiscoveryService,\n private readonly metadataScanner: MetadataScanner,\n private readonly reflector: Reflector,\n private readonly processorRegistry: ProcessorRegistryService,\n ) {}\n\n /**\n * 모듈 초기화 시 프로세서 스캔\n */\n async onModuleInit(): Promise<void> {\n this.logger.log('Scanning for processors...');\n await this.explore();\n this.logger.log('Processor scan completed');\n }\n\n /**\n * 모든 프로바이더를 스캔하여 @Processor 클래스 찾기\n */\n async explore(): Promise<void> {\n const providers = this.discoveryService.getProviders();\n\n for (const wrapper of providers) {\n await this.processWrapper(wrapper);\n }\n }\n\n /**\n * 프로바이더 래퍼 처리\n */\n private async processWrapper(wrapper: InstanceWrapper): Promise<void> {\n const {instance, metatype} = wrapper;\n\n // 인스턴스와 메타타입이 없으면 스킵\n if (!instance || !metatype) {\n return;\n }\n\n // @Processor 메타데이터 확인\n const processorMetadata = this.reflector.get<ProcessorMetadata>(\n PROCESSOR_METADATA_KEY,\n metatype,\n );\n\n if (!processorMetadata) {\n return;\n }\n\n // 핸들러 스캔\n const handlers = this.scanHandlers(instance, metatype);\n const completeHandlers = this.scanCompleteHandlers(instance, metatype);\n const failedHandlers = this.scanFailedHandlers(instance, metatype);\n\n // 프로세서 등록\n const registeredProcessor: RegisteredProcessor = {\n queueName: processorMetadata.queueName,\n instance,\n metatype,\n handlers,\n completeHandlers,\n failedHandlers,\n };\n\n this.processorRegistry.register(registeredProcessor);\n\n this.logger.log(\n `Processor '${metatype.name}' registered (Queue: ${processorMetadata.queueName}, Handlers: ${handlers.size})`,\n );\n }\n\n /**\n * @OnJob 메서드 스캔\n */\n private scanHandlers(instance: unknown, _metatype: object): Map<string, RegisteredHandler> {\n const handlers = new Map<string, RegisteredHandler>();\n const prototype = Object.getPrototypeOf(instance);\n const methodNames = this.metadataScanner.getAllMethodNames(prototype);\n\n for (const methodName of methodNames) {\n const methodRef = prototype[methodName];\n\n // @OnJob 메타데이터 확인\n const onJobMetadata = this.reflector.get<OnJobMetadata>(ON_JOB_METADATA_KEY, methodRef);\n\n if (!onJobMetadata) {\n continue;\n }\n\n // @Retry 메타데이터 확인\n const retryOptions = this.reflector.get<RetryOptions>(RETRY_OPTIONS_METADATA_KEY, methodRef);\n\n const handler: RegisteredHandler = {\n methodName,\n jobName: onJobMetadata.jobName,\n options: onJobMetadata.options,\n retryOptions,\n };\n\n handlers.set(onJobMetadata.jobName, handler);\n\n this.logger.debug(` - Job '${onJobMetadata.jobName}' -> ${methodName}()`);\n }\n\n return handlers;\n }\n\n /**\n * @OnJobComplete 메서드 스캔\n */\n private scanCompleteHandlers(instance: unknown, _metatype: object): Map<string, string> {\n const handlers = new Map<string, string>();\n const prototype = Object.getPrototypeOf(instance);\n const methodNames = this.metadataScanner.getAllMethodNames(prototype);\n\n for (const methodName of methodNames) {\n const methodRef = prototype[methodName];\n\n // @OnJobComplete 메타데이터 확인\n const jobName = this.reflector.get<string | undefined>(\n ON_JOB_COMPLETE_METADATA_KEY,\n methodRef,\n );\n\n if (jobName !== undefined) {\n // jobName이 빈 문자열이면 모든 Job에 대해 호출 ('*')\n const key = jobName || '*';\n handlers.set(key, methodName);\n this.logger.debug(` - OnJobComplete '${key}' -> ${methodName}()`);\n }\n }\n\n return handlers;\n }\n\n /**\n * @OnJobFailed 메서드 스캔\n */\n private scanFailedHandlers(instance: unknown, _metatype: object): Map<string, string> {\n const handlers = new Map<string, string>();\n const prototype = Object.getPrototypeOf(instance);\n const methodNames = this.metadataScanner.getAllMethodNames(prototype);\n\n for (const methodName of methodNames) {\n const methodRef = prototype[methodName];\n\n // @OnJobFailed 메타데이터 확인\n const jobName = this.reflector.get<string | undefined>(ON_JOB_FAILED_METADATA_KEY, methodRef);\n\n if (jobName !== undefined) {\n // jobName이 빈 문자열이면 모든 Job에 대해 호출 ('*')\n const key = jobName || '*';\n handlers.set(key, methodName);\n this.logger.debug(` - OnJobFailed '${key}' -> ${methodName}()`);\n }\n }\n\n return handlers;\n }\n}\n","import {DynamicModule, Global, Module, Provider} from '@nestjs/common';\nimport {DiscoveryModule} from '@nestjs/core';\nimport {SIDEQUEST_MODULE_OPTIONS, getQueueToken} from '../constants.js';\nimport {SidequestAdapter} from '../core/sidequest.adapter.js';\nimport type {\n SidequestModuleOptions,\n SidequestModuleAsyncOptions,\n SidequestOptionsFactory,\n} from '../interfaces/module-options.interface.js';\nimport {SidequestEngineService} from '../services/sidequest-engine.service.js';\nimport {QueueRegistryService} from '../services/queue-registry.service.js';\nimport {ProcessorRegistryService} from '../services/processor-registry.service.js';\nimport {ClsIntegrationService} from '../services/cls-integration.service.js';\nimport {ProcessorExplorer} from '../explorers/processor.explorer.js';\n\n/**\n * SidequestModule\n *\n * NestJS에서 Sidequest.js를 사용하기 위한 메인 모듈입니다.\n *\n * @example\n * ```typescript\n * // 동기 설정\n * @Module({\n * imports: [\n * SidequestModule.forRoot({\n * backend: {\n * driver: '@sidequest/postgres-backend',\n * config: process.env.DATABASE_URL,\n * },\n * queues: [\n * { name: 'email', concurrency: 5 },\n * { name: 'report', concurrency: 2 },\n * ],\n * }),\n * ],\n * })\n * export class AppModule {}\n *\n * // 비동기 설정 (ConfigService 사용)\n * @Module({\n * imports: [\n * SidequestModule.forRootAsync({\n * imports: [ConfigModule],\n * useFactory: (config: ConfigService) => ({\n * backend: {\n * driver: '@sidequest/postgres-backend',\n * config: config.get('DATABASE_URL'),\n * },\n * queues: [{ name: 'default' }],\n * }),\n * inject: [ConfigService],\n * }),\n * ],\n * })\n * export class AppModule {}\n * ```\n */\n@Global()\n@Module({})\nexport class SidequestModule {\n /**\n * 동기 설정으로 모듈 등록\n */\n static forRoot(options: SidequestModuleOptions): DynamicModule {\n const isGlobal = options.isGlobal ?? true;\n const queueProviders = this.createQueueProviders(options);\n\n return {\n module: SidequestModule,\n global: isGlobal,\n imports: [DiscoveryModule],\n providers: [\n {\n provide: SIDEQUEST_MODULE_OPTIONS,\n useValue: options,\n },\n SidequestAdapter,\n SidequestEngineService,\n QueueRegistryService,\n ProcessorRegistryService,\n ClsIntegrationService,\n ProcessorExplorer,\n ...queueProviders,\n ],\n exports: [\n SIDEQUEST_MODULE_OPTIONS,\n SidequestAdapter,\n SidequestEngineService,\n QueueRegistryService,\n ProcessorRegistryService,\n ClsIntegrationService,\n ...queueProviders.map(p => (p as {provide: symbol | string}).provide),\n ],\n };\n }\n\n /**\n * 비동기 설정으로 모듈 등록\n */\n static forRootAsync(asyncOptions: SidequestModuleAsyncOptions): DynamicModule {\n const isGlobal = asyncOptions.isGlobal ?? true;\n\n return {\n module: SidequestModule,\n global: isGlobal,\n imports: [DiscoveryModule, ...(asyncOptions.imports || [])],\n providers: [\n ...this.createAsyncProviders(asyncOptions),\n SidequestAdapter,\n SidequestEngineService,\n QueueRegistryService,\n ProcessorRegistryService,\n ClsIntegrationService,\n ProcessorExplorer,\n // 동적 큐 프로바이더 - options에서 queues를 읽어 생성\n {\n provide: 'SIDEQUEST_QUEUE_PROVIDERS_INIT',\n useFactory: () => {\n // QueueRegistryService가 자동으로 큐를 초기화하므로 별도 처리 불필요\n return true;\n },\n inject: [QueueRegistryService],\n },\n ],\n exports: [\n SIDEQUEST_MODULE_OPTIONS,\n SidequestAdapter,\n SidequestEngineService,\n QueueRegistryService,\n ProcessorRegistryService,\n ClsIntegrationService,\n ],\n };\n }\n\n /**\n * 큐별 DI 프로바이더 생성\n */\n private static createQueueProviders(options: SidequestModuleOptions): Provider[] {\n const queues = options.queues ?? [{name: 'default'}];\n\n return queues.map(queue => ({\n provide: getQueueToken(queue.name),\n useFactory: (registry: QueueRegistryService) => registry.getQueueOrThrow(queue.name),\n inject: [QueueRegistryService],\n }));\n }\n\n /**\n * 비동기 프로바이더 생성\n */\n private static createAsyncProviders(asyncOptions: SidequestModuleAsyncOptions): Provider[] {\n if (asyncOptions.useFactory) {\n return [\n {\n provide: SIDEQUEST_MODULE_OPTIONS,\n useFactory: asyncOptions.useFactory,\n inject: asyncOptions.inject || [],\n },\n ];\n }\n\n if (asyncOptions.useClass) {\n return [\n {\n provide: asyncOptions.useClass,\n useClass: asyncOptions.useClass,\n },\n {\n provide: SIDEQUEST_MODULE_OPTIONS,\n useFactory: async (optionsFactory: SidequestOptionsFactory) =>\n optionsFactory.createSidequestOptions(),\n inject: [asyncOptions.useClass],\n },\n ];\n }\n\n if (asyncOptions.useExisting) {\n return [\n {\n provide: SIDEQUEST_MODULE_OPTIONS,\n useFactory: async (optionsFactory: SidequestOptionsFactory) =>\n optionsFactory.createSidequestOptions(),\n inject: [asyncOptions.useExisting],\n },\n ];\n }\n\n return [\n {\n provide: SIDEQUEST_MODULE_OPTIONS,\n useValue: {},\n },\n ];\n }\n}\n","import {Injectable, SetMetadata} from '@nestjs/common';\nimport {PROCESSOR_METADATA_KEY} from '../constants.js';\nimport type {ProcessorOptions, ProcessorMetadata} from '../interfaces/processor.interface.js';\n\n/**\n * 클래스를 Sidequest Job Processor로 지정합니다.\n *\n * @Processor 데코레이터가 붙은 클래스는 모듈 초기화 시 자동으로 스캔되어\n * 해당 큐의 Job 핸들러로 등록됩니다.\n *\n * @param queueName - 처리할 큐 이름\n * @param options - 프로세서 옵션\n *\n * @example\n * ```typescript\n * @Processor('email')\n * export class EmailProcessor {\n * @OnJob('send-welcome-email')\n * async handleWelcomeEmail(job: JobContext) {\n * const { to, subject, body } = job.data;\n * await this.mailer.send({ to, subject, body });\n * }\n * }\n *\n * // 동시성 설정과 함께\n * @Processor('report', { concurrency: 2 })\n * export class ReportProcessor {\n * @OnJob('generate-daily-report')\n * async handleDailyReport(job: JobContext) {\n * // 리포트 생성 로직\n * }\n * }\n * ```\n */\nexport function Processor(queueName: string, options?: ProcessorOptions): ClassDecorator {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n return (target: Function): void => {\n const metadata: ProcessorMetadata = {\n queueName,\n options,\n };\n\n // 메타데이터 설정\n SetMetadata(PROCESSOR_METADATA_KEY, metadata)(target);\n\n // @Injectable() 자동 적용\n Injectable()(target);\n };\n}\n","import {SetMetadata} from '@nestjs/common';\nimport {ON_JOB_METADATA_KEY} from '../constants.js';\nimport type {OnJobOptions, OnJobMetadata} from '../interfaces/processor.interface.js';\n\n/**\n * 메서드를 특정 Job 타입의 핸들러로 지정합니다.\n *\n * @Processor 데코레이터가 붙은 클래스 내부에서 사용합니다.\n * 해당 Job이 큐에서 처리될 때 이 메서드가 호출됩니다.\n *\n * @param jobName - Job 이름 (일반적으로 Job 클래스명)\n * @param options - Job 실행 옵션 (우선순위, 타임아웃 등)\n *\n * @example\n * ```typescript\n * @Processor('email')\n * export class EmailProcessor {\n * @OnJob('SendWelcomeEmailJob')\n * async handleWelcomeEmail(job: JobContext) {\n * const { to, subject, body } = job.data;\n * await this.mailer.send({ to, subject, body });\n * }\n *\n * // 우선순위와 타임아웃 설정\n * @OnJob('SendPriorityEmailJob', { priority: 100, timeout: 5000 })\n * async handlePriorityEmail(job: JobContext) {\n * // 우선순위가 높은 이메일 처리\n * }\n * }\n * ```\n */\nexport function OnJob(jobName: string, options?: OnJobOptions): MethodDecorator {\n return (\n target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor,\n ): PropertyDescriptor => {\n const metadata: OnJobMetadata = {\n jobName,\n options,\n };\n\n SetMetadata(ON_JOB_METADATA_KEY, metadata)(target, propertyKey, descriptor);\n\n return descriptor;\n };\n}\n","import {SetMetadata} from '@nestjs/common';\nimport {RETRY_OPTIONS_METADATA_KEY} from '../constants.js';\nimport type {RetryOptions} from '../interfaces/processor.interface.js';\n\n/**\n * Job 재시도 정책을 설정합니다.\n *\n * @OnJob 데코레이터와 함께 사용하여 Job 실패 시 재시도 동작을 정의합니다.\n *\n * @param options - 재시도 옵션\n *\n * @example\n * ```typescript\n * @Processor('payment')\n * export class PaymentProcessor {\n * // 고정 지연 재시도\n * @OnJob('ProcessPaymentJob')\n * @Retry({ maxAttempts: 3, delay: 1000 })\n * async handlePayment(job: JobContext) {\n * // 결제 처리 로직\n * }\n *\n * // 지수 백오프 재시도\n * @OnJob('RefundJob')\n * @Retry({ maxAttempts: 5, delay: 500, backoff: 'exponential' })\n * async handleRefund(job: JobContext) {\n * // 환불 처리 로직\n * }\n * }\n * ```\n */\nexport function Retry(options: RetryOptions): MethodDecorator {\n return (\n target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor,\n ): PropertyDescriptor => {\n SetMetadata(RETRY_OPTIONS_METADATA_KEY, options)(target, propertyKey, descriptor);\n return descriptor;\n };\n}\n","import {Inject} from '@nestjs/common';\nimport {getQueueToken} from '../constants.js';\n\n/**\n * Queue 인스턴스를 주입합니다.\n *\n * SidequestModule.forRoot()에서 등록된 큐를 서비스에 주입받아 사용할 수 있습니다.\n *\n * @param queueName - 주입받을 큐 이름\n *\n * @example\n * ```typescript\n * @Injectable()\n * export class UserService {\n * constructor(\n * @InjectQueue('email') private emailQueue: IQueueService,\n * @InjectQueue('notification') private notificationQueue: IQueueService,\n * ) {}\n *\n * async createUser(email: string, name: string) {\n * // 사용자 생성 로직...\n *\n * // 환영 이메일 발송\n * await this.emailQueue.add(SendWelcomeEmailJob, email, `Welcome, ${name}!`);\n *\n * // 알림 발송\n * await this.notificationQueue.add(SendNotificationJob, email, 'new-user');\n * }\n * }\n * ```\n */\nexport function InjectQueue(queueName: string): ParameterDecorator {\n return Inject(getQueueToken(queueName));\n}\n","import {SetMetadata} from '@nestjs/common';\nimport {ON_JOB_COMPLETE_METADATA_KEY} from '../constants.js';\n\n/**\n * Job 완료 이벤트 핸들러를 지정합니다.\n *\n * @Processor 클래스 내부에서 사용하며, Job이 성공적으로 완료되면 호출됩니다.\n *\n * @param jobName - 대상 Job 이름 (생략 시 모든 Job에 대해 호출)\n *\n * @example\n * ```typescript\n * @Processor('email')\n * export class EmailProcessor {\n * @OnJob('SendWelcomeEmailJob')\n * async handleWelcomeEmail(job: JobContext) {\n * await this.mailer.send(job.data);\n * }\n *\n * // 특정 Job 완료 이벤트\n * @OnJobComplete('SendWelcomeEmailJob')\n * async onWelcomeEmailComplete(event: JobCompleteEvent) {\n * this.logger.log(`환영 이메일 발송 완료: ${event.result}`);\n * await this.analytics.track('email_sent', { type: 'welcome' });\n * }\n *\n * // 모든 Job 완료 이벤트 (jobName 생략)\n * @OnJobComplete()\n * async onAnyJobComplete(event: JobCompleteEvent) {\n * this.logger.log(`Job 완료: ${event.jobName}`);\n * }\n * }\n * ```\n */\nexport function OnJobComplete(jobName?: string): MethodDecorator {\n return (\n target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor,\n ): PropertyDescriptor => {\n // jobName이 undefined면 빈 문자열로 저장 (모든 Job에 대해 호출)\n SetMetadata(ON_JOB_COMPLETE_METADATA_KEY, jobName ?? '')(target, propertyKey, descriptor);\n return descriptor;\n };\n}\n\n/**\n * Job 완료 이벤트 데이터\n */\nexport interface JobCompleteEvent {\n /** Job 이름 */\n jobName: string;\n\n /** Job 실행 인자 */\n args: unknown[];\n\n /** Job 실행 결과 */\n result: unknown;\n}\n","import {SetMetadata} from '@nestjs/common';\nimport {ON_JOB_FAILED_METADATA_KEY} from '../constants.js';\n\n/**\n * Job 실패 이벤트 핸들러를 지정합니다.\n *\n * @Processor 클래스 내부에서 사용하며, Job 실행이 실패하면 호출됩니다.\n * 재시도 횟수를 모두 소진한 후 최종 실패 시에만 호출됩니다.\n *\n * @param jobName - 대상 Job 이름 (생략 시 모든 Job에 대해 호출)\n *\n * @example\n * ```typescript\n * @Processor('payment')\n * export class PaymentProcessor {\n * @OnJob('ProcessPaymentJob')\n * @Retry({ maxAttempts: 3 })\n * async handlePayment(job: JobContext) {\n * await this.paymentService.process(job.data);\n * }\n *\n * // 특정 Job 실패 이벤트\n * @OnJobFailed('ProcessPaymentJob')\n * async onPaymentFailed(event: JobFailedEvent) {\n * this.logger.error(`결제 처리 실패: ${event.error.message}`);\n * await this.alertService.notify('payment-failure', {\n * orderId: event.args[0],\n * error: event.error.message,\n * });\n * }\n *\n * // 모든 Job 실패 이벤트 (jobName 생략)\n * @OnJobFailed()\n * async onAnyJobFailed(event: JobFailedEvent) {\n * this.logger.error(`Job 실패: ${event.jobName}`, event.error);\n * }\n * }\n * ```\n */\nexport function OnJobFailed(jobName?: string): MethodDecorator {\n return (\n target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor,\n ): PropertyDescriptor => {\n // jobName이 undefined면 빈 문자열로 저장 (모든 Job에 대해 호출)\n SetMetadata(ON_JOB_FAILED_METADATA_KEY, jobName ?? '')(target, propertyKey, descriptor);\n return descriptor;\n };\n}\n\n/**\n * Job 실패 이벤트 데이터\n */\nexport interface JobFailedEvent {\n /** Job 이름 */\n jobName: string;\n\n /** Job 실행 인자 */\n args: unknown[];\n\n /** 발생한 에러 */\n error: Error;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/constants.ts","../src/core/sidequest.adapter.ts","../src/services/sidequest-engine.service.ts","../src/services/queue-registry.service.ts","../src/services/cls-integration.service.ts","../src/services/processor-registry.service.ts","../src/explorers/processor.explorer.ts","../src/modules/sidequest.module.ts","../src/decorators/processor.decorator.ts","../src/decorators/on-job.decorator.ts","../src/decorators/retry.decorator.ts","../src/decorators/inject-queue.decorator.ts","../src/decorators/on-job-complete.decorator.ts","../src/decorators/on-job-failed.decorator.ts"],"names":["SIDEQUEST_MODULE_OPTIONS","Symbol","SIDEQUEST_ENGINE","PROCESSOR_METADATA_KEY","ON_JOB_METADATA_KEY","RETRY_OPTIONS_METADATA_KEY","ON_JOB_COMPLETE_METADATA_KEY","ON_JOB_FAILED_METADATA_KEY","QUEUE_TOKEN_PREFIX","getQueueToken","queueName","DEFAULT_QUEUE_NAME","DEFAULT_MAX_ATTEMPTS","DEFAULT_TIMEOUT","DEFAULT_CONCURRENCY","SidequestAdapter","logger","Logger","name","isStarted","registeredJobs","Map","start","options","warn","log","config","backend","driver","queues","map","q","concurrency","priority","state","maxConcurrentJobs","undefined","minThreads","maxThreads","jobPollingInterval","releaseStaleJobsIntervalMin","cleanupFinishedJobsIntervalMin","level","json","dashboard","Sidequest","error","shutdown","stop","registerJob","jobName","JobClass","set","debug","addJob","args","get","Error","builder","build","queue","maxAttempts","timeout","scheduledAt","availableAt","retryDelay","backoffStrategy","uniqueKey","unique","jobData","enqueue","jobId","String","id","Date","now","addBulkJobs","jobs","jobIds","push","getJob","numericId","parseInt","isNaN","job","attempt","max_attempts","insertedAt","inserted_at","attemptedAt","attempted_at","completedAt","completed_at","result","errors","started","getRegisteredJob","getAllRegisteredJobs","SidequestEngineService","adapter","onModuleInit","onModuleDestroy","gracefulShutdown","enabled","getAdapter","QueueRegistryService","queueServices","initializeQueues","queueConfig","registerQueue","has","queueService","createQueueService","getQueue","getQueueOrThrow","getAllQueues","add","addWithOptions","addScheduled","addBulk","bulkJobs","ClsIntegrationService","clsService","enableCls","runInContext","metadata","callback","Promise","resolve","reject","run","key","value","Object","entries","then","catch","getTraceId","setTraceId","traceId","isEnabled","ProcessorRegistryService","processors","register","processor","metatype","getProcessor","getAllProcessors","getJobHandler","handlers","getCompleteHandler","completeHandlers","getFailedHandler","failedHandlers","dispatch","handler","instance","method","methodName","executeJob","apply","completeHandlerName","completeHandler","failedHandlerName","failedHandler","ProcessorExplorer","discoveryService","metadataScanner","reflector","processorRegistry","explore","providers","getProviders","wrapper","processWrapper","processorMetadata","scanHandlers","scanCompleteHandlers","scanFailedHandlers","registeredProcessor","size","_metatype","prototype","getPrototypeOf","methodNames","getAllMethodNames","methodRef","onJobMetadata","retryOptions","SidequestModule","forRoot","isGlobal","queueProviders","createQueueProviders","module","global","imports","DiscoveryModule","provide","useValue","exports","p","forRootAsync","asyncOptions","createAsyncProviders","useFactory","inject","registry","useClass","optionsFactory","createSidequestOptions","useExisting","Processor","target","SetMetadata","Injectable","OnJob","propertyKey","descriptor","Retry","InjectQueue","Inject","OnJobComplete","OnJobFailed"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * SidequestModule 상수\n */\n\n// DI 토큰\nexport const SIDEQUEST_MODULE_OPTIONS = Symbol('SIDEQUEST_MODULE_OPTIONS');\nexport const SIDEQUEST_ENGINE = Symbol('SIDEQUEST_ENGINE');\n\n// 메타데이터 키\nexport const PROCESSOR_METADATA_KEY = Symbol('sidequest:processor');\nexport const ON_JOB_METADATA_KEY = Symbol('sidequest:on-job');\nexport const RETRY_OPTIONS_METADATA_KEY = Symbol('sidequest:retry');\nexport const ON_JOB_COMPLETE_METADATA_KEY = Symbol('sidequest:on-job-complete');\nexport const ON_JOB_FAILED_METADATA_KEY = Symbol('sidequest:on-job-failed');\n\n// Queue 토큰 프리픽스\nexport const QUEUE_TOKEN_PREFIX = 'SIDEQUEST_QUEUE_';\n\n/**\n * Queue DI 토큰 생성\n */\nexport function getQueueToken(queueName: string): string {\n return `${QUEUE_TOKEN_PREFIX}${queueName}`;\n}\n\n// 기본값\nexport const DEFAULT_QUEUE_NAME = 'default';\nexport const DEFAULT_MAX_ATTEMPTS = 3;\nexport const DEFAULT_TIMEOUT = 30000;\nexport const DEFAULT_CONCURRENCY = 10;\n\n// Log messages\nexport const LOG_MESSAGES = {\n ENGINE_STARTING: 'Starting Sidequest engine...',\n ENGINE_STARTED: 'Sidequest engine started',\n ENGINE_STOPPING: 'Stopping Sidequest engine...',\n ENGINE_STOPPED: 'Sidequest engine stopped',\n QUEUE_REGISTERED: (name: string) => `Queue '${name}' registered`,\n PROCESSOR_REGISTERED: (name: string) => `Processor '${name}' registered`,\n JOB_HANDLER_REGISTERED: (jobName: string, queueName: string) =>\n `Job handler '${jobName}' (Queue: ${queueName}) registered`,\n} as const;\n","import {Injectable, Logger} from '@nestjs/common';\nimport {Sidequest, Job, JobBuilder} from 'sidequest';\nimport type {SidequestModuleOptions} from '../interfaces/module-options.interface.js';\nimport type {JobAddOptions, JobInfo, JobState, ErrorData} from '../interfaces/queue.interface.js';\n\n// Job 클래스 타입\ntype JobClassType = new (...args: unknown[]) => Job;\n\n/**\n * Sidequest.js API Adapter\n *\n * Sidequest.js의 API를 NestJS와 통합합니다.\n * 실제 sidequest 패키지를 사용하여 Job 처리를 수행합니다.\n */\n@Injectable()\nexport class SidequestAdapter {\n private readonly logger = new Logger(SidequestAdapter.name);\n private isStarted = false;\n private readonly registeredJobs = new Map<string, JobClassType>();\n\n /**\n * Sidequest 엔진 시작\n */\n async start(options: SidequestModuleOptions): Promise<void> {\n if (this.isStarted) {\n this.logger.warn('Sidequest engine is already started');\n return;\n }\n\n this.logger.log('Starting Sidequest engine...');\n\n try {\n // Sidequest 설정 구성\n const config: Record<string, unknown> = {\n backend: {\n driver: options.backend.driver,\n config: options.backend.config,\n },\n };\n\n // 큐 설정\n if (options.queues) {\n config.queues = options.queues.map(q => ({\n name: q.name,\n concurrency: q.concurrency,\n priority: q.priority,\n state: q.state,\n }));\n }\n\n // 엔진 설정\n if (options.maxConcurrentJobs !== undefined) {\n config.maxConcurrentJobs = options.maxConcurrentJobs;\n }\n if (options.minThreads !== undefined) {\n config.minThreads = options.minThreads;\n }\n if (options.maxThreads !== undefined) {\n config.maxThreads = options.maxThreads;\n }\n if (options.jobPollingInterval !== undefined) {\n config.jobPollingInterval = options.jobPollingInterval;\n }\n if (options.releaseStaleJobsIntervalMin !== undefined) {\n config.releaseStaleJobsIntervalMin = options.releaseStaleJobsIntervalMin;\n }\n if (options.cleanupFinishedJobsIntervalMin !== undefined) {\n config.cleanupFinishedJobsIntervalMin = options.cleanupFinishedJobsIntervalMin;\n }\n\n // 로거 설정\n if (options.logger) {\n config.logger = {\n level: options.logger.level ?? 'info',\n json: options.logger.json ?? false,\n };\n }\n\n // 대시보드 설정\n if (options.dashboard) {\n config.dashboard = options.dashboard;\n }\n\n // Sidequest 엔진 시작\n await Sidequest.start(config as Parameters<typeof Sidequest.start>[0]);\n\n this.isStarted = true;\n this.logger.log('Sidequest engine started');\n } catch (error) {\n this.logger.error('Failed to start Sidequest engine', error);\n throw error;\n }\n }\n\n /**\n * Sidequest 엔진 종료\n */\n async shutdown(): Promise<void> {\n if (!this.isStarted) {\n return;\n }\n\n this.logger.log('Stopping Sidequest engine...');\n\n try {\n await Sidequest.stop();\n this.isStarted = false;\n this.logger.log('Sidequest engine stopped');\n } catch (error) {\n this.logger.error('Failed to stop Sidequest engine', error);\n throw error;\n }\n }\n\n /**\n * Job 클래스 등록\n */\n registerJob(jobName: string, JobClass: JobClassType): void {\n this.registeredJobs.set(jobName, JobClass);\n this.logger.debug(`Job '${jobName}' registered`);\n }\n\n /**\n * Job 추가\n */\n async addJob(\n queueName: string,\n jobName: string,\n args: unknown[],\n options?: JobAddOptions,\n ): Promise<string> {\n const JobClass = this.registeredJobs.get(jobName);\n if (!JobClass) {\n throw new Error(`Job class '${jobName}' not found. Make sure it's registered.`);\n }\n\n let builder: JobBuilder<JobClassType> = Sidequest.build(JobClass).queue(queueName);\n\n // 옵션 적용\n if (options?.maxAttempts !== undefined) {\n builder = builder.maxAttempts(options.maxAttempts);\n }\n if (options?.timeout !== undefined) {\n builder = builder.timeout(options.timeout);\n }\n if (options?.priority !== undefined) {\n // priority는 queue 레벨에서 설정됨\n }\n if (options?.scheduledAt !== undefined) {\n builder = builder.availableAt(options.scheduledAt);\n }\n if (options?.retryDelay !== undefined) {\n builder = builder.retryDelay(options.retryDelay);\n }\n if (options?.backoffStrategy !== undefined) {\n builder = builder.backoffStrategy(options.backoffStrategy);\n }\n if (options?.uniqueKey !== undefined) {\n builder = builder.unique(true);\n }\n\n // Job 실행 (enqueue)\n const jobData = await builder.enqueue(...args);\n const jobId = String(jobData?.id ?? `job_${Date.now()}`);\n\n this.logger.debug(`Job '${jobName}' (ID: ${jobId}) added to Queue '${queueName}'`);\n\n return jobId;\n }\n\n /**\n * Bulk Job 추가\n */\n async addBulkJobs(\n queueName: string,\n jobs: Array<{jobName: string; args: unknown[]; options?: JobAddOptions}>,\n ): Promise<string[]> {\n const jobIds: string[] = [];\n\n for (const {jobName, args, options} of jobs) {\n const jobId = await this.addJob(queueName, jobName, args, options);\n jobIds.push(jobId);\n }\n\n return jobIds;\n }\n\n /**\n * Job 조회\n */\n async getJob(jobId: string | number): Promise<JobInfo | undefined> {\n try {\n const numericId = typeof jobId === 'string' ? parseInt(jobId, 10) : jobId;\n if (isNaN(numericId)) {\n return undefined;\n }\n\n const job = await Sidequest.job.get(numericId);\n if (!job) {\n return undefined;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const jobData = job as any;\n\n return {\n id: String(job.id),\n name: jobData.name as string | undefined,\n queue: job.queue,\n state: job.state as JobState,\n attempt: job.attempt,\n maxAttempts: job.max_attempts,\n insertedAt: job.inserted_at,\n attemptedAt: job.attempted_at ?? undefined,\n completedAt: job.completed_at ?? undefined,\n result: job.result,\n errors: job.errors as ErrorData[] | null | undefined,\n };\n } catch {\n return undefined;\n }\n }\n\n /**\n * 엔진 시작 여부\n */\n get started(): boolean {\n return this.isStarted;\n }\n\n /**\n * 등록된 Job 클래스 반환\n */\n getRegisteredJob(jobName: string): JobClassType | undefined {\n return this.registeredJobs.get(jobName);\n }\n\n /**\n * 모든 등록된 Job 클래스 반환\n */\n getAllRegisteredJobs(): Map<string, JobClassType> {\n return this.registeredJobs;\n }\n}\n\n// Job 베이스 클래스 re-export\nexport {Job} from 'sidequest';\n","import {Inject, Injectable, Logger, OnModuleDestroy, OnModuleInit} from '@nestjs/common';\nimport {SIDEQUEST_MODULE_OPTIONS} from '../constants.js';\nimport {SidequestAdapter} from '../core/sidequest.adapter.js';\nimport type {SidequestModuleOptions} from '../interfaces/module-options.interface.js';\n\n/**\n * Sidequest 엔진 관리 서비스\n *\n * Sidequest.js 엔진의 라이프사이클을 관리합니다.\n * 모듈 초기화 시 엔진을 시작하고, 종료 시 graceful shutdown을 수행합니다.\n */\n@Injectable()\nexport class SidequestEngineService implements OnModuleInit, OnModuleDestroy {\n private readonly logger = new Logger(SidequestEngineService.name);\n\n constructor(\n @Inject(SIDEQUEST_MODULE_OPTIONS)\n private readonly options: SidequestModuleOptions,\n private readonly adapter: SidequestAdapter,\n ) {}\n\n /**\n * 모듈 초기화 시 엔진 시작\n */\n async onModuleInit(): Promise<void> {\n this.logger.log('Initializing Sidequest engine...');\n await this.adapter.start(this.options);\n this.logger.log('Sidequest engine initialized');\n }\n\n /**\n * 모듈 종료 시 엔진 종료\n */\n async onModuleDestroy(): Promise<void> {\n const gracefulShutdown = this.options.gracefulShutdown ?? {enabled: true, timeout: 30000};\n\n if (gracefulShutdown.enabled) {\n this.logger.log(\n `Sidequest engine graceful shutdown (timeout: ${gracefulShutdown.timeout}ms)`,\n );\n }\n\n await this.adapter.shutdown();\n this.logger.log('Sidequest engine stopped');\n }\n\n /**\n * 엔진 시작 여부\n */\n get isStarted(): boolean {\n return this.adapter.started;\n }\n\n /**\n * Adapter 인스턴스 반환\n */\n getAdapter(): SidequestAdapter {\n return this.adapter;\n }\n}\n","import {Inject, Injectable, Logger} from '@nestjs/common';\nimport {SIDEQUEST_MODULE_OPTIONS} from '../constants.js';\nimport {SidequestAdapter} from '../core/sidequest.adapter.js';\nimport type {SidequestModuleOptions, QueueConfig} from '../interfaces/module-options.interface.js';\nimport type {IQueueService, JobAddOptions} from '../interfaces/queue.interface.js';\n\n/**\n * Queue 레지스트리 서비스\n *\n * 큐 인스턴스를 관리하고 @InjectQueue()를 위한 DI 프로바이더를 제공합니다.\n */\n@Injectable()\nexport class QueueRegistryService {\n private readonly logger = new Logger(QueueRegistryService.name);\n private readonly queueServices = new Map<string, IQueueService>();\n\n constructor(\n @Inject(SIDEQUEST_MODULE_OPTIONS)\n private readonly options: SidequestModuleOptions,\n private readonly adapter: SidequestAdapter,\n ) {\n this.initializeQueues();\n }\n\n /**\n * 설정된 큐 초기화\n */\n private initializeQueues(): void {\n const queues = this.options.queues ?? [];\n\n for (const queueConfig of queues) {\n this.registerQueue(queueConfig);\n }\n\n // 기본 큐가 없으면 생성\n if (!this.queueServices.has('default')) {\n this.registerQueue({name: 'default'});\n }\n }\n\n /**\n * 큐 등록\n */\n registerQueue(config: QueueConfig): void {\n const queueService = this.createQueueService(config.name);\n this.queueServices.set(config.name, queueService);\n this.logger.log(`Queue '${config.name}' registered`);\n }\n\n /**\n * 큐 서비스 조회\n */\n getQueue(name: string): IQueueService | undefined {\n return this.queueServices.get(name);\n }\n\n /**\n * 큐 서비스 조회 (없으면 에러)\n */\n getQueueOrThrow(name: string): IQueueService {\n const queue = this.getQueue(name);\n if (!queue) {\n throw new Error(\n `Queue '${name}' not found. Make sure it is registered in SidequestModule.forRoot().`,\n );\n }\n return queue;\n }\n\n /**\n * 모든 큐 조회\n */\n getAllQueues(): Map<string, IQueueService> {\n return this.queueServices;\n }\n\n /**\n * 큐 서비스 인스턴스 생성\n */\n private createQueueService(queueName: string): IQueueService {\n const adapter = this.adapter;\n\n return {\n name: queueName,\n\n async add<T>(JobClass: new (...args: unknown[]) => T, ...args: unknown[]): Promise<string> {\n const jobName = JobClass.name;\n return adapter.addJob(queueName, jobName, args);\n },\n\n async addWithOptions<T>(\n JobClass: new (...args: unknown[]) => T,\n options: JobAddOptions,\n ...args: unknown[]\n ): Promise<string> {\n const jobName = JobClass.name;\n return adapter.addJob(queueName, jobName, args, options);\n },\n\n async addScheduled<T>(\n JobClass: new (...args: unknown[]) => T,\n scheduledAt: Date,\n ...args: unknown[]\n ): Promise<string> {\n const jobName = JobClass.name;\n return adapter.addJob(queueName, jobName, args, {scheduledAt});\n },\n\n async addBulk<T>(\n jobs: Array<{\n JobClass: new (...args: unknown[]) => T;\n args: unknown[];\n options?: JobAddOptions;\n }>,\n ): Promise<string[]> {\n const bulkJobs = jobs.map(job => {\n const result: {jobName: string; args: unknown[]; options?: JobAddOptions} = {\n jobName: job.JobClass.name,\n args: job.args,\n };\n if (job.options !== undefined) {\n result.options = job.options;\n }\n return result;\n });\n return adapter.addBulkJobs(queueName, bulkJobs);\n },\n };\n }\n}\n","import {Injectable, Logger, Optional, Inject} from '@nestjs/common';\nimport {SIDEQUEST_MODULE_OPTIONS} from '../constants.js';\nimport type {SidequestModuleOptions} from '../interfaces/module-options.interface.js';\n\n// nestjs-cls 타입 (optional dependency)\ninterface ClsService {\n getId(): string | undefined;\n get<T>(key: string): T | undefined;\n set<T>(key: string, value: T): void;\n run<T>(callback: () => T): T;\n}\n\n/**\n * CLS(Continuation Local Storage) 통합 서비스\n *\n * nestjs-cls가 설치되어 있을 경우 Job 실행 시 context를 전파합니다.\n * nestjs-cls가 없으면 no-op으로 동작합니다.\n */\n@Injectable()\nexport class ClsIntegrationService {\n private readonly logger = new Logger(ClsIntegrationService.name);\n private readonly enabled: boolean;\n private clsService: ClsService | null = null;\n\n constructor(\n @Inject(SIDEQUEST_MODULE_OPTIONS)\n options: SidequestModuleOptions,\n @Optional() @Inject('ClsService') clsService?: ClsService,\n ) {\n this.enabled = options.enableCls ?? false;\n this.clsService = clsService ?? null;\n\n if (this.enabled && !this.clsService) {\n this.logger.warn(\n 'CLS integration is enabled but nestjs-cls is not installed. ' +\n 'Install nestjs-cls to enable context propagation.',\n );\n }\n }\n\n /**\n * CLS context 내에서 콜백 실행\n */\n async runInContext<T>(metadata: Record<string, unknown>, callback: () => Promise<T>): Promise<T> {\n if (!this.enabled || !this.clsService) {\n return callback();\n }\n\n // nestjs-cls의 run 메서드를 사용하여 새 context에서 실행\n return new Promise((resolve, reject) => {\n try {\n this.clsService!.run(() => {\n // 메타데이터를 CLS에 설정\n for (const [key, value] of Object.entries(metadata)) {\n this.clsService!.set(key, value);\n }\n\n callback().then(resolve).catch(reject);\n });\n } catch (error) {\n reject(error);\n }\n });\n }\n\n /**\n * 현재 traceId 조회\n */\n getTraceId(): string | undefined {\n if (!this.enabled || !this.clsService) {\n return undefined;\n }\n\n return this.clsService.get<string>('traceId');\n }\n\n /**\n * traceId 설정\n */\n setTraceId(traceId: string): void {\n if (!this.enabled || !this.clsService) {\n return;\n }\n\n this.clsService.set('traceId', traceId);\n }\n\n /**\n * CLS에서 값 조회\n */\n get<T>(key: string): T | undefined {\n if (!this.enabled || !this.clsService) {\n return undefined;\n }\n\n return this.clsService.get<T>(key);\n }\n\n /**\n * CLS에 값 설정\n */\n set<T>(key: string, value: T): void {\n if (!this.enabled || !this.clsService) {\n return;\n }\n\n this.clsService.set(key, value);\n }\n\n /**\n * CLS 통합 활성화 여부\n */\n isEnabled(): boolean {\n return this.enabled && this.clsService !== null;\n }\n}\n","import {Injectable, Logger, Optional} from '@nestjs/common';\nimport type {RegisteredProcessor, RegisteredHandler} from '../interfaces/processor.interface.js';\nimport {ClsIntegrationService} from './cls-integration.service.js';\n\n/**\n * Processor 레지스트리 서비스\n *\n * @Processor 데코레이터로 등록된 프로세서와 핸들러를 관리합니다.\n */\n@Injectable()\nexport class ProcessorRegistryService {\n private readonly logger = new Logger(ProcessorRegistryService.name);\n private readonly processors = new Map<string, RegisteredProcessor>();\n\n constructor(@Optional() private readonly clsService?: ClsIntegrationService) {}\n\n /**\n * 프로세서 등록\n */\n register(processor: RegisteredProcessor): void {\n this.processors.set(processor.queueName, processor);\n this.logger.log(\n `Processor '${processor.metatype.name}' (Queue: ${processor.queueName}) registered`,\n );\n }\n\n /**\n * 프로세서 조회\n */\n getProcessor(queueName: string): RegisteredProcessor | undefined {\n return this.processors.get(queueName);\n }\n\n /**\n * 모든 프로세서 조회\n */\n getAllProcessors(): Map<string, RegisteredProcessor> {\n return this.processors;\n }\n\n /**\n * Job 핸들러 조회\n */\n getJobHandler(queueName: string, jobName: string): RegisteredHandler | undefined {\n const processor = this.processors.get(queueName);\n if (!processor) {\n return undefined;\n }\n return processor.handlers.get(jobName);\n }\n\n /**\n * Job 완료 핸들러 조회\n */\n getCompleteHandler(queueName: string, jobName: string): string | undefined {\n const processor = this.processors.get(queueName);\n if (!processor) {\n return undefined;\n }\n return processor.completeHandlers.get(jobName) ?? processor.completeHandlers.get('*');\n }\n\n /**\n * Job 실패 핸들러 조회\n */\n getFailedHandler(queueName: string, jobName: string): string | undefined {\n const processor = this.processors.get(queueName);\n if (!processor) {\n return undefined;\n }\n return processor.failedHandlers.get(jobName) ?? processor.failedHandlers.get('*');\n }\n\n /**\n * Job 디스패치 (실행)\n *\n * @param queueName - 큐 이름\n * @param jobName - Job 이름\n * @param args - Job 인자\n * @param metadata - Job 메타데이터 (traceId 등)\n */\n async dispatch(\n queueName: string,\n jobName: string,\n args: unknown[],\n metadata?: Record<string, unknown>,\n ): Promise<unknown> {\n const processor = this.processors.get(queueName);\n if (!processor) {\n throw new Error(`Processor not found for Queue '${queueName}'`);\n }\n\n const handler = processor.handlers.get(jobName);\n if (!handler) {\n throw new Error(`Handler not found for Job '${jobName}' (Queue: ${queueName})`);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n const instance = processor.instance as Record<string, Function>;\n const method = instance[handler.methodName];\n\n if (typeof method !== 'function') {\n throw new Error(`Handler method '${handler.methodName}' not found`);\n }\n\n // CLS context에서 실행\n const executeJob = async (): Promise<unknown> => {\n try {\n const result = await method.apply(processor.instance, args);\n\n // 완료 핸들러 호출\n const completeHandlerName = this.getCompleteHandler(queueName, jobName);\n if (completeHandlerName) {\n const completeHandler = instance[completeHandlerName];\n if (typeof completeHandler === 'function') {\n await completeHandler.apply(processor.instance, [{jobName, args, result}]);\n }\n }\n\n return result;\n } catch (error) {\n // 실패 핸들러 호출\n const failedHandlerName = this.getFailedHandler(queueName, jobName);\n if (failedHandlerName) {\n const failedHandler = instance[failedHandlerName];\n if (typeof failedHandler === 'function') {\n await failedHandler.apply(processor.instance, [{jobName, args, error}]);\n }\n }\n\n throw error;\n }\n };\n\n // CLS 통합이 활성화되어 있으면 context 내에서 실행\n if (this.clsService?.isEnabled() && metadata) {\n return this.clsService.runInContext(metadata, executeJob);\n }\n\n return executeJob();\n }\n}\n","import {Injectable, Logger, OnModuleInit} from '@nestjs/common';\nimport {DiscoveryService, MetadataScanner, Reflector} from '@nestjs/core';\nimport {InstanceWrapper} from '@nestjs/core/injector/instance-wrapper';\nimport {\n PROCESSOR_METADATA_KEY,\n ON_JOB_METADATA_KEY,\n RETRY_OPTIONS_METADATA_KEY,\n ON_JOB_COMPLETE_METADATA_KEY,\n ON_JOB_FAILED_METADATA_KEY,\n} from '../constants.js';\nimport {ProcessorRegistryService} from '../services/processor-registry.service.js';\nimport type {\n ProcessorMetadata,\n OnJobMetadata,\n RetryOptions,\n RegisteredHandler,\n RegisteredProcessor,\n} from '../interfaces/processor.interface.js';\n\n/**\n * Processor Explorer\n *\n * 애플리케이션 시작 시 @Processor 데코레이터가 붙은 클래스를 스캔하고,\n * @OnJob, @Retry, @OnJobComplete, @OnJobFailed 메타데이터를 수집하여\n * ProcessorRegistry에 등록합니다.\n */\n@Injectable()\nexport class ProcessorExplorer implements OnModuleInit {\n private readonly logger = new Logger(ProcessorExplorer.name);\n\n constructor(\n private readonly discoveryService: DiscoveryService,\n private readonly metadataScanner: MetadataScanner,\n private readonly reflector: Reflector,\n private readonly processorRegistry: ProcessorRegistryService,\n ) {}\n\n /**\n * 모듈 초기화 시 프로세서 스캔\n */\n async onModuleInit(): Promise<void> {\n this.logger.log('Scanning for processors...');\n await this.explore();\n this.logger.log('Processor scan completed');\n }\n\n /**\n * 모든 프로바이더를 스캔하여 @Processor 클래스 찾기\n */\n async explore(): Promise<void> {\n const providers = this.discoveryService.getProviders();\n\n for (const wrapper of providers) {\n await this.processWrapper(wrapper);\n }\n }\n\n /**\n * 프로바이더 래퍼 처리\n */\n private async processWrapper(wrapper: InstanceWrapper): Promise<void> {\n const {instance, metatype} = wrapper;\n\n // 인스턴스와 메타타입이 없으면 스킵\n if (!instance || !metatype) {\n return;\n }\n\n // @Processor 메타데이터 확인\n const processorMetadata = this.reflector.get<ProcessorMetadata>(\n PROCESSOR_METADATA_KEY,\n metatype,\n );\n\n if (!processorMetadata) {\n return;\n }\n\n // 핸들러 스캔\n const handlers = this.scanHandlers(instance, metatype);\n const completeHandlers = this.scanCompleteHandlers(instance, metatype);\n const failedHandlers = this.scanFailedHandlers(instance, metatype);\n\n // 프로세서 등록\n const registeredProcessor: RegisteredProcessor = {\n queueName: processorMetadata.queueName,\n instance,\n metatype,\n handlers,\n completeHandlers,\n failedHandlers,\n };\n\n this.processorRegistry.register(registeredProcessor);\n\n this.logger.log(\n `Processor '${metatype.name}' registered (Queue: ${processorMetadata.queueName}, Handlers: ${handlers.size})`,\n );\n }\n\n /**\n * @OnJob 메서드 스캔\n */\n private scanHandlers(instance: unknown, _metatype: object): Map<string, RegisteredHandler> {\n const handlers = new Map<string, RegisteredHandler>();\n const prototype = Object.getPrototypeOf(instance);\n const methodNames = this.metadataScanner.getAllMethodNames(prototype);\n\n for (const methodName of methodNames) {\n const methodRef = prototype[methodName];\n\n // @OnJob 메타데이터 확인\n const onJobMetadata = this.reflector.get<OnJobMetadata>(ON_JOB_METADATA_KEY, methodRef);\n\n if (!onJobMetadata) {\n continue;\n }\n\n // @Retry 메타데이터 확인\n const retryOptions = this.reflector.get<RetryOptions>(RETRY_OPTIONS_METADATA_KEY, methodRef);\n\n const handler: RegisteredHandler = {\n methodName,\n jobName: onJobMetadata.jobName,\n options: onJobMetadata.options,\n retryOptions,\n };\n\n handlers.set(onJobMetadata.jobName, handler);\n\n this.logger.debug(` - Job '${onJobMetadata.jobName}' -> ${methodName}()`);\n }\n\n return handlers;\n }\n\n /**\n * @OnJobComplete 메서드 스캔\n */\n private scanCompleteHandlers(instance: unknown, _metatype: object): Map<string, string> {\n const handlers = new Map<string, string>();\n const prototype = Object.getPrototypeOf(instance);\n const methodNames = this.metadataScanner.getAllMethodNames(prototype);\n\n for (const methodName of methodNames) {\n const methodRef = prototype[methodName];\n\n // @OnJobComplete 메타데이터 확인\n const jobName = this.reflector.get<string | undefined>(\n ON_JOB_COMPLETE_METADATA_KEY,\n methodRef,\n );\n\n if (jobName !== undefined) {\n // jobName이 빈 문자열이면 모든 Job에 대해 호출 ('*')\n const key = jobName || '*';\n handlers.set(key, methodName);\n this.logger.debug(` - OnJobComplete '${key}' -> ${methodName}()`);\n }\n }\n\n return handlers;\n }\n\n /**\n * @OnJobFailed 메서드 스캔\n */\n private scanFailedHandlers(instance: unknown, _metatype: object): Map<string, string> {\n const handlers = new Map<string, string>();\n const prototype = Object.getPrototypeOf(instance);\n const methodNames = this.metadataScanner.getAllMethodNames(prototype);\n\n for (const methodName of methodNames) {\n const methodRef = prototype[methodName];\n\n // @OnJobFailed 메타데이터 확인\n const jobName = this.reflector.get<string | undefined>(ON_JOB_FAILED_METADATA_KEY, methodRef);\n\n if (jobName !== undefined) {\n // jobName이 빈 문자열이면 모든 Job에 대해 호출 ('*')\n const key = jobName || '*';\n handlers.set(key, methodName);\n this.logger.debug(` - OnJobFailed '${key}' -> ${methodName}()`);\n }\n }\n\n return handlers;\n }\n}\n","import {DynamicModule, Global, Module, Provider} from '@nestjs/common';\nimport {DiscoveryModule} from '@nestjs/core';\nimport {SIDEQUEST_MODULE_OPTIONS, getQueueToken} from '../constants.js';\nimport {SidequestAdapter} from '../core/sidequest.adapter.js';\nimport type {\n SidequestModuleOptions,\n SidequestModuleAsyncOptions,\n SidequestOptionsFactory,\n} from '../interfaces/module-options.interface.js';\nimport {SidequestEngineService} from '../services/sidequest-engine.service.js';\nimport {QueueRegistryService} from '../services/queue-registry.service.js';\nimport {ProcessorRegistryService} from '../services/processor-registry.service.js';\nimport {ClsIntegrationService} from '../services/cls-integration.service.js';\nimport {ProcessorExplorer} from '../explorers/processor.explorer.js';\n\n/**\n * SidequestModule\n *\n * NestJS에서 Sidequest.js를 사용하기 위한 메인 모듈입니다.\n *\n * @example\n * ```typescript\n * // 동기 설정\n * @Module({\n * imports: [\n * SidequestModule.forRoot({\n * backend: {\n * driver: '@sidequest/postgres-backend',\n * config: process.env.DATABASE_URL,\n * },\n * queues: [\n * { name: 'email', concurrency: 5 },\n * { name: 'report', concurrency: 2 },\n * ],\n * }),\n * ],\n * })\n * export class AppModule {}\n *\n * // 비동기 설정 (ConfigService 사용)\n * @Module({\n * imports: [\n * SidequestModule.forRootAsync({\n * imports: [ConfigModule],\n * useFactory: (config: ConfigService) => ({\n * backend: {\n * driver: '@sidequest/postgres-backend',\n * config: config.get('DATABASE_URL'),\n * },\n * queues: [{ name: 'default' }],\n * }),\n * inject: [ConfigService],\n * }),\n * ],\n * })\n * export class AppModule {}\n * ```\n */\n@Global()\n@Module({})\nexport class SidequestModule {\n /**\n * 동기 설정으로 모듈 등록\n */\n static forRoot(options: SidequestModuleOptions): DynamicModule {\n const isGlobal = options.isGlobal ?? true;\n const queueProviders = this.createQueueProviders(options);\n\n return {\n module: SidequestModule,\n global: isGlobal,\n imports: [DiscoveryModule],\n providers: [\n {\n provide: SIDEQUEST_MODULE_OPTIONS,\n useValue: options,\n },\n SidequestAdapter,\n SidequestEngineService,\n QueueRegistryService,\n ProcessorRegistryService,\n ClsIntegrationService,\n ProcessorExplorer,\n ...queueProviders,\n ],\n exports: [\n SIDEQUEST_MODULE_OPTIONS,\n SidequestAdapter,\n SidequestEngineService,\n QueueRegistryService,\n ProcessorRegistryService,\n ClsIntegrationService,\n ...queueProviders.map(p => (p as {provide: symbol | string}).provide),\n ],\n };\n }\n\n /**\n * 비동기 설정으로 모듈 등록\n */\n static forRootAsync(asyncOptions: SidequestModuleAsyncOptions): DynamicModule {\n const isGlobal = asyncOptions.isGlobal ?? true;\n\n return {\n module: SidequestModule,\n global: isGlobal,\n imports: [DiscoveryModule, ...(asyncOptions.imports || [])],\n providers: [\n ...this.createAsyncProviders(asyncOptions),\n SidequestAdapter,\n SidequestEngineService,\n QueueRegistryService,\n ProcessorRegistryService,\n ClsIntegrationService,\n ProcessorExplorer,\n // 동적 큐 프로바이더 - options에서 queues를 읽어 생성\n {\n provide: 'SIDEQUEST_QUEUE_PROVIDERS_INIT',\n useFactory: () => {\n // QueueRegistryService가 자동으로 큐를 초기화하므로 별도 처리 불필요\n return true;\n },\n inject: [QueueRegistryService],\n },\n ],\n exports: [\n SIDEQUEST_MODULE_OPTIONS,\n SidequestAdapter,\n SidequestEngineService,\n QueueRegistryService,\n ProcessorRegistryService,\n ClsIntegrationService,\n ],\n };\n }\n\n /**\n * 큐별 DI 프로바이더 생성\n */\n private static createQueueProviders(options: SidequestModuleOptions): Provider[] {\n const queues = options.queues ?? [{name: 'default'}];\n\n return queues.map(queue => ({\n provide: getQueueToken(queue.name),\n useFactory: (registry: QueueRegistryService) => registry.getQueueOrThrow(queue.name),\n inject: [QueueRegistryService],\n }));\n }\n\n /**\n * 비동기 프로바이더 생성\n */\n private static createAsyncProviders(asyncOptions: SidequestModuleAsyncOptions): Provider[] {\n if (asyncOptions.useFactory) {\n return [\n {\n provide: SIDEQUEST_MODULE_OPTIONS,\n useFactory: asyncOptions.useFactory,\n inject: asyncOptions.inject || [],\n },\n ];\n }\n\n if (asyncOptions.useClass) {\n return [\n {\n provide: asyncOptions.useClass,\n useClass: asyncOptions.useClass,\n },\n {\n provide: SIDEQUEST_MODULE_OPTIONS,\n useFactory: async (optionsFactory: SidequestOptionsFactory) =>\n optionsFactory.createSidequestOptions(),\n inject: [asyncOptions.useClass],\n },\n ];\n }\n\n if (asyncOptions.useExisting) {\n return [\n {\n provide: SIDEQUEST_MODULE_OPTIONS,\n useFactory: async (optionsFactory: SidequestOptionsFactory) =>\n optionsFactory.createSidequestOptions(),\n inject: [asyncOptions.useExisting],\n },\n ];\n }\n\n return [\n {\n provide: SIDEQUEST_MODULE_OPTIONS,\n useValue: {},\n },\n ];\n }\n}\n","import {Injectable, SetMetadata} from '@nestjs/common';\nimport {PROCESSOR_METADATA_KEY} from '../constants.js';\nimport type {ProcessorOptions, ProcessorMetadata} from '../interfaces/processor.interface.js';\n\n/**\n * 클래스를 Sidequest Job Processor로 지정합니다.\n *\n * @Processor 데코레이터가 붙은 클래스는 모듈 초기화 시 자동으로 스캔되어\n * 해당 큐의 Job 핸들러로 등록됩니다.\n *\n * @param queueName - 처리할 큐 이름\n * @param options - 프로세서 옵션\n *\n * @example\n * ```typescript\n * @Processor('email')\n * export class EmailProcessor {\n * @OnJob('send-welcome-email')\n * async handleWelcomeEmail(job: JobContext) {\n * const { to, subject, body } = job.data;\n * await this.mailer.send({ to, subject, body });\n * }\n * }\n *\n * // 동시성 설정과 함께\n * @Processor('report', { concurrency: 2 })\n * export class ReportProcessor {\n * @OnJob('generate-daily-report')\n * async handleDailyReport(job: JobContext) {\n * // 리포트 생성 로직\n * }\n * }\n * ```\n */\nexport function Processor(queueName: string, options?: ProcessorOptions): ClassDecorator {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n return (target: Function): void => {\n const metadata: ProcessorMetadata = {\n queueName,\n options,\n };\n\n // 메타데이터 설정\n SetMetadata(PROCESSOR_METADATA_KEY, metadata)(target);\n\n // @Injectable() 자동 적용\n Injectable()(target);\n };\n}\n","import {SetMetadata} from '@nestjs/common';\nimport {ON_JOB_METADATA_KEY} from '../constants.js';\nimport type {OnJobOptions, OnJobMetadata} from '../interfaces/processor.interface.js';\n\n/**\n * 메서드를 특정 Job 타입의 핸들러로 지정합니다.\n *\n * @Processor 데코레이터가 붙은 클래스 내부에서 사용합니다.\n * 해당 Job이 큐에서 처리될 때 이 메서드가 호출됩니다.\n *\n * @param jobName - Job 이름 (일반적으로 Job 클래스명)\n * @param options - Job 실행 옵션 (우선순위, 타임아웃 등)\n *\n * @example\n * ```typescript\n * @Processor('email')\n * export class EmailProcessor {\n * @OnJob('SendWelcomeEmailJob')\n * async handleWelcomeEmail(job: JobContext) {\n * const { to, subject, body } = job.data;\n * await this.mailer.send({ to, subject, body });\n * }\n *\n * // 우선순위와 타임아웃 설정\n * @OnJob('SendPriorityEmailJob', { priority: 100, timeout: 5000 })\n * async handlePriorityEmail(job: JobContext) {\n * // 우선순위가 높은 이메일 처리\n * }\n * }\n * ```\n */\nexport function OnJob(jobName: string, options?: OnJobOptions): MethodDecorator {\n return (\n target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor,\n ): PropertyDescriptor => {\n const metadata: OnJobMetadata = {\n jobName,\n options,\n };\n\n SetMetadata(ON_JOB_METADATA_KEY, metadata)(target, propertyKey, descriptor);\n\n return descriptor;\n };\n}\n","import {SetMetadata} from '@nestjs/common';\nimport {RETRY_OPTIONS_METADATA_KEY} from '../constants.js';\nimport type {RetryOptions} from '../interfaces/processor.interface.js';\n\n/**\n * Job 재시도 정책을 설정합니다.\n *\n * @OnJob 데코레이터와 함께 사용하여 Job 실패 시 재시도 동작을 정의합니다.\n *\n * @param options - 재시도 옵션\n *\n * @example\n * ```typescript\n * @Processor('payment')\n * export class PaymentProcessor {\n * // 고정 지연 재시도\n * @OnJob('ProcessPaymentJob')\n * @Retry({ maxAttempts: 3, delay: 1000 })\n * async handlePayment(job: JobContext) {\n * // 결제 처리 로직\n * }\n *\n * // 지수 백오프 재시도\n * @OnJob('RefundJob')\n * @Retry({ maxAttempts: 5, delay: 500, backoff: 'exponential' })\n * async handleRefund(job: JobContext) {\n * // 환불 처리 로직\n * }\n * }\n * ```\n */\nexport function Retry(options: RetryOptions): MethodDecorator {\n return (\n target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor,\n ): PropertyDescriptor => {\n SetMetadata(RETRY_OPTIONS_METADATA_KEY, options)(target, propertyKey, descriptor);\n return descriptor;\n };\n}\n","import {Inject} from '@nestjs/common';\nimport {getQueueToken} from '../constants.js';\n\n/**\n * Queue 인스턴스를 주입합니다.\n *\n * SidequestModule.forRoot()에서 등록된 큐를 서비스에 주입받아 사용할 수 있습니다.\n *\n * @param queueName - 주입받을 큐 이름\n *\n * @example\n * ```typescript\n * @Injectable()\n * export class UserService {\n * constructor(\n * @InjectQueue('email') private emailQueue: IQueueService,\n * @InjectQueue('notification') private notificationQueue: IQueueService,\n * ) {}\n *\n * async createUser(email: string, name: string) {\n * // 사용자 생성 로직...\n *\n * // 환영 이메일 발송\n * await this.emailQueue.add(SendWelcomeEmailJob, email, `Welcome, ${name}!`);\n *\n * // 알림 발송\n * await this.notificationQueue.add(SendNotificationJob, email, 'new-user');\n * }\n * }\n * ```\n */\nexport function InjectQueue(queueName: string): ParameterDecorator {\n return Inject(getQueueToken(queueName));\n}\n","import {SetMetadata} from '@nestjs/common';\nimport {ON_JOB_COMPLETE_METADATA_KEY} from '../constants.js';\n\n/**\n * Job 완료 이벤트 핸들러를 지정합니다.\n *\n * @Processor 클래스 내부에서 사용하며, Job이 성공적으로 완료되면 호출됩니다.\n *\n * @param jobName - 대상 Job 이름 (생략 시 모든 Job에 대해 호출)\n *\n * @example\n * ```typescript\n * @Processor('email')\n * export class EmailProcessor {\n * @OnJob('SendWelcomeEmailJob')\n * async handleWelcomeEmail(job: JobContext) {\n * await this.mailer.send(job.data);\n * }\n *\n * // 특정 Job 완료 이벤트\n * @OnJobComplete('SendWelcomeEmailJob')\n * async onWelcomeEmailComplete(event: JobCompleteEvent) {\n * this.logger.log(`환영 이메일 발송 완료: ${event.result}`);\n * await this.analytics.track('email_sent', { type: 'welcome' });\n * }\n *\n * // 모든 Job 완료 이벤트 (jobName 생략)\n * @OnJobComplete()\n * async onAnyJobComplete(event: JobCompleteEvent) {\n * this.logger.log(`Job 완료: ${event.jobName}`);\n * }\n * }\n * ```\n */\nexport function OnJobComplete(jobName?: string): MethodDecorator {\n return (\n target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor,\n ): PropertyDescriptor => {\n // jobName이 undefined면 빈 문자열로 저장 (모든 Job에 대해 호출)\n SetMetadata(ON_JOB_COMPLETE_METADATA_KEY, jobName ?? '')(target, propertyKey, descriptor);\n return descriptor;\n };\n}\n\n/**\n * Job 완료 이벤트 데이터\n */\nexport interface JobCompleteEvent {\n /** Job 이름 */\n jobName: string;\n\n /** Job 실행 인자 */\n args: unknown[];\n\n /** Job 실행 결과 */\n result: unknown;\n}\n","import {SetMetadata} from '@nestjs/common';\nimport {ON_JOB_FAILED_METADATA_KEY} from '../constants.js';\n\n/**\n * Job 실패 이벤트 핸들러를 지정합니다.\n *\n * @Processor 클래스 내부에서 사용하며, Job 실행이 실패하면 호출됩니다.\n * 재시도 횟수를 모두 소진한 후 최종 실패 시에만 호출됩니다.\n *\n * @param jobName - 대상 Job 이름 (생략 시 모든 Job에 대해 호출)\n *\n * @example\n * ```typescript\n * @Processor('payment')\n * export class PaymentProcessor {\n * @OnJob('ProcessPaymentJob')\n * @Retry({ maxAttempts: 3 })\n * async handlePayment(job: JobContext) {\n * await this.paymentService.process(job.data);\n * }\n *\n * // 특정 Job 실패 이벤트\n * @OnJobFailed('ProcessPaymentJob')\n * async onPaymentFailed(event: JobFailedEvent) {\n * this.logger.error(`결제 처리 실패: ${event.error.message}`);\n * await this.alertService.notify('payment-failure', {\n * orderId: event.args[0],\n * error: event.error.message,\n * });\n * }\n *\n * // 모든 Job 실패 이벤트 (jobName 생략)\n * @OnJobFailed()\n * async onAnyJobFailed(event: JobFailedEvent) {\n * this.logger.error(`Job 실패: ${event.jobName}`, event.error);\n * }\n * }\n * ```\n */\nexport function OnJobFailed(jobName?: string): MethodDecorator {\n return (\n target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor,\n ): PropertyDescriptor => {\n // jobName이 undefined면 빈 문자열로 저장 (모든 Job에 대해 호출)\n SetMetadata(ON_JOB_FAILED_METADATA_KEY, jobName ?? '')(target, propertyKey, descriptor);\n return descriptor;\n };\n}\n\n/**\n * Job 실패 이벤트 데이터\n */\nexport interface JobFailedEvent {\n /** Job 이름 */\n jobName: string;\n\n /** Job 실행 인자 */\n args: unknown[];\n\n /** 발생한 에러 */\n error: Error;\n}\n"]}
|
package/package.json
CHANGED