npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@pager/minion

v3.10.0

Published

Microservice Framework for RabbitMQ Workers

Downloads

2,863

Readme

Minion

MinionMicroservice Framework for RabbitMQ Workers

Features

  • Easy and Minionmalistic setup
  • Simple to use and configure
  • Designed to use with sync functions aswell as promises or async/await ones

Usage

install minion:

npm install --save @pager/minion

Single handler

Create an index.js and export a function like this:

module.exports = (message) => {
   return 'Hello World'
}

Ensure that the main property inside package.json points to your microservice (which is inside index.js in this example case) and add a start script:

{
  "main": "index.js",
  "scripts": {
    "start": "minion"
  }
}

Multiple handlers

Instead of pointing to a single file on the package.json main property, set it to a directory, and create a file for each service you want:

{
  "main": "lib",
  "scripts": {
    "start": "minion"
  }
}

Running Options

Once the project is done, start the worker:

npm start

Optionally you can configure a default exchange name or exchange type when launching minion, if not set the exchange name will be the same of the service, and the type of the exchange will be topic

Exchange Type

{
  "main": "lib",
  "scripts": {
    "start": "minion -t fanout"
  }
}

Exchange Name

{
  "main": "lib",
  "scripts": {
    "start": "minion -x myExchange"
  }
}

Debug Mode

Minion provides a debug mode to test services via node repl

{
  "main": "myService.js",
  "scripts": {
    "debug": "minion -i"
  }
}
npm run debug

This will launch an interactive console where you can debug existing services or use minion itself

▶ npm run debug
> Ready to process myService
> services.myService.publish({ test: 'message'})

Within the console you have acces to services thats a list of existing services, each service have a publish method that you can use to test the service, you can also access minion itself to test new services

> const hello = (message) => { console.log(`Hello ${message}`) }
> const service = minion(hello)
> service.publish('World')
> Processing "World" routed with key hello
Hello World

Configuration

You can change default worker configuration by adding a setting property as an object with configuration values like this:

const handler = (message) => {
  return 'Hello World'
}

handler.settings = {
  key: 'message.example.key',
  name: 'message.queue'
}

module.exports = handler

Check below for supported options and default values.

Options

  • name- Queue name. Defaults to handler function or file name
  • exchangeType - Defaults to 'topic'
  • exchangeName - Defautls to the name of the handler function.
  • key - Key to bind the queue to. Defaults to service file name or queue name.
  • exclusive - Defaults to false.
  • durable - Defaults to true.
  • autoDelete - Defaults to false.
  • deadLetterExchange - By default all queues are created with a dead letter exchange. The name defaults to the name of the exchange following the .dead suffix. If you want to disable the dead letter exchange , set it as false.
  • logger - Defaults to Bunyan logger, but can receive a custom logger.
  • rabbitUrl - (Optional) RabbitMQ connection URL string. Defaults to 'amqp://localhost'.
  • rabbit - (Optional) Jackrabbit connection instance, in case you want to build your own. Make sure to use this if you want the connection to be shared amongst several minions.

Programmatic use

As a Service

You can create Minion services programmatically by requiring it directly, and passing a handler as the first argument and options as the second argument:

const minion = require('@pager/minion')

minion((message) => {
  return 'Hello World'
}, {
  key: 'my.routing.key'
})

With async / await support

const minion = require('@pager/minion')

minion(async (message) => {
  return await request('https://foo.bar.zz')
})

As a publisher

You can create a Minion publisher programmatically by requiring it directly, and passing options as the first argument and an optional properties object:

const minion = require('@pager/minion')

const publish = minion()

publish({ hello: 'world' }, 'a.routing.key')
const minion = require('@pager/minion')

const publish = minion()

// adding an object with a property to give to the message a time-to-live of 60 seconds.
publish({ hello: 'world' }, 'a.routing.key', { expiration: 60000 })

You can also test your services by publishing directly to them

const minion = require('@pager/minion')

const service = minion((message) => {
  return 'Hello World'
}, {
  key: 'my.routing.key'
})

service.publish({ hola: 'mundo' })

Validation

We recommend using minion-joi or writing your own validation following that as an example.

Environment Configuration

The RabbitMQ connection URL is read from a RABBIT_URL env var, if not present it will default to: amqp://localhost

Error Handling

If the handler throws an error the message will be nacked and not requeued ({ requeue: false }), if you want to requeue on failure minion provider a custom error to do so

Your service:

const minion = require('@pager/minion')
const Requeue = minion.Requeue

const handler = async (message) => {
    throw new Requeue('My message')
}

Also errors will be logged to stderr when thrown

Testing

When calling Minion programatically you receive an instance of a function you can use to inject messages directly. Assuming you're using ava for testing (as we do), you can test like this:

Your service:

const handler = (message) => {
    return true
}

Your test:

test('acks message with true', async t => {
    const service = minion(handler)
    const message = {hello: 'world'}

    const res = await service.handle(message)
    t.true(res)
})