micromq

Microservice framework based on native Node.js HTTP module and AMQP protocol (express integration as feature).

Downloads in past

Stats

StarsIssuesVersionUpdatedCreatedSize
micromq
5783.0.25 years ago5 years agoMinified + gzip package size for micromq in KB

Readme

micromq
micromq
Microservice framework based on native Node.js HTTP module and AMQP protocol with express middleware & built-in prometheus. 🔬 🐇

Install

$ npm i micromq

Tests

$ RABBIT_URL=amqp://localhost node tests/apps/users.js &
$ RABBIT_URL=amqp://localhost node tests/apps/balances.js &
$ RABBIT_URL=amqp://localhost PORT=3000 node tests/apps/gateway.js &
$ PORT=3000 npm test

Examples

There are some simple examples.

API

Gateway

.constructor(options)

- microservices <Array<string>> Microservices for connect. - rabbit <Object>
- `url` <[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type)> RabbitMQ connection url.
- requests <?Object>
- `timeout` <[?number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Number_type)> Timeout for each request (in ms).
This method creates gateway.
const Gateway = require('micromq/gateway');

const gateway = new Gateway({
  microservices: ['users', 'orders'],
  rabbit: {
    url: 'amqp://localhost:5672',
  },
  requests: {
    timeout: 5000,
  },
});

.action(name, handler)


This method creates RPC action.
const Gateway = require('micromq/gateway');
const { Users } = require('./db');

const gateway = new Gateway({ ... });

gateway.action('increase_balance', async (meta, res) => {
  if (!meta.amount || Number.isNaN(+meta.amount)) {
    res.status(400);
    res.json({ error: 'Bad data' });
    
    return;
  }
  
  await Users.updateOne({
    userId: meta.userId,
  }, {
    $inc: {
      balance: meta.amount,
    },
  });

  res.json({ ok: true });
});

gateway.listen(3000);

const MicroMQ = require('micromq');

const app = new MicroMQ({ ... });

app.post('/deposit', (req, res) => {
  // send rpc action to the gateway
  res.json({
    server: {
      action: 'increase_balance',
      meta: {
        userId: 1,
        amount: 500,
      },
    },
  });
});

app.start();

.on(name, handler)


This method creates application event (read more).
const MicroMQ = require('micromq');

const app = new MicroMQ({ ... });

// register event
app.on('error', (err, req, res) => {
  console.error(err); // 'Random error!'
});

app.use(async (req, res, next) => {
  try {
    await next();
  } catch (err) {
    res.status(err.status || 500);
    res.json({ error: err.message || 'Server error' });

    // emit event
    app.emit('error', err, req, res);
  }
});

app.post('/throw', (req, res) => {
  throw 'Random error!';
});

app.start();

.emit(name, ...args)

  • name <string> Event name
  • ...args <...any> - Arguments

This method emits application event.

.enablePrometheus(endpoint, credentials)

  • endpoint <string> Metrics' endpoint
  • credentials <Object> Credentials for prometheus target
- user <string> - password <string>
This method enables prometheus monitoring.
const Gateway = require('micromq/gateway');

const gateway = new Gateway({ ... });

// start prometheus with default /metrics endpoint & without credentials
gateway.enablePrometheus();

// start prometheus with /users/metrics endpoint & without credentials
gateway.enablePrometheus('/users/metrics');

// start prometheus with /users/metrics endpoint & credentials
gateway.enablePrometheus('/users/metrics', {
  user: 'admin',
  password: 'admin',
});

// start prometheus with default /metrics endpoint & credentials
gateway.enablePrometheus({
  user: 'admin',
  password: 'admin',
});

gateway.listen(3000);

.use(...middlewares)

  • ...middlewares <...function> Middlewares

This method adds middlewares.

.all(path, ...middlewares)


This method creates endpoint for all HTTP-methods.

.options(path, ...middlewares),

.get(path, ...middlewares),

.post(path, ...middlewares),

.put(path, ...middlewares),

.patch(path, ...middlewares),

.delete(path, ...middlewares)


This method creates endpoint with needed method.

.middleware()


This method returns middleware for express.
const express = require('express');
const bodyParser = require('body-parser');
const Gateway = require('micromq/gateway');
const users = require('./routers/users');

const app = express();
const gateway = new Gateway({ ... });

app.use(bodyParser.json());

// apply middleware
app.use(gateway.middleware());

// monolith router
app.use('/users', users);

// delegate requests to the microservice
app.use('/orders', (req, res) => res.delegate('orders'));

.listen(port)

  • port <number> Port for listen.

This method creates HTTP-server and starts listen needed port.

MicroMQ

.constructor(options)

- microservices <Array<string>> Microservices for connect. - name <string> Microservice name - rabbit <Object>
- `url` <[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type)> RabbitMQ connection url.
This method creates microservice.
const MicroMQ = require('micromq');

const app = new MicroMQ({
  microservice: 'users',
  rabbit: {
    url: 'amqp://localhost:5672',
  },
});

.action(name, handler)


This method creates RPC action.
const MicroMQ = require('micromq');
const { Users } = require('./db');

const app = new MicroMQ({ ... });

app.action('new_deposit', async (meta, res) => {
  await Users.updateOne({
    userId: meta.userId,
  }, {
    $inc: {
      level: 1,
    },
  });


  res.json({ ok: true });
});

app.start();

.enablePrometheus(endpoint, credentials)

  • endpoint <string> Metrics' endpoint
  • credentials <Object> Credentials for prometheus target
- user <string> - password <string>
This method enables prometheus monitoring.
const MicroMQ = require('micromq');

const app = new MicroMQ({ ... });

// start prometheus with default /metrics endpoint & without credentials
app.enablePrometheus();

// start prometheus with /users/metrics endpoint & without credentials
app.enablePrometheus('/users/metrics');

// start prometheus with /users/metrics endpoint & credentials
app.enablePrometheus('/users/metrics', {
  user: 'admin',
  password: 'admin',
});

// start prometheus with default /metrics endpoint & credentials
app.enablePrometheus({
  user: 'admin',
  password: 'admin',
});

app.start();

.use(...middlewares)

  • ...middlewares <...function> Middlewares

This method adds middlewares.

.all(path, ...middlewares)


This method creates endpoint for all HTTP-methods.

.options(path, ...middlewares),

.get(path, ...middlewares),

.post(path, ...middlewares),

.put(path, ...middlewares),

.patch(path, ...middlewares),

.delete(path, ...middlewares)


This method creates endpoint with needed method.

.ask(name, query)

- `path` <[?string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type)> Endpoint path
- `method` <[?string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type)> Endpoint method
- `query` <[?Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)> Query params
- `params` <[?Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)> URL params
- `body` <[?Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)> Body params

This method asks other microservice.
const MicroMQ = require('micromq');

const app = new MicroMQ({
  ...,
  microservices: ['balances'],
});

app.get('/users/me/info', async (req, res) => {
  // ask microservice endpoint
  const { response } = await app.ask('balances', {
    path: '/balances/me',
    method: 'get',
    params: {
      userId: req.params.id,
    },
  });
  
  // ask microservice action
  const { response } = await app.ask('balances', {
    server: {
      action: 'new_deposit',
      meta: {
        amount: 250,
      },
    },
  });
  
  res.json({
    id: req.params.id,
    name: `${req.session.first_name} ${req.session.last_name}`,
    balance: response.amount,
  });
});

app.start();

.listen(port)

  • port <number> Port for listen.

This method creates HTTP-server and starts listen needed port. The usual use case for this method is run tests.

.start()

This method starts microservice.