mirror of
https://github.com/EvernodeXRPL/hpcore.git
synced 2026-04-29 15:37:59 +00:00
Cluster event stream scripts. (#321)
This commit is contained in:
5
test/vm-cluster/.gitignore
vendored
5
test/vm-cluster/.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
cfg
|
||||
*.json
|
||||
hpfiles
|
||||
config.json
|
||||
hpfiles
|
||||
node_modules
|
||||
@@ -123,7 +123,7 @@ if [[ ${_host1parts[0]} == "vultr" ]]; then
|
||||
[ -z "$_vultrvms" ] && exit 1
|
||||
_vultrips=$(echo $(echo $_vultrvms | jq -r ".instances | sort_by(.label) | .[] | .main_ip"))
|
||||
readarray -d " " -t hostaddrs < <(printf '%s' "$_vultrips") # Populate hostaddrs with ips retrieved from vultr.
|
||||
echo "Retrieved ${#hostaddrs[@]} host addresses from vultr."
|
||||
echo "Retrieved ${#hostaddrs[@]} host addresses from vultr group: '${_host1parts[1]}'"
|
||||
fi
|
||||
hostcount=${#hostaddrs[@]}
|
||||
|
||||
|
||||
511
test/vm-cluster/package-lock.json
generated
Normal file
511
test/vm-cluster/package-lock.json
generated
Normal file
@@ -0,0 +1,511 @@
|
||||
{
|
||||
"requires": true,
|
||||
"lockfileVersion": 1,
|
||||
"dependencies": {
|
||||
"ajv": {
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||
"requires": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
}
|
||||
},
|
||||
"asn1": {
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
|
||||
"integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
|
||||
"requires": {
|
||||
"safer-buffer": "~2.1.0"
|
||||
}
|
||||
},
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
|
||||
},
|
||||
"async-limiter": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
|
||||
"integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="
|
||||
},
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
|
||||
},
|
||||
"aws-sign2": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
||||
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
|
||||
},
|
||||
"aws4": {
|
||||
"version": "1.11.0",
|
||||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
|
||||
"integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA=="
|
||||
},
|
||||
"azure-storage": {
|
||||
"version": "2.10.4",
|
||||
"resolved": "https://registry.npmjs.org/azure-storage/-/azure-storage-2.10.4.tgz",
|
||||
"integrity": "sha512-zlfRPl4js92JC6+79C2EUmNGYjSknRl8pOiHQF78zy+pbOFOHtlBF6BU/OxPeHQX3gaa6NdEZnVydFxhhndkEw==",
|
||||
"requires": {
|
||||
"browserify-mime": "~1.2.9",
|
||||
"extend": "^3.0.2",
|
||||
"json-edm-parser": "0.1.2",
|
||||
"md5.js": "1.3.4",
|
||||
"readable-stream": "~2.0.0",
|
||||
"request": "^2.86.0",
|
||||
"underscore": "^1.12.1",
|
||||
"uuid": "^3.0.0",
|
||||
"validator": "~9.4.1",
|
||||
"xml2js": "0.2.8",
|
||||
"xmlbuilder": "^9.0.7"
|
||||
}
|
||||
},
|
||||
"bcrypt-pbkdf": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
|
||||
"integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
|
||||
"requires": {
|
||||
"tweetnacl": "^0.14.3"
|
||||
}
|
||||
},
|
||||
"blake3": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/blake3/-/blake3-2.1.4.tgz",
|
||||
"integrity": "sha512-70hmx0lPd6zmtNwxPT4/1P0pqaEUlTJ0noUBvCXPLfMpN0o8PPaK3q7ZlpRIyhrqcXxeMAJSowNm/L9oi/x1XA=="
|
||||
},
|
||||
"browserify-mime": {
|
||||
"version": "1.2.9",
|
||||
"resolved": "https://registry.npmjs.org/browserify-mime/-/browserify-mime-1.2.9.tgz",
|
||||
"integrity": "sha1-rrGvKN5sDXpqLOQK22j/GEIq8x8="
|
||||
},
|
||||
"caseless": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
|
||||
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"requires": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
|
||||
},
|
||||
"dashdash": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
|
||||
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
|
||||
},
|
||||
"ecc-jsbn": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
|
||||
"integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
|
||||
"requires": {
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"extend": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
|
||||
},
|
||||
"extsprintf": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
|
||||
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
|
||||
},
|
||||
"fast-json-stable-stringify": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
|
||||
},
|
||||
"forever-agent": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
|
||||
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
|
||||
},
|
||||
"form-data": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
|
||||
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.6",
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
},
|
||||
"getpass": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
|
||||
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"har-schema": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
|
||||
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
|
||||
},
|
||||
"har-validator": {
|
||||
"version": "5.1.5",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
|
||||
"integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
|
||||
"requires": {
|
||||
"ajv": "^6.12.3",
|
||||
"har-schema": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"hash-base": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz",
|
||||
"integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==",
|
||||
"requires": {
|
||||
"inherits": "^2.0.4",
|
||||
"readable-stream": "^3.6.0",
|
||||
"safe-buffer": "^5.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"readable-stream": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||
"requires": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
"util-deprecate": "^1.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"http-signature": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
|
||||
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"jsprim": "^1.2.2",
|
||||
"sshpk": "^1.7.0"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
|
||||
},
|
||||
"isarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
|
||||
},
|
||||
"isstream": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
|
||||
},
|
||||
"jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
||||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
|
||||
},
|
||||
"json-edm-parser": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/json-edm-parser/-/json-edm-parser-0.1.2.tgz",
|
||||
"integrity": "sha1-HmCw/vG8CvZ7wNFG393lSGzWFbQ=",
|
||||
"requires": {
|
||||
"jsonparse": "~1.2.0"
|
||||
}
|
||||
},
|
||||
"json-schema": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
|
||||
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
|
||||
},
|
||||
"json-stringify-safe": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
||||
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
|
||||
},
|
||||
"jsonparse": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.2.0.tgz",
|
||||
"integrity": "sha1-XAxWhRBxYOcv50ib3eoLRMK8Z70="
|
||||
},
|
||||
"jsprim": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
|
||||
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0",
|
||||
"extsprintf": "1.3.0",
|
||||
"json-schema": "0.2.3",
|
||||
"verror": "1.10.0"
|
||||
}
|
||||
},
|
||||
"libsodium": {
|
||||
"version": "0.7.6",
|
||||
"resolved": "https://registry.npmjs.org/libsodium/-/libsodium-0.7.6.tgz",
|
||||
"integrity": "sha512-hPb/04sEuLcTRdWDtd+xH3RXBihpmbPCsKW/Jtf4PsvdyKh+D6z2D2gvp/5BfoxseP+0FCOg66kE+0oGUE/loQ=="
|
||||
},
|
||||
"libsodium-wrappers": {
|
||||
"version": "0.7.6",
|
||||
"resolved": "https://registry.npmjs.org/libsodium-wrappers/-/libsodium-wrappers-0.7.6.tgz",
|
||||
"integrity": "sha512-OUO2CWW5bHdLr6hkKLHIKI4raEkZrf3QHkhXsJ1yCh6MZ3JDA7jFD3kCATNquuGSG6MjjPHQIQms0y0gBDzjQg==",
|
||||
"requires": {
|
||||
"libsodium": "0.7.6"
|
||||
}
|
||||
},
|
||||
"md5.js": {
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz",
|
||||
"integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=",
|
||||
"requires": {
|
||||
"hash-base": "^3.0.0",
|
||||
"inherits": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.48.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz",
|
||||
"integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ=="
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.31",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz",
|
||||
"integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==",
|
||||
"requires": {
|
||||
"mime-db": "1.48.0"
|
||||
}
|
||||
},
|
||||
"oauth-sign": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
|
||||
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
|
||||
},
|
||||
"performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
|
||||
},
|
||||
"process-nextick-args": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
|
||||
"integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
|
||||
},
|
||||
"psl": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
|
||||
"integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ=="
|
||||
},
|
||||
"punycode": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.5.2",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
|
||||
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
|
||||
"integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
|
||||
"requires": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.1",
|
||||
"isarray": "~1.0.0",
|
||||
"process-nextick-args": "~1.0.6",
|
||||
"string_decoder": "~0.10.x",
|
||||
"util-deprecate": "~1.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"string_decoder": {
|
||||
"version": "0.10.31",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
|
||||
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
|
||||
}
|
||||
}
|
||||
},
|
||||
"request": {
|
||||
"version": "2.88.2",
|
||||
"resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
|
||||
"integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
|
||||
"requires": {
|
||||
"aws-sign2": "~0.7.0",
|
||||
"aws4": "^1.8.0",
|
||||
"caseless": "~0.12.0",
|
||||
"combined-stream": "~1.0.6",
|
||||
"extend": "~3.0.2",
|
||||
"forever-agent": "~0.6.1",
|
||||
"form-data": "~2.3.2",
|
||||
"har-validator": "~5.1.3",
|
||||
"http-signature": "~1.2.0",
|
||||
"is-typedarray": "~1.0.0",
|
||||
"isstream": "~0.1.2",
|
||||
"json-stringify-safe": "~5.0.1",
|
||||
"mime-types": "~2.1.19",
|
||||
"oauth-sign": "~0.9.0",
|
||||
"performance-now": "^2.1.0",
|
||||
"qs": "~6.5.2",
|
||||
"safe-buffer": "^5.1.2",
|
||||
"tough-cookie": "~2.5.0",
|
||||
"tunnel-agent": "^0.6.0",
|
||||
"uuid": "^3.3.2"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"sax": {
|
||||
"version": "0.5.8",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-0.5.8.tgz",
|
||||
"integrity": "sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE="
|
||||
},
|
||||
"sshpk": {
|
||||
"version": "1.16.1",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
|
||||
"integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
|
||||
"requires": {
|
||||
"asn1": "~0.2.3",
|
||||
"assert-plus": "^1.0.0",
|
||||
"bcrypt-pbkdf": "^1.0.0",
|
||||
"dashdash": "^1.12.0",
|
||||
"ecc-jsbn": "~0.1.1",
|
||||
"getpass": "^0.1.1",
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.0.2",
|
||||
"tweetnacl": "~0.14.0"
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
||||
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
|
||||
"requires": {
|
||||
"safe-buffer": "~5.2.0"
|
||||
}
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
|
||||
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
|
||||
"requires": {
|
||||
"psl": "^1.1.28",
|
||||
"punycode": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"tunnel-agent": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
|
||||
"requires": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"tweetnacl": {
|
||||
"version": "0.14.5",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
||||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
|
||||
},
|
||||
"underscore": {
|
||||
"version": "1.13.1",
|
||||
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz",
|
||||
"integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g=="
|
||||
},
|
||||
"uri-js": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
|
||||
"requires": {
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
|
||||
},
|
||||
"validator": {
|
||||
"version": "9.4.1",
|
||||
"resolved": "https://registry.npmjs.org/validator/-/validator-9.4.1.tgz",
|
||||
"integrity": "sha512-YV5KjzvRmSyJ1ee/Dm5UED0G+1L4GZnLN3w6/T+zZm8scVua4sOhYKWTUrKa0H/tMiJyO9QLHMPN+9mB/aMunA=="
|
||||
},
|
||||
"verror": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
|
||||
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"core-util-is": "1.0.2",
|
||||
"extsprintf": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"ws": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.1.2.tgz",
|
||||
"integrity": "sha512-gftXq3XI81cJCgkUiAVixA0raD9IVmXqsylCrjRygw4+UOOGzPoxnQ6r/CnVL9i+mDncJo94tSkyrtuuQVBmrg==",
|
||||
"requires": {
|
||||
"async-limiter": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"xml2js": {
|
||||
"version": "0.2.8",
|
||||
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.2.8.tgz",
|
||||
"integrity": "sha1-m4FpCTFjH/CdGVdUn69U9PmAs8I=",
|
||||
"requires": {
|
||||
"sax": "0.5.x"
|
||||
}
|
||||
},
|
||||
"xmlbuilder": {
|
||||
"version": "9.0.7",
|
||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
|
||||
"integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0="
|
||||
}
|
||||
}
|
||||
}
|
||||
8
test/vm-cluster/package.json
Normal file
8
test/vm-cluster/package.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"azure-storage": "2.10.4",
|
||||
"blake3": "2.1.4",
|
||||
"libsodium-wrappers": "0.7.6",
|
||||
"ws": "7.1.2"
|
||||
}
|
||||
}
|
||||
271
test/vm-cluster/stream.js
Normal file
271
test/vm-cluster/stream.js
Normal file
@@ -0,0 +1,271 @@
|
||||
const HotPocket = require('../../examples/js_client/lib/hp-client-lib');
|
||||
const azure = require('azure-storage');
|
||||
const fs = require('fs');
|
||||
const https = require('https');
|
||||
|
||||
const dispatchInterval = process.env.DISPATCH || 1000;
|
||||
const stateUploadInterval = process.env.STATEUPLOAD || 10000;
|
||||
const metricsTrackInterval = process.env.METRICSTRACK || 10000;
|
||||
const backoffDelayMax = process.env.BACKOFFMAX || 60000;
|
||||
const eventsBatchSize = process.env.EVENTBATCH || 10;
|
||||
const stateBatchSize = process.env.STATEBATCH || 20;
|
||||
|
||||
let keys = null;
|
||||
let vultrApiKey = null;
|
||||
let azureTable = null;
|
||||
let tableSvc = null;
|
||||
const queue = [];
|
||||
const metrics = {};
|
||||
const nodeGroups = {};
|
||||
|
||||
async function main() {
|
||||
|
||||
keys = await HotPocket.generateKeys();
|
||||
|
||||
const pkhex = Buffer.from(keys.publicKey).toString('hex');
|
||||
console.log('My public key is: ' + pkhex);
|
||||
|
||||
// Load cluster config.
|
||||
const config = JSON.parse(fs.readFileSync("config.json"));
|
||||
vultrApiKey = config.vultr.api_key;
|
||||
|
||||
// Create Azure table service.
|
||||
if (!config.azure_table) {
|
||||
console.log("Azure table config missing.");
|
||||
return;
|
||||
}
|
||||
tableSvc = azure.createTableServiceWithSas(config.azure_table.host, config.azure_table.sas);
|
||||
azureTable = config.azure_table.table;
|
||||
|
||||
// We only consider clusters with stream=true.
|
||||
const clusters = config.contracts.filter(c => c.stream == true).map(c => ({
|
||||
name: c.name,
|
||||
hosts: c.hosts,
|
||||
userPort: c.config.user.port
|
||||
}));
|
||||
console.log(`${clusters.length} clusters found with streaming enabled.`);
|
||||
if (clusters.length == 0)
|
||||
return;
|
||||
|
||||
// Resolve any vultr hosts.
|
||||
await Promise.all(clusters.map(c => resolveHosts(c)));
|
||||
if (clusters.filter(c => c.hosts.length > 0).length == 0)
|
||||
return;
|
||||
|
||||
// Start node state uploader.
|
||||
// This keeps uploading latest node state into table storage.
|
||||
nodeStateUploader();
|
||||
|
||||
// Start event dispatcher.
|
||||
// This keeps sending events to the ingestion endpoint.
|
||||
eventDispatcher();
|
||||
|
||||
// Start event metrics tracker.
|
||||
// metricsTracker();
|
||||
|
||||
// Start streaming events from all clusters.
|
||||
clusters.forEach(c => streamCluster(c));
|
||||
}
|
||||
|
||||
async function resolveHosts(cluster) {
|
||||
// If first host is an element with the pattern "vultr:", then we fetch hosts from vultr.
|
||||
if (cluster.hosts.length > 0 && cluster.hosts[0].startsWith("vultr:"))
|
||||
cluster.hosts = await getVultrHosts(cluster.hosts[0].split(":")[1]);
|
||||
|
||||
console.log(`${cluster.hosts.length} hosts in '${cluster.name}' cluster.`)
|
||||
}
|
||||
|
||||
function eventDispatcher() {
|
||||
|
||||
// Dispatch all queued events in batches.
|
||||
const events = queue.splice(0);
|
||||
|
||||
for (let i = 0, j = events.length; i < j; i += eventsBatchSize) {
|
||||
const batch = events.slice(i, i + eventsBatchSize);
|
||||
|
||||
// TODO: Upload batch of events.
|
||||
}
|
||||
|
||||
setTimeout(() => eventDispatcher(), dispatchInterval);
|
||||
}
|
||||
|
||||
function nodeStateUploader() {
|
||||
|
||||
|
||||
for (const [cluster, nodes] of Object.entries(nodeGroups)) {
|
||||
|
||||
// Collect nodes with updates inside this cluster.
|
||||
const updated = [];
|
||||
for (const node of nodes.filter(n => n.hasUpdates)) {
|
||||
node.hasUpdates = false;
|
||||
updated.push(node);
|
||||
}
|
||||
|
||||
const ent = azure.TableUtilities.entityGenerator;
|
||||
for (let i = 0, j = updated.length; i < j; i += stateBatchSize) {
|
||||
const batch = updated.slice(i, i + stateBatchSize);
|
||||
const tableBatch = new azure.TableBatch();
|
||||
|
||||
for (const node of batch) {
|
||||
tableBatch.insertOrReplaceEntity({
|
||||
PartitionKey: ent.String(node.cluster),
|
||||
RowKey: ent.String(node.idx.toString()),
|
||||
Uri: ent.String(node.uri),
|
||||
LastUpdated: ent.DateTime(new Date(node.lastUpdated)),
|
||||
Status: ent.String(node.status),
|
||||
LastLedger: ent.String(JSON.stringify(node.lastLedger))
|
||||
});
|
||||
}
|
||||
|
||||
tableSvc.executeBatch(azureTable, tableBatch, (err) => err && console.log(err));
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(() => nodeStateUploader(), stateUploadInterval);
|
||||
}
|
||||
|
||||
function metricsTracker() {
|
||||
|
||||
for (const [name, count] of Object.entries(metrics)) {
|
||||
console.log(`${name}: ${count} events.`);
|
||||
}
|
||||
|
||||
setTimeout(() => metricsTracker(), metricsTrackInterval);
|
||||
}
|
||||
|
||||
async function streamCluster(cluster) {
|
||||
console.log(`Starting to stream cluster '${cluster.name}'...`);
|
||||
|
||||
// TODO: Resolve Vultr vm groups.
|
||||
|
||||
cluster.hosts.forEach((h, idx) => streamNode(cluster.name, (idx + 1), h, cluster.userPort));
|
||||
}
|
||||
|
||||
function streamNode(clusterName, nodeIdx, host, port) {
|
||||
const uri = `wss://${host}:${port}`;
|
||||
const node = {
|
||||
cluster: clusterName,
|
||||
idx: nodeIdx,
|
||||
uri: uri,
|
||||
failureCount: 0,
|
||||
lastLedger: null,
|
||||
status: null,
|
||||
lastUpdated: null
|
||||
};
|
||||
|
||||
if (!nodeGroups[clusterName])
|
||||
nodeGroups[clusterName] = [];
|
||||
|
||||
nodeGroups[clusterName].push(node);
|
||||
|
||||
establishClientConnection(node);
|
||||
}
|
||||
|
||||
async function establishClientConnection(node) {
|
||||
|
||||
const hpc = await HotPocket.createClient([node.uri], keys, { connectionTimeoutMs: 2000 });
|
||||
|
||||
hpc.on(HotPocket.events.disconnect, () => {
|
||||
onConnectionFail(node);
|
||||
});
|
||||
|
||||
// This will get fired when any ledger event occurs (ledger created, sync status change).
|
||||
hpc.on(HotPocket.events.ledgerEvent, (ev) => {
|
||||
reportEvent(node, ev);
|
||||
});
|
||||
|
||||
// Establish HotPocket connection.
|
||||
if (!await hpc.connect()) {
|
||||
onConnectionFail(node);
|
||||
}
|
||||
else {
|
||||
node.failureCount = 0;
|
||||
reportEvent(node, { event: "online" });
|
||||
await hpc.subscribe(HotPocket.notificationChannels.ledgerEvent);
|
||||
}
|
||||
}
|
||||
|
||||
function onConnectionFail(node) {
|
||||
|
||||
node.failureCount++;
|
||||
|
||||
// Calculate back-off delay.
|
||||
let delay = (2000 * node.failureCount);
|
||||
if (delay > backoffDelayMax)
|
||||
delay = backoffDelayMax;
|
||||
|
||||
console.log(`${node.uri} connection failed. Backoff ${delay}ms.`);
|
||||
|
||||
// Report offline event and connect again after a small delay.
|
||||
reportEvent(node, { event: "offline" });
|
||||
setTimeout(() => establishClientConnection(node), delay);
|
||||
}
|
||||
|
||||
async function reportEvent(node, ev) {
|
||||
|
||||
const ts = new Date().getTime(); // Epoch milliseconds.
|
||||
|
||||
queue.push({
|
||||
cluster: node.cluster,
|
||||
idx: node.idx,
|
||||
uri: node.uri,
|
||||
timestamp: ts,
|
||||
data: ev
|
||||
});
|
||||
|
||||
if (ev.event == 'ledger_created') {
|
||||
node.status = 'in_sync';
|
||||
node.lastLedger = ev.ledger;
|
||||
}
|
||||
else if (ev.event == 'sync_status') {
|
||||
node.status = ev.inSync ? 'in_sync' : 'desync';
|
||||
}
|
||||
else if (ev.event == 'online') {
|
||||
node.status = 'online';
|
||||
}
|
||||
else if (ev.event == 'offline') {
|
||||
node.status = 'offline';
|
||||
}
|
||||
|
||||
node.hasUpdates = true;
|
||||
node.lastUpdated = ts;
|
||||
|
||||
const count = metrics[node.cluster];
|
||||
metrics[node.cluster] = count ? (count + 1) : 1;
|
||||
}
|
||||
|
||||
function getVultrHosts(group) {
|
||||
|
||||
return new Promise(resolve => {
|
||||
|
||||
if (!group || group.trim().length == 0)
|
||||
resolve([]);
|
||||
|
||||
const req = https.request({
|
||||
hostname: 'api.vultr.com',
|
||||
port: 443,
|
||||
path: `/v2/instances?tag=${group}`,
|
||||
method: 'GET',
|
||||
headers: { "Authorization": `Bearer ${vultrApiKey}` }
|
||||
}, res => {
|
||||
if (res.statusCode >= 200 && res.statusCode < 300)
|
||||
res.on('data', d => {
|
||||
// Sort vms by label.
|
||||
const vms = JSON.parse(d).instances;
|
||||
const ips = vms.sort((a, b) => (a.label < b.label) ? -1 : 1).map(i => i.main_ip);
|
||||
resolve(ips)
|
||||
});
|
||||
else
|
||||
resolve([]);
|
||||
})
|
||||
|
||||
req.on('error', error => {
|
||||
console.error(error);
|
||||
resolve([]);
|
||||
})
|
||||
|
||||
req.end();
|
||||
})
|
||||
}
|
||||
|
||||
main();
|
||||
Reference in New Issue
Block a user