{"id":10858,"library":"exframe-mq","title":"Exframe Messaging Queue","description":"exframe-mq is a messaging framework module providing a simplified abstraction layer over RabbitMQ for Node.js applications, currently stable at version 5.2.0. It is part of the broader exframe ecosystem and is typically used in conjunction with other exframe-* packages like exframe-context, exframe-health, and exframe-logger. The library primarily focuses on a Publish/Subscribe topology, makes a key assumption of JSON payloads for all messages, and manages persistent and shared connections to the RabbitMQ server. While a specific release cadence isn't detailed, its close ties to other exframe modules suggest coordinated releases. Key differentiators include its opinionated, simplified API for common RabbitMQ patterns and deep integration with the exframe application framework.","status":"active","version":"5.2.0","language":"javascript","source_language":"en","source_url":null,"tags":["javascript"],"install":[{"cmd":"npm install exframe-mq","lang":"bash","label":"npm"},{"cmd":"yarn add exframe-mq","lang":"bash","label":"yarn"},{"cmd":"pnpm add exframe-mq","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Required for integrating with the exframe application context, handling request lifecycle and shared data.","package":"exframe-context","optional":false},{"reason":"Used for exposing health check endpoints related to the RabbitMQ connection status.","package":"exframe-health","optional":false},{"reason":"Provides a consistent logging interface across exframe modules; mq.create expects a logger instance.","package":"exframe-logger","optional":false},{"reason":"Integrates the messaging client within the broader exframe service architecture.","package":"exframe-service","optional":false}],"imports":[{"note":"The 'exframe-mq' module exports a single object containing its main functions (create, getConnection, client) as properties. Use a default import in ESM or direct require in CJS.","wrong":"import { create } from 'exframe-mq';","symbol":"mq","correct":"import mq from 'exframe-mq';"},{"note":"The 'create' function is a method on the default-exported 'mq' object, not a named export. It initializes the RabbitMQ client.","wrong":"import { create } from 'exframe-mq';","symbol":"create","correct":"import mq from 'exframe-mq'; const client = mq.create(...);"},{"note":"The 'client' function is a method on the default-exported 'mq' object used to create an instance for subscribing and publishing messages.","wrong":"import { client } from 'exframe-mq';","symbol":"client","correct":"import mq from 'exframe-mq'; const clientInstance = mq.client(options);"}],"quickstart":{"code":"import mq from 'exframe-mq'; // Use 'const mq = require(\"exframe-mq\");' for CommonJS\n\n// Mock a logger for demonstration purposes\nconst logger = {\n  info: (message, ...args) => console.log('INFO:', message, ...args),\n  error: (message, ...args) => console.error('ERROR:', message, ...args),\n  warn: (message, ...args) => console.warn('WARN:', message, ...args),\n  debug: (message, ...args) => console.debug('DEBUG:', message, ...args),\n};\n\nasync function runMessagingExample() {\n  const rabbitmqUrl = process.env.RABBITMQ_URL ?? 'amqp://localhost';\n\n  console.log(`Attempting to connect to RabbitMQ at ${rabbitmqUrl}...`);\n\n  try {\n    // Initialize the main exframe-mq client\n    const mqClient = mq.create({\n      logger,\n      url: rabbitmqUrl,\n      heartbeat: 30,\n      baseTimeout: 500,\n      maxAttempts: 5,\n      responseTimeout: 60 * 1000,\n    });\n\n    // Get a messaging client instance for publish/subscribe operations\n    const client = mqClient.client();\n\n    const EXCHANGE_NAME = 'my-app-exchange';\n    const ROUTING_KEY_PATTERN = 'my.topic.#'; // Subscribe to all messages under 'my.topic'\n    const PUBLISH_ROUTING_KEY = 'my.topic.hello';\n\n    // Subscribe to messages on a topic exchange\n    await client.subscribe(EXCHANGE_NAME, ROUTING_KEY_PATTERN, async (context, message, extraParams = {}) => {\n      logger.info(`Received message: ${JSON.stringify(message)} with context ${JSON.stringify(context)} and extraParams ${JSON.stringify(extraParams)}`);\n      // Simulate some asynchronous processing\n      await new Promise(resolve => setTimeout(resolve, 100));\n    }, { exchangeType: 'topic' });\n\n    logger.info(`Successfully subscribed to '${EXCHANGE_NAME}' with routing key pattern '${ROUTING_KEY_PATTERN}'.`);\n\n    // Publish a message after a short delay to allow subscription to establish\n    setTimeout(() => {\n      const messagePayload = { sender: 'quickstart-app', content: 'Hello from exframe-mq!' };\n      logger.info(`Publishing message '${JSON.stringify(messagePayload)}' to '${EXCHANGE_NAME}' with routing key '${PUBLISH_ROUTING_KEY}'.`);\n      client.publish(EXCHANGE_NAME, PUBLISH_ROUTING_KEY, messagePayload);\n    }, 2000);\n\n    console.log('Application running. Awaiting messages. Press Ctrl+C to exit.');\n  } catch (error) {\n    logger.error('Failed to initialize or connect to RabbitMQ:', error);\n    process.exit(1);\n  }\n}\n\nrunMessagingExample();","lang":"javascript","description":"This example demonstrates how to initialize the `exframe-mq` module, configure a connection to RabbitMQ, create a messaging client, and then subscribe to and publish messages using a topic exchange topology."},"warnings":[{"fix":"Ensure all messages published through `exframe-mq` are valid JSON objects. If receiving messages from external, non-JSON sources, implement custom middleware to handle parsing or validation before `exframe-mq`'s default processing.","message":"The library assumes all message payloads are JSON. Non-JSON messages will likely cause parsing errors in subscribers when the module attempts to process them.","severity":"gotcha","affected_versions":">=5.0"},{"fix":"Install all listed peer dependencies at compatible versions (e.g., `npm install exframe-context@1 exframe-health@1 exframe-logger@3 exframe-service@1`). Ensure they are properly initialized and passed where required (e.g., `logger` in `mq.create()`).","message":"`exframe-mq` has several peer dependencies (`exframe-context`, `exframe-health`, `exframe-logger`, `exframe-service`) that must be installed and configured alongside it for full functionality. Missing or incompatible versions can lead to runtime errors.","severity":"gotcha","affected_versions":">=1.0"},{"fix":"Always explicitly configure the `url`, `maxAttempts`, `baseTimeout`, `heartbeat`, and `responseTimeout` in `mq.create()` for production deployments, ideally using environment variables.","message":"The default RabbitMQ URL (`amqp://localhost`) and connection retry settings (e.g., `maxAttempts`, `baseTimeout`) are suitable for local development but are generally insufficient for robust production environments, which require proper authentication and more resilient retry logic.","severity":"gotcha","affected_versions":">=5.0"},{"fix":"Ensure all message processing functions passed to `client.subscribe` are `async` functions or explicitly return `Promise.resolve()` or `Promise.reject()`.","message":"Message processing middleware functions passed to `client.subscribe` are expected to return Promises that resolve. Failing to return a Promise or returning a synchronous value without wrapping it can lead to unexpected behavior in message acknowledgment or error handling.","severity":"gotcha","affected_versions":">=5.0"},{"fix":"Provide a logger object that implements `info`, `error`, `warn`, and `debug` methods, or use an instance of `winston` (or a `winston`-compatible logger) directly.","message":"The `logger` option passed to `mq.create` expects an object with an interface compatible with `winston` logger methods (e.g., `info`, `error`, `warn`, `debug`). While a default logger outputs to stdout, custom logging requires a compliant object.","severity":"gotcha","affected_versions":">=5.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure the RabbitMQ server is running and accessible from the application's host. Verify the `url` configuration in `mq.create()` is correct.","cause":"The RabbitMQ server is not running or is inaccessible at the configured address and port.","error":"Error: connect ECONNREFUSED 127.0.0.1:5672"},{"fix":"Adjust your import statement to `import mq from 'exframe-mq';` (ESM) or `const mq = require('exframe-mq');` (CommonJS), then access the `create` method as `mq.create()`.","cause":"The `exframe-mq` module was imported incorrectly, likely using named import syntax (e.g., `import { create } from 'exframe-mq';`) instead of importing the default object.","error":"TypeError: mq.create is not a function"},{"fix":"Install the missing peer dependency using `npm install <package-name>@<version-range>` (e.g., `npm install exframe-logger@3`) to satisfy the requirement. Repeat for any other missing `exframe-*` peer dependencies.","cause":"A required peer dependency of `exframe-mq` is not installed or its version does not match the expected range specified in `package.json`.","error":"Error: Missing peer dependency \"exframe-logger@3.x\""}],"ecosystem":"npm"}