node-red-contrib-teamogy-api 0.0.3 → 0.0.5
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/examples/examples.json +88 -0
- package/package.json +1 -1
- package/teamogy-client.js +101 -48
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "62054fac29909a02",
|
|
4
|
+
"type": "tab",
|
|
5
|
+
"label": "Teamogy API",
|
|
6
|
+
"disabled": false,
|
|
7
|
+
"info": "",
|
|
8
|
+
"env": []
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"id": "05bbee7aa38f796a",
|
|
12
|
+
"type": "inject",
|
|
13
|
+
"z": "62054fac29909a02",
|
|
14
|
+
"name": "start",
|
|
15
|
+
"props": [
|
|
16
|
+
{
|
|
17
|
+
"p": "payload"
|
|
18
|
+
}
|
|
19
|
+
],
|
|
20
|
+
"repeat": "",
|
|
21
|
+
"crontab": "",
|
|
22
|
+
"once": false,
|
|
23
|
+
"onceDelay": 0.1,
|
|
24
|
+
"topic": "",
|
|
25
|
+
"payload": "",
|
|
26
|
+
"payloadType": "date",
|
|
27
|
+
"x": 110,
|
|
28
|
+
"y": 80,
|
|
29
|
+
"wires": [
|
|
30
|
+
[
|
|
31
|
+
"25be0ae5bfcab80b"
|
|
32
|
+
]
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"id": "7bf1dfbdafb4256d",
|
|
37
|
+
"type": "debug",
|
|
38
|
+
"z": "62054fac29909a02",
|
|
39
|
+
"name": "debug",
|
|
40
|
+
"active": true,
|
|
41
|
+
"tosidebar": true,
|
|
42
|
+
"console": false,
|
|
43
|
+
"tostatus": false,
|
|
44
|
+
"complete": "payload",
|
|
45
|
+
"targetType": "msg",
|
|
46
|
+
"statusVal": "",
|
|
47
|
+
"statusType": "auto",
|
|
48
|
+
"x": 450,
|
|
49
|
+
"y": 80,
|
|
50
|
+
"wires": []
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"id": "25be0ae5bfcab80b",
|
|
54
|
+
"type": "teamogy-client",
|
|
55
|
+
"z": "62054fac29909a02",
|
|
56
|
+
"name": "",
|
|
57
|
+
"configuration": "",
|
|
58
|
+
"mode": true,
|
|
59
|
+
"method": "GET",
|
|
60
|
+
"entity": "v_users",
|
|
61
|
+
"source": "static",
|
|
62
|
+
"cparams": "",
|
|
63
|
+
"cbody": "",
|
|
64
|
+
"bodysource": "payload",
|
|
65
|
+
"merge": false,
|
|
66
|
+
"limit": "0",
|
|
67
|
+
"paging": "1000",
|
|
68
|
+
"offset": "0",
|
|
69
|
+
"delay": "0",
|
|
70
|
+
"repeat": "5",
|
|
71
|
+
"rdelay": "30",
|
|
72
|
+
"x": 280,
|
|
73
|
+
"y": 80,
|
|
74
|
+
"wires": [
|
|
75
|
+
[
|
|
76
|
+
"7bf1dfbdafb4256d"
|
|
77
|
+
]
|
|
78
|
+
]
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"id": "b7904e06c3ec62bd",
|
|
82
|
+
"type": "global-config",
|
|
83
|
+
"env": [],
|
|
84
|
+
"modules": {
|
|
85
|
+
"node-red-contrib-teamogy-api": "0.0.4"
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
]
|
package/package.json
CHANGED
package/teamogy-client.js
CHANGED
|
@@ -1,37 +1,63 @@
|
|
|
1
1
|
function isEmpty(value) { return (value == null || (typeof value === "string" && value.trim().length === 0)); }
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
for (let i = 0; i <= retries; i++) {
|
|
5
|
-
try {
|
|
6
|
-
const response = await fetch(url, options);
|
|
7
|
-
if (response.status >= 200 && response.status < 300) {
|
|
8
|
-
return response;
|
|
9
|
-
}
|
|
3
|
+
module.exports = function(RED) {
|
|
10
4
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
5
|
+
if (typeof globalNextAvailableSlot === 'undefined') {
|
|
6
|
+
var globalNextAvailableSlot = Date.now();
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
async function fetchWithRetry(url, options, retries, delay, node, limit) {
|
|
10
|
+
|
|
11
|
+
const minInterval = 60000 / limit;
|
|
12
|
+
|
|
13
|
+
for (let i = 0; i <= retries; i++) {
|
|
14
|
+
try {
|
|
15
|
+
let now = Date.now();
|
|
16
|
+
let waitTime = 0;
|
|
17
|
+
|
|
18
|
+
let scheduledTime = Math.max(now, globalNextAvailableSlot);
|
|
19
|
+
globalNextAvailableSlot = scheduledTime + minInterval;
|
|
20
|
+
|
|
21
|
+
waitTime = scheduledTime - now;
|
|
22
|
+
|
|
23
|
+
if (waitTime > 0) {
|
|
24
|
+
await new Promise(resolve => setTimeout(resolve, waitTime));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (node.closingId == node.id) {
|
|
28
|
+
return { status: 0 };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const response = await fetch(url, options);
|
|
32
|
+
|
|
33
|
+
if (response.status >= 200 && response.status < 300) {
|
|
34
|
+
return response;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let o = {
|
|
38
|
+
status: response.status,
|
|
39
|
+
message: await response.text() ?? '',
|
|
40
|
+
attempt: i + 1,
|
|
41
|
+
delay: delay / 1000
|
|
42
|
+
};
|
|
43
|
+
node.warn(o);
|
|
44
|
+
|
|
45
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
46
|
+
|
|
47
|
+
} catch (error) {
|
|
48
|
+
let o = {
|
|
49
|
+
status: 0,
|
|
50
|
+
message: 'Request failed: ' + error.message,
|
|
51
|
+
attempt: i + 1,
|
|
52
|
+
delay: delay / 1000
|
|
53
|
+
};
|
|
54
|
+
node.warn(o);
|
|
55
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
32
60
|
|
|
33
|
-
module.exports = function(RED) {
|
|
34
|
-
|
|
35
61
|
function getConfigId(name) {
|
|
36
62
|
var configNodes = [];
|
|
37
63
|
RED.nodes.eachNode(function(node) {
|
|
@@ -61,9 +87,13 @@ module.exports = function(RED) {
|
|
|
61
87
|
let cache = []
|
|
62
88
|
this.context().global.set('cache_' + this.host, cache)
|
|
63
89
|
}
|
|
90
|
+
|
|
91
|
+
if(typeof this.context().global.get('count_' + this.host ) == 'undefined') {
|
|
92
|
+
this.context().global.set('count_' + this.host, 0)
|
|
93
|
+
}
|
|
64
94
|
|
|
65
95
|
} catch (e) {
|
|
66
|
-
node.error(e);
|
|
96
|
+
node.error(e.message);
|
|
67
97
|
}
|
|
68
98
|
}
|
|
69
99
|
|
|
@@ -76,7 +106,9 @@ module.exports = function(RED) {
|
|
|
76
106
|
function teamogyClient(data) {
|
|
77
107
|
try {
|
|
78
108
|
var node = this;
|
|
79
|
-
|
|
109
|
+
|
|
110
|
+
node.closingId = '';
|
|
111
|
+
|
|
80
112
|
RED.nodes.createNode(node,data);
|
|
81
113
|
|
|
82
114
|
this.config = RED.nodes.getNode(data.configuration);
|
|
@@ -85,9 +117,11 @@ module.exports = function(RED) {
|
|
|
85
117
|
let host = this.config.host.replace(/^https?:\/\//, '').split('/')[0];
|
|
86
118
|
let unit = this.config.unit
|
|
87
119
|
let connName = this.config.name
|
|
120
|
+
let apiLimit = this.config.apilimit
|
|
88
121
|
|
|
89
122
|
let clientid = data.id
|
|
90
123
|
let c = this.context().global.get('cache_' + host)
|
|
124
|
+
let ct = this.context().global.get('count_' + host)
|
|
91
125
|
let st = null;
|
|
92
126
|
|
|
93
127
|
async function sendmsg(mesg) {
|
|
@@ -190,9 +224,9 @@ module.exports = function(RED) {
|
|
|
190
224
|
metadata.count = 0
|
|
191
225
|
metadata.limit = 0
|
|
192
226
|
let rdata = [];
|
|
193
|
-
|
|
227
|
+
|
|
194
228
|
let offset = moffset
|
|
195
|
-
|
|
229
|
+
|
|
196
230
|
if(method == 'GET') { body = null }
|
|
197
231
|
|
|
198
232
|
if(entity.split('_')[0] == 'v') {
|
|
@@ -200,14 +234,14 @@ module.exports = function(RED) {
|
|
|
200
234
|
|
|
201
235
|
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
202
236
|
|
|
203
|
-
while (offset != null) {
|
|
237
|
+
while (offset != null && node.closingId != clientid) {
|
|
204
238
|
|
|
205
239
|
if(parseInt(mlimit) == 0) { mlimit = 1000000000}
|
|
206
240
|
if(parseInt(mlimit) < parseInt(mpaging)) { mpaging = mlimit }
|
|
207
241
|
|
|
208
242
|
eurl = encodeURI(url + 'limit=' + mpaging +'&offset=' + offset)
|
|
209
243
|
|
|
210
|
-
const response = await fetchWithRetry(eurl, { headers, method, body }, repeat, rdelay, node);
|
|
244
|
+
const response = await fetchWithRetry(eurl, { headers, method, body }, repeat, rdelay, node, apiLimit);
|
|
211
245
|
|
|
212
246
|
if(response && response.status >= 200 && response.status < 300) {
|
|
213
247
|
|
|
@@ -232,11 +266,11 @@ module.exports = function(RED) {
|
|
|
232
266
|
}
|
|
233
267
|
|
|
234
268
|
if(mlimit <= metadata.count) { break; }
|
|
269
|
+
|
|
235
270
|
if (offset != null && delay > 0) { await sleep(delay); }
|
|
236
271
|
|
|
237
272
|
} else {
|
|
238
273
|
if (!response) {
|
|
239
|
-
node.error('Request failed after all attempts.');
|
|
240
274
|
msg.error = 'Request failed after all attempts.'
|
|
241
275
|
msg.payload = null;
|
|
242
276
|
if(msg.res){
|
|
@@ -244,7 +278,7 @@ module.exports = function(RED) {
|
|
|
244
278
|
msg.statusCode = 500;
|
|
245
279
|
}
|
|
246
280
|
node.send(msg);
|
|
247
|
-
} else {
|
|
281
|
+
} else if(response.status != 0) {
|
|
248
282
|
node.error('Response status: ' + response.status);
|
|
249
283
|
node.error('Response text: ' + await response.text());
|
|
250
284
|
}
|
|
@@ -265,7 +299,7 @@ module.exports = function(RED) {
|
|
|
265
299
|
|
|
266
300
|
if(entity.split('_')[0] == 'r') {
|
|
267
301
|
|
|
268
|
-
const response = await fetchWithRetry(encodeURI(url), { headers, method, body }, repeat, rdelay, node);
|
|
302
|
+
const response = await fetchWithRetry(encodeURI(url), { headers, method, body }, repeat, rdelay, node, apiLimit);
|
|
269
303
|
|
|
270
304
|
if(response && response.status >= 200 && response.status < 300) {
|
|
271
305
|
const body = await response.json();
|
|
@@ -273,7 +307,6 @@ module.exports = function(RED) {
|
|
|
273
307
|
node.send(msg);
|
|
274
308
|
} else {
|
|
275
309
|
if (!response) {
|
|
276
|
-
node.error('Request failed after all attempts.');
|
|
277
310
|
msg.error = 'Request failed after all attempts.'
|
|
278
311
|
msg.payload = null;
|
|
279
312
|
if(msg.res){
|
|
@@ -281,21 +314,21 @@ module.exports = function(RED) {
|
|
|
281
314
|
msg.statusCode = 500;
|
|
282
315
|
}
|
|
283
316
|
node.send(msg);
|
|
284
|
-
} else {
|
|
317
|
+
} else if(response.status != 0) {
|
|
285
318
|
node.error('Response status: ' + response.status);
|
|
286
319
|
node.error('Response text: ' + await response.text());
|
|
287
320
|
}
|
|
288
321
|
}
|
|
289
322
|
}
|
|
290
323
|
} catch (e) {
|
|
291
|
-
node.error(e);
|
|
324
|
+
node.error(e.message);
|
|
292
325
|
}
|
|
293
326
|
}
|
|
294
327
|
|
|
295
328
|
await doAsyncJobs();
|
|
296
329
|
|
|
297
330
|
} catch (e) {
|
|
298
|
-
node.error(e);
|
|
331
|
+
node.error(e.message);
|
|
299
332
|
}
|
|
300
333
|
}
|
|
301
334
|
|
|
@@ -306,12 +339,20 @@ module.exports = function(RED) {
|
|
|
306
339
|
});
|
|
307
340
|
return na.length
|
|
308
341
|
} catch (e) {
|
|
309
|
-
node.error(e);
|
|
342
|
+
node.error(e.message);
|
|
310
343
|
}
|
|
311
344
|
}
|
|
312
345
|
|
|
313
346
|
async function setTimer(host) {
|
|
314
347
|
try {
|
|
348
|
+
if(node.closingId == clientid) {
|
|
349
|
+
for (let i = c.length - 1; i >= 0; i--) {
|
|
350
|
+
if (c[i].clientid === clientid) {
|
|
351
|
+
c.splice(i, 1);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
315
356
|
if(c.length > 0) {
|
|
316
357
|
let nd = new Date()
|
|
317
358
|
if(nd.getTime() > c[0].stime) {
|
|
@@ -329,16 +370,17 @@ module.exports = function(RED) {
|
|
|
329
370
|
node.status({fill: "yellow", shape: "dot", text: fal + " waiting messages"});
|
|
330
371
|
}
|
|
331
372
|
} else {
|
|
373
|
+
node.status({fill: "green", shape: "dot", text: "0 waiting messages"});
|
|
332
374
|
clearInterval(st)
|
|
333
375
|
st = null
|
|
334
376
|
}
|
|
335
377
|
}
|
|
336
378
|
catch (e) {
|
|
337
|
-
node.error(e);
|
|
379
|
+
node.error(e.message);
|
|
338
380
|
}
|
|
339
381
|
}
|
|
340
382
|
|
|
341
|
-
node.on('input', async function(msg) {
|
|
383
|
+
node.on('input', async function(msg, send, done) {
|
|
342
384
|
try {
|
|
343
385
|
if(st == null){ st = setInterval(function () { setTimer(host) }, 1000)}
|
|
344
386
|
|
|
@@ -363,15 +405,26 @@ module.exports = function(RED) {
|
|
|
363
405
|
} else {
|
|
364
406
|
node.send(msg)
|
|
365
407
|
}
|
|
408
|
+
if (done) {
|
|
409
|
+
done();
|
|
410
|
+
}
|
|
366
411
|
}
|
|
367
412
|
catch (e) {
|
|
368
|
-
node.error(e);
|
|
413
|
+
node.error(e.message);
|
|
369
414
|
}
|
|
370
415
|
});
|
|
371
416
|
|
|
372
417
|
} catch (e) {
|
|
373
|
-
node.error(e);
|
|
418
|
+
node.error(e.message);
|
|
374
419
|
}
|
|
420
|
+
|
|
421
|
+
node.on('close', function(done) {
|
|
422
|
+
node.closingId = this.id;
|
|
423
|
+
|
|
424
|
+
if (done) {
|
|
425
|
+
done();
|
|
426
|
+
}
|
|
427
|
+
});
|
|
375
428
|
}
|
|
376
429
|
|
|
377
430
|
RED.nodes.registerType("teamogy-client",teamogyClient);
|