vrpc 3.13.0 → 3.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +100 -77
- package/browser/vrpc.js +5 -5
- package/index.js +7 -7
- package/package.json +25 -15
- package/vrpc/ReconnectBackoff.js +79 -0
- package/vrpc/Registrations.js +850 -0
- package/vrpc/SubscribeRetrier.js +33 -0
- package/vrpc/VrpcAdapter.js +552 -294
- package/vrpc/VrpcAgent.js +242 -154
- package/vrpc/VrpcBrowserAdapter.js +417 -285
- package/vrpc/VrpcBrowserAgent.js +239 -128
- package/vrpc/VrpcClient.js +1221 -233
- package/vrpc/VrpcNative.js +10 -5
- package/vrpc/VrpcPersistor.js +1 -1
- package/vrpc/adapter.hpp +1 -1
- package/vrpc/addon.cpp +1 -1
- package/vrpc/comment-parser/parser.js +23 -0
- package/vrpc/namePattern.js +86 -0
- package/vrpc/vrpc-agent-js +3 -11
package/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
// one assignment per name: Node detects them as named exports, so
|
|
3
|
+
// `import { VrpcClient } from 'vrpc'` works from ES modules, too
|
|
4
|
+
exports.VrpcNative = require('./vrpc/VrpcNative')
|
|
5
|
+
exports.VrpcClient = require('./vrpc/VrpcClient')
|
|
6
|
+
exports.VrpcAdapter = require('./vrpc/VrpcAdapter')
|
|
7
|
+
exports.VrpcAgent = require('./vrpc/VrpcAgent')
|
|
8
|
+
exports.VrpcPersistor = require('./vrpc/VrpcPersistor')
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vrpc",
|
|
3
|
-
"version": "3.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "3.15.0",
|
|
4
|
+
"description": "Remote objects over MQTT: call classes in other programs as if they were local - Node.js, browser, C++, Python, Arduino",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"directories": {
|
|
7
7
|
"example": "examples",
|
|
@@ -11,10 +11,14 @@
|
|
|
11
11
|
"scripts": {
|
|
12
12
|
"build:addon": "ln -sf binding.gyp.no-auto binding.gyp && node-gyp rebuild && rm binding.gyp",
|
|
13
13
|
"build:browser": "./node_modules/.bin/webpack --stats-error-details",
|
|
14
|
-
"build:doc": "
|
|
15
|
-
"
|
|
14
|
+
"build:doc": "node scripts/build-docs.js",
|
|
15
|
+
"check:links": "node scripts/check-links.js",
|
|
16
|
+
"test": "npm run test:adapter && npm run test:subscriptions && npm run test:examples && npm run test:reconnect && npm run test:agent && npm run test:client && npm run test:persistor && npm run test:lifecycle && npm run test:legacy-runtime && npm run test:production",
|
|
16
17
|
"test:adapter": "./node_modules/.bin/mocha tests/adapter/*.js --exit",
|
|
17
18
|
"test:native": "./node_modules/.bin/mocha tests/native/*.js --exit",
|
|
19
|
+
"test:reconnect": "./node_modules/.bin/mocha tests/reconnect/*.spec.js --exit",
|
|
20
|
+
"test:subscriptions": "./node_modules/.bin/mocha tests/subscriptions/*.spec.js --exit",
|
|
21
|
+
"test:examples": "./node_modules/.bin/mocha tests/examples/*.spec.js --exit",
|
|
18
22
|
"test:agent": "tests/agent/test.sh",
|
|
19
23
|
"test:client": "tests/client/test.sh",
|
|
20
24
|
"test:performance": "tests/performance/test.sh",
|
|
@@ -27,27 +31,32 @@
|
|
|
27
31
|
"vrpc-agent-js": "./vrpc/vrpc-agent-js"
|
|
28
32
|
},
|
|
29
33
|
"keywords": [
|
|
30
|
-
"
|
|
31
|
-
"iot",
|
|
34
|
+
"rpc",
|
|
32
35
|
"mqtt",
|
|
36
|
+
"remote objects",
|
|
37
|
+
"remote procedure call",
|
|
38
|
+
"mqtt-rpc",
|
|
39
|
+
"iot",
|
|
33
40
|
"edge-to-cloud",
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
41
|
+
"events",
|
|
42
|
+
"microservices",
|
|
43
|
+
"browser",
|
|
44
|
+
"react",
|
|
45
|
+
"arduino",
|
|
46
|
+
"esp32",
|
|
47
|
+
"python",
|
|
48
|
+
"c++"
|
|
40
49
|
],
|
|
41
50
|
"repository": {
|
|
42
51
|
"type": "git",
|
|
43
|
-
"url": "git+https://github.com/heisenware/vrpc.git"
|
|
52
|
+
"url": "git+https://github.com/heisenware/vrpc-js.git"
|
|
44
53
|
},
|
|
45
54
|
"author": "Burkhard C. Heisen <burkhard.heisen@heisenware.com>",
|
|
46
55
|
"license": "MIT",
|
|
47
56
|
"bugs": {
|
|
48
|
-
"url": "https://github.com/heisenware/vrpc/issues"
|
|
57
|
+
"url": "https://github.com/heisenware/vrpc-js/issues"
|
|
49
58
|
},
|
|
50
|
-
"homepage": "https://
|
|
59
|
+
"homepage": "https://vrpc.io",
|
|
51
60
|
"devDependencies": {
|
|
52
61
|
"@heisenware/storage": "^3.0.2",
|
|
53
62
|
"assert": "^2.1.0",
|
|
@@ -57,6 +66,7 @@
|
|
|
57
66
|
"fs-extra": "^11.3.1",
|
|
58
67
|
"jsdoc-to-markdown": "^7.0.1",
|
|
59
68
|
"mocha": "^9.2.2",
|
|
69
|
+
"mqtt-packet": "^9.0.2",
|
|
60
70
|
"os-browserify": "^0.3.0",
|
|
61
71
|
"sinon": "^21.0.0",
|
|
62
72
|
"stream-browserify": "^3.0.0",
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Paces the reconnects of an mqtt.js client after refused CONNACKs.
|
|
3
|
+
*
|
|
4
|
+
* mqtt.js retries at a fixed `reconnectPeriod`. A connection the broker
|
|
5
|
+
* refuses - a stale credential, an authorization service that is away -
|
|
6
|
+
* would knock once per period for as long as it lives, and an
|
|
7
|
+
* authorization service may block a client id that knocks too often. So
|
|
8
|
+
* every refusal doubles the wait up to `max`, and a successful connect
|
|
9
|
+
* restores the base. The refusal itself stays visible as the client's
|
|
10
|
+
* 'error' event, so a host can renew its credentials and `hurry()`.
|
|
11
|
+
*
|
|
12
|
+
* mqtt.js reads `reconnectPeriod` only when it arms its reconnect
|
|
13
|
+
* interval, once per outage; re-arming it takes the internal
|
|
14
|
+
* `_clearReconnect` / `_setupReconnect`. Without them (a future mqtt.js)
|
|
15
|
+
* a new period applies from the next outage on.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const REFUSED = /^Connection refused/
|
|
19
|
+
|
|
20
|
+
class ReconnectBackoff {
|
|
21
|
+
/**
|
|
22
|
+
* @param {Object} client an mqtt.js client created with
|
|
23
|
+
* `reconnectOnConnackError: true`
|
|
24
|
+
* @param {Object} [options]
|
|
25
|
+
* @param {Number} [options.max=30000] longest wait in ms between attempts
|
|
26
|
+
*/
|
|
27
|
+
constructor (client, { max = 30000 } = {}) {
|
|
28
|
+
this._client = client
|
|
29
|
+
this._base = client.options.reconnectPeriod
|
|
30
|
+
this._max = Math.max(max, this._base)
|
|
31
|
+
this._next = this._base
|
|
32
|
+
client.on('error', err => {
|
|
33
|
+
if (ReconnectBackoff.isRefusal(err)) this._slowDown()
|
|
34
|
+
})
|
|
35
|
+
client.on('connect', () => this._restore())
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Whether an mqtt.js error is a refused CONNACK. */
|
|
39
|
+
static isRefusal (err) {
|
|
40
|
+
return (
|
|
41
|
+
!!err && typeof err.code === 'number' && REFUSED.test(err.message || '')
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** The wait in ms before the next attempt. */
|
|
46
|
+
get period () {
|
|
47
|
+
return this._client.options.reconnectPeriod
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* New credentials: the next attempt follows within the base period
|
|
52
|
+
* instead of waiting out the back-off. A live connection stays as it is.
|
|
53
|
+
*/
|
|
54
|
+
hurry () {
|
|
55
|
+
this._restore()
|
|
56
|
+
const client = this._client
|
|
57
|
+
if (client.connected || client.disconnecting || !client.reconnecting) return
|
|
58
|
+
if (typeof client._clearReconnect !== 'function') return
|
|
59
|
+
client._clearReconnect()
|
|
60
|
+
client._setupReconnect()
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Runs inside the CONNACK handler's 'error' emit: the handler re-arms
|
|
64
|
+
// the reconnect interval right after (reconnectOnConnackError), with the
|
|
65
|
+
// period set here
|
|
66
|
+
_slowDown () {
|
|
67
|
+
const client = this._client
|
|
68
|
+
client.options.reconnectPeriod = this._next
|
|
69
|
+
this._next = Math.min(this._next * 2, this._max)
|
|
70
|
+
if (typeof client._clearReconnect === 'function') client._clearReconnect()
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
_restore () {
|
|
74
|
+
this._next = this._base
|
|
75
|
+
this._client.options.reconnectPeriod = this._base
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
module.exports = ReconnectBackoff
|