From 2ff3a4e0b78d532528611a80c4b8180f7267a8b1 Mon Sep 17 00:00:00 2001 From: Philipp Kunz Date: Tue, 15 Aug 2023 01:01:16 +0200 Subject: [PATCH] fix(core): update --- package.json | 8 +- pnpm-lock.yaml | 118 +++++++++--------- test/test.distributedcoordinator.ts | 54 ++++---- test/test.easystore.ts | 2 +- test/test.watch.ts | 2 +- ts/00_commitinfo_data.ts | 2 +- ...martdata.classes.distributedcoordinator.ts | 114 +++++++++++++---- ts/smartdata.classes.doc.ts | 2 +- 8 files changed, 186 insertions(+), 116 deletions(-) diff --git a/package.json b/package.json index 922ea6d..1f06d8c 100644 --- a/package.json +++ b/package.json @@ -22,16 +22,16 @@ }, "homepage": "https://gitlab.com/pushrocks/smartdata#README", "dependencies": { - "@push.rocks/lik": "^6.0.2", + "@push.rocks/lik": "^6.0.5", "@push.rocks/smartdelay": "^3.0.1", "@push.rocks/smartlog": "^3.0.2", "@push.rocks/smartmongo": "^2.0.10", "@push.rocks/smartpromise": "^4.0.2", "@push.rocks/smartrx": "^3.0.6", "@push.rocks/smartstring": "^4.0.7", - "@push.rocks/smarttime": "^4.0.1", + "@push.rocks/smarttime": "^4.0.5", "@push.rocks/smartunique": "^3.0.3", - "@push.rocks/taskbuffer": "^3.1.2", + "@push.rocks/taskbuffer": "^3.1.3", "@tsclass/tsclass": "^4.0.42", "mongodb": "^5.7.0" }, @@ -41,7 +41,7 @@ "@gitzone/tstest": "^1.0.77", "@push.rocks/qenv": "^6.0.2", "@push.rocks/tapbundle": "^5.0.15", - "@types/node": "^20.4.10", + "@types/node": "^20.5.0", "@types/shortid": "0.0.29" }, "files": [ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index be00474..191657f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,8 +6,8 @@ settings: dependencies: '@push.rocks/lik': - specifier: ^6.0.2 - version: 6.0.3 + specifier: ^6.0.5 + version: 6.0.5 '@push.rocks/smartdelay': specifier: ^3.0.1 version: 3.0.5 @@ -27,14 +27,14 @@ dependencies: specifier: ^4.0.7 version: 4.0.7 '@push.rocks/smarttime': - specifier: ^4.0.1 - version: 4.0.4 + specifier: ^4.0.5 + version: 4.0.5 '@push.rocks/smartunique': specifier: ^3.0.3 version: 3.0.3 '@push.rocks/taskbuffer': - specifier: ^3.1.2 - version: 3.1.2 + specifier: ^3.1.3 + version: 3.1.3 '@tsclass/tsclass': specifier: ^4.0.42 version: 4.0.42 @@ -48,10 +48,10 @@ devDependencies: version: 2.1.66 '@gitzone/tsrun': specifier: ^1.2.44 - version: 1.2.44(@types/node@20.4.10) + version: 1.2.44(@types/node@20.5.0) '@gitzone/tstest': specifier: ^1.0.77 - version: 1.0.77(@types/node@20.4.10)(sinon@15.2.0) + version: 1.0.77(@types/node@20.5.0)(sinon@15.2.0) '@push.rocks/qenv': specifier: ^6.0.2 version: 6.0.2 @@ -59,8 +59,8 @@ devDependencies: specifier: ^5.0.15 version: 5.0.15(sinon@15.2.0) '@types/node': - specifier: ^20.4.10 - version: 20.4.10 + specifier: ^20.5.0 + version: 20.5.0 '@types/shortid': specifier: 0.0.29 version: 0.0.29 @@ -87,7 +87,7 @@ packages: dependencies: '@api.global/typedrequest-interfaces': 3.0.1 '@push.rocks/isounique': 1.0.5 - '@push.rocks/lik': 6.0.3 + '@push.rocks/lik': 6.0.5 '@push.rocks/smartdelay': 3.0.5 '@push.rocks/smartpromise': 4.0.3 '@push.rocks/webrequest': 3.0.32 @@ -929,13 +929,13 @@ packages: - supports-color dev: true - /@gitzone/tsrun@1.2.44(@types/node@20.4.10): + /@gitzone/tsrun@1.2.44(@types/node@20.5.0): resolution: {integrity: sha512-7AfL9u+TmD7gLiRaTCimhWm5rq9GGBQnOF4q1FnFh2CAb1FbK5fzUVbj6wo3zGS2H+MSm6dqFA6mvdBI1ox0mQ==} hasBin: true dependencies: '@push.rocks/smartfile': 10.0.28 '@push.rocks/smartshell': 3.0.3 - ts-node: 10.9.1(@types/node@20.4.10)(typescript@5.1.6) + ts-node: 10.9.1(@types/node@20.5.0)(typescript@5.1.6) typescript: 5.1.6 transitivePeerDependencies: - '@swc/core' @@ -944,13 +944,13 @@ packages: - supports-color dev: true - /@gitzone/tstest@1.0.77(@types/node@20.4.10)(sinon@15.2.0): + /@gitzone/tstest@1.0.77(@types/node@20.5.0)(sinon@15.2.0): resolution: {integrity: sha512-YzBXnNqkYOiFf8xAA+m8owblrmAut8ukINghYy4DXoUR+5g1IKrpTjK4A8HzIsvVsQRyHPsQ2YFtsk+utqdivQ==} hasBin: true dependencies: '@apiglobal/typedserver': 2.0.65 '@gitzone/tsbundle': 2.0.8 - '@gitzone/tsrun': 1.2.44(@types/node@20.4.10) + '@gitzone/tsrun': 1.2.44(@types/node@20.5.0) '@push.rocks/consolecolor': 2.0.1 '@push.rocks/smartbrowser': 2.0.5 '@push.rocks/smartdelay': 3.0.5 @@ -1113,14 +1113,14 @@ packages: /@push.rocks/isounique@1.0.5: resolution: {integrity: sha512-Z0BVqZZOCif1THTbIKWMgg0wxCzt9CyBtBBqQJiZ+jJ0KlQFrQHNHrPt81/LXe/L4x0cxWsn0bpL6W5DNSvNLw==} - /@push.rocks/lik@6.0.3: - resolution: {integrity: sha512-YPA2PfubtD6YSWo5AXx8J10ZbEMkGezrBw93+2jq7ASSNnmGnXYMNuCOnfj+ZLqT7mT0cQOaUxmfyBKF1gG+ng==} + /@push.rocks/lik@6.0.5: + resolution: {integrity: sha512-rDSPVknpJDcY3yx4w3lNQfpRkBRuxYVIJKrkiODdH27X0z3+XU4e/iAWKySuLq6H7dAoxSHJDf6BrCO+3Y8kcw==} dependencies: '@push.rocks/smartdelay': 3.0.5 '@push.rocks/smartmatch': 2.0.0 '@push.rocks/smartpromise': 4.0.3 '@push.rocks/smartrx': 3.0.6 - '@push.rocks/smarttime': 4.0.4 + '@push.rocks/smarttime': 4.0.5 '@types/minimatch': 5.1.2 '@types/symbol-tree': 3.2.2 symbol-tree: 3.2.4 @@ -1170,16 +1170,16 @@ packages: /@push.rocks/smartdata@5.0.23: resolution: {integrity: sha512-t2bHJpULbckTQZhBpWQ9OWvq0iTwklHIKs66CrgNQATFHvjTQnxrCBLY+NC+gE+53OOC6qv5Z52SAoTGlirxuQ==} dependencies: - '@push.rocks/lik': 6.0.3 + '@push.rocks/lik': 6.0.5 '@push.rocks/smartdelay': 3.0.5 '@push.rocks/smartlog': 3.0.3 '@push.rocks/smartmongo': 2.0.10 '@push.rocks/smartpromise': 4.0.3 '@push.rocks/smartrx': 3.0.6 '@push.rocks/smartstring': 4.0.7 - '@push.rocks/smarttime': 4.0.4 + '@push.rocks/smarttime': 4.0.5 '@push.rocks/smartunique': 3.0.3 - '@push.rocks/taskbuffer': 3.1.2 + '@push.rocks/taskbuffer': 3.1.3 '@tsclass/tsclass': 4.0.42 mongodb: 5.7.0 transitivePeerDependencies: @@ -1218,7 +1218,7 @@ packages: /@push.rocks/smartfile@10.0.28: resolution: {integrity: sha512-Bza5xwJuXGeIokr9xeLx1LSGuXvIYLtJimz0X6lB2Sv2kurlIjpb+/ix4KqsG9eBhvzo6ncqqjgnLAUyUQQjfw==} dependencies: - '@push.rocks/lik': 6.0.3 + '@push.rocks/lik': 6.0.5 '@push.rocks/smartdelay': 3.0.5 '@push.rocks/smartfile-interfaces': 1.0.7 '@push.rocks/smarthash': 3.0.2 @@ -1358,10 +1358,10 @@ packages: url: 0.11.1 dev: false - /@push.rocks/smarttime@4.0.4: - resolution: {integrity: sha512-PTYxvl6Rr5eSOKPbB0S5+ym6z6zfI/e1wqmVxX8QjnZ5ZIvhGfAoCZ7sie+Zd4OJ4nCG8UClgk5LrFaN3zUnZA==} + /@push.rocks/smarttime@4.0.5: + resolution: {integrity: sha512-vf0Jh+jnMt59l4zbmxdkoPdIMhtO5ghFQn8wn9hX+oOtog56ddrwvdubs9CtDNCPoA8YEKL8Izp1uY21NIgrmA==} dependencies: - '@push.rocks/lik': 6.0.3 + '@push.rocks/lik': 6.0.5 '@push.rocks/smartdelay': 3.0.5 '@push.rocks/smartpromise': 4.0.3 croner: 5.7.0 @@ -1390,7 +1390,7 @@ packages: '@push.rocks/smartenv': 5.0.5 '@push.rocks/smartexpect': 1.0.21 '@push.rocks/smartpromise': 4.0.3 - '@push.rocks/smarttime': 4.0.4 + '@push.rocks/smarttime': 4.0.5 transitivePeerDependencies: - bufferutil - sinon @@ -1398,16 +1398,16 @@ packages: - utf-8-validate dev: true - /@push.rocks/taskbuffer@3.1.2: - resolution: {integrity: sha512-hPhxYaPTu+UyGB8xboPC7cHcEtzAO0Co57Zw2T/bDtTeijCgKV6WtGvYXQjwA2JBT9KVjkQXRWRonskN70G5Mg==} + /@push.rocks/taskbuffer@3.1.3: + resolution: {integrity: sha512-f5v02i/sb47dZkCmC+tnrwhvPLKtJpDQsg/gc3IqWu4Ufy7+X2y4TT85z43/qDIMb/Afm5ljUEavlsTXi1ctWQ==} dependencies: '@push.rocks/isounique': 1.0.5 - '@push.rocks/lik': 6.0.3 + '@push.rocks/lik': 6.0.5 '@push.rocks/smartdelay': 3.0.5 '@push.rocks/smartlog': 3.0.3 '@push.rocks/smartpromise': 4.0.3 '@push.rocks/smartrx': 3.0.6 - '@push.rocks/smarttime': 4.0.4 + '@push.rocks/smarttime': 4.0.5 dev: false /@push.rocks/webrequest@3.0.32: @@ -1429,7 +1429,7 @@ packages: resolution: {integrity: sha512-B/a/M+udyr0pByGdOEcWyY+gugIx36YJXWwNUrslh9XjIWs+0NKSFJRnZKuVYSCHOnc/WblAOceSlGVwFmYVBw==} dependencies: '@apiglobal/typedrequest-interfaces': 2.0.1 - '@push.rocks/lik': 6.0.3 + '@push.rocks/lik': 6.0.5 '@push.rocks/smartenv': 5.0.5 '@push.rocks/smartjson': 5.0.6 '@push.rocks/smartpromise': 4.0.3 @@ -2572,7 +2572,7 @@ packages: /@types/accepts@1.3.5: resolution: {integrity: sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==} dependencies: - '@types/node': 20.4.10 + '@types/node': 20.5.0 dev: true /@types/babel__code-frame@7.0.3: @@ -2583,7 +2583,7 @@ packages: resolution: {integrity: sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==} dependencies: '@types/connect': 3.4.35 - '@types/node': 20.4.10 + '@types/node': 20.5.0 dev: true /@types/buffer-json@2.0.1: @@ -2609,14 +2609,14 @@ packages: /@types/clean-css@4.2.6: resolution: {integrity: sha512-Ze1tf+LnGPmG6hBFMi0B4TEB0mhF7EiMM5oyjLDNPE9hxrPU0W+5+bHvO+eFPA+bt0iC1zkQMoU/iGdRVjcRbw==} dependencies: - '@types/node': 20.4.10 + '@types/node': 20.5.0 source-map: 0.6.1 dev: true /@types/co-body@6.1.0: resolution: {integrity: sha512-3e0q2jyDAnx/DSZi0z2H0yoZ2wt5yRDZ+P7ymcMObvq0ufWRT4tsajyO+Q1VwVWiv9PRR4W3YEjEzBjeZlhF+w==} dependencies: - '@types/node': 20.4.10 + '@types/node': 20.5.0 '@types/qs': 6.9.7 dev: true @@ -2629,7 +2629,7 @@ packages: /@types/connect@3.4.35: resolution: {integrity: sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==} dependencies: - '@types/node': 20.4.10 + '@types/node': 20.5.0 dev: true /@types/content-disposition@0.5.5: @@ -2650,13 +2650,13 @@ packages: '@types/connect': 3.4.35 '@types/express': 4.17.17 '@types/keygrip': 1.0.2 - '@types/node': 20.4.10 + '@types/node': 20.5.0 dev: true /@types/cors@2.8.13: resolution: {integrity: sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==} dependencies: - '@types/node': 20.4.10 + '@types/node': 20.5.0 dev: true /@types/debounce@1.2.1: @@ -2670,7 +2670,7 @@ packages: /@types/express-serve-static-core@4.17.35: resolution: {integrity: sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==} dependencies: - '@types/node': 20.4.10 + '@types/node': 20.5.0 '@types/qs': 6.9.7 '@types/range-parser': 1.2.4 '@types/send': 0.17.1 @@ -2695,40 +2695,40 @@ packages: /@types/finalhandler@1.2.0: resolution: {integrity: sha512-NgEZKOhxUSXkwNnWNaMXZaopQ5aFGPAYiEpEWIkQ6Dzc4iS0M1oQsvWne2t+ex9QZUAdTz/ZT4tOXJhWtP6mCw==} dependencies: - '@types/node': 20.4.10 + '@types/node': 20.5.0 dev: true /@types/from2@2.3.2: resolution: {integrity: sha512-s1pdctxW2+CA4FOxxTBRxC3RKQL9Br1a2s2LngP4jh1BI84JBL3mDXj87EwcckN9z/IXp8o3ySmvZveGEAAwqw==} dependencies: - '@types/node': 20.4.10 + '@types/node': 20.5.0 dev: true /@types/fs-extra@11.0.1: resolution: {integrity: sha512-MxObHvNl4A69ofaTRU8DFqvgzzv8s9yRtaPPm5gud9HDNvpB3GPQFvNuTWAI59B9huVGV5jXYJwbCsmBsOGYWA==} dependencies: '@types/jsonfile': 6.1.1 - '@types/node': 20.4.10 + '@types/node': 20.5.0 dev: true /@types/fs-extra@9.0.13: resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==} dependencies: - '@types/node': 20.4.10 + '@types/node': 20.5.0 dev: false /@types/glob@7.2.0: resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} dependencies: '@types/minimatch': 5.1.2 - '@types/node': 20.4.10 + '@types/node': 20.5.0 dev: false /@types/glob@8.1.0: resolution: {integrity: sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==} dependencies: '@types/minimatch': 5.1.2 - '@types/node': 20.4.10 + '@types/node': 20.5.0 dev: true /@types/html-minifier@4.0.2: @@ -2777,7 +2777,7 @@ packages: /@types/jsonfile@6.1.1: resolution: {integrity: sha512-GSgiRCVeapDN+3pqA35IkQwasaCh/0YFH5dEF6S88iDvEn901DjOeH3/QPY+XYP1DFzDZPvIvfeEgk+7br5png==} dependencies: - '@types/node': 20.4.10 + '@types/node': 20.5.0 dev: true /@types/keygrip@1.0.2: @@ -2800,7 +2800,7 @@ packages: '@types/http-errors': 2.0.1 '@types/keygrip': 1.0.2 '@types/koa-compose': 3.2.5 - '@types/node': 20.4.10 + '@types/node': 20.5.0 dev: true /@types/mime-types@2.1.1: @@ -2824,8 +2824,8 @@ packages: resolution: {integrity: sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==} dev: true - /@types/node@20.4.10: - resolution: {integrity: sha512-vwzFiiy8Rn6E0MtA13/Cxxgpan/N6UeNYR9oUu6kuJWxu6zCk98trcDp8CBhbtaeuq9SykCmXkFr2lWLoPcvLg==} + /@types/node@20.5.0: + resolution: {integrity: sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q==} /@types/parse5@6.0.3: resolution: {integrity: sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==} @@ -2854,7 +2854,7 @@ packages: resolution: {integrity: sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==} dependencies: '@types/mime': 1.3.2 - '@types/node': 20.4.10 + '@types/node': 20.5.0 dev: true /@types/serve-static@1.15.2: @@ -2862,7 +2862,7 @@ packages: dependencies: '@types/http-errors': 2.0.1 '@types/mime': 3.0.1 - '@types/node': 20.4.10 + '@types/node': 20.5.0 dev: true /@types/shortid@0.0.29: @@ -2891,7 +2891,7 @@ packages: /@types/through2@2.0.38: resolution: {integrity: sha512-YFu+nHmjxMurkH1BSzA0Z1WrKDAY8jUKPZctNQn7mc+/KKtp2XxnclHFXxdB1m7Iqnzb5aywgP8TMK283LezGQ==} dependencies: - '@types/node': 20.4.10 + '@types/node': 20.5.0 /@types/trusted-types@2.0.3: resolution: {integrity: sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==} @@ -2913,7 +2913,7 @@ packages: /@types/whatwg-url@8.2.2: resolution: {integrity: sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==} dependencies: - '@types/node': 20.4.10 + '@types/node': 20.5.0 '@types/webidl-conversions': 7.0.0 dev: false @@ -2928,14 +2928,14 @@ packages: /@types/ws@7.4.7: resolution: {integrity: sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==} dependencies: - '@types/node': 20.4.10 + '@types/node': 20.5.0 dev: true /@types/yauzl@2.10.0: resolution: {integrity: sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==} requiresBuild: true dependencies: - '@types/node': 20.4.10 + '@types/node': 20.5.0 dev: true optional: true @@ -3876,7 +3876,7 @@ packages: dependencies: '@types/cookie': 0.4.1 '@types/cors': 2.8.13 - '@types/node': 20.4.10 + '@types/node': 20.5.0 accepts: 1.3.8 base64id: 2.0.0 cookie: 0.4.2 @@ -3896,7 +3896,7 @@ packages: dependencies: '@types/cookie': 0.4.1 '@types/cors': 2.8.13 - '@types/node': 20.4.10 + '@types/node': 20.5.0 accepts: 1.3.8 base64id: 2.0.0 cookie: 0.4.2 @@ -6618,7 +6618,7 @@ packages: hasBin: true dev: true - /ts-node@10.9.1(@types/node@20.4.10)(typescript@5.1.6): + /ts-node@10.9.1(@types/node@20.5.0)(typescript@5.1.6): resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} hasBin: true peerDependencies: @@ -6637,7 +6637,7 @@ packages: '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 20.4.10 + '@types/node': 20.5.0 acorn: 8.10.0 acorn-walk: 8.2.0 arg: 4.1.3 diff --git a/test/test.distributedcoordinator.ts b/test/test.distributedcoordinator.ts index f21cfe8..9d2caf3 100644 --- a/test/test.distributedcoordinator.ts +++ b/test/test.distributedcoordinator.ts @@ -27,34 +27,31 @@ tap.test('should instantiate DistributedClass', async (tools) => { tap.test('DistributedClass should update the time', async (tools) => { const distributedCoordinator = new SmartdataDistributedCoordinator(testDb); await distributedCoordinator.start(); - console.log('test: started'); const initialTime = distributedCoordinator.ownInstance.data.lastUpdated; await distributedCoordinator.sendHeartbeat(); - console.log('test: sent heartbeat'); const updatedTime = distributedCoordinator.ownInstance.data.lastUpdated; expect(updatedTime).toBeGreaterThan(initialTime); await distributedCoordinator.stop(); }); tap.test('should instantiate SmartdataDistributedCoordinator', async (tools) => { - const coordinator = new SmartdataDistributedCoordinator(testDb); - await coordinator.start(); - expect(coordinator).toBeInstanceOf(SmartdataDistributedCoordinator); - await coordinator.stop(); + const distributedCoordinator = new SmartdataDistributedCoordinator(testDb); + await distributedCoordinator.start(); + expect(distributedCoordinator).toBeInstanceOf(SmartdataDistributedCoordinator); + await distributedCoordinator.stop(); }); tap.test('SmartdataDistributedCoordinator should update leader status', async (tools) => { - const coordinator = new SmartdataDistributedCoordinator(testDb); - await coordinator.start(); - await coordinator.checkAndMaybeLead(); - expect(coordinator.ownInstance.data.elected).toBeOneOf([true, false]); - await coordinator.stop(); - process.exit(0); + const distributedCoordinator = new SmartdataDistributedCoordinator(testDb); + await distributedCoordinator.start(); + await distributedCoordinator.checkAndMaybeLead(); + expect(distributedCoordinator.ownInstance.data.elected).toBeOneOf([true, false]); + await distributedCoordinator.stop(); }); tap.test('SmartdataDistributedCoordinator should handle distributed task requests', async (tools) => { - const coordinator = new SmartdataDistributedCoordinator(testDb); - await coordinator.start(); + const distributedCoordinator = new SmartdataDistributedCoordinator(testDb); + await distributedCoordinator.start(); const mockTaskRequest: taskbuffer.distributedCoordination.IDistributedTaskRequest = { submitterId: "mockSubmitter12345", // Some unique mock submitter ID @@ -66,15 +63,15 @@ tap.test('SmartdataDistributedCoordinator should handle distributed task request status: 'requesting' }; - const response = await coordinator.fireDistributedTaskRequest(mockTaskRequest); - expect(response).toBeTruthy(); // based on your expected structure for the response - await coordinator.stop(); + const response = await distributedCoordinator.fireDistributedTaskRequest(mockTaskRequest); + console.log(response) // based on your expected structure for the response + await distributedCoordinator.stop(); }); tap.test('SmartdataDistributedCoordinator should update distributed task requests', async (tools) => { - const coordinator = new SmartdataDistributedCoordinator(testDb); + const distributedCoordinator = new SmartdataDistributedCoordinator(testDb); - await coordinator.start(); + await distributedCoordinator.start(); const mockTaskRequest: taskbuffer.distributedCoordination.IDistributedTaskRequest = { submitterId: "mockSubmitter12345", // Some unique mock submitter ID @@ -87,18 +84,27 @@ tap.test('SmartdataDistributedCoordinator should update distributed task request }; - await coordinator.updateDistributedTaskRequest(mockTaskRequest); + await distributedCoordinator.updateDistributedTaskRequest(mockTaskRequest); // Here, we can potentially check if a DB entry got updated or some other side-effect of the update method. + await distributedCoordinator.stop(); }); tap.test('should elect only one leader amongst multiple instances', async (tools) => { const coordinators = Array.from({ length: totalInstances }).map(() => new SmartdataDistributedCoordinator(testDb)); - await Promise.all(coordinators.map(coordinator => coordinator.init())); - - await Promise.all(coordinators.map(coordinator => coordinator.checkAndMaybeLead())); - + await Promise.all(coordinators.map(coordinator => coordinator.start())); const leaders = coordinators.filter(coordinator => coordinator.ownInstance.data.elected); + for (const leader of leaders) { + console.log(leader.ownInstance); + } expect(leaders.length).toEqual(1); + + // stopping clears a coordinator from being elected. + await Promise.all(coordinators.map(coordinator => coordinator.stop())); }); +tap.test('should clean up', async () => { + await smartmongoInstance.stopAndDumpToDir(`.nogit/testdata/`); + setTimeout(() => process.exit(0), 1000); +}) + tap.start({ throwOnError: true }); diff --git a/test/test.easystore.ts b/test/test.easystore.ts index 8e7bcf4..c11a9fa 100644 --- a/test/test.easystore.ts +++ b/test/test.easystore.ts @@ -26,7 +26,7 @@ tap.test('should create a testinstance as database', async () => { tap.skip.test('should connect to atlas', async (tools) => { const databaseName = `test-smartdata-${smartunique.shortId()}`; testDb = new smartdata.SmartdataDb({ - mongoDbUrl: testQenv.getEnvVarOnDemand('MONGO_URL'), + mongoDbUrl: await testQenv.getEnvVarOnDemand('MONGO_URL'), mongoDbName: databaseName, }); await testDb.init(); diff --git a/test/test.watch.ts b/test/test.watch.ts index ef4a627..5d4397b 100644 --- a/test/test.watch.ts +++ b/test/test.watch.ts @@ -28,7 +28,7 @@ tap.test('should create a testinstance as database', async () => { tap.skip.test('should connect to atlas', async (tools) => { const databaseName = `test-smartdata-${smartunique.shortId()}`; testDb = new smartdata.SmartdataDb({ - mongoDbUrl: testQenv.getEnvVarOnDemand('MONGO_URL'), + mongoDbUrl: await testQenv.getEnvVarOnDemand('MONGO_URL'), mongoDbName: databaseName, }); await testDb.init(); diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index c21b321..f474eee 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@push.rocks/smartdata', - version: '5.0.26', + version: '5.0.27', description: 'do more with data' } diff --git a/ts/smartdata.classes.distributedcoordinator.ts b/ts/smartdata.classes.distributedcoordinator.ts index e3b0f03..63a6c51 100644 --- a/ts/smartdata.classes.distributedcoordinator.ts +++ b/ts/smartdata.classes.distributedcoordinator.ts @@ -13,6 +13,7 @@ export class DistributedClass extends SmartDataDbDoc { + if (this.ownInstance?.data.elected) { + this.ownInstance.data.elected = false; + } + if (this.ownInstance?.data.status === 'stopped') { + console.log(`stopping a distributed instance that has not been started yet.`); + } + this.ownInstance.data.status = 'stopped'; + await this.ownInstance.save(); + console.log(`stopped ${this.ownInstance.id}`); + }); } public id = plugins.smartunique.uni('distributedInstance'); @@ -64,15 +71,32 @@ export class SmartdataDistributedCoordinator extends plugins.taskbuffer.distribu private startHeartbeat = async () => { while (this.ownInstance.data.status !== 'stopped') { await this.sendHeartbeat(); - await plugins.smartdelay.delayFor(10000); + await plugins.smartdelay.delayForRandom(5000, 10000); } }; public async sendHeartbeat() { await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { + if (this.ownInstance.data.status === 'stopped') { + console.log(`aborted sending heartbeat because status is stopped`); + return; + } await this.ownInstance.updateFromDb(); this.ownInstance.data.lastUpdated = Date.now(); await this.ownInstance.save(); + console.log(`sent heartbeat for ${this.ownInstance.id}`); + const allInstances = DistributedClass.getInstances({}); + }); + if (this.ownInstance.data.status === 'stopped') { + console.log(`aborted sending heartbeat because status is stopped`); + return; + } + const eligibleLeader = await this.getEligibleLeader(); + // not awaiting here because we don't want to block the heartbeat + this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { + if (!eligibleLeader && this.ownInstance.data.status === 'settled') { + this.checkAndMaybeLead(); + } }); } private async init() { @@ -90,6 +114,8 @@ export class SmartdataDistributedCoordinator extends plugins.taskbuffer.distribu }; await this.ownInstance.save(); }); + } else { + console.warn(`distributed instance already initialized`); } // lets enable the heartbeat @@ -101,42 +127,73 @@ export class SmartdataDistributedCoordinator extends plugins.taskbuffer.distribu return this.ownInstance; } + public async getEligibleLeader() { + return this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { + const allInstances = await DistributedClass.getInstances({}); + let leaders = allInstances.filter((instanceArg) => instanceArg.data.elected === true); + const eligibleLeader = leaders.find( + (leader) => + leader.data.lastUpdated >= + Date.now() - plugins.smarttime.getMilliSecondsFromUnits({ seconds: 20 }) + ); + return eligibleLeader; + }); + } + // --> leader election public async checkAndMaybeLead() { - const allInstances = await DistributedClass.getInstances({}); - let leader = allInstances.find((instanceArg) => instanceArg.data.elected === true); - if ( - leader && - leader.data.lastUpdated >= - Date.now() - plugins.smarttime.getMilliSecondsFromUnits({ minutes: 1 }) - ) { + await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { + this.ownInstance.data.status = 'initializing'; + this.ownInstance.save(); + }); + if (await this.getEligibleLeader()) { await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { await this.ownInstance.updateFromDb(); this.ownInstance.data.status = 'settled'; await this.ownInstance.save(); + console.log(`${this.ownInstance.id} settled as follower`); }); return; + } else if ( + (await DistributedClass.getInstances({})).find((instanceArg) => { + instanceArg.data.status === 'bidding' && + instanceArg.data.biddingStartTime <= Date.now() - 4000 && + instanceArg.data.biddingStartTime >= Date.now() - 30000; + }) + ) { + console.log('too late to the bidding party... waiting for next round.'); + return; } else { await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { + await this.ownInstance.updateFromDb(); this.ownInstance.data.status = 'bidding'; + this.ownInstance.data.biddingStartTime = Date.now(); this.ownInstance.data.biddingShortcode = plugins.smartunique.shortId(); await this.ownInstance.save(); + console.log('bidding code stored.'); }); - await plugins.smartdelay.delayFor(plugins.smarttime.getMilliSecondsFromUnits({ minutes: 2 })); + console.log(`bidding for leadership...`); + await plugins.smartdelay.delayFor( + plugins.smarttime.getMilliSecondsFromUnits({ seconds: 20 }) + ); await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { let biddingInstances = await DistributedClass.getInstances({}); biddingInstances = biddingInstances.filter( (instanceArg) => - !instanceArg.data.elected && + instanceArg.data.status === 'bidding' && instanceArg.data.lastUpdated >= - Date.now() - plugins.smarttime.getMilliSecondsFromUnits({ minutes: 1 }) + Date.now() - plugins.smarttime.getMilliSecondsFromUnits({ seconds: 25 }) ); + console.log(`found ${biddingInstances.length} bidding instances...`); this.ownInstance.data.elected = true; for (const biddingInstance of biddingInstances) { if (biddingInstance.data.biddingShortcode < this.ownInstance.data.biddingShortcode) { this.ownInstance.data.elected = false; } } + await plugins.smartdelay.delayFor(5000); + console.log(`settling with status elected = ${this.ownInstance.data.elected}`); + this.ownInstance.data.status = 'settled'; await this.ownInstance.save(); }); if (this.ownInstance.data.elected) { @@ -151,20 +208,20 @@ export class SmartdataDistributedCoordinator extends plugins.taskbuffer.distribu * the leading is implemented here */ public async leadFunction() { - const ownInstance = await this.init(); const watcher = await DistributedClass.watch({}); - /** - * this function is started once per unique job request - */ - const startResultTimer = async () => {}; - watcher.changeSubject.subscribe({ next: async (distributedDoc) => { distributedDoc; }, }); - while (this.ownInstance.data.status !== 'stopped') { - await plugins.smartdelay.delayFor(1000); + while (this.ownInstance.data.status !== 'stopped' && this.ownInstance.data.elected) { + const allInstances = await DistributedClass.getInstances({}); + for (const instance of allInstances) { + if (instance.data.status === 'stopped') { + await instance.delete(); + }; + } + await plugins.smartdelay.delayFor(10000); } } @@ -172,8 +229,11 @@ export class SmartdataDistributedCoordinator extends plugins.taskbuffer.distribu public async fireDistributedTaskRequest( taskRequestArg: plugins.taskbuffer.distributedCoordination.IDistributedTaskRequest ): Promise { - const ownInstance = await this.init(); await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { + if (!this.ownInstance) { + console.error('instance need to be started first...'); + return; + } this.ownInstance.data.taskRequests.push(taskRequestArg); await this.ownInstance.save(); }); @@ -190,6 +250,10 @@ export class SmartdataDistributedCoordinator extends plugins.taskbuffer.distribu infoBasisItem.taskExecutionTime === infoBasisArg.taskExecutionTime ); }); + if (!existingInfoBasis) { + console.warn('trying to update a non existing task request... aborting!'); + return; + } Object.assign(existingInfoBasis, infoBasisArg); await this.ownInstance.save(); plugins.smartdelay.delayFor(60000).then(() => { diff --git a/ts/smartdata.classes.doc.ts b/ts/smartdata.classes.doc.ts index a34f8d2..45e1e28 100644 --- a/ts/smartdata.classes.doc.ts +++ b/ts/smartdata.classes.doc.ts @@ -257,7 +257,7 @@ export class SmartDataDbDoc