Number of Packages 95th Percentile

Flow to check the number of packages listed in the dependencies for each package published in the Node-RED catalog and then calculate the 95th Percentile value.

This flow requests each pacakge from npm so it is limited to 1req/sec, with ~3600 pacakges in the catalog it takes around an hour to run!

[{"id":"d0cb60334e2c6512","type":"tab","label":"Flow 5","disabled":false,"info":""},{"id":"75b1098e0fa46eb4","type":"inject","z":"d0cb60334e2c6512","name":"Full Catalog","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payloadType":"date","x":410,"y":260,"wires":[["60be104f813122bb"]]},{"id":"60be104f813122bb","type":"http request","z":"d0cb60334e2c6512","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"https:///catalogue.nodered.org/catalogue.json","tls":"","persist":false,"proxy":"","authType":"","x":590,"y":260,"wires":[["3e9ac94517b5c37d"]]},{"id":"2e21a335aa215015","type":"split","z":"d0cb60334e2c6512","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":990,"y":260,"wires":[["9dc0009e7aaad0fe"]]},{"id":"3e9ac94517b5c37d","type":"change","z":"d0cb60334e2c6512","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.modules","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":800,"y":260,"wires":[["2e21a335aa215015"]]},{"id":"9dc0009e7aaad0fe","type":"delay","z":"d0cb60334e2c6512","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"x":1150,"y":260,"wires":[["e0dc454418e58837"]]},{"id":"e0dc454418e58837","type":"function","z":"d0cb60334e2c6512","name":"npm-ls-remote","func":"var ls = npmls.ls\nvar config = npmls.config\nmsg.topic = msg.payload.id+\"@\"+msg.payload.version\n\nconfig({\n  development: false,\n  optional: false\n})\n\ntry{\n    ls(msg.payload.id, msg.payload.version,  function(obj) {\n    msg.payload =  obj\n    node.send(msg)\n    });\n}\ncatch(err){\n    node.error(msg.topic)\n}\n    \n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"npmls","module":"npm-remote-ls"}],"x":1340,"y":260,"wires":[["287a1487d78865e5"]]},{"id":"287a1487d78865e5","type":"change","z":"d0cb60334e2c6512","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"$count($keys(payload.*))\t\t","tot":"jsonata"},{"t":"set","p":"topic","pt":"msg","to":"95","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":1560,"y":260,"wires":[["7b2df8564492932d"]]},{"id":"7b2df8564492932d","type":"join","z":"d0cb60334e2c6512","name":"","mode":"auto","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":"false","timeout":"","count":"","reduceRight":false,"x":1750,"y":260,"wires":[["e5fc698e6e22cbbb"]]},{"id":"7fc803eabf6e5beb","type":"debug","z":"d0cb60334e2c6512","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":2130,"y":260,"wires":[]},{"id":"e5fc698e6e22cbbb","type":"function","z":"d0cb60334e2c6512","name":"Percentile","func":"function sumArr(arr) {\n    var a = arr.slice();\n    return a.reduce(function (a, b) { return parseFloat(a) + parseFloat(b); });\n}\n\n/** Sort values into ascending order\n*\n*/\nfunction sortArr(arr) {\n    var ary = arr.slice();\n    ary.sort(function (a, b) { return parseFloat(a) - parseFloat(b); });\n    return ary;\n}\n\nfunction calcQuartile(arr, q) {\n    var a = arr.slice();\n    // Turn q into a decimal (e.g. 95 becomes 0.95)\n    q = q / 100;\n\n    // Sort the array into ascending order\n    var data = sortArr(a);\n\n    // Work out the position in the array of the percentile point\n    var p = ((data.length) - 1) * q;\n    var b = Math.floor(p);\n\n    // Work out what we rounded off (if anything)\n    var remainder = p - b;\n\n    // See whether that data exists directly\n    if (data[b + 1] !== undefined) {\n        return parseFloat(data[b]) + remainder * (parseFloat(data[b + 1]) - parseFloat(data[b]));\n    } else {\n        return parseFloat(data[b]);\n    }\n}\n\nmsg.payload = calcQuartile(msg.payload, msg.topic)\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1940,"y":260,"wires":[["7fc803eabf6e5beb"]]},{"id":"4d161013d0ba7e50","type":"inject","z":"d0cb60334e2c6512","name":"Reset","props":[{"p":"reset","v":"true","vt":"bool"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":990,"y":180,"wires":[["9dc0009e7aaad0fe"]]}]

Flow Info

Created 3 years, 11 months ago
Rating: not yet rated

Owner

Actions

Rate:

Node Types

Core
  • change (x2)
  • debug (x1)
  • delay (x1)
  • function (x2)
  • http request (x1)
  • inject (x2)
  • join (x1)
  • split (x1)
Other
  • tab (x1)

Tags

Copy this flow JSON to your clipboard and then import into Node-RED using the Import From > Clipboard (Ctrl-I) menu option