maxpool 1.1.0 → 1.2.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/package.json +1 -1
- package/src/account-manager.js +34 -12
package/package.json
CHANGED
package/src/account-manager.js
CHANGED
|
@@ -34,14 +34,20 @@ const DEFAULT_SCHEDULER = {
|
|
|
34
34
|
weeklyCriticalThreshold: 0.95,
|
|
35
35
|
weeklyExhaustedThreshold: 0.985,
|
|
36
36
|
weeklyBurnDebtWeight: 0.6,
|
|
37
|
-
// Routing-cost tuning (lower cost = preferred).
|
|
38
|
-
//
|
|
39
|
-
//
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
37
|
+
// Routing-cost tuning (lower cost = preferred). The goal is to AVOID
|
|
38
|
+
// short-term (rate/concurrency) throttling by spreading load across healthy
|
|
39
|
+
// accounts. So in-flight concurrency is the DOMINANT term, with a steep
|
|
40
|
+
// per-account soft cap; burn-pace is only a soft de-preference (never a
|
|
41
|
+
// bench); quota "use-it-or-lose-it" is intentionally a minor signal here.
|
|
42
|
+
concurrencyWeight: 2, // multiplies in-flight load (activeWeight+reqWeight) — dominant
|
|
43
|
+
perAccountConcurrencyTarget: 3, // D: soft per-account in-flight target; past it, capPenalty bites
|
|
44
|
+
capPenaltyWeight: 10, // steep penalty per unit of in-flight depth past D (throttle safety floor)
|
|
45
|
+
paceCostWeight: 1.5, // soft de-preference of accounts burning ahead of pace (was the ×6 term)
|
|
46
|
+
scarcityWeight: 6, // legacy; superseded by paceCostWeight (kept so old configs don't error)
|
|
47
|
+
spreadShareWeight: 3, // multiplies an account's share of recent fleet load (0..1)
|
|
48
|
+
recoveryRampWeight: 4, // decaying penalty applied to a just-recovered account
|
|
49
|
+
recoveryRampMs: 5 * 60_000, // how long the post-recovery ramp lasts
|
|
50
|
+
spreadWindowMs: 15 * 60_000, // rolling window used to measure recent per-account load
|
|
45
51
|
};
|
|
46
52
|
const LOAD_EVENT_MAX_AGE_MS = 60 * 60 * 1000;
|
|
47
53
|
const WEEK_MS = 7 * 24 * 60 * 60 * 1000;
|
|
@@ -454,7 +460,10 @@ export class AccountManager {
|
|
|
454
460
|
if (this.getGlobalInFlight() >= this.scheduler.safetyMaxGlobalActive) return false;
|
|
455
461
|
if (account.status === 'exhausted' || account.status === 'error') return false;
|
|
456
462
|
if (this._isSessionQuotaUnavailable(account)) return false;
|
|
457
|
-
|
|
463
|
+
// Gate on RAW weekly usage, not pace-adjusted: an account with real
|
|
464
|
+
// headroom (e.g. 69% used, resets in days) must stay in the healthy-spread
|
|
465
|
+
// pool even if it's burning fast. Pace is a soft SCORE cost, never a bench.
|
|
466
|
+
const weeklyState = this._weeklyRawState(account);
|
|
458
467
|
if (weeklyState === 'exhausted') return false;
|
|
459
468
|
if (weeklyState === 'critical' && !options.allowWeeklyCritical) return false;
|
|
460
469
|
if (weeklyState === 'reserve' && !options.allowWeeklyReserve) return false;
|
|
@@ -1125,8 +1134,21 @@ export class AccountManager {
|
|
|
1125
1134
|
_scoreAccount(account, requestInfo = {}, ctx = null) {
|
|
1126
1135
|
const now = ctx?.now ?? Date.now();
|
|
1127
1136
|
const reqWeight = Math.max(1, requestInfo.weight || 1);
|
|
1128
|
-
const
|
|
1129
|
-
|
|
1137
|
+
const inflight = account.activeWeight + reqWeight;
|
|
1138
|
+
|
|
1139
|
+
// DOMINANT term: in-flight concurrency. Short-term throttling is driven by
|
|
1140
|
+
// how many requests pile on one account, so least-loaded-first spread is
|
|
1141
|
+
// the primary objective.
|
|
1142
|
+
const concurrency = inflight * this.scheduler.concurrencyWeight;
|
|
1143
|
+
|
|
1144
|
+
// Steep soft cap past depth D — the throttle safety floor. No single
|
|
1145
|
+
// account absorbs a deep concurrent burst no matter how "cheap" it looks.
|
|
1146
|
+
const capPenalty = this.scheduler.capPenaltyWeight
|
|
1147
|
+
* Math.max(0, inflight - this.scheduler.perAccountConcurrencyTarget);
|
|
1148
|
+
|
|
1149
|
+
// Burn-pace COST only (demoted from the old dominant scarcity×6 term): a
|
|
1150
|
+
// soft de-preference of accounts burning ahead of an even pace. Never a bench.
|
|
1151
|
+
const paceCost = this._accountScarcity(account, now) * this.scheduler.paceCostWeight;
|
|
1130
1152
|
|
|
1131
1153
|
const fleetRecentWeight = ctx?.fleetRecentWeight ?? 0;
|
|
1132
1154
|
const recentWeight = this._loadSummary(account, this.scheduler.spreadWindowMs, now).weight;
|
|
@@ -1139,7 +1161,7 @@ export class AccountManager {
|
|
|
1139
1161
|
// probed and learned (matches the legacy unknown-quota exploration nudge).
|
|
1140
1162
|
const explorationBonus = account.quota.unified7dReset == null ? -0.5 : 0;
|
|
1141
1163
|
|
|
1142
|
-
return concurrency +
|
|
1164
|
+
return concurrency + capPenalty + paceCost + spread + ramp + failurePenalty + explorationBonus;
|
|
1143
1165
|
}
|
|
1144
1166
|
|
|
1145
1167
|
/**
|