{"id":22486481,"url":"https://github.com/weyoss/slim-rabbit","last_synced_at":"2025-04-24T00:18:06.178Z","repository":{"id":57363223,"uuid":"110548333","full_name":"weyoss/slim-rabbit","owner":"weyoss","description":"A Node.js micro-services framework based on RabbitMQ.","archived":false,"fork":false,"pushed_at":"2018-02-09T11:47:34.000Z","size":9,"stargazers_count":10,"open_issues_count":1,"forks_count":6,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-24T00:18:01.457Z","etag":null,"topics":["amqp","app","framework","microservice","middleware","rabbitmq"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/weyoss.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-11-13T12:56:04.000Z","updated_at":"2019-12-28T14:43:27.000Z","dependencies_parsed_at":"2022-09-26T16:33:25.059Z","dependency_job_id":null,"html_url":"https://github.com/weyoss/slim-rabbit","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/weyoss%2Fslim-rabbit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/weyoss%2Fslim-rabbit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/weyoss%2Fslim-rabbit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/weyoss%2Fslim-rabbit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/weyoss","download_url":"https://codeload.github.com/weyoss/slim-rabbit/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250535103,"owners_count":21446510,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["amqp","app","framework","microservice","middleware","rabbitmq"],"created_at":"2024-12-06T17:14:40.518Z","updated_at":"2025-04-24T00:18:06.157Z","avatar_url":"https://github.com/weyoss.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# SlimRabbit\n\nA Node.js micro-services framework based on RabbitMQ. Being heavily inspired by KOA, SlimRabbit is a\nsimple yet powerful foundation with a very small footprint (~290 SLOC codebase) which tries to helps you build\nlightning fast micro-services with elegance.\n\n# Installation\n\n```text\nnpm install slim-rabbit --save\n```\nSlimRabbit requires node v7.6.0 or higher for ES2015 and async function support.\n\n# Application API Reference\n\n## Middleware\n\nA SlimRabbit application is an object containing an array of middleware functions which are composed and executed in a\nstack-like manner once a message is delivered.\n\nSlimRabbit is based on `koa-compose` node module and adopts the same vision and architecture as KOA framework which\nis similar to many other middleware systems that you may have encountered, such as Connect, however it provides high\nlevel \"sugar\" at the otherwise low-level middleware layer. This improves interoperability, robustness, and makes\nwriting middleware much more enjoyable.\n\nThe obligatory hello world application:\n\n```js\nconst SlimRabbit = require('slim-rabbit');\n\nconst app = new SlimRabbit('test_queue');\n\napp.on('consumer:error', (err, context) =\u003e {\n    console.error(err);\n});\n\napp.use(async (ctx) =\u003e {\n    const message = ctx.message;\n\n    console.log(message);\n    ctx.ack(message);\n});\n\napp.connect();\n```\n\nMiddlewares can take two different kinds of functions as middleware:\n\n***Async functions:***\n\n```js\napp.use(async (ctx, next) =\u003e {\n    const start = Date.now();\n    await next();\n    const ms = Date.now() - start;\n    console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);\n});\n```\n\n***Common function which return promises:***\n\n```js\napp.use((ctx, next) =\u003e {\n    const start = Date.now();\n    return next().then(() =\u003e {\n        const ms = Date.now() - start;\n        console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);\n    });\n});\n```\n\n## Context\n\nEach middleware receives a `Context` object which encapsulates an incoming AMQP message and provides helpful\nmethods for working with AMQP prototocol.\n\nA Context is created per message and many of its accessors and methods simply delegate to their ctx.message or\nctx.consumerChannel equivalents for convenience, and are otherwise identical.\n\n### Context properties\n\n#### ctx.app\n\nApplication instance reference.\n\n#### ctx.state\n\nThe recommended namespace for passing information through middleware.\n\n#### ctx.queueName\n\nApplication queue name from which the messages are consumed.\n\n#### ctx.queueOpts\n\nApplication queue options. Queue options are the same options which amqplib `assertQueue` method accepts.\n\nSee http://www.squaremobius.net/amqp.node/channel_api.html#channel_assertQueue\n\n#### ctx.consumeOpts\n\nApplication consume's options. `consumeOpts` are the same options which amqplib `consume` method accepts.\n\nSee http://www.squaremobius.net/amqp.node/channel_api.html#channel_consume\n\n#### ctx.message\n\nReceived message from RabbitMQ.\n\n#### ctx.connection\n\nThe created amqplib connection to RabbitMQ server.\n\n#### ctx.consumerChannel\n\nThe created amqplib channel for consuming messages.\n\nSee http://www.squaremobius.net/amqp.node/channel_api.html#channel\n\n#### ctx.publisherChannel\n\nThe created amqplib channel for publishing messages.\n\nSee http://www.squaremobius.net/amqp.node/channel_api.html#channel\n\n### Context methods\n\n#### context.ack\n\nAcknowledge the given message, or all messages up to and including the given message. Delegated to amqplib Channel#ack.\n\nSee http://www.squaremobius.net/amqp.node/channel_api.html#channel_ack\n\n#### context.ackAll\n\nAcknowledge all outstanding messages on the channel. Delegated to amqplib Channel#ackAll.\n\nSee http://www.squaremobius.net/amqp.node/channel_api.html#channel_ackAll\n\n#### context.nack\n\nReject a message. This instructs the server to either requeue the message or throw it away. \nDelegated to amqplib Channel#nack.\n\nSee http://www.squaremobius.net/amqp.node/channel_api.html#channel_nack\n\n#### context.nackAll\n\nReject all messages outstanding on this channel. Delegated to amqplib Channel#nackAll.\n\nSee http://www.squaremobius.net/amqp.node/channel_api.html#channel_nackAll\n\n#### context.reject\n\nReject a message. Equivalent to context.nack(message, false, requeue), but works in older versions of RabbitMQ (\u003c v2.3.0)\nwhere context.nack does not.  Delegated to amqplib Channel#reject.\n\nSee http://www.squaremobius.net/amqp.node/channel_api.html#channel_reject\n\n#### context.publish\n\nPublish a single message to an exchange. The relevant method parameters are:\n\n```text\n/**\n *\n * @param {string} exchange\n * @param {string} routingKey\n * @param {(string|object|Buffer)} content\n * @param {object} options\n * @return {*}\n */\nasync publish(exchange, routingKey, content, options = {})\n```\n\nThis method is the same as amqplib Channel#publish method except that [content] parameter can be of any javascript type. It is \nautomatically converted to a Buffer instance.\n\nSee http://www.squaremobius.net/amqp.node/channel_api.html#channel_publish\n\n#### context.sendToQueue\n\nSend a single message with the content given as a buffer to the specific queue named, bypassing routing.\nThe options and return value are exactly the same as for context.publish.\n\n```text\n/**\n *\n * @param {string} queue\n * @param {(string|object|Buffer)} content\n * @param {object} options\n * @return {*}\n */\nasync sendToQueue(queue, content, options = {})\n```\n\nThis method is the same as amqplib Channel#sendToQueue method except that [content] parameter can be of any javascript type. It is \nautomatically converted to a Buffer instance.\n\nSee http://www.squaremobius.net/amqp.node/channel_api.html#channel_sendToQueue\n\n## Application\n\nThe object created when executing `new SlimRabbit(queueName, queueOpts, consumeOpts)` is known as the SlimRabbit\napplication object. The application class is the heart of SlimRabbit which run all the micro-service logic, manage\nmiddlewares registration, handles errors as well as the configuration of the context, consumerChannel and publisherChannel objects.\n\nApplication accepts the following parameters:\n\n- `queueName`: Queue name.\n- `queueOpts`: Queue options. See http://www.squaremobius.net/amqp.node/channel_api.html#channel_assertQueue\n- `consumeOpts`: Consume's options. See http://www.squaremobius.net/amqp.node/channel_api.html#channel_consume\n\n```js\nconst queueOpts = {\n    durable: true\n};\n\nconst consumeOpts = {\n    noAck: false,\n    exclusive: true\n};\n\nconst app = new SlimRabbit('test_queue', queueOpts, consumeOpts)\n```\n\n### app.use\n\nAdd a given middleware function to this application.\n\n***Example:***\n\n```js\napp.use(async function (ctx, next) {\n    try {\n        const string = ctx.message.content.toString();\n        ctx.message.content = string;\n        ctx.message.content = JSON.parse(string);\n    } catch (err) {}\n    await next();\n});\n```\n\nSee [Middleware](https://github.com/weyoss/slim-rabbit#middleware)\n \n### app.connect\n\nOpen a connection to the RabbitMQ server, create consumerChannel, publisherChannel and begin consuming messages from\nthe given queue. `app.connect` accepts the same parameters as amqplib `connect` method.\n\n```text\n/**\n *\n * @param {string} url\n * @param {object} socketOpts\n * @return {Promise.\u003cvoid\u003e}\n */\nasync connect(url, socketOpts = {}) \n```\n\nSee http://www.squaremobius.net/amqp.node/channel_api.html#connect\n\n### app.context\n\n`app.context` is the prototype from which ctx is created from. You may add additional properties to ctx by editing\napp.context. This is useful for adding properties or methods to ctx to be used across your entire app, which may be\nmore performant (no middleware) and/or easier (fewer require()s) at the expense of relying more on ctx, which could\nbe considered an anti-pattern.\n\nFor example, to add a reference to your database from ctx:\n\n```js\napp.context.db = db();\n\napp.use(async ctx =\u003e {\n  console.log(ctx.db);\n});\n```\n\nNote: Many properties on ctx are defined using getters and setters. You can only edit these properties (not recommended)\nby using Object.defineProperty() on app.context.\n\n### app.prefetch\n\nSetup prefetch options for the application's consumer channel (consumerChannel).\n\n```js\nconst SlimRabbit = require('slim-rabbit');\n\nconst app = new SlimRabbit('test_queue');\n\napp.prefetch(20, false);\n\napp.on('consumer:error', (err, context) =\u003e {\n    console.error(err);\n});\n\napp.use(async (ctx) =\u003e {\n    const message = ctx.message;\n\n    console.log(message);\n    ctx.ack(message);\n});\n\napp.connect();\n```\n\nSee http://www.squaremobius.net/amqp.node/channel_api.html#channel_prefetch\n\n### app.close\n\nClose channels and disconnect from RabbitMQ.\n\n## Error handling\n\nAn error handler is required to handle errors which may occur while consuming messages. Errors are emitted on the app.\nTo setup error-handling logic such as centralized logging you can add an \"consumer:error\" event listener.\n\n***Simple error handler example:***\n\n```js\napp.on('consumer:error', (err, context) =\u003e {\n    console.error(err);\n});\n```\n\n***An advanced error handler can be such as:***\n\n```js\napp.on('consumer:error', (err, context) =\u003e {\n    console.log(err);\n\n    const message = context.message;\n    const headers = message.properties.headers;\n    const content = message.content;\n\n    headers.hasOwnProperty('x-delivered-count') || (headers['x-delivered-count'] = 0);\n    headers['x-delivered-count'] += 1;\n\n    if (headers['x-delivered-count'] \u003c= config.amqp.retriesThreshold) {\n        console.log(`Message retries # ${headers['x-delivered-count']}. Re-queuing message...`);\n        const {exchange, routingKey} = message.fields;\n        context.publish(exchange, routingKey, content, {headers}).then(() =\u003e {\n            context.ack(message);\n        })\n    } else {\n        console.log('Message retries threshold exceeded. Purging message.');\n        console.log('Message dump:', JSON.stringify(message));\n        context.nack(message, false, false);\n    }\n});\n```\n\n## Events\n\nThe following events are emitted from the application during different stages of its lifecycle:\n\n### connection:created\n\n```js\napp.on('connection:created', (connection) =\u003e {})\n```\n\n### connection:closed\n\n```js\napp.on('connection:closed', () =\u003e {})\n```\n\n### connection:error\n\n```js\napp.on('connection:error', (err) =\u003e {})\n```\n\n### consumer-channel:created\n\n```js\napp.on('consumer-channel:created', (channel) =\u003e {})\n```\n\n### consumer-channel:closed\n\n```js\napp.on('consumer-channel:closed', () =\u003e {})\n```\n\n### consumer-channel:error\n\n```js\napp.on('consumer-channel:error', (err) =\u003e {})\n```\n\n### publisher-channel:created\n\n```js\napp.on('publisher-channel:created', (channel) =\u003e {})\n```\n\n### publisher-channel:closed\n\n```js\napp.on('publisher-channel:closed', (channel) =\u003e {})\n```\n\n### publisher-channel:error\n\n```js\napp.on('publisher-channel:error', (err) =\u003e {})\n```\n\n### consumer:listen\n\n```js\napp.on('consumer:listen', (queueName, consumerTag) =\u003e {})\n```\n\n### consumer:error\n\n```js\napp.on('consumer:error', (err, context) =\u003e {})\n```\n\n# Contributing\n\nSo you are interested in contributing to this project? Please see [CONTRIBUTING.md](https://github.com/weyoss/guidelines/blob/master/CONTRIBUTIONS.md).\n\n# License\n\n[MIT](https://github.com/weyoss/slim-rabbit/blob/master/LICENSE)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fweyoss%2Fslim-rabbit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fweyoss%2Fslim-rabbit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fweyoss%2Fslim-rabbit/lists"}