{"_id":"@avoylenko/nestjs-groupmq","_rev":"3-6e119dcf727aa5196095f2679deca110","name":"@avoylenko/nestjs-groupmq","dist-tags":{"latest":"2.0.0"},"versions":{"0.1.0":{"name":"@avoylenko/nestjs-groupmq","version":"0.1.0","keywords":["nestjs","groupmq","queue","redis","fifo","jobs","worker"],"author":{"name":"Anton Voylenko"},"license":"MIT","_id":"@avoylenko/nestjs-groupmq@0.1.0","maintainers":[{"name":"avoylenko","email":"anton.voylenko@gmail.com"}],"homepage":"https://github.com/avoylenko/nestjs-groupmq#readme","bugs":{"url":"https://github.com/avoylenko/nestjs-groupmq/issues"},"dist":{"shasum":"ff05999380c8eb5c6e819f3cec2f204a92759a5c","tarball":"https://registry.npmjs.org/@avoylenko/nestjs-groupmq/-/nestjs-groupmq-0.1.0.tgz","fileCount":65,"integrity":"sha512-CmI4dtvmGKWfM9zlotRZaz0Gfi5DWKMX8e5SadDDIDSeo4LkwyKIuG4uuTQis20NNWWfmmGDRHlAVNOMSPNU7A==","signatures":[{"sig":"MEYCIQDDVvSfkqk9ienjO6LcxeaVtGC9ScnleUSv56J6F4hEoQIhAOM0iridbI0o44bvZ4MGDhLAgSzVektuSJR7L1bg4J40","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":61307},"main":"dist/index.js","type":"commonjs","types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js","require":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"3cea44434b5a4455e568f426cf2b375fc77ab35e","scripts":{"test":"vitest run","build":"rimraf dist && tsc -p tsconfig.build.json","test:dev":"vitest","test:e2e":"vitest run --config vitest.config.e2e.mts","test:e2e:dev":"vitest --config vitest.config.e2e.mts","example:start":"ts-node --transpile-only --project examples/tsconfig.json examples/main.ts","prepublishOnly":"npm run build"},"_npmUser":{"name":"avoylenko","email":"anton.voylenko@gmail.com"},"repository":{"url":"git+https://github.com/avoylenko/nestjs-groupmq.git","type":"git"},"_npmVersion":"11.11.0","description":"NestJS module for groupmq - per-group FIFO Redis queues, in the style of @nestjs/bullmq","directories":{},"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"rxjs":"7.8.2","rimraf":"6.0.1","vitest":"3.0.5","groupmq":"1.1.0","ioredis":"5.4.1","ts-node":"^10.9.2","@swc/core":"^1.15.43","typescript":"5.7.3","@types/node":"24.12.4","@nestjs/core":"11.1.21","unplugin-swc":"^1.5.9","@nestjs/common":"11.1.21","@nestjs/testing":"11.1.21","reflect-metadata":"0.2.2","@nestjs/platform-express":"11.1.21"},"peerDependencies":{"groupmq":"^1.0.0","ioredis":"^5.0.0","@nestjs/core":"^10.0.0 || ^11.0.0","@nestjs/common":"^10.0.0 || ^11.0.0"},"_npmOperationalInternal":{"tmp":"tmp/nestjs-groupmq_0.1.0_1782564421886_0.32631282381268223","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@avoylenko/nestjs-groupmq","version":"0.1.1","keywords":["nestjs","groupmq","queue","redis","fifo","jobs","worker"],"author":{"name":"Anton Voylenko"},"license":"MIT","_id":"@avoylenko/nestjs-groupmq@0.1.1","maintainers":[{"name":"avoylenko","email":"anton.voylenko@gmail.com"}],"homepage":"https://github.com/avoylenko/nestjs-groupmq#readme","bugs":{"url":"https://github.com/avoylenko/nestjs-groupmq/issues"},"dist":{"shasum":"351c0edcf2f0d82049372c51802c48eb4c3f4603","tarball":"https://registry.npmjs.org/@avoylenko/nestjs-groupmq/-/nestjs-groupmq-0.1.1.tgz","fileCount":65,"integrity":"sha512-ZEno9gRQGpZ2W5nyLnitJbPIB2cpJcPy56emnC7vYlH6rHoGgr2JgdlazH927MDfr5WT7n1ccF9lkUD8tbGk8Q==","signatures":[{"sig":"MEYCIQCG5cYo/GqbElF6Qg3Yb4Law7kQINuuDPcJhoY8Mk0skwIhAK0yAQAXFgfY9dwltTbbuzIf0SGhCt5V5YAaBhGo0bNh","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":61393},"main":"dist/index.js","type":"commonjs","types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js","require":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"4b6b3528a46a51d4d53809a94f545d45e9d775e8","scripts":{"test":"vitest run","build":"rimraf dist && tsc -p tsconfig.build.json","test:dev":"vitest","test:e2e":"vitest run --config vitest.config.e2e.mts","typecheck":"tsc -p tsconfig.typecheck.json","test:e2e:dev":"vitest --config vitest.config.e2e.mts","example:start":"ts-node --transpile-only --project examples/tsconfig.json examples/main.ts","prepublishOnly":"npm run build"},"_npmUser":{"name":"avoylenko","email":"anton.voylenko@gmail.com"},"repository":{"url":"git+https://github.com/avoylenko/nestjs-groupmq.git","type":"git"},"_npmVersion":"11.11.0","description":"NestJS module for groupmq - per-group FIFO Redis queues, in the style of @nestjs/bullmq","directories":{},"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"rxjs":"7.8.2","rimraf":"6.0.1","vitest":"3.0.5","groupmq":"1.1.0","ioredis":"5.4.1","ts-node":"^10.9.2","@swc/core":"^1.15.43","typescript":"5.7.3","@types/node":"24.12.4","@nestjs/core":"11.1.21","unplugin-swc":"^1.5.9","@nestjs/common":"11.1.21","@nestjs/testing":"11.1.21","reflect-metadata":"0.2.2","@nestjs/platform-express":"11.1.21"},"peerDependencies":{"groupmq":"^1.0.0","ioredis":"^5.0.0","@nestjs/core":"^10.0.0 || ^11.0.0","@nestjs/common":"^10.0.0 || ^11.0.0"},"_npmOperationalInternal":{"tmp":"tmp/nestjs-groupmq_0.1.1_1788382268465_0.7329599788324834","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"_id":"@avoylenko/nestjs-groupmq@2.0.0","bugs":{"url":"https://github.com/avoylenko/nestjs-groupmq/issues"},"dist":{"shasum":"5ad9bf5a3f4569f1071b6b6fcf4cdce6911b56e4","tarball":"https://registry.npmjs.org/@avoylenko/nestjs-groupmq/-/nestjs-groupmq-2.0.0.tgz","fileCount":65,"integrity":"sha512-UntVOXQ2BfM7jS4vI5VoWDLdAapwuzgzZY4cZ3oBUnDtHgdb0mev2BBcVkO+k8NTQAM8f0MvBd6gDk603bFD9Q==","signatures":[{"sig":"MEYCIQD9hqExLhSl+YoC/S6BvBuZ1K4cUFJRVKHaA2BjMAKmyQIhAMhTI8/WKOLe5jPWqFpMtEYZOowxRAKUB4ZmmCEdBijZ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIANUaNfQZ2UUq9JRhY/xQ0Jzvog6FQCbV9kBNKCZ5CC9AiEA6LRBuZ6wYOW8eFIs2KXAHmRy0OXBBwvsGMwwj0sCSq0="}],"unpackedSize":59320},"main":"dist/index.js","name":"@avoylenko/nestjs-groupmq","type":"commonjs","types":"dist/index.d.ts","author":{"name":"Anton Voylenko"},"engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js","require":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"36480d2631a10df0dff8ca80a2c4563c6399aabf","license":"MIT","scripts":{"test":"vitest run","build":"rimraf dist && tsc -p tsconfig.build.json","test:dev":"vitest","test:e2e":"vitest run --config vitest.config.e2e.mts","typecheck":"tsc -p tsconfig.typecheck.json","test:e2e:dev":"vitest --config vitest.config.e2e.mts","example:start":"ts-node --transpile-only --project examples/tsconfig.json examples/main.ts","prepublishOnly":"npm run build"},"version":"2.0.0","_npmUser":{"name":"avoylenko","email":"anton.voylenko@gmail.com"},"homepage":"https://github.com/avoylenko/nestjs-groupmq#readme","keywords":["nestjs","groupmq","queue","redis","fifo","jobs","worker"],"repository":{"url":"git+https://github.com/avoylenko/nestjs-groupmq.git","type":"git"},"_npmVersion":"11.11.0","description":"NestJS module for groupmq - per-group FIFO Redis queues, in the style of @nestjs/bullmq","directories":{},"maintainers":[{"name":"avoylenko","email":"anton.voylenko@gmail.com"}],"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"rxjs":"7.8.2","rimraf":"6.0.1","vitest":"3.0.5","groupmq":"2.0.0-next.7","ioredis":"5.4.1","ts-node":"^10.9.2","@swc/core":"^1.15.43","typescript":"5.7.3","@types/node":"24.12.4","@nestjs/core":"11.1.21","unplugin-swc":"^1.5.9","@nestjs/common":"11.1.21","@nestjs/testing":"11.1.21","reflect-metadata":"0.2.2","@nestjs/platform-express":"11.1.21"},"peerDependencies":{"groupmq":"^2.0.0-0","ioredis":"^5.0.0 || ^6.0.0","@nestjs/core":"^10.0.0 || ^11.0.0","@nestjs/common":"^10.0.0 || ^11.0.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/nestjs-groupmq_2.0.0_1790371525880_0.2492637817347454"}}},"time":{"created":"2026-06-27T12:47:01.645Z","modified":"2026-09-25T21:25:26.221Z","0.1.0":"2026-06-27T12:47:02.027Z","0.1.1":"2026-09-02T20:51:08.604Z","2.0.0":"2026-09-25T21:25:26.042Z"},"bugs":{"url":"https://github.com/avoylenko/nestjs-groupmq/issues"},"author":{"name":"Anton Voylenko"},"license":"MIT","homepage":"https://github.com/avoylenko/nestjs-groupmq#readme","keywords":["nestjs","groupmq","queue","redis","fifo","jobs","worker"],"repository":{"url":"git+https://github.com/avoylenko/nestjs-groupmq.git","type":"git"},"description":"NestJS module for groupmq - per-group FIFO Redis queues, in the style of @nestjs/bullmq","maintainers":[{"name":"avoylenko","email":"anton.voylenko@gmail.com"}],"readme":"# @avoylenko/nestjs-groupmq\n\nNestJS module for [groupmq](https://github.com/Openpanel-dev/groupmq) — a fast,\nRedis-backed **per-group FIFO** queue with guaranteed in-group ordering and\nparallel processing across groups.\n\nThe API mirrors [`@nestjs/bullmq`](https://github.com/nestjs/bull) as closely as\ngroupmq allows, so if you know `@nestjs/bullmq` you already know this package.\n\n## Features\n\n- `GroupMqModule.forRoot()` / `forRootAsync()` — shared Redis connection + defaults\n- `GroupMqModule.registerQueue()` / `registerQueueAsync()` — DI-injectable queues\n- `@InjectQueue()`, `@Processor()`, `WorkerHost`, `@OnWorkerEvent()`\n- Automatic worker lifecycle (start on bootstrap, graceful close on shutdown)\n- Request-scoped processors\n- Bull Board helper\n\n## Installation\n\n```bash\nnpm i @avoylenko/nestjs-groupmq groupmq ioredis\n```\n\n`@nestjs/common`, `@nestjs/core`, `groupmq` and `ioredis` are peer dependencies.\n\n## Quick start\n\n### 1. Register the module\n\n```ts\nimport { Module } from '@nestjs/common';\nimport { GroupMqModule } from '@avoylenko/nestjs-groupmq';\n\n@Module({\n  imports: [\n    GroupMqModule.forRoot({\n      // ioredis options (the module creates & owns the client) or an existing Redis instance\n      connection: { host: 'localhost', port: 6379 },\n      // optional groupmq defaults merged into every queue\n      defaultJobOptions: { maxAttempts: 5 },\n    }),\n    GroupMqModule.registerQueue({\n      name: 'orders', // injection token + default namespace (\"orders\")\n      jobTimeoutMs: 30_000,\n    }),\n  ],\n})\nexport class AppModule {}\n```\n\n### 2. Define a processor\n\nA processor is a class decorated with `@Processor()` that extends `WorkerHost`\nand implements `process()`. The returned promise is used as the groupmq worker\nhandler; jobs within the same `groupId` are processed strictly in order.\n\n```ts\nimport { Processor, WorkerHost, OnWorkerEvent } from '@avoylenko/nestjs-groupmq';\nimport type { Job, ReservedJob } from '@avoylenko/nestjs-groupmq';\n\ninterface OrderData {\n  userId: string;\n  amount: number;\n}\n\n@Processor('orders', { concurrency: 8 })\nexport class OrdersProcessor extends WorkerHost {\n  async process(job: ReservedJob<OrderData>): Promise<void> {\n    // do work; per-group FIFO is guaranteed by groupmq\n  }\n\n  @OnWorkerEvent('completed')\n  onCompleted(job: Job<OrderData>) {}\n\n  @OnWorkerEvent('failed')\n  onFailed(job: Job<OrderData>) {}\n}\n```\n\nRegister the processor as a provider in the same module that imports the queue:\n\n```ts\n@Module({\n  imports: [GroupMqModule.registerQueue({ name: 'orders' })],\n  providers: [OrdersProcessor],\n})\nexport class OrdersModule {}\n```\n\n### 3. Enqueue jobs\n\n```ts\nimport { Injectable } from '@nestjs/common';\nimport { InjectQueue } from '@avoylenko/nestjs-groupmq';\nimport type { Queue } from '@avoylenko/nestjs-groupmq';\n\n@Injectable()\nexport class OrdersService {\n  constructor(@InjectQueue('orders') private readonly queue: Queue<OrderData>) {}\n\n  enqueue(data: OrderData) {\n    return this.queue.add({ groupId: `user:${data.userId}`, data });\n  }\n}\n```\n\n## Async configuration\n\n```ts\nGroupMqModule.forRootAsync({\n  imports: [ConfigModule],\n  inject: [ConfigService],\n  useFactory: (config: ConfigService) => ({\n    connection: { host: config.get('REDIS_HOST'), port: config.get('REDIS_PORT') },\n  }),\n});\n\nGroupMqModule.registerQueueAsync({\n  name: 'orders',\n  imports: [ConfigModule],\n  inject: [ConfigService],\n  useFactory: (config: ConfigService) => ({\n    jobTimeoutMs: config.get('ORDERS_TIMEOUT'),\n  }),\n});\n```\n\n## Multiple connections (`configKey`)\n\nRegister several independent shared configurations and bind a queue to one:\n\n```ts\nGroupMqModule.forRoot('analytics', { connection: { host: 'analytics-redis' } });\nGroupMqModule.registerQueue({ name: 'events', configKey: 'analytics' });\n```\n\nA queue may also override the connection directly:\n\n```ts\nGroupMqModule.registerQueue({\n  name: 'events',\n  connection: { host: 'other-redis', port: 6380 },\n});\n```\n\n## Worker events\n\n`@OnWorkerEvent(eventName)` registers a method as a listener on the underlying\ngroupmq worker. Supported events: `completed`, `failed`, `ready`, `error`,\n`closed`, `graceful-timeout`, `stalled`, `ioredis:close`.\n\n> Not supported on request-scoped processors.\n\n## Bull Board\n\n```ts\nimport { createBullBoard } from '@bull-board/api';\nimport { createGroupMqBoardAdapter, InjectQueue } from '@avoylenko/nestjs-groupmq';\nimport type { Queue } from '@avoylenko/nestjs-groupmq';\n\n@Injectable()\nexport class BoardService {\n  constructor(@InjectQueue('orders') queue: Queue) {\n    createBullBoard({\n      queues: [createGroupMqBoardAdapter(queue, { displayName: 'Orders' })],\n      serverAdapter,\n    });\n  }\n}\n```\n\n## Manual worker registration\n\nBy default workers start during `onApplicationBootstrap`. To control this\nyourself, enable `manualRegistration` and call `GroupMqRegistrar.register()`:\n\n```ts\nGroupMqModule.forRoot({ connection: {/* ... */}, manualRegistration: true });\n\nconst app = await NestFactory.createApplicationContext(AppModule);\n// ...warm caches, run migrations, etc.\nawait GroupMqRegistrar.register(app);\n```\n\n## Differences from `@nestjs/bullmq`\n\ngroupmq has no `FlowProducer` and no separate `QueueEvents` class, so this\npackage intentionally omits `registerFlowProducer*`, `@InjectFlowProducer`,\n`@QueueEventsListener` and `@OnQueueEvent`. Job names do not exist in groupmq, so\nthere is a single `process()` method per processor (no named `@Process`).\nConnections are ioredis-based: `forRoot({ connection })` accepts `RedisOptions`\nor an existing `Redis` instance.\n\n## Development\n\n```bash\nnpm install\nnpm run build\nnpm test            # unit tests\nnpm run test:e2e    # e2e tests (requires Redis at 127.0.0.1:6379)\n```\n\nThe e2e suite exercises the integration end-to-end against a real Redis,\nincluding module wiring (sync + async registration) and the groupmq behaviours\nthe wrapper surfaces — per-group FIFO ordering, cross-group concurrency,\nretry/backoff with the `failed` event, and graceful shutdown of in-flight jobs.\n\n## License\n\nMIT\n","readmeFilename":"README.md"}