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.
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-teamogy-api",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"
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
- async function fetchWithRetry(url, options, retries, delay, node) {
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
- let o = {}
12
- o.status = response.status;
13
- o.message = await response.text();
14
- o.attempt = i + 1;
15
- o.delay = delay / 1000;
16
-
17
- await new Promise(resolve => setTimeout(resolve, delay));
18
-
19
- } catch (error) {
20
-
21
- let o = {}
22
- o.status = 0;
23
- o.message = 'Request failed';
24
- o.attempt = i + 1;
25
- o.delay = delay / 1000;
26
-
27
- await new Promise(resolve => setTimeout(resolve, delay));
28
- }
29
- }
30
- return null;
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);