Socket
Socket
Sign inDemoInstall

mole-rpc-transport-mqtt

Package Overview
Dependencies
49
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.3.0 to 1.0.0

.travis.yml

2

.prettierrc.json

@@ -5,2 +5,2 @@ {

"singleQuote": true
}
}
{
"name": "mole-rpc-transport-mqtt",
"version": "0.3.0",
"version": "1.0.0",
"description": "MQTT transport for Mole-RPC (JSON RPC library)",

@@ -14,8 +14,9 @@ "main": "index.js",

"peerDependencies": {
"mole-rpc": "^0.3.0",
"async-mqtt": "^2.0.0"
"mole-rpc": "1.*",
"async-mqtt": "^2.5.0"
},
"devDependencies": {
"mole-rpc": "^0.3.0",
"async-mqtt": "^2.0.0"
"async-mqtt": "^2.5.0",
"mole-rpc": "1.*",
"mole-rpc-autotester": "1.*"
},

@@ -43,2 +44,2 @@ "keywords": [

"homepage": "https://github.com/koorchik/node-mole-rpc-transport-mqtt#readme"
}
}
MQTT Transport for Mole RPC (JSON RPC Library)
---------------------------------------------
[![npm version](https://badge.fury.io/js/mole-rpc-transport-mqtt.svg)](https://badge.fury.io/js/mole-rpc-transport-mqtt)
[![Build Status](https://travis-ci.org/koorchik/node-mole-rpc-transport-mqtt.svg?branch=master)](https://travis-ci.org/koorchik/node-mole-rpc-transport-mqtt)
[![Known Vulnerabilities](https://snyk.io/test/github/koorchik/node-mole-rpc-transport-mqtt/badge.svg?targetFile=package.json)](https://snyk.io/test/github/koorchik/node-mole-rpc-transport-mqtt?targetFile=package.json)
Mole-RPC is a tiny transport agnostic JSON-RPC 2.0 client and server which can work both in NodeJs, Browser, Electron etc.
This is MQTT based tranport but there are [many more transports](https://www.npmjs.com/search?q=keywords:mole-transport).
**What is the reason of using MQTT for JSON-RPC?**
MQTT is a standard broker in IoT world. It is lightweight and fast message broker and the same time it contains a lot of advanced features like (persistence, retained messaged, QoS, ACL etc).
You can organize many to many RPC-connunication between microservices via MQTT.
*For example, in our case, we use this module to connect microservices deployed to an IoT Hub*
**Which MQTT server to use?**
You can use anyone you wish. As for us, we use in production:
1. [Eclipse Mosquitto](https://mosquitto.org/). Very lightweight but works greatly.
2. [EMQ X](https://www.emqx.io/). More powerful if you need more features.
The easiest way to start playing is to run mosquitto in docker:
```sh
docker run -it -p 1883:1883 eclipse-mosquitto
```
After that you can try the example below.
## Usage Example
```javascript

@@ -13,71 +48,128 @@ const MoleClient = require('mole-rpc/MoleClient');

async function main() {
await runServer();
await runClients();
await runServer();
await runClients();
}
async function runServer() {
const mqttClient = MQTT.connect("tcp://localhost:1883");
await waitForEvent(mqttClient, 'connect');
const mqttClient = MQTT.connect("tcp://localhost:1883");
const server = new MoleServer({
transports: [
new MQTTTransportServer({
mqttClient,
inTopic: 'fromClient/+',
outTopic: ({inTopic}) => inTopic.replace('fromClient', 'toClient')
// outTopic: 'toClient/1' // static outTopic
})
],
});
server.expose({
getGreeting(name) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(`Hi, ${name}`)
}, 1000);
});
}
});
}
const server = new MoleServer({
transports: [
new MQTTTransportServer({
mqttClient,
inTopic: 'fromClient/+',
outTopic: ({inTopic}) => inTopic.replace('fromClient', 'toClient')
})
],
});
server.expose({
getGreeting(name) {
return `Hi, ${name}`;
}
});
await server.run();
}
async function runClients() {
const mqttClient = MQTT.connect("tcp://localhost:1883");
await waitForEvent(mqttClient, 'connect');
const client1 = new MoleClient({
transport: new MQTTTransportClient({
mqttClient,
inTopic: 'toClient/1',
outTopic: 'fromClient/1'
}),
transport: new MQTTTransportClient({
mqttClient,
inTopic: 'toClient/1',
outTopic: 'fromClient/1'
}),
});
const client2 = new MoleClient({
transport: new MQTTTransportClient({
mqttClient,
inTopic: 'toClient/2',
outTopic: 'fromClient/2'
}),
transport: new MQTTTransportClient({
mqttClient,
inTopic: 'toClient/2',
outTopic: 'fromClient/2'
}),
});
console.log(
'CLIENT 1',
await client1.callMethod('getGreeting', ['User1'])
'CLIENT 1',
await client1.callMethod('getGreeting', ['User1'])
);
console.log(
'CLIENT 2',
await client2.callMethod('getGreeting', ['User2'])
'CLIENT 2',
await client2.callMethod('getGreeting', ['User2'])
);
}
function waitForEvent(emitter, eventName) {
return new Promise((resolve, reject) => {
emitter.on(eventName, resolve);
});
main(console.log, console.error);
```
## How does it work?
MQTT has topics. Different services can subscribe to different topic. You can use wildcard characters in names like "+" or "#".
**MQTTTransportClient** has two topic related parameters:
* outTopic - sends request to this topic.
* inTopic - gets response in this topic.
**MQTTTransportServer** has two topic related parameters:
* inTopic - listend to requests from client in this topic. If you have many clients it makes sense use wildcard topic.
* outTopic - sends response to this topic. You can pass callback which will convert in topic to outtopic.
## Universal approach for to how to name topics in scalable way
One of the pattern can be the following:
* Send data to: `/rpc/${FROM}/${TO}`
* Get data from: `/rpc/${TO}/${FROM}`
*See "Usage Example" for a simpler approach*
### Many RPC clients and one RPC Server.
Let's assume that is an authentication server
**Server:**
```js
const inTopic = '/rpc/+/auth-server';
const outTopic = inTopicToOutTopic;
function inTopicToOutTopic({ inTopic }) {
const [ namespace, from, to ] = inTopic.split('/');
const outTopic = `/${namespace}/${to}/${from}`;
return outTopic;
}
```
main();
```
**Client**
```js
const clientId = 'client123'; // you can use UUID for automatic id generation.
const inTopic = `/rpc/auth-server/${clientId}`;
const outTopic = `/rpc/${clientId}/auth-server`
```
So, for each clients connection to server you will have a pair of topics.
It looks a little bit more complecated but allows easely switch to many-to-many connection apprach.
### Many-to-many connections
For this case, you can use the same approach as for "Many RPC clients and one RPC Server" case.
1. You run every service as an Mole RPC server.
2. You use instantiate Mole RPC clients with corresponding topics.
You can notive that if SERVICE_A talks to SEVICE_B we need 2 topics. But when SERVICE_B talks to SERVICE_A we will use the same topic names and that is ok. This transport handles this situation, so you can use understandable topics which always follow this pattern:
* Always send data to: `/rpc/${FROM}/${TO}`
* Always get data from: `/rpc/${TO}/${FROM}`
This is the approach we use for many-to-many communication approach but you can use other approaces.
For example, if you want to allow SERVICE_A to get request only from SERVICE_B, you can use inTopic name without wildcard - `/rpc/SERVICE_B/SERVICE_A` (outTopic can be set to static value `/rpc/SERVICE_A/SERVICE_B` as well ).

@@ -5,3 +5,4 @@ const MQTT = require('async-mqtt');

const MoleServer = require('mole-rpc/MoleServer');
const AutoTester = require('mole-rpc/AutoTester');
const X = require('mole-rpc/X');
const AutoTester = require('mole-rpc-autotester');

@@ -11,2 +12,4 @@ const TransportClient = require('../TransportClient');

const MQTT_ENDPOINT = 'tcp://test.mosquitto.org:1883'; // "tcp://localhost:1883" for local testing
async function main() {

@@ -17,2 +20,3 @@ const server = await prepareServer();

const autoTester = new AutoTester({
X,
server,

@@ -27,4 +31,3 @@ simpleClient: clients.simpleClient,

async function prepareServer() {
const mqttClient = MQTT.connect('tcp://localhost:1883');
await waitForEvent(mqttClient, 'connect');
const mqttClient = MQTT.connect(MQTT_ENDPOINT);

@@ -43,4 +46,3 @@ return new MoleServer({

async function prepareClients() {
const mqttClient = MQTT.connect('tcp://localhost:1883');
await waitForEvent(mqttClient, 'connect');
const mqttClient = MQTT.connect(MQTT_ENDPOINT);

@@ -68,10 +70,4 @@ const simpleClient = new MoleClient({

function waitForEvent(emitter, eventName) {
return new Promise((resolve, reject) => {
emitter.on(eventName, resolve);
});
}
main().then(() => {
process.exit();
}, console.error);
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc