@hivehub/rulebook 4.1.0 → 4.2.1
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/.claude/commands/continue.md +33 -33
- package/.claude/commands/ralph-config.md +112 -112
- package/.claude/commands/ralph-history.md +110 -110
- package/.claude/commands/ralph-init.md +72 -72
- package/.claude/commands/ralph-pause-resume.md +105 -105
- package/.claude/commands/ralph-run.md +101 -101
- package/.claude/commands/ralph-status.md +76 -76
- package/.claude/commands/rulebook-memory-save.md +48 -48
- package/.claude/commands/rulebook-memory-search.md +47 -47
- package/.claude/commands/rulebook-task-apply.md +67 -67
- package/.claude/commands/rulebook-task-archive.md +70 -70
- package/.claude/commands/rulebook-task-create.md +93 -93
- package/.claude/commands/rulebook-task-list.md +42 -42
- package/.claude/commands/rulebook-task-show.md +52 -52
- package/.claude/commands/rulebook-task-validate.md +53 -53
- package/.claude-plugin/marketplace.json +28 -28
- package/.claude-plugin/plugin.json +8 -8
- package/README.md +137 -1
- package/dist/cli/commands.d.ts +18 -6
- package/dist/cli/commands.d.ts.map +1 -1
- package/dist/cli/commands.js +727 -406
- package/dist/cli/commands.js.map +1 -1
- package/dist/core/claude-mcp.d.ts +4 -2
- package/dist/core/claude-mcp.d.ts.map +1 -1
- package/dist/core/claude-mcp.js +14 -9
- package/dist/core/claude-mcp.js.map +1 -1
- package/dist/core/generator.d.ts.map +1 -1
- package/dist/core/generator.js +13 -0
- package/dist/core/generator.js.map +1 -1
- package/dist/core/indexer/background-indexer.d.ts.map +1 -1
- package/dist/core/indexer/background-indexer.js +26 -5
- package/dist/core/indexer/background-indexer.js.map +1 -1
- package/dist/core/indexer/file-parser.d.ts.map +1 -1
- package/dist/core/indexer/file-parser.js +1 -1
- package/dist/core/indexer/file-parser.js.map +1 -1
- package/dist/core/indexer/indexer-types.d.ts.map +1 -1
- package/dist/core/workspace/legacy-migrator.d.ts +29 -0
- package/dist/core/workspace/legacy-migrator.d.ts.map +1 -0
- package/dist/core/workspace/legacy-migrator.js +142 -0
- package/dist/core/workspace/legacy-migrator.js.map +1 -0
- package/dist/core/workspace/project-worker.d.ts +49 -0
- package/dist/core/workspace/project-worker.d.ts.map +1 -0
- package/dist/core/workspace/project-worker.js +108 -0
- package/dist/core/workspace/project-worker.js.map +1 -0
- package/dist/core/workspace/workspace-manager.d.ts +90 -0
- package/dist/core/workspace/workspace-manager.d.ts.map +1 -0
- package/dist/core/workspace/workspace-manager.js +347 -0
- package/dist/core/workspace/workspace-manager.js.map +1 -0
- package/dist/core/workspace/workspace-types.d.ts +37 -0
- package/dist/core/workspace/workspace-types.d.ts.map +1 -0
- package/dist/core/workspace/workspace-types.js +8 -0
- package/dist/core/workspace/workspace-types.js.map +1 -0
- package/dist/index.js +43 -7
- package/dist/index.js.map +1 -1
- package/dist/mcp/rulebook-server.d.ts.map +1 -1
- package/dist/mcp/rulebook-server.js +367 -100
- package/dist/mcp/rulebook-server.js.map +1 -1
- package/dist/memory/memory-manager.js +2 -2
- package/dist/memory/memory-manager.js.map +1 -1
- package/dist/memory/memory-search.js.map +1 -1
- package/dist/memory/memory-store.d.ts.map +1 -1
- package/dist/memory/memory-store.js +1 -1
- package/dist/memory/memory-store.js.map +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +22 -21
- package/templates/agents/implementer.md +35 -35
- package/templates/agents/researcher.md +34 -34
- package/templates/agents/team-lead.md +34 -34
- package/templates/agents/tester.md +42 -42
- package/templates/ci/rulebook-review.yml +26 -26
- package/templates/cli/AIDER.md +49 -49
- package/templates/cli/AMAZON_Q.md +25 -25
- package/templates/cli/AUGGIE.md +32 -32
- package/templates/cli/CLAUDE.md +117 -117
- package/templates/cli/CLINE.md +99 -99
- package/templates/cli/CODEBUDDY.md +20 -20
- package/templates/cli/CODEIUM.md +20 -20
- package/templates/cli/CODEX.md +21 -21
- package/templates/cli/CONTINUE.md +34 -34
- package/templates/cli/CURSOR_CLI.md +62 -62
- package/templates/cli/FACTORY.md +18 -18
- package/templates/cli/GEMINI.md +35 -35
- package/templates/cli/KILOCODE.md +18 -18
- package/templates/cli/OPENCODE.md +18 -18
- package/templates/cli/_GENERIC_TEMPLATE.md +29 -29
- package/templates/commands/rulebook-memory-save.md +48 -48
- package/templates/commands/rulebook-memory-search.md +47 -47
- package/templates/commands/rulebook-task-apply.md +67 -67
- package/templates/commands/rulebook-task-archive.md +94 -94
- package/templates/commands/rulebook-task-create.md +93 -93
- package/templates/commands/rulebook-task-list.md +42 -42
- package/templates/commands/rulebook-task-show.md +52 -52
- package/templates/commands/rulebook-task-validate.md +53 -53
- package/templates/core/AGENTS_LEAN.md +25 -25
- package/templates/core/AGENTS_OVERRIDE.md +16 -16
- package/templates/core/AGENT_AUTOMATION.md +288 -288
- package/templates/core/DAG.md +304 -304
- package/templates/core/DOCUMENTATION_RULES.md +36 -36
- package/templates/core/MULTI_AGENT.md +74 -74
- package/templates/core/PLANS.md +28 -28
- package/templates/core/QUALITY_ENFORCEMENT.md +68 -68
- package/templates/core/RALPH.md +471 -471
- package/templates/core/RULEBOOK.md +1935 -1935
- package/templates/core/WORKSPACE.md +69 -0
- package/templates/frameworks/ANGULAR.md +36 -36
- package/templates/frameworks/DJANGO.md +83 -83
- package/templates/frameworks/ELECTRON.md +147 -147
- package/templates/frameworks/FLASK.md +38 -38
- package/templates/frameworks/FLUTTER.md +55 -55
- package/templates/frameworks/JQUERY.md +32 -32
- package/templates/frameworks/LARAVEL.md +38 -38
- package/templates/frameworks/NESTJS.md +43 -43
- package/templates/frameworks/NEXTJS.md +127 -127
- package/templates/frameworks/NUXT.md +40 -40
- package/templates/frameworks/RAILS.md +66 -66
- package/templates/frameworks/REACT.md +38 -38
- package/templates/frameworks/REACT_NATIVE.md +47 -47
- package/templates/frameworks/SPRING.md +39 -39
- package/templates/frameworks/SYMFONY.md +36 -36
- package/templates/frameworks/VUE.md +36 -36
- package/templates/frameworks/ZEND.md +35 -35
- package/templates/git/CI_CD_PATTERNS.md +661 -661
- package/templates/git/GITHUB_ACTIONS.md +728 -728
- package/templates/git/GITLAB_CI.md +730 -730
- package/templates/git/GIT_WORKFLOW.md +1157 -1157
- package/templates/git/SECRETS_MANAGEMENT.md +585 -585
- package/templates/hooks/COMMIT_MSG.md +530 -530
- package/templates/hooks/POST_CHECKOUT.md +546 -546
- package/templates/hooks/PREPARE_COMMIT_MSG.md +619 -619
- package/templates/hooks/PRE_COMMIT.md +414 -414
- package/templates/hooks/PRE_PUSH.md +601 -601
- package/templates/ides/CONTINUE_RULES.md +16 -16
- package/templates/ides/COPILOT.md +37 -37
- package/templates/ides/COPILOT_INSTRUCTIONS.md +23 -23
- package/templates/ides/CURSOR.md +43 -43
- package/templates/ides/GEMINI_RULES.md +17 -17
- package/templates/ides/JETBRAINS_AI.md +35 -35
- package/templates/ides/REPLIT.md +36 -36
- package/templates/ides/TABNINE.md +29 -29
- package/templates/ides/VSCODE.md +40 -40
- package/templates/ides/WINDSURF.md +36 -36
- package/templates/ides/WINDSURF_RULES.md +14 -14
- package/templates/ides/ZED.md +32 -32
- package/templates/ides/cursor-mdc/go.mdc +24 -24
- package/templates/ides/cursor-mdc/python.mdc +24 -24
- package/templates/ides/cursor-mdc/quality.mdc +25 -25
- package/templates/ides/cursor-mdc/ralph.mdc +39 -39
- package/templates/ides/cursor-mdc/rulebook.mdc +38 -38
- package/templates/ides/cursor-mdc/rust.mdc +24 -24
- package/templates/ides/cursor-mdc/typescript.mdc +25 -25
- package/templates/languages/C.md +333 -333
- package/templates/languages/CPP.md +743 -743
- package/templates/languages/CSHARP.md +417 -417
- package/templates/languages/ELIXIR.md +454 -454
- package/templates/languages/ERLANG.md +361 -361
- package/templates/languages/GO.md +645 -645
- package/templates/languages/HASKELL.md +177 -177
- package/templates/languages/JAVA.md +607 -607
- package/templates/languages/JAVASCRIPT.md +631 -631
- package/templates/languages/JULIA.md +97 -97
- package/templates/languages/KOTLIN.md +511 -511
- package/templates/languages/LISP.md +100 -100
- package/templates/languages/LUA.md +74 -74
- package/templates/languages/OBJECTIVEC.md +90 -90
- package/templates/languages/PHP.md +416 -416
- package/templates/languages/PYTHON.md +682 -682
- package/templates/languages/RUBY.md +421 -421
- package/templates/languages/RUST.md +477 -477
- package/templates/languages/SAS.md +73 -73
- package/templates/languages/SCALA.md +348 -348
- package/templates/languages/SOLIDITY.md +580 -580
- package/templates/languages/SQL.md +137 -137
- package/templates/languages/SWIFT.md +466 -466
- package/templates/languages/TYPESCRIPT.md +591 -591
- package/templates/languages/ZIG.md +265 -265
- package/templates/modules/ATLASSIAN.md +255 -255
- package/templates/modules/CONTEXT7.md +54 -54
- package/templates/modules/FIGMA.md +267 -267
- package/templates/modules/GITHUB_MCP.md +64 -64
- package/templates/modules/GRAFANA.md +328 -328
- package/templates/modules/MEMORY.md +126 -126
- package/templates/modules/NOTION.md +247 -247
- package/templates/modules/PLAYWRIGHT.md +90 -90
- package/templates/modules/RULEBOOK_MCP.md +156 -156
- package/templates/modules/SERENA.md +337 -337
- package/templates/modules/SUPABASE.md +223 -223
- package/templates/modules/SYNAP.md +69 -69
- package/templates/modules/VECTORIZER.md +63 -63
- package/templates/modules/sequential-thinking.md +42 -42
- package/templates/ralph/ralph-history.bat +4 -4
- package/templates/ralph/ralph-history.sh +5 -5
- package/templates/ralph/ralph-init.bat +5 -5
- package/templates/ralph/ralph-init.sh +5 -5
- package/templates/ralph/ralph-pause.bat +5 -5
- package/templates/ralph/ralph-pause.sh +5 -5
- package/templates/ralph/ralph-run.bat +5 -5
- package/templates/ralph/ralph-run.sh +5 -5
- package/templates/ralph/ralph-status.bat +4 -4
- package/templates/ralph/ralph-status.sh +5 -5
- package/templates/services/AZURE_BLOB.md +184 -184
- package/templates/services/CASSANDRA.md +239 -239
- package/templates/services/DATADOG.md +26 -26
- package/templates/services/DOCKER.md +124 -124
- package/templates/services/DOCKER_COMPOSE.md +168 -168
- package/templates/services/DYNAMODB.md +308 -308
- package/templates/services/ELASTICSEARCH.md +347 -347
- package/templates/services/GCS.md +178 -178
- package/templates/services/HELM.md +194 -194
- package/templates/services/INFLUXDB.md +265 -265
- package/templates/services/KAFKA.md +341 -341
- package/templates/services/KUBERNETES.md +208 -208
- package/templates/services/MARIADB.md +183 -183
- package/templates/services/MEMCACHED.md +242 -242
- package/templates/services/MINIO.md +201 -201
- package/templates/services/MONGODB.md +268 -268
- package/templates/services/MYSQL.md +358 -358
- package/templates/services/NEO4J.md +247 -247
- package/templates/services/OPENTELEMETRY.md +25 -25
- package/templates/services/ORACLE.md +290 -290
- package/templates/services/PINO.md +24 -24
- package/templates/services/POSTGRESQL.md +326 -326
- package/templates/services/PROMETHEUS.md +33 -33
- package/templates/services/RABBITMQ.md +286 -286
- package/templates/services/REDIS.md +292 -292
- package/templates/services/S3.md +298 -298
- package/templates/services/SENTRY.md +23 -23
- package/templates/services/SQLITE.md +294 -294
- package/templates/services/SQLSERVER.md +294 -294
- package/templates/services/WINSTON.md +30 -30
- package/templates/skills/cli/aider/SKILL.md +59 -59
- package/templates/skills/cli/amazon-q/SKILL.md +35 -35
- package/templates/skills/cli/auggie/SKILL.md +42 -42
- package/templates/skills/cli/claude/SKILL.md +42 -42
- package/templates/skills/cli/cline/SKILL.md +42 -42
- package/templates/skills/cli/codebuddy/SKILL.md +30 -30
- package/templates/skills/cli/codeium/SKILL.md +30 -30
- package/templates/skills/cli/codex/SKILL.md +31 -31
- package/templates/skills/cli/continue/SKILL.md +44 -44
- package/templates/skills/cli/cursor-cli/SKILL.md +38 -38
- package/templates/skills/cli/factory/SKILL.md +28 -28
- package/templates/skills/cli/gemini/SKILL.md +45 -45
- package/templates/skills/cli/kilocode/SKILL.md +28 -28
- package/templates/skills/cli/opencode/SKILL.md +28 -28
- package/templates/skills/core/agent-automation/SKILL.md +194 -194
- package/templates/skills/core/dag/SKILL.md +314 -314
- package/templates/skills/core/documentation-rules/SKILL.md +46 -46
- package/templates/skills/core/quality-enforcement/SKILL.md +78 -78
- package/templates/skills/core/rulebook/SKILL.md +176 -176
- package/templates/skills/frameworks/angular/SKILL.md +46 -46
- package/templates/skills/frameworks/django/SKILL.md +93 -93
- package/templates/skills/frameworks/electron/SKILL.md +157 -157
- package/templates/skills/frameworks/flask/SKILL.md +48 -48
- package/templates/skills/frameworks/flutter/SKILL.md +65 -65
- package/templates/skills/frameworks/jquery/SKILL.md +42 -42
- package/templates/skills/frameworks/laravel/SKILL.md +48 -48
- package/templates/skills/frameworks/nestjs/SKILL.md +53 -53
- package/templates/skills/frameworks/nextjs/SKILL.md +137 -137
- package/templates/skills/frameworks/nuxt/SKILL.md +50 -50
- package/templates/skills/frameworks/rails/SKILL.md +76 -76
- package/templates/skills/frameworks/react/SKILL.md +48 -48
- package/templates/skills/frameworks/react-native/SKILL.md +57 -57
- package/templates/skills/frameworks/spring/SKILL.md +49 -49
- package/templates/skills/frameworks/symfony/SKILL.md +46 -46
- package/templates/skills/frameworks/vue/SKILL.md +46 -46
- package/templates/skills/frameworks/zend/SKILL.md +45 -45
- package/templates/skills/ides/copilot/SKILL.md +47 -47
- package/templates/skills/ides/cursor/SKILL.md +53 -53
- package/templates/skills/ides/jetbrains-ai/SKILL.md +45 -45
- package/templates/skills/ides/replit/SKILL.md +46 -46
- package/templates/skills/ides/tabnine/SKILL.md +39 -39
- package/templates/skills/ides/vscode/SKILL.md +50 -50
- package/templates/skills/ides/windsurf/SKILL.md +46 -46
- package/templates/skills/ides/zed/SKILL.md +42 -42
- package/templates/skills/languages/c/SKILL.md +343 -343
- package/templates/skills/languages/cpp/SKILL.md +753 -753
- package/templates/skills/languages/csharp/SKILL.md +427 -427
- package/templates/skills/languages/elixir/SKILL.md +464 -464
- package/templates/skills/languages/erlang/SKILL.md +371 -371
- package/templates/skills/languages/go/SKILL.md +655 -655
- package/templates/skills/languages/haskell/SKILL.md +187 -187
- package/templates/skills/languages/java/SKILL.md +617 -617
- package/templates/skills/languages/javascript/SKILL.md +641 -641
- package/templates/skills/languages/julia/SKILL.md +107 -107
- package/templates/skills/languages/kotlin/SKILL.md +521 -521
- package/templates/skills/languages/lisp/SKILL.md +110 -110
- package/templates/skills/languages/lua/SKILL.md +84 -84
- package/templates/skills/languages/objectivec/SKILL.md +100 -100
- package/templates/skills/languages/php/SKILL.md +426 -426
- package/templates/skills/languages/python/SKILL.md +692 -692
- package/templates/skills/languages/ruby/SKILL.md +431 -431
- package/templates/skills/languages/rust/SKILL.md +487 -487
- package/templates/skills/languages/sas/SKILL.md +83 -83
- package/templates/skills/languages/scala/SKILL.md +358 -358
- package/templates/skills/languages/solidity/SKILL.md +590 -590
- package/templates/skills/languages/sql/SKILL.md +147 -147
- package/templates/skills/languages/swift/SKILL.md +476 -476
- package/templates/skills/languages/typescript/SKILL.md +302 -302
- package/templates/skills/languages/zig/SKILL.md +275 -275
- package/templates/skills/modules/atlassian/SKILL.md +265 -265
- package/templates/skills/modules/context7/SKILL.md +64 -64
- package/templates/skills/modules/figma/SKILL.md +277 -277
- package/templates/skills/modules/github-mcp/SKILL.md +74 -74
- package/templates/skills/modules/grafana/SKILL.md +338 -338
- package/templates/skills/modules/memory/SKILL.md +73 -73
- package/templates/skills/modules/notion/SKILL.md +257 -257
- package/templates/skills/modules/playwright/SKILL.md +100 -100
- package/templates/skills/modules/rulebook-mcp/SKILL.md +166 -166
- package/templates/skills/modules/serena/SKILL.md +347 -347
- package/templates/skills/modules/supabase/SKILL.md +233 -233
- package/templates/skills/modules/synap/SKILL.md +79 -79
- package/templates/skills/modules/vectorizer/SKILL.md +73 -73
- package/templates/skills/services/azure-blob/SKILL.md +194 -194
- package/templates/skills/services/cassandra/SKILL.md +249 -249
- package/templates/skills/services/dynamodb/SKILL.md +318 -318
- package/templates/skills/services/elasticsearch/SKILL.md +357 -357
- package/templates/skills/services/gcs/SKILL.md +188 -188
- package/templates/skills/services/influxdb/SKILL.md +275 -275
- package/templates/skills/services/kafka/SKILL.md +351 -351
- package/templates/skills/services/mariadb/SKILL.md +193 -193
- package/templates/skills/services/memcached/SKILL.md +252 -252
- package/templates/skills/services/minio/SKILL.md +211 -211
- package/templates/skills/services/mongodb/SKILL.md +278 -278
- package/templates/skills/services/mysql/SKILL.md +368 -368
- package/templates/skills/services/neo4j/SKILL.md +257 -257
- package/templates/skills/services/oracle/SKILL.md +300 -300
- package/templates/skills/services/postgresql/SKILL.md +336 -336
- package/templates/skills/services/rabbitmq/SKILL.md +296 -296
- package/templates/skills/services/redis/SKILL.md +302 -302
- package/templates/skills/services/s3/SKILL.md +308 -308
- package/templates/skills/services/sqlite/SKILL.md +304 -304
- package/templates/skills/services/sqlserver/SKILL.md +304 -304
- package/templates/skills/workflows/ralph/SKILL.md +309 -309
- package/templates/skills/workflows/ralph/install.sh +87 -87
- package/templates/skills/workflows/ralph/manifest.json +158 -158
|
@@ -1,296 +1,296 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: "RabbitMQ"
|
|
3
|
-
description: "Use RabbitMQ for reliable message queuing, pub/sub messaging, and task distribution with multiple exchange types."
|
|
4
|
-
version: "1.0.0"
|
|
5
|
-
category: "services"
|
|
6
|
-
author: "Rulebook"
|
|
7
|
-
tags: ["services", "messaging"]
|
|
8
|
-
dependencies: []
|
|
9
|
-
conflicts: []
|
|
10
|
-
---
|
|
11
|
-
<!-- RABBITMQ:START -->
|
|
12
|
-
# RabbitMQ Message Queue Instructions
|
|
13
|
-
|
|
14
|
-
**CRITICAL**: Use RabbitMQ for reliable message queuing, pub/sub messaging, and task distribution with multiple exchange types.
|
|
15
|
-
|
|
16
|
-
## Core Features
|
|
17
|
-
|
|
18
|
-
### Connection
|
|
19
|
-
```typescript
|
|
20
|
-
// Using amqplib
|
|
21
|
-
import amqp from 'amqplib'
|
|
22
|
-
|
|
23
|
-
const connection = await amqp.connect(process.env.RABBITMQ_URL || 'amqp://localhost:5672')
|
|
24
|
-
const channel = await connection.createChannel()
|
|
25
|
-
|
|
26
|
-
// Connection with options
|
|
27
|
-
const connection = await amqp.connect({
|
|
28
|
-
protocol: 'amqp',
|
|
29
|
-
hostname: process.env.RABBITMQ_HOST || 'localhost',
|
|
30
|
-
port: parseInt(process.env.RABBITMQ_PORT || '5672'),
|
|
31
|
-
username: process.env.RABBITMQ_USER || 'guest',
|
|
32
|
-
password: process.env.RABBITMQ_PASSWORD || 'guest',
|
|
33
|
-
vhost: process.env.RABBITMQ_VHOST || '/',
|
|
34
|
-
})
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
### Basic Operations
|
|
38
|
-
```typescript
|
|
39
|
-
// Declare queue
|
|
40
|
-
await channel.assertQueue('tasks', {
|
|
41
|
-
durable: true, // Survive broker restart
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
// Send message
|
|
45
|
-
channel.sendToQueue('tasks', Buffer.from(JSON.stringify({ task: 'process' })), {
|
|
46
|
-
persistent: true, // Survive broker restart
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
// Consume messages
|
|
50
|
-
await channel.consume('tasks', (msg) => {
|
|
51
|
-
if (msg) {
|
|
52
|
-
const content = JSON.parse(msg.content.toString())
|
|
53
|
-
console.log('Received:', content)
|
|
54
|
-
|
|
55
|
-
// Process message
|
|
56
|
-
processTask(content)
|
|
57
|
-
|
|
58
|
-
// Acknowledge
|
|
59
|
-
channel.ack(msg)
|
|
60
|
-
}
|
|
61
|
-
}, {
|
|
62
|
-
noAck: false, // Manual acknowledgment
|
|
63
|
-
})
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
### Exchange Types
|
|
67
|
-
```typescript
|
|
68
|
-
// Direct exchange
|
|
69
|
-
await channel.assertExchange('logs', 'direct', { durable: true })
|
|
70
|
-
await channel.bindQueue('queue', 'logs', 'error')
|
|
71
|
-
await channel.publish('logs', 'error', Buffer.from('Error message'))
|
|
72
|
-
|
|
73
|
-
// Topic exchange
|
|
74
|
-
await channel.assertExchange('events', 'topic', { durable: true })
|
|
75
|
-
await channel.bindQueue('queue', 'events', 'user.*.created')
|
|
76
|
-
await channel.publish('events', 'user.123.created', Buffer.from(JSON.stringify(data)))
|
|
77
|
-
|
|
78
|
-
// Fanout exchange (broadcast)
|
|
79
|
-
await channel.assertExchange('notifications', 'fanout', { durable: true })
|
|
80
|
-
await channel.bindQueue('queue1', 'notifications', '')
|
|
81
|
-
await channel.bindQueue('queue2', 'notifications', '')
|
|
82
|
-
await channel.publish('notifications', '', Buffer.from('Broadcast message'))
|
|
83
|
-
|
|
84
|
-
// Headers exchange
|
|
85
|
-
await channel.assertExchange('headers_exchange', 'headers', { durable: true })
|
|
86
|
-
await channel.bindQueue('queue', 'headers_exchange', '', {
|
|
87
|
-
'x-match': 'all',
|
|
88
|
-
type: 'notification',
|
|
89
|
-
priority: 'high',
|
|
90
|
-
})
|
|
91
|
-
await channel.publish('headers_exchange', '', Buffer.from('Message'), {
|
|
92
|
-
headers: { type: 'notification', priority: 'high' },
|
|
93
|
-
})
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
## Common Patterns
|
|
97
|
-
|
|
98
|
-
### Work Queue (Task Distribution)
|
|
99
|
-
```typescript
|
|
100
|
-
// Producer
|
|
101
|
-
async function publishTask(task: any) {
|
|
102
|
-
await channel.assertQueue('tasks', { durable: true })
|
|
103
|
-
channel.sendToQueue('tasks', Buffer.from(JSON.stringify(task)), {
|
|
104
|
-
persistent: true,
|
|
105
|
-
})
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Consumer
|
|
109
|
-
async function consumeTasks() {
|
|
110
|
-
await channel.assertQueue('tasks', { durable: true })
|
|
111
|
-
channel.prefetch(1) // Process one message at a time
|
|
112
|
-
|
|
113
|
-
await channel.consume('tasks', async (msg) => {
|
|
114
|
-
if (msg) {
|
|
115
|
-
try {
|
|
116
|
-
const task = JSON.parse(msg.content.toString())
|
|
117
|
-
await processTask(task)
|
|
118
|
-
channel.ack(msg)
|
|
119
|
-
} catch (error) {
|
|
120
|
-
// Reject and requeue
|
|
121
|
-
channel.nack(msg, false, true)
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
})
|
|
125
|
-
}
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
### Pub/Sub
|
|
129
|
-
```typescript
|
|
130
|
-
// Publisher
|
|
131
|
-
async function publishEvent(eventType: string, data: any) {
|
|
132
|
-
await channel.assertExchange('events', 'topic', { durable: true })
|
|
133
|
-
channel.publish('events', eventType, Buffer.from(JSON.stringify(data)), {
|
|
134
|
-
persistent: true,
|
|
135
|
-
})
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// Subscriber
|
|
139
|
-
async function subscribeToEvents(routingKey: string, handler: (data: any) => void) {
|
|
140
|
-
await channel.assertExchange('events', 'topic', { durable: true })
|
|
141
|
-
const queue = await channel.assertQueue('', { exclusive: true })
|
|
142
|
-
await channel.bindQueue(queue.queue, 'events', routingKey)
|
|
143
|
-
|
|
144
|
-
await channel.consume(queue.queue, (msg) => {
|
|
145
|
-
if (msg) {
|
|
146
|
-
const data = JSON.parse(msg.content.toString())
|
|
147
|
-
handler(data)
|
|
148
|
-
channel.ack(msg)
|
|
149
|
-
}
|
|
150
|
-
})
|
|
151
|
-
}
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
### RPC Pattern
|
|
155
|
-
```typescript
|
|
156
|
-
// RPC Server
|
|
157
|
-
async function setupRPCServer() {
|
|
158
|
-
await channel.assertQueue('rpc_queue', { durable: false })
|
|
159
|
-
channel.prefetch(1)
|
|
160
|
-
|
|
161
|
-
await channel.consume('rpc_queue', async (msg) => {
|
|
162
|
-
if (msg) {
|
|
163
|
-
const request = JSON.parse(msg.content.toString())
|
|
164
|
-
const response = await processRequest(request)
|
|
165
|
-
|
|
166
|
-
channel.sendToQueue(
|
|
167
|
-
msg.properties.replyTo,
|
|
168
|
-
Buffer.from(JSON.stringify(response)),
|
|
169
|
-
{
|
|
170
|
-
correlationId: msg.properties.correlationId,
|
|
171
|
-
}
|
|
172
|
-
)
|
|
173
|
-
|
|
174
|
-
channel.ack(msg)
|
|
175
|
-
}
|
|
176
|
-
})
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// RPC Client
|
|
180
|
-
async function rpcCall(request: any): Promise<any> {
|
|
181
|
-
const queue = await channel.assertQueue('', { exclusive: true })
|
|
182
|
-
const correlationId = generateUuid()
|
|
183
|
-
|
|
184
|
-
return new Promise((resolve, reject) => {
|
|
185
|
-
const timeout = setTimeout(() => {
|
|
186
|
-
channel.deleteQueue(queue.queue)
|
|
187
|
-
reject(new Error('RPC timeout'))
|
|
188
|
-
}, 10000)
|
|
189
|
-
|
|
190
|
-
channel.consume(queue.queue, (msg) => {
|
|
191
|
-
if (msg && msg.properties.correlationId === correlationId) {
|
|
192
|
-
clearTimeout(timeout)
|
|
193
|
-
const response = JSON.parse(msg.content.toString())
|
|
194
|
-
channel.deleteQueue(queue.queue)
|
|
195
|
-
resolve(response)
|
|
196
|
-
}
|
|
197
|
-
}, { noAck: true })
|
|
198
|
-
|
|
199
|
-
channel.sendToQueue('rpc_queue', Buffer.from(JSON.stringify(request)), {
|
|
200
|
-
correlationId,
|
|
201
|
-
replyTo: queue.queue,
|
|
202
|
-
})
|
|
203
|
-
})
|
|
204
|
-
}
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
## Best Practices
|
|
208
|
-
|
|
209
|
-
✅ **DO:**
|
|
210
|
-
- Use durable queues and exchanges for important messages
|
|
211
|
-
- Set message persistence for critical messages
|
|
212
|
-
- Use manual acknowledgment (noAck: false)
|
|
213
|
-
- Implement proper error handling
|
|
214
|
-
- Use prefetch to control message distribution
|
|
215
|
-
- Monitor queue lengths
|
|
216
|
-
- Use dead letter exchanges for failed messages
|
|
217
|
-
- Implement connection retry logic
|
|
218
|
-
- Use appropriate exchange types
|
|
219
|
-
- Set message TTL when needed
|
|
220
|
-
|
|
221
|
-
❌ **DON'T:**
|
|
222
|
-
- Skip acknowledgment (lose messages on crash)
|
|
223
|
-
- Use auto-ack for critical messages
|
|
224
|
-
- Ignore connection errors
|
|
225
|
-
- Hardcode connection strings
|
|
226
|
-
- Store large messages (use external storage)
|
|
227
|
-
- Skip error handling
|
|
228
|
-
- Ignore queue monitoring
|
|
229
|
-
- Use non-durable queues for important data
|
|
230
|
-
- Skip message persistence
|
|
231
|
-
- Ignore memory limits
|
|
232
|
-
|
|
233
|
-
## Configuration
|
|
234
|
-
|
|
235
|
-
### Environment Variables
|
|
236
|
-
```bash
|
|
237
|
-
RABBITMQ_URL=amqp://localhost:5672
|
|
238
|
-
RABBITMQ_URL=amqp://user:password@host:5672/vhost
|
|
239
|
-
RABBITMQ_HOST=localhost
|
|
240
|
-
RABBITMQ_PORT=5672
|
|
241
|
-
RABBITMQ_USER=guest
|
|
242
|
-
RABBITMQ_PASSWORD=guest
|
|
243
|
-
RABBITMQ_VHOST=/
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
### Docker Compose
|
|
247
|
-
```yaml
|
|
248
|
-
services:
|
|
249
|
-
rabbitmq:
|
|
250
|
-
image: rabbitmq:3-management-alpine
|
|
251
|
-
ports:
|
|
252
|
-
- "5672:5672" # AMQP
|
|
253
|
-
- "15672:15672" # Management UI
|
|
254
|
-
environment:
|
|
255
|
-
RABBITMQ_DEFAULT_USER: admin
|
|
256
|
-
RABBITMQ_DEFAULT_PASS: securepassword
|
|
257
|
-
volumes:
|
|
258
|
-
- rabbitmq_data:/var/lib/rabbitmq
|
|
259
|
-
healthcheck:
|
|
260
|
-
test: ["CMD", "rabbitmq-diagnostics", "ping"]
|
|
261
|
-
interval: 10s
|
|
262
|
-
timeout: 5s
|
|
263
|
-
retries: 5
|
|
264
|
-
|
|
265
|
-
volumes:
|
|
266
|
-
rabbitmq_data:
|
|
267
|
-
```
|
|
268
|
-
|
|
269
|
-
## Integration with Development
|
|
270
|
-
|
|
271
|
-
### Testing
|
|
272
|
-
```typescript
|
|
273
|
-
// Use test connection
|
|
274
|
-
const testConnection = await amqp.connect('amqp://localhost:5673') // Different port
|
|
275
|
-
|
|
276
|
-
// Clean up after tests
|
|
277
|
-
afterEach(async () => {
|
|
278
|
-
// Delete test queues/exchanges or use separate vhost
|
|
279
|
-
})
|
|
280
|
-
```
|
|
281
|
-
|
|
282
|
-
### Health Checks
|
|
283
|
-
```typescript
|
|
284
|
-
async function checkRabbitMQHealth(): Promise<boolean> {
|
|
285
|
-
try {
|
|
286
|
-
const connection = await amqp.connect(process.env.RABBITMQ_URL)
|
|
287
|
-
await connection.close()
|
|
288
|
-
return true
|
|
289
|
-
} catch {
|
|
290
|
-
return false
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
<!-- RABBITMQ:END -->
|
|
296
|
-
|
|
1
|
+
---
|
|
2
|
+
name: "RabbitMQ"
|
|
3
|
+
description: "Use RabbitMQ for reliable message queuing, pub/sub messaging, and task distribution with multiple exchange types."
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
category: "services"
|
|
6
|
+
author: "Rulebook"
|
|
7
|
+
tags: ["services", "messaging"]
|
|
8
|
+
dependencies: []
|
|
9
|
+
conflicts: []
|
|
10
|
+
---
|
|
11
|
+
<!-- RABBITMQ:START -->
|
|
12
|
+
# RabbitMQ Message Queue Instructions
|
|
13
|
+
|
|
14
|
+
**CRITICAL**: Use RabbitMQ for reliable message queuing, pub/sub messaging, and task distribution with multiple exchange types.
|
|
15
|
+
|
|
16
|
+
## Core Features
|
|
17
|
+
|
|
18
|
+
### Connection
|
|
19
|
+
```typescript
|
|
20
|
+
// Using amqplib
|
|
21
|
+
import amqp from 'amqplib'
|
|
22
|
+
|
|
23
|
+
const connection = await amqp.connect(process.env.RABBITMQ_URL || 'amqp://localhost:5672')
|
|
24
|
+
const channel = await connection.createChannel()
|
|
25
|
+
|
|
26
|
+
// Connection with options
|
|
27
|
+
const connection = await amqp.connect({
|
|
28
|
+
protocol: 'amqp',
|
|
29
|
+
hostname: process.env.RABBITMQ_HOST || 'localhost',
|
|
30
|
+
port: parseInt(process.env.RABBITMQ_PORT || '5672'),
|
|
31
|
+
username: process.env.RABBITMQ_USER || 'guest',
|
|
32
|
+
password: process.env.RABBITMQ_PASSWORD || 'guest',
|
|
33
|
+
vhost: process.env.RABBITMQ_VHOST || '/',
|
|
34
|
+
})
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Basic Operations
|
|
38
|
+
```typescript
|
|
39
|
+
// Declare queue
|
|
40
|
+
await channel.assertQueue('tasks', {
|
|
41
|
+
durable: true, // Survive broker restart
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
// Send message
|
|
45
|
+
channel.sendToQueue('tasks', Buffer.from(JSON.stringify({ task: 'process' })), {
|
|
46
|
+
persistent: true, // Survive broker restart
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
// Consume messages
|
|
50
|
+
await channel.consume('tasks', (msg) => {
|
|
51
|
+
if (msg) {
|
|
52
|
+
const content = JSON.parse(msg.content.toString())
|
|
53
|
+
console.log('Received:', content)
|
|
54
|
+
|
|
55
|
+
// Process message
|
|
56
|
+
processTask(content)
|
|
57
|
+
|
|
58
|
+
// Acknowledge
|
|
59
|
+
channel.ack(msg)
|
|
60
|
+
}
|
|
61
|
+
}, {
|
|
62
|
+
noAck: false, // Manual acknowledgment
|
|
63
|
+
})
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Exchange Types
|
|
67
|
+
```typescript
|
|
68
|
+
// Direct exchange
|
|
69
|
+
await channel.assertExchange('logs', 'direct', { durable: true })
|
|
70
|
+
await channel.bindQueue('queue', 'logs', 'error')
|
|
71
|
+
await channel.publish('logs', 'error', Buffer.from('Error message'))
|
|
72
|
+
|
|
73
|
+
// Topic exchange
|
|
74
|
+
await channel.assertExchange('events', 'topic', { durable: true })
|
|
75
|
+
await channel.bindQueue('queue', 'events', 'user.*.created')
|
|
76
|
+
await channel.publish('events', 'user.123.created', Buffer.from(JSON.stringify(data)))
|
|
77
|
+
|
|
78
|
+
// Fanout exchange (broadcast)
|
|
79
|
+
await channel.assertExchange('notifications', 'fanout', { durable: true })
|
|
80
|
+
await channel.bindQueue('queue1', 'notifications', '')
|
|
81
|
+
await channel.bindQueue('queue2', 'notifications', '')
|
|
82
|
+
await channel.publish('notifications', '', Buffer.from('Broadcast message'))
|
|
83
|
+
|
|
84
|
+
// Headers exchange
|
|
85
|
+
await channel.assertExchange('headers_exchange', 'headers', { durable: true })
|
|
86
|
+
await channel.bindQueue('queue', 'headers_exchange', '', {
|
|
87
|
+
'x-match': 'all',
|
|
88
|
+
type: 'notification',
|
|
89
|
+
priority: 'high',
|
|
90
|
+
})
|
|
91
|
+
await channel.publish('headers_exchange', '', Buffer.from('Message'), {
|
|
92
|
+
headers: { type: 'notification', priority: 'high' },
|
|
93
|
+
})
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Common Patterns
|
|
97
|
+
|
|
98
|
+
### Work Queue (Task Distribution)
|
|
99
|
+
```typescript
|
|
100
|
+
// Producer
|
|
101
|
+
async function publishTask(task: any) {
|
|
102
|
+
await channel.assertQueue('tasks', { durable: true })
|
|
103
|
+
channel.sendToQueue('tasks', Buffer.from(JSON.stringify(task)), {
|
|
104
|
+
persistent: true,
|
|
105
|
+
})
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Consumer
|
|
109
|
+
async function consumeTasks() {
|
|
110
|
+
await channel.assertQueue('tasks', { durable: true })
|
|
111
|
+
channel.prefetch(1) // Process one message at a time
|
|
112
|
+
|
|
113
|
+
await channel.consume('tasks', async (msg) => {
|
|
114
|
+
if (msg) {
|
|
115
|
+
try {
|
|
116
|
+
const task = JSON.parse(msg.content.toString())
|
|
117
|
+
await processTask(task)
|
|
118
|
+
channel.ack(msg)
|
|
119
|
+
} catch (error) {
|
|
120
|
+
// Reject and requeue
|
|
121
|
+
channel.nack(msg, false, true)
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
})
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Pub/Sub
|
|
129
|
+
```typescript
|
|
130
|
+
// Publisher
|
|
131
|
+
async function publishEvent(eventType: string, data: any) {
|
|
132
|
+
await channel.assertExchange('events', 'topic', { durable: true })
|
|
133
|
+
channel.publish('events', eventType, Buffer.from(JSON.stringify(data)), {
|
|
134
|
+
persistent: true,
|
|
135
|
+
})
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Subscriber
|
|
139
|
+
async function subscribeToEvents(routingKey: string, handler: (data: any) => void) {
|
|
140
|
+
await channel.assertExchange('events', 'topic', { durable: true })
|
|
141
|
+
const queue = await channel.assertQueue('', { exclusive: true })
|
|
142
|
+
await channel.bindQueue(queue.queue, 'events', routingKey)
|
|
143
|
+
|
|
144
|
+
await channel.consume(queue.queue, (msg) => {
|
|
145
|
+
if (msg) {
|
|
146
|
+
const data = JSON.parse(msg.content.toString())
|
|
147
|
+
handler(data)
|
|
148
|
+
channel.ack(msg)
|
|
149
|
+
}
|
|
150
|
+
})
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### RPC Pattern
|
|
155
|
+
```typescript
|
|
156
|
+
// RPC Server
|
|
157
|
+
async function setupRPCServer() {
|
|
158
|
+
await channel.assertQueue('rpc_queue', { durable: false })
|
|
159
|
+
channel.prefetch(1)
|
|
160
|
+
|
|
161
|
+
await channel.consume('rpc_queue', async (msg) => {
|
|
162
|
+
if (msg) {
|
|
163
|
+
const request = JSON.parse(msg.content.toString())
|
|
164
|
+
const response = await processRequest(request)
|
|
165
|
+
|
|
166
|
+
channel.sendToQueue(
|
|
167
|
+
msg.properties.replyTo,
|
|
168
|
+
Buffer.from(JSON.stringify(response)),
|
|
169
|
+
{
|
|
170
|
+
correlationId: msg.properties.correlationId,
|
|
171
|
+
}
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
channel.ack(msg)
|
|
175
|
+
}
|
|
176
|
+
})
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// RPC Client
|
|
180
|
+
async function rpcCall(request: any): Promise<any> {
|
|
181
|
+
const queue = await channel.assertQueue('', { exclusive: true })
|
|
182
|
+
const correlationId = generateUuid()
|
|
183
|
+
|
|
184
|
+
return new Promise((resolve, reject) => {
|
|
185
|
+
const timeout = setTimeout(() => {
|
|
186
|
+
channel.deleteQueue(queue.queue)
|
|
187
|
+
reject(new Error('RPC timeout'))
|
|
188
|
+
}, 10000)
|
|
189
|
+
|
|
190
|
+
channel.consume(queue.queue, (msg) => {
|
|
191
|
+
if (msg && msg.properties.correlationId === correlationId) {
|
|
192
|
+
clearTimeout(timeout)
|
|
193
|
+
const response = JSON.parse(msg.content.toString())
|
|
194
|
+
channel.deleteQueue(queue.queue)
|
|
195
|
+
resolve(response)
|
|
196
|
+
}
|
|
197
|
+
}, { noAck: true })
|
|
198
|
+
|
|
199
|
+
channel.sendToQueue('rpc_queue', Buffer.from(JSON.stringify(request)), {
|
|
200
|
+
correlationId,
|
|
201
|
+
replyTo: queue.queue,
|
|
202
|
+
})
|
|
203
|
+
})
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Best Practices
|
|
208
|
+
|
|
209
|
+
✅ **DO:**
|
|
210
|
+
- Use durable queues and exchanges for important messages
|
|
211
|
+
- Set message persistence for critical messages
|
|
212
|
+
- Use manual acknowledgment (noAck: false)
|
|
213
|
+
- Implement proper error handling
|
|
214
|
+
- Use prefetch to control message distribution
|
|
215
|
+
- Monitor queue lengths
|
|
216
|
+
- Use dead letter exchanges for failed messages
|
|
217
|
+
- Implement connection retry logic
|
|
218
|
+
- Use appropriate exchange types
|
|
219
|
+
- Set message TTL when needed
|
|
220
|
+
|
|
221
|
+
❌ **DON'T:**
|
|
222
|
+
- Skip acknowledgment (lose messages on crash)
|
|
223
|
+
- Use auto-ack for critical messages
|
|
224
|
+
- Ignore connection errors
|
|
225
|
+
- Hardcode connection strings
|
|
226
|
+
- Store large messages (use external storage)
|
|
227
|
+
- Skip error handling
|
|
228
|
+
- Ignore queue monitoring
|
|
229
|
+
- Use non-durable queues for important data
|
|
230
|
+
- Skip message persistence
|
|
231
|
+
- Ignore memory limits
|
|
232
|
+
|
|
233
|
+
## Configuration
|
|
234
|
+
|
|
235
|
+
### Environment Variables
|
|
236
|
+
```bash
|
|
237
|
+
RABBITMQ_URL=amqp://localhost:5672
|
|
238
|
+
RABBITMQ_URL=amqp://user:password@host:5672/vhost
|
|
239
|
+
RABBITMQ_HOST=localhost
|
|
240
|
+
RABBITMQ_PORT=5672
|
|
241
|
+
RABBITMQ_USER=guest
|
|
242
|
+
RABBITMQ_PASSWORD=guest
|
|
243
|
+
RABBITMQ_VHOST=/
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Docker Compose
|
|
247
|
+
```yaml
|
|
248
|
+
services:
|
|
249
|
+
rabbitmq:
|
|
250
|
+
image: rabbitmq:3-management-alpine
|
|
251
|
+
ports:
|
|
252
|
+
- "5672:5672" # AMQP
|
|
253
|
+
- "15672:15672" # Management UI
|
|
254
|
+
environment:
|
|
255
|
+
RABBITMQ_DEFAULT_USER: admin
|
|
256
|
+
RABBITMQ_DEFAULT_PASS: securepassword
|
|
257
|
+
volumes:
|
|
258
|
+
- rabbitmq_data:/var/lib/rabbitmq
|
|
259
|
+
healthcheck:
|
|
260
|
+
test: ["CMD", "rabbitmq-diagnostics", "ping"]
|
|
261
|
+
interval: 10s
|
|
262
|
+
timeout: 5s
|
|
263
|
+
retries: 5
|
|
264
|
+
|
|
265
|
+
volumes:
|
|
266
|
+
rabbitmq_data:
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## Integration with Development
|
|
270
|
+
|
|
271
|
+
### Testing
|
|
272
|
+
```typescript
|
|
273
|
+
// Use test connection
|
|
274
|
+
const testConnection = await amqp.connect('amqp://localhost:5673') // Different port
|
|
275
|
+
|
|
276
|
+
// Clean up after tests
|
|
277
|
+
afterEach(async () => {
|
|
278
|
+
// Delete test queues/exchanges or use separate vhost
|
|
279
|
+
})
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Health Checks
|
|
283
|
+
```typescript
|
|
284
|
+
async function checkRabbitMQHealth(): Promise<boolean> {
|
|
285
|
+
try {
|
|
286
|
+
const connection = await amqp.connect(process.env.RABBITMQ_URL)
|
|
287
|
+
await connection.close()
|
|
288
|
+
return true
|
|
289
|
+
} catch {
|
|
290
|
+
return false
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
<!-- RABBITMQ:END -->
|
|
296
|
+
|