@prosopo/load-balancer 2.10.15 → 2.10.17
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/.turbo/turbo-build$colon$cjs.log +12 -10
- package/.turbo/turbo-build$colon$tsc.log +11 -11
- package/.turbo/turbo-build.log +14 -11
- package/CHANGELOG.md +19 -0
- package/dist/_virtual/_rolldown/runtime.js +3 -0
- package/dist/balancer.js +32 -52
- package/dist/cjs/balancer.cjs +33 -49
- package/dist/cjs/index.cjs +14 -15
- package/dist/cjs/providers.cjs +124 -121
- package/dist/cjs/retry.cjs +22 -26
- package/dist/index.js +3 -15
- package/dist/providers.js +123 -126
- package/dist/retry.js +23 -28
- package/package.json +7 -7
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @prosopo/load-balancer@2.10.
|
|
2
|
+
> @prosopo/load-balancer@2.10.17 build:cjs
|
|
3
3
|
> NODE_ENV=${NODE_ENV:-development}; vite build --config vite.cjs.config.ts --mode $NODE_ENV
|
|
4
4
|
|
|
5
5
|
ViteCommonJSConfig: .
|
|
@@ -23,14 +23,16 @@ ViteCommonJSConfig: .
|
|
|
23
23
|
'@prosopo/util-crypto'
|
|
24
24
|
]
|
|
25
25
|
}
|
|
26
|
-
[
|
|
26
|
+
[33mThe plugin "vite-tsconfig-paths" is detected. Vite now supports tsconfig paths resolution natively via the [1mresolve.tsconfigPaths[22m option. You can remove the plugin and set [1mresolve.tsconfigPaths: true[22m in your Vite config instead.[39m
|
|
27
|
+
[36mvite v8.1.5 [32mbuilding ssr environment for production...[36m[39m
|
|
27
28
|
Bundle build started
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
[32m✓[39m 4 modules transformed.
|
|
29
|
+
[2K
|
|
30
|
+
✓ 5 modules transformed.
|
|
31
31
|
rendering chunks...
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
computing gzip size...
|
|
33
|
+
dist/cjs/index.cjs 1.00 kB │ gzip: 0.31 kB
|
|
34
|
+
dist/cjs/retry.cjs 1.13 kB │ gzip: 0.56 kB
|
|
35
|
+
dist/cjs/balancer.cjs 1.95 kB │ gzip: 0.95 kB
|
|
36
|
+
dist/cjs/providers.cjs 5.75 kB │ gzip: 2.02 kB
|
|
37
|
+
|
|
38
|
+
[32m✓ built in 63ms[39m
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
|
-
> @prosopo/load-balancer@2.10.
|
|
2
|
+
> @prosopo/load-balancer@2.10.17 build:tsc
|
|
3
3
|
> tsc --build --verbose
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
11:09:54 AM - Projects in this build:
|
|
6
6
|
* ../../dev/config/tsconfig.json
|
|
7
7
|
* ../locale/tsconfig.json
|
|
8
8
|
* ../util/tsconfig.json
|
|
@@ -12,21 +12,21 @@
|
|
|
12
12
|
* ../common/tsconfig.json
|
|
13
13
|
* tsconfig.json
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
11:09:54 AM - Project '../../dev/config/tsconfig.json' is up to date because newest input '../../dev/config/src/webpack/webpack.config.ts' is older than output '../../dev/config/tsconfig.tsbuildinfo'
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
11:09:54 AM - Project '../locale/tsconfig.json' is up to date because newest input '../locale/src/translationKey.ts' is older than output '../locale/tsconfig.tsbuildinfo'
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
11:09:54 AM - Project '../util/tsconfig.json' is up to date because newest input '../util/src/url.ts' is older than output '../util/tsconfig.tsbuildinfo'
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
11:09:54 AM - Project '../logger/tsconfig.json' is up to date because newest input '../logger/src/index.ts' is older than output '../logger/tsconfig.tsbuildinfo'
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
11:09:54 AM - Project '../util-crypto/tsconfig.json' is up to date because newest input '../util-crypto/src/types.ts' is older than output '../util-crypto/tsconfig.tsbuildinfo'
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
11:09:54 AM - Project '../types/tsconfig.json' is up to date because newest input '../types/src/types.test-d.ts' is older than output '../types/tsconfig.tsbuildinfo'
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
11:09:54 AM - Project '../common/tsconfig.json' is up to date because newest input '../common/src/tests/utils/batches.unit.test.ts' is older than output '../common/tsconfig.tsbuildinfo'
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
11:09:54 AM - Project 'tsconfig.json' is out of date because output file 'tsconfig.tsbuildinfo' does not exist
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
11:09:54 AM - Building project '/home/runner/work/captcha/captcha/packages/load-balancer/tsconfig.json'...
|
|
32
32
|
|
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
|
|
2
|
-
> @prosopo/load-balancer@2.10.
|
|
2
|
+
> @prosopo/load-balancer@2.10.17 build
|
|
3
3
|
> npm run build:cross-env -- --mode ${NODE_ENV:-development}
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
> @prosopo/load-balancer@2.10.
|
|
6
|
+
> @prosopo/load-balancer@2.10.17 build:cross-env
|
|
7
7
|
> vite build --config vite.esm.config.ts --mode production
|
|
8
8
|
|
|
9
9
|
ViteEsmConfig: .
|
|
@@ -27,14 +27,17 @@ ViteEsmConfig: .
|
|
|
27
27
|
'@prosopo/util-crypto'
|
|
28
28
|
]
|
|
29
29
|
}
|
|
30
|
-
[
|
|
30
|
+
[33mThe plugin "vite-tsconfig-paths" is detected. Vite now supports tsconfig paths resolution natively via the [1mresolve.tsconfigPaths[22m option. You can remove the plugin and set [1mresolve.tsconfigPaths: true[22m in your Vite config instead.[39m
|
|
31
|
+
[36mvite v8.1.5 [32mbuilding ssr environment for production...[36m[39m
|
|
31
32
|
Bundle build started
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
[32m✓[39m 4 modules transformed.
|
|
33
|
+
[2K
|
|
34
|
+
✓ 5 modules transformed.
|
|
35
35
|
rendering chunks...
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
computing gzip size...
|
|
37
|
+
dist/_virtual/_rolldown/runtime.js 0.04 kB │ gzip: 0.06 kB
|
|
38
|
+
dist/index.js 0.62 kB │ gzip: 0.23 kB
|
|
39
|
+
dist/retry.js 1.09 kB │ gzip: 0.55 kB
|
|
40
|
+
dist/balancer.js 1.78 kB │ gzip: 0.92 kB
|
|
41
|
+
dist/providers.js 5.51 kB │ gzip: 2.00 kB
|
|
42
|
+
|
|
43
|
+
[32m✓ built in 86ms[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @prosopo/load-balancer
|
|
2
2
|
|
|
3
|
+
## 2.10.17
|
|
4
|
+
### Patch Changes
|
|
5
|
+
|
|
6
|
+
- Updated dependencies [787017b]
|
|
7
|
+
- Updated dependencies [787017b]
|
|
8
|
+
- Updated dependencies [787017b]
|
|
9
|
+
- Updated dependencies [6f19cde]
|
|
10
|
+
- @prosopo/types@5.0.0
|
|
11
|
+
|
|
12
|
+
## 2.10.16
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- e14fce6: chore(deps): bump vite to 6.4.3 and mongoose to 8.24.1, and adjust types for the mongoose 8.24 Document/ObjectId changes
|
|
16
|
+
- Updated dependencies [103318c]
|
|
17
|
+
- Updated dependencies [270a8d8]
|
|
18
|
+
- Updated dependencies [e14fce6]
|
|
19
|
+
- @prosopo/types@4.10.0
|
|
20
|
+
- @prosopo/common@3.1.48
|
|
21
|
+
|
|
3
22
|
## 2.10.15
|
|
4
23
|
### Patch Changes
|
|
5
24
|
|
package/dist/balancer.js
CHANGED
|
@@ -1,58 +1,38 @@
|
|
|
1
1
|
import { ProsopoEnvError } from "@prosopo/common";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
//#region src/balancer.ts
|
|
4
|
+
var HardcodedProviderSchema = z.object({
|
|
5
|
+
address: z.string(),
|
|
6
|
+
url: z.string(),
|
|
7
|
+
datasetId: z.string(),
|
|
8
|
+
weight: z.number().optional().default(1).transform((val) => {
|
|
9
|
+
return Math.max(1, Math.min(100, Math.round(val)));
|
|
10
|
+
})
|
|
11
11
|
});
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
return providers.sort((a, b) => a.url.localeCompare(b.url));
|
|
12
|
+
var IP_MODE_KEYS = ["ipv4", "ipv6"];
|
|
13
|
+
var isProviderRecord = (value) => typeof value === "object" && value !== null;
|
|
14
|
+
var convertHostedProvider = (provider, ipMode) => {
|
|
15
|
+
const source = ipMode && isProviderRecord(provider[ipMode]) ? provider[ipMode] : provider;
|
|
16
|
+
return Object.entries(source).filter(([key]) => !IP_MODE_KEYS.includes(key)).map(([, value]) => HardcodedProviderSchema.parse(value)).sort((a, b) => a.url.localeCompare(b.url));
|
|
18
17
|
};
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if (environment === "staging") {
|
|
26
|
-
return "https://provider-list.prosopo.io/staging.json";
|
|
27
|
-
}
|
|
28
|
-
throw new ProsopoEnvError("CONFIG.UNKNOWN_ENVIRONMENT", {
|
|
29
|
-
context: { environment }
|
|
30
|
-
});
|
|
18
|
+
var stripIpModeLabel = (hostname) => hostname.replace(/^ipv[46]\./, "");
|
|
19
|
+
var getProviderHostname = (provider) => stripIpModeLabel(new URL(provider.url).hostname);
|
|
20
|
+
var getLoadBalancerUrl = (environment) => {
|
|
21
|
+
if (environment === "production") return "https://provider-list.prosopo.io/";
|
|
22
|
+
if (environment === "staging") return "https://provider-list.prosopo.io/staging.json";
|
|
23
|
+
throw new ProsopoEnvError("CONFIG.UNKNOWN_ENVIRONMENT", { context: { environment } });
|
|
31
24
|
};
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const providers = await fetch(
|
|
44
|
-
getLoadBalancerUrl(environment),
|
|
45
|
-
{
|
|
46
|
-
method: "GET",
|
|
47
|
-
mode: "cors"
|
|
48
|
-
}
|
|
49
|
-
).then((res) => res.json());
|
|
50
|
-
return convertHostedProvider(providers);
|
|
51
|
-
};
|
|
52
|
-
export {
|
|
53
|
-
convertHostedProvider,
|
|
54
|
-
getLoadBalancerUrl,
|
|
55
|
-
getProviderHostname,
|
|
56
|
-
loadBalancer,
|
|
57
|
-
stripIpModeLabel
|
|
25
|
+
var loadBalancer = async (environment) => {
|
|
26
|
+
if (environment === "development") return [{
|
|
27
|
+
address: "5EjTA28bKSbFPPyMbUjNtArxyqjwq38r1BapVmLZShaqEedV",
|
|
28
|
+
url: "https://localhost:9229",
|
|
29
|
+
datasetId: "0x7984714b92d61fd92fd6a7bc9b56b729481470bcc771c19c382ec679acf02e67",
|
|
30
|
+
weight: 1
|
|
31
|
+
}];
|
|
32
|
+
return convertHostedProvider(await fetch(getLoadBalancerUrl(environment), {
|
|
33
|
+
method: "GET",
|
|
34
|
+
mode: "cors"
|
|
35
|
+
}).then((res) => res.json()));
|
|
58
36
|
};
|
|
37
|
+
//#endregion
|
|
38
|
+
export { convertHostedProvider, getLoadBalancerUrl, getProviderHostname, loadBalancer, stripIpModeLabel };
|
package/dist/cjs/balancer.cjs
CHANGED
|
@@ -1,56 +1,40 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
return Math.max(1, Math.min(100, weight));
|
|
12
|
-
})
|
|
1
|
+
let _prosopo_common = require("@prosopo/common");
|
|
2
|
+
let zod = require("zod");
|
|
3
|
+
//#region src/balancer.ts
|
|
4
|
+
var HardcodedProviderSchema = zod.z.object({
|
|
5
|
+
address: zod.z.string(),
|
|
6
|
+
url: zod.z.string(),
|
|
7
|
+
datasetId: zod.z.string(),
|
|
8
|
+
weight: zod.z.number().optional().default(1).transform((val) => {
|
|
9
|
+
return Math.max(1, Math.min(100, Math.round(val)));
|
|
10
|
+
})
|
|
13
11
|
});
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
return providers.sort((a, b) => a.url.localeCompare(b.url));
|
|
12
|
+
var IP_MODE_KEYS = ["ipv4", "ipv6"];
|
|
13
|
+
var isProviderRecord = (value) => typeof value === "object" && value !== null;
|
|
14
|
+
var convertHostedProvider = (provider, ipMode) => {
|
|
15
|
+
const source = ipMode && isProviderRecord(provider[ipMode]) ? provider[ipMode] : provider;
|
|
16
|
+
return Object.entries(source).filter(([key]) => !IP_MODE_KEYS.includes(key)).map(([, value]) => HardcodedProviderSchema.parse(value)).sort((a, b) => a.url.localeCompare(b.url));
|
|
20
17
|
};
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if (environment === "staging") {
|
|
28
|
-
return "https://provider-list.prosopo.io/staging.json";
|
|
29
|
-
}
|
|
30
|
-
throw new common.ProsopoEnvError("CONFIG.UNKNOWN_ENVIRONMENT", {
|
|
31
|
-
context: { environment }
|
|
32
|
-
});
|
|
18
|
+
var stripIpModeLabel = (hostname) => hostname.replace(/^ipv[46]\./, "");
|
|
19
|
+
var getProviderHostname = (provider) => stripIpModeLabel(new URL(provider.url).hostname);
|
|
20
|
+
var getLoadBalancerUrl = (environment) => {
|
|
21
|
+
if (environment === "production") return "https://provider-list.prosopo.io/";
|
|
22
|
+
if (environment === "staging") return "https://provider-list.prosopo.io/staging.json";
|
|
23
|
+
throw new _prosopo_common.ProsopoEnvError("CONFIG.UNKNOWN_ENVIRONMENT", { context: { environment } });
|
|
33
24
|
};
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const providers = await fetch(
|
|
46
|
-
getLoadBalancerUrl(environment),
|
|
47
|
-
{
|
|
48
|
-
method: "GET",
|
|
49
|
-
mode: "cors"
|
|
50
|
-
}
|
|
51
|
-
).then((res) => res.json());
|
|
52
|
-
return convertHostedProvider(providers);
|
|
25
|
+
var loadBalancer = async (environment) => {
|
|
26
|
+
if (environment === "development") return [{
|
|
27
|
+
address: "5EjTA28bKSbFPPyMbUjNtArxyqjwq38r1BapVmLZShaqEedV",
|
|
28
|
+
url: "https://localhost:9229",
|
|
29
|
+
datasetId: "0x7984714b92d61fd92fd6a7bc9b56b729481470bcc771c19c382ec679acf02e67",
|
|
30
|
+
weight: 1
|
|
31
|
+
}];
|
|
32
|
+
return convertHostedProvider(await fetch(getLoadBalancerUrl(environment), {
|
|
33
|
+
method: "GET",
|
|
34
|
+
mode: "cors"
|
|
35
|
+
}).then((res) => res.json()));
|
|
53
36
|
};
|
|
37
|
+
//#endregion
|
|
54
38
|
exports.convertHostedProvider = convertHostedProvider;
|
|
55
39
|
exports.getLoadBalancerUrl = getLoadBalancerUrl;
|
|
56
40
|
exports.getProviderHostname = getProviderHostname;
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
exports._resetHealthzRetryPolicy =
|
|
6
|
-
exports._resetPinCache =
|
|
7
|
-
exports._resetProviderListCache =
|
|
8
|
-
exports._setHealthzRetryPolicy =
|
|
9
|
-
exports.
|
|
10
|
-
exports.
|
|
11
|
-
exports.
|
|
12
|
-
exports.
|
|
13
|
-
exports.
|
|
14
|
-
exports.
|
|
15
|
-
exports.loadBalancer =
|
|
16
|
-
exports.stripIpModeLabel =
|
|
2
|
+
const require_balancer = require("./balancer.cjs");
|
|
3
|
+
const require_providers = require("./providers.cjs");
|
|
4
|
+
exports._resetHealthzRetryPolicy = require_providers._resetHealthzRetryPolicy;
|
|
5
|
+
exports._resetPinCache = require_providers._resetPinCache;
|
|
6
|
+
exports._resetProviderListCache = require_providers._resetProviderListCache;
|
|
7
|
+
exports._setHealthzRetryPolicy = require_providers._setHealthzRetryPolicy;
|
|
8
|
+
exports.convertHostedProvider = require_balancer.convertHostedProvider;
|
|
9
|
+
exports.getLoadBalancerUrl = require_balancer.getLoadBalancerUrl;
|
|
10
|
+
exports.getProviderHostname = require_balancer.getProviderHostname;
|
|
11
|
+
exports.getProviders = require_providers.getProviders;
|
|
12
|
+
exports.getRandomActiveProvider = require_providers.getRandomActiveProvider;
|
|
13
|
+
exports.getRandomProviderFromList = require_providers.getRandomProviderFromList;
|
|
14
|
+
exports.loadBalancer = require_balancer.loadBalancer;
|
|
15
|
+
exports.stripIpModeLabel = require_balancer.stripIpModeLabel;
|
package/dist/cjs/providers.cjs
CHANGED
|
@@ -1,137 +1,140 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
production: "https://pronode.prosopo.io"
|
|
1
|
+
const require_balancer = require("./balancer.cjs");
|
|
2
|
+
const require_retry = require("./retry.cjs");
|
|
3
|
+
//#region src/providers.ts
|
|
4
|
+
var DNS_ENDPOINT = {
|
|
5
|
+
development: "https://localhost:9229",
|
|
6
|
+
staging: "https://staging.pronode.prosopo.io",
|
|
7
|
+
production: "https://pronode.prosopo.io"
|
|
9
8
|
};
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
9
|
+
var withIpModeLabel = (hostname, ipMode) => ipMode ? `${ipMode}.${hostname}` : hostname;
|
|
10
|
+
var applyIpModeToUrl = (url, ipMode) => {
|
|
11
|
+
if (!ipMode) return url;
|
|
12
|
+
try {
|
|
13
|
+
const parsed = new URL(url);
|
|
14
|
+
parsed.hostname = withIpModeLabel(parsed.hostname, ipMode);
|
|
15
|
+
return parsed.toString().replace(/\/$/, "");
|
|
16
|
+
} catch {
|
|
17
|
+
return url;
|
|
18
|
+
}
|
|
20
19
|
};
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if (typeof body.host !== "string" || body.host.length === 0) {
|
|
40
|
-
throw new Error("healthz response missing host field");
|
|
41
|
-
}
|
|
42
|
-
return body.host;
|
|
20
|
+
var cacheKey = (env, ipMode) => `${env}|${ipMode ?? "dual"}`;
|
|
21
|
+
var pinPromiseCache = /* @__PURE__ */ new Map();
|
|
22
|
+
var HEALTHZ_MAX_ATTEMPTS = 3;
|
|
23
|
+
var HEALTHZ_RETRY_BASE_DELAY_MS = 250;
|
|
24
|
+
var HEALTHZ_RETRY_MAX_DELAY_MS = 2e3;
|
|
25
|
+
var healthzMaxAttempts = HEALTHZ_MAX_ATTEMPTS;
|
|
26
|
+
var healthzRetryBaseDelayMs = HEALTHZ_RETRY_BASE_DELAY_MS;
|
|
27
|
+
var healthzRetryMaxDelayMs = HEALTHZ_RETRY_MAX_DELAY_MS;
|
|
28
|
+
var fetchPinnedHost = async (baseUrl) => {
|
|
29
|
+
const res = await fetch(`${baseUrl}/healthz`, {
|
|
30
|
+
method: "GET",
|
|
31
|
+
cache: "no-store",
|
|
32
|
+
credentials: "omit"
|
|
33
|
+
});
|
|
34
|
+
if (!res.ok) throw new Error(`healthz responded with ${res.status}`);
|
|
35
|
+
const body = await res.json();
|
|
36
|
+
if (typeof body.host !== "string" || body.host.length === 0) throw new Error("healthz response missing host field");
|
|
37
|
+
return body.host;
|
|
43
38
|
};
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
39
|
+
var fetchPinnedHostWithRetry = (baseUrl) => require_retry.retryWithBackoff(() => fetchPinnedHost(baseUrl), {
|
|
40
|
+
maxAttempts: healthzMaxAttempts,
|
|
41
|
+
baseDelayMs: healthzRetryBaseDelayMs,
|
|
42
|
+
maxDelayMs: healthzRetryMaxDelayMs
|
|
48
43
|
});
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
44
|
+
var resolveBaseUrl = (env) => DNS_ENDPOINT[env] ?? DNS_ENDPOINT.development;
|
|
45
|
+
var resolvePinnedUrl = async (env, ipMode) => {
|
|
46
|
+
const base = applyIpModeToUrl(resolveBaseUrl(env), ipMode);
|
|
47
|
+
if (env === "development") return base;
|
|
48
|
+
const key = cacheKey(env, ipMode);
|
|
49
|
+
const cached = pinPromiseCache.get(key);
|
|
50
|
+
if (cached) return cached;
|
|
51
|
+
const promise = (async () => {
|
|
52
|
+
try {
|
|
53
|
+
const host = await fetchPinnedHostWithRetry(base);
|
|
54
|
+
const parsed = new URL(base);
|
|
55
|
+
parsed.hostname = withIpModeLabel(host, ipMode);
|
|
56
|
+
return parsed.toString().replace(/\/$/, "");
|
|
57
|
+
} catch (err) {
|
|
58
|
+
pinPromiseCache.delete(key);
|
|
59
|
+
throw err;
|
|
60
|
+
}
|
|
61
|
+
})();
|
|
62
|
+
pinPromiseCache.set(key, promise);
|
|
63
|
+
return promise;
|
|
69
64
|
};
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
65
|
+
var providerListPromiseCache = /* @__PURE__ */ new Map();
|
|
66
|
+
/**
|
|
67
|
+
* Returns the full (cached) list of active providers for an environment.
|
|
68
|
+
* Used to look up a provider by url/address, e.g. to find the provider that
|
|
69
|
+
* issued a token before forwarding a verification request to it.
|
|
70
|
+
*/
|
|
71
|
+
var getProviders = async (env) => {
|
|
72
|
+
const cached = providerListPromiseCache.get(env);
|
|
73
|
+
if (cached) return cached;
|
|
74
|
+
const promise = require_balancer.loadBalancer(env).catch((err) => {
|
|
75
|
+
providerListPromiseCache.delete(env);
|
|
76
|
+
throw err;
|
|
77
|
+
});
|
|
78
|
+
providerListPromiseCache.set(env, promise);
|
|
79
|
+
return promise;
|
|
80
80
|
};
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
};
|
|
81
|
+
var getRandomActiveProvider = async (env, ipMode) => {
|
|
82
|
+
return {
|
|
83
|
+
providerAccount: "dns-routed",
|
|
84
|
+
provider: { url: await resolvePinnedUrl(env, ipMode) }
|
|
85
|
+
};
|
|
87
86
|
};
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
87
|
+
var sameProviderUrl = (a, b) => a.replace(/\/$/, "") === b.replace(/\/$/, "");
|
|
88
|
+
var pickWeightedProvider = (providers, random) => {
|
|
89
|
+
const totalWeight = providers.reduce((sum, p) => sum + p.weight, 0);
|
|
90
|
+
let threshold = random() * totalWeight;
|
|
91
|
+
let chosen;
|
|
92
|
+
for (const provider of providers) {
|
|
93
|
+
chosen = provider;
|
|
94
|
+
threshold -= provider.weight;
|
|
95
|
+
if (threshold < 0) break;
|
|
96
|
+
}
|
|
97
|
+
return chosen;
|
|
99
98
|
};
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
99
|
+
/**
|
|
100
|
+
* Pick a random provider directly from the provider list, bypassing the
|
|
101
|
+
* DNS-routed endpoint. This is the error-fallback path: once a provider has
|
|
102
|
+
* errored, retrying it re-hits the same (possibly-down) endpoint, and a fleet
|
|
103
|
+
* of widgets doing that in a tight loop can accidentally DDoS the provider — so
|
|
104
|
+
* instead we spread the retry across the fleet by choosing a random provider
|
|
105
|
+
* from the list. `excludeUrl` (the provider that just failed) is dropped from
|
|
106
|
+
* the pool when other providers remain. In development the list holds only the
|
|
107
|
+
* single local provider, so this naturally degrades to retrying that provider.
|
|
108
|
+
* `random` is injectable so tests can make the pick deterministic.
|
|
109
|
+
*/
|
|
110
|
+
var getRandomProviderFromList = async (env, ipMode, excludeUrl, random = Math.random) => {
|
|
111
|
+
const providers = await getProviders(env);
|
|
112
|
+
if (providers.length === 0) return getRandomActiveProvider(env, ipMode);
|
|
113
|
+
const eligible = excludeUrl && providers.length > 1 ? providers.filter((p) => !sameProviderUrl(applyIpModeToUrl(p.url, ipMode), excludeUrl)) : providers;
|
|
114
|
+
const chosen = pickWeightedProvider(eligible.length > 0 ? eligible : providers, random);
|
|
115
|
+
if (!chosen) return getRandomActiveProvider(env, ipMode);
|
|
116
|
+
return {
|
|
117
|
+
providerAccount: chosen.address,
|
|
118
|
+
provider: { url: applyIpModeToUrl(chosen.url, ipMode) }
|
|
119
|
+
};
|
|
117
120
|
};
|
|
118
|
-
|
|
119
|
-
|
|
121
|
+
var _resetPinCache = () => {
|
|
122
|
+
pinPromiseCache.clear();
|
|
120
123
|
};
|
|
121
|
-
|
|
122
|
-
|
|
124
|
+
var _resetProviderListCache = () => {
|
|
125
|
+
providerListPromiseCache.clear();
|
|
123
126
|
};
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
if (opts.maxDelayMs !== void 0) healthzRetryMaxDelayMs = opts.maxDelayMs;
|
|
127
|
+
var _setHealthzRetryPolicy = (opts) => {
|
|
128
|
+
if (opts.maxAttempts !== void 0) healthzMaxAttempts = opts.maxAttempts;
|
|
129
|
+
if (opts.baseDelayMs !== void 0) healthzRetryBaseDelayMs = opts.baseDelayMs;
|
|
130
|
+
if (opts.maxDelayMs !== void 0) healthzRetryMaxDelayMs = opts.maxDelayMs;
|
|
129
131
|
};
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
132
|
+
var _resetHealthzRetryPolicy = () => {
|
|
133
|
+
healthzMaxAttempts = HEALTHZ_MAX_ATTEMPTS;
|
|
134
|
+
healthzRetryBaseDelayMs = HEALTHZ_RETRY_BASE_DELAY_MS;
|
|
135
|
+
healthzRetryMaxDelayMs = HEALTHZ_RETRY_MAX_DELAY_MS;
|
|
134
136
|
};
|
|
137
|
+
//#endregion
|
|
135
138
|
exports._resetHealthzRetryPolicy = _resetHealthzRetryPolicy;
|
|
136
139
|
exports._resetPinCache = _resetPinCache;
|
|
137
140
|
exports._resetProviderListCache = _resetProviderListCache;
|