@jeffusion/bungee-core 4.2.0 → 4.3.0
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/dist/master.js +120 -76
- package/dist/worker.js +1267 -491
- package/package.json +2 -2
package/dist/master.js
CHANGED
|
@@ -16341,7 +16341,43 @@ function uniqueServiceName(preferredName, existingNames) {
|
|
|
16341
16341
|
}
|
|
16342
16342
|
function moveRouteConfigToService(route, service, routeIndex, changes) {
|
|
16343
16343
|
if (route.failover && !service.failover) {
|
|
16344
|
-
|
|
16344
|
+
const failover = route.failover;
|
|
16345
|
+
if (isPlainRecord(failover.health_check) && !service.health_check) {
|
|
16346
|
+
service.health_check = failover.health_check;
|
|
16347
|
+
changes.push({
|
|
16348
|
+
type: "move",
|
|
16349
|
+
path: `routes.${routeIndex}.failover.health_check`,
|
|
16350
|
+
from: `routes.${routeIndex}.failover.health_check`,
|
|
16351
|
+
to: `services.${service.name}.health_check`,
|
|
16352
|
+
message: `Extracted health_check from failover to service "${service.name}" top-level`
|
|
16353
|
+
});
|
|
16354
|
+
delete failover.health_check;
|
|
16355
|
+
}
|
|
16356
|
+
if (failover.passive_health?.auto_enable_on_active_health_check !== undefined) {
|
|
16357
|
+
if (service.health_check) {
|
|
16358
|
+
service.health_check.auto_enable_on_active_health_check = failover.passive_health.auto_enable_on_active_health_check;
|
|
16359
|
+
changes.push({
|
|
16360
|
+
type: "move",
|
|
16361
|
+
path: `routes.${routeIndex}.failover.passive_health.auto_enable_on_active_health_check`,
|
|
16362
|
+
from: "failover.passive_health.auto_enable_on_active_health_check",
|
|
16363
|
+
to: `services.${service.name}.health_check.auto_enable_on_active_health_check`,
|
|
16364
|
+
message: `Moved auto_enable_on_active_health_check from passive_health to health_check`
|
|
16365
|
+
});
|
|
16366
|
+
}
|
|
16367
|
+
delete failover.passive_health.auto_enable_on_active_health_check;
|
|
16368
|
+
}
|
|
16369
|
+
if (failover.recovery?.probe_interval_ms !== undefined) {
|
|
16370
|
+
failover.recovery.backoff_base_ms = failover.recovery.probe_interval_ms;
|
|
16371
|
+
delete failover.recovery.probe_interval_ms;
|
|
16372
|
+
changes.push({
|
|
16373
|
+
type: "rename",
|
|
16374
|
+
path: `routes.${routeIndex}.failover.recovery.probe_interval_ms`,
|
|
16375
|
+
from: "probe_interval_ms",
|
|
16376
|
+
to: "backoff_base_ms",
|
|
16377
|
+
message: `Renamed probe_interval_ms to backoff_base_ms (semantics: exponential backoff base)`
|
|
16378
|
+
});
|
|
16379
|
+
}
|
|
16380
|
+
service.failover = failover;
|
|
16345
16381
|
changes.push({
|
|
16346
16382
|
type: "move",
|
|
16347
16383
|
path: `routes.${routeIndex}.failover`,
|
|
@@ -16350,14 +16386,18 @@ function moveRouteConfigToService(route, service, routeIndex, changes) {
|
|
|
16350
16386
|
message: `Moved route failover to service "${service.name}"`
|
|
16351
16387
|
});
|
|
16352
16388
|
}
|
|
16353
|
-
if (route.sticky_session && !service.
|
|
16354
|
-
|
|
16389
|
+
if (route.sticky_session && !service.load_balancing) {
|
|
16390
|
+
const key_expression = route.sticky_session.key_expression;
|
|
16391
|
+
service.load_balancing = {
|
|
16392
|
+
policy: "consistent_hash",
|
|
16393
|
+
...key_expression ? { hash_policy: { expression: key_expression } } : {}
|
|
16394
|
+
};
|
|
16355
16395
|
changes.push({
|
|
16356
16396
|
type: "move",
|
|
16357
16397
|
path: `routes.${routeIndex}.sticky_session`,
|
|
16358
16398
|
from: `routes.${routeIndex}.sticky_session`,
|
|
16359
|
-
to: `services.${service.name}.
|
|
16360
|
-
message: `
|
|
16399
|
+
to: `services.${service.name}.load_balancing`,
|
|
16400
|
+
message: `Migrated route sticky_session to service "${service.name}" as load_balancing.policy=consistent_hash`
|
|
16361
16401
|
});
|
|
16362
16402
|
}
|
|
16363
16403
|
if (route.failover) {
|
|
@@ -16372,7 +16412,7 @@ var init_v3_to_v4 = __esm(() => {
|
|
|
16372
16412
|
v3ToV4Migration = {
|
|
16373
16413
|
fromVersion: 3,
|
|
16374
16414
|
toVersion: 4,
|
|
16375
|
-
description: "Move failover and sticky_session
|
|
16415
|
+
description: "Move failover and migrate sticky_session to load_balancing.consistent_hash on services",
|
|
16376
16416
|
migrate(input) {
|
|
16377
16417
|
const config = cloneJson(input);
|
|
16378
16418
|
if (!isPlainRecord(config)) {
|
|
@@ -16415,11 +16455,26 @@ var init_v3_to_v4 = __esm(() => {
|
|
|
16415
16455
|
}
|
|
16416
16456
|
const serviceName = uniqueServiceName(serviceNameFromPath(route.path), serviceNames);
|
|
16417
16457
|
const routeEndpoints = route.endpoints ?? [];
|
|
16458
|
+
const failover = route.failover;
|
|
16459
|
+
const extractedHealthCheck = isPlainRecord(failover?.health_check) ? failover.health_check : undefined;
|
|
16460
|
+
if (extractedHealthCheck) {
|
|
16461
|
+
delete failover.health_check;
|
|
16462
|
+
}
|
|
16463
|
+
if (failover?.recovery?.probe_interval_ms !== undefined) {
|
|
16464
|
+
failover.recovery.backoff_base_ms = failover.recovery.probe_interval_ms;
|
|
16465
|
+
delete failover.recovery.probe_interval_ms;
|
|
16466
|
+
}
|
|
16418
16467
|
const service = {
|
|
16419
16468
|
name: serviceName,
|
|
16420
16469
|
endpoints: routeEndpoints,
|
|
16421
|
-
...
|
|
16422
|
-
...
|
|
16470
|
+
...failover && { failover },
|
|
16471
|
+
...extractedHealthCheck && { health_check: extractedHealthCheck },
|
|
16472
|
+
...route.sticky_session && {
|
|
16473
|
+
load_balancing: {
|
|
16474
|
+
policy: "consistent_hash",
|
|
16475
|
+
...route.sticky_session.key_expression ? { hash_policy: { expression: route.sticky_session.key_expression } } : {}
|
|
16476
|
+
}
|
|
16477
|
+
}
|
|
16423
16478
|
};
|
|
16424
16479
|
services.push(service);
|
|
16425
16480
|
route.service = serviceName;
|
|
@@ -16429,7 +16484,7 @@ var init_v3_to_v4 = __esm(() => {
|
|
|
16429
16484
|
path: `routes.${routeIndex}`,
|
|
16430
16485
|
from: `routes.${routeIndex}.endpoints/failover/sticky_session`,
|
|
16431
16486
|
to: `services.${serviceName}`,
|
|
16432
|
-
message: `Created service "${serviceName}" from route "${route.path}"`
|
|
16487
|
+
message: `Created service "${serviceName}" from route "${route.path}" (sticky_session migrated to load_balancing${extractedHealthCheck ? ", health_check extracted" : ""})`
|
|
16433
16488
|
});
|
|
16434
16489
|
moveRouteConfigToService(route, service, routeIndex, changes);
|
|
16435
16490
|
}
|
|
@@ -19355,33 +19410,6 @@ var init_sortBy = __esm(() => {
|
|
|
19355
19410
|
sortBy_default = sortBy;
|
|
19356
19411
|
});
|
|
19357
19412
|
|
|
19358
|
-
// ../../node_modules/lodash-es/_baseSum.js
|
|
19359
|
-
function baseSum(array, iteratee) {
|
|
19360
|
-
var result, index = -1, length = array.length;
|
|
19361
|
-
while (++index < length) {
|
|
19362
|
-
var current = iteratee(array[index]);
|
|
19363
|
-
if (current !== undefined) {
|
|
19364
|
-
result = result === undefined ? current : result + current;
|
|
19365
|
-
}
|
|
19366
|
-
}
|
|
19367
|
-
return result;
|
|
19368
|
-
}
|
|
19369
|
-
var _baseSum_default;
|
|
19370
|
-
var init__baseSum = __esm(() => {
|
|
19371
|
-
_baseSum_default = baseSum;
|
|
19372
|
-
});
|
|
19373
|
-
|
|
19374
|
-
// ../../node_modules/lodash-es/sumBy.js
|
|
19375
|
-
function sumBy(array, iteratee) {
|
|
19376
|
-
return array && array.length ? _baseSum_default(array, _baseIteratee_default(iteratee, 2)) : 0;
|
|
19377
|
-
}
|
|
19378
|
-
var sumBy_default;
|
|
19379
|
-
var init_sumBy = __esm(() => {
|
|
19380
|
-
init__baseIteratee();
|
|
19381
|
-
init__baseSum();
|
|
19382
|
-
sumBy_default = sumBy;
|
|
19383
|
-
});
|
|
19384
|
-
|
|
19385
19413
|
// ../../node_modules/lodash-es/lodash.js
|
|
19386
19414
|
var init_lodash = __esm(() => {
|
|
19387
19415
|
init_find();
|
|
@@ -19392,7 +19420,6 @@ var init_lodash = __esm(() => {
|
|
|
19392
19420
|
init_map();
|
|
19393
19421
|
init_mergeWith();
|
|
19394
19422
|
init_sortBy();
|
|
19395
|
-
init_sumBy();
|
|
19396
19423
|
});
|
|
19397
19424
|
|
|
19398
19425
|
// src/expression-engine.ts
|
|
@@ -19794,21 +19821,29 @@ function normalizeRouteConfig(route, services) {
|
|
|
19794
19821
|
}
|
|
19795
19822
|
return route;
|
|
19796
19823
|
}
|
|
19797
|
-
function
|
|
19798
|
-
|
|
19824
|
+
function validateLoadBalancing(service) {
|
|
19825
|
+
const lb = service.load_balancing;
|
|
19826
|
+
if (!lb)
|
|
19799
19827
|
return;
|
|
19800
|
-
|
|
19801
|
-
if (
|
|
19802
|
-
logger.error(`Invalid
|
|
19803
|
-
process.exit(1);
|
|
19804
|
-
}
|
|
19805
|
-
if (service.sticky_session.enabled !== undefined && typeof service.sticky_session.enabled !== "boolean") {
|
|
19806
|
-
logger.error(`Invalid sticky_session.enabled in service "${service.name}". sticky_session.enabled must be a boolean.`);
|
|
19828
|
+
const validPolicies = ["weighted_random", "round_robin", "least_requests", "consistent_hash"];
|
|
19829
|
+
if (!validPolicies.includes(lb.policy)) {
|
|
19830
|
+
logger.error(`Invalid load_balancing.policy "${lb.policy}" in service "${service.name}". Must be one of: ${validPolicies.join(", ")}`);
|
|
19807
19831
|
process.exit(1);
|
|
19808
19832
|
}
|
|
19809
|
-
if (
|
|
19810
|
-
|
|
19811
|
-
|
|
19833
|
+
if (lb.policy === "consistent_hash") {
|
|
19834
|
+
const hp = lb.hash_policy;
|
|
19835
|
+
if (!hp || !hp.header && !hp.expression) {
|
|
19836
|
+
logger.error(`Service "${service.name}" with policy=consistent_hash requires hash_policy with at least one of header or expression.`);
|
|
19837
|
+
process.exit(1);
|
|
19838
|
+
}
|
|
19839
|
+
if (hp.header !== undefined && typeof hp.header !== "string") {
|
|
19840
|
+
logger.error(`Invalid load_balancing.hash_policy.header in service "${service.name}". Must be a string.`);
|
|
19841
|
+
process.exit(1);
|
|
19842
|
+
}
|
|
19843
|
+
if (hp.expression !== undefined && typeof hp.expression !== "string") {
|
|
19844
|
+
logger.error(`Invalid load_balancing.hash_policy.expression in service "${service.name}". Must be a string.`);
|
|
19845
|
+
process.exit(1);
|
|
19846
|
+
}
|
|
19812
19847
|
}
|
|
19813
19848
|
}
|
|
19814
19849
|
function validateFailoverConfig(service) {
|
|
@@ -19823,8 +19858,8 @@ function validateFailoverConfig(service) {
|
|
|
19823
19858
|
if (service.endpoints.length < 2 && failover.enabled) {
|
|
19824
19859
|
logger.warn(`Service "${service.name}" has failover enabled but less than 2 endpoints. Failover will not be active.`);
|
|
19825
19860
|
}
|
|
19826
|
-
if (failover.recovery?.
|
|
19827
|
-
ensurePositiveNumber(failover.recovery.
|
|
19861
|
+
if (failover.recovery?.backoff_base_ms !== undefined) {
|
|
19862
|
+
ensurePositiveNumber(failover.recovery.backoff_base_ms, "failover.recovery.backoff_base_ms", `service "${service.name}"`);
|
|
19828
19863
|
}
|
|
19829
19864
|
if (failover.recovery?.probe_timeout_ms !== undefined) {
|
|
19830
19865
|
ensurePositiveNumber(failover.recovery.probe_timeout_ms, "failover.recovery.probe_timeout_ms", `service "${service.name}"`);
|
|
@@ -19838,10 +19873,6 @@ function validateFailoverConfig(service) {
|
|
|
19838
19873
|
if (failover.passive_health?.auto_disable_threshold !== undefined) {
|
|
19839
19874
|
ensurePositiveNumber(failover.passive_health.auto_disable_threshold, "failover.passive_health.auto_disable_threshold", `service "${service.name}"`);
|
|
19840
19875
|
}
|
|
19841
|
-
if (failover.passive_health?.auto_enable_on_active_health_check !== undefined && typeof failover.passive_health.auto_enable_on_active_health_check !== "boolean") {
|
|
19842
|
-
logger.error(`Invalid failover.passive_health.auto_enable_on_active_health_check in service "${service.name}". It must be a boolean.`);
|
|
19843
|
-
process.exit(1);
|
|
19844
|
-
}
|
|
19845
19876
|
if (failover.slow_start) {
|
|
19846
19877
|
if (typeof failover.slow_start.enabled !== "boolean") {
|
|
19847
19878
|
logger.error(`Invalid failover.slow_start.enabled in service "${service.name}". It must be a boolean.`);
|
|
@@ -19858,23 +19889,26 @@ function validateFailoverConfig(service) {
|
|
|
19858
19889
|
}
|
|
19859
19890
|
}
|
|
19860
19891
|
}
|
|
19861
|
-
|
|
19862
|
-
|
|
19863
|
-
|
|
19864
|
-
|
|
19865
|
-
|
|
19866
|
-
|
|
19867
|
-
|
|
19868
|
-
|
|
19869
|
-
|
|
19870
|
-
|
|
19871
|
-
}
|
|
19872
|
-
|
|
19873
|
-
|
|
19874
|
-
|
|
19875
|
-
|
|
19876
|
-
|
|
19877
|
-
}
|
|
19892
|
+
}
|
|
19893
|
+
function validateServiceHealthCheck(service) {
|
|
19894
|
+
const hc = service.health_check;
|
|
19895
|
+
if (!hc)
|
|
19896
|
+
return;
|
|
19897
|
+
if (typeof hc.enabled !== "boolean") {
|
|
19898
|
+
logger.error(`Invalid health_check.enabled in service "${service.name}". It must be a boolean.`);
|
|
19899
|
+
process.exit(1);
|
|
19900
|
+
}
|
|
19901
|
+
if (hc.interval_ms !== undefined)
|
|
19902
|
+
ensurePositiveNumber(hc.interval_ms, "health_check.interval_ms", `service "${service.name}"`);
|
|
19903
|
+
if (hc.timeout_ms !== undefined)
|
|
19904
|
+
ensurePositiveNumber(hc.timeout_ms, "health_check.timeout_ms", `service "${service.name}"`);
|
|
19905
|
+
if (hc.unhealthy_threshold !== undefined)
|
|
19906
|
+
ensurePositiveNumber(hc.unhealthy_threshold, "health_check.unhealthy_threshold", `service "${service.name}"`);
|
|
19907
|
+
if (hc.healthy_threshold !== undefined)
|
|
19908
|
+
ensurePositiveNumber(hc.healthy_threshold, "health_check.healthy_threshold", `service "${service.name}"`);
|
|
19909
|
+
if (hc.auto_enable_on_active_health_check !== undefined && typeof hc.auto_enable_on_active_health_check !== "boolean") {
|
|
19910
|
+
logger.error(`Invalid health_check.auto_enable_on_active_health_check in service "${service.name}". It must be a boolean.`);
|
|
19911
|
+
process.exit(1);
|
|
19878
19912
|
}
|
|
19879
19913
|
}
|
|
19880
19914
|
function validateAuthConfig(authConfig, context) {
|
|
@@ -19923,10 +19957,23 @@ function validateServices(services) {
|
|
|
19923
19957
|
process.exit(1);
|
|
19924
19958
|
}
|
|
19925
19959
|
}
|
|
19926
|
-
|
|
19960
|
+
validateLoadBalancing(service);
|
|
19927
19961
|
validateFailoverConfig(service);
|
|
19962
|
+
validateServiceTimeouts(service);
|
|
19963
|
+
validateServiceHealthCheck(service);
|
|
19928
19964
|
}
|
|
19929
19965
|
}
|
|
19966
|
+
function validateServiceTimeouts(service) {
|
|
19967
|
+
const t = service.timeouts;
|
|
19968
|
+
if (!t)
|
|
19969
|
+
return;
|
|
19970
|
+
if (t.connect_ms !== undefined)
|
|
19971
|
+
ensurePositiveNumber(t.connect_ms, "timeouts.connect_ms", `service "${service.name}"`);
|
|
19972
|
+
if (t.send_ms !== undefined)
|
|
19973
|
+
ensurePositiveNumber(t.send_ms, "timeouts.send_ms", `service "${service.name}"`);
|
|
19974
|
+
if (t.read_ms !== undefined)
|
|
19975
|
+
ensurePositiveNumber(t.read_ms, "timeouts.read_ms", `service "${service.name}"`);
|
|
19976
|
+
}
|
|
19930
19977
|
function validateAndNormalizeConfig(config) {
|
|
19931
19978
|
if (!config.routes || !Array.isArray(config.routes)) {
|
|
19932
19979
|
logger.error('Error: "routes" is not defined or not an array in config.json.');
|
|
@@ -19959,9 +20006,6 @@ function validateAndNormalizeConfig(config) {
|
|
|
19959
20006
|
validateAuthConfig(route.auth, `route "${route.path}"`);
|
|
19960
20007
|
}
|
|
19961
20008
|
normalizeRouteConfig(route, config.services);
|
|
19962
|
-
if (route.timeouts?.connect_ms !== undefined) {
|
|
19963
|
-
ensurePositiveNumber(route.timeouts.connect_ms, "timeouts.connect_ms", `route "${route.path}"`);
|
|
19964
|
-
}
|
|
19965
20009
|
if (route.timeouts?.request_ms !== undefined) {
|
|
19966
20010
|
ensurePositiveNumber(route.timeouts.request_ms, "timeouts.request_ms", `route "${route.path}"`);
|
|
19967
20011
|
}
|