Merge pull request #366 from rexname/feature/codex-account-limit-rotation

Thanks @rexname (Maulana Hasanudin)! 🎉 

Codex account quota policy (5h/weekly) with auto-rotation is now merged. Highlights:
- Per-account policy toggles (5h + weekly ON/OFF) in the Provider dashboard
- Accounts automatically skipped when enabled quota window reaches 90% threshold
- Auto re-eligibility when resetAt timestamp passes (no manual intervention needed)
- Side-effect free `getQuotaWindowStatus` getter design
- Safe partial merge of `codexLimitPolicy` on provider updates

Merged on top of main (v2.5.0) with no conflicts. Analytics label fix (#356) included. Thanks for the excellent quality and the 2-commit cleanup round! 🙏
This commit is contained in:
Diego Rodrigues de Sa e Souza
2026-03-14 15:54:07 -03:00
committed by GitHub
7 changed files with 365 additions and 6 deletions

View File

@@ -1292,6 +1292,23 @@ Models:
cx/gpt-5.1-codex-max
```
#### Codex Account Limit Management (5h + Weekly)
Each Codex account now has policy toggles in `Dashboard -> Providers`:
- `5h` (ON/OFF): enforce the 5-hour window threshold policy.
- `Weekly` (ON/OFF): enforce the weekly window threshold policy.
- Threshold behavior: when an enabled window reaches >=90% usage, that account is skipped.
- Rotation behavior: OmniRoute routes to the next eligible Codex account automatically.
- Reset behavior: when the provider `resetAt` time passes, the account becomes eligible again automatically.
Scenarios:
- `5h ON` + `Weekly ON`: account is skipped when either window reaches threshold.
- `5h OFF` + `Weekly ON`: only weekly usage can block the account.
- `5h ON` + `Weekly OFF`: only 5-hour usage can block the account.
- `resetAt` passed: account re-enters rotation automatically (no manual re-enable).
### Gemini CLI (FREE 180K/month!)
```bash

View File

@@ -9,4 +9,13 @@ This directory contains machine-assisted translations based on the English docs.
- **TROUBLESHOOTING.md**: 🇺🇸 [English](../TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](./pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](./es/TROUBLESHOOTING.md) | 🇫🇷 [Français](./fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](./it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](./ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](./zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](./de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](./in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](./th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](./uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](./ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](./ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](./vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](./bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](./da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](./fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](./he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](./hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](./id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](./ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](./ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](./nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](./no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](./pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](./ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](./pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](./sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](./sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](./phi/TROUBLESHOOTING.md)
- **USER_GUIDE.md**: 🇺🇸 [English](../USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](./pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](./es/USER_GUIDE.md) | 🇫🇷 [Français](./fr/USER_GUIDE.md) | 🇮🇹 [Italiano](./it/USER_GUIDE.md) | 🇷🇺 [Русский](./ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](./zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](./de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](./in/USER_GUIDE.md) | 🇹🇭 [ไทย](./th/USER_GUIDE.md) | 🇺🇦 [Українська](./uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](./ar/USER_GUIDE.md) | 🇯🇵 [日本語](./ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](./vi/USER_GUIDE.md) | 🇧🇬 [Български](./bg/USER_GUIDE.md) | 🇩🇰 [Dansk](./da/USER_GUIDE.md) | 🇫🇮 [Suomi](./fi/USER_GUIDE.md) | 🇮🇱 [עברית](./he/USER_GUIDE.md) | 🇭🇺 [Magyar](./hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](./id/USER_GUIDE.md) | 🇰🇷 [한국어](./ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](./ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](./nl/USER_GUIDE.md) | 🇳🇴 [Norsk](./no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](./pt/USER_GUIDE.md) | 🇷🇴 [Română](./ro/USER_GUIDE.md) | 🇵🇱 [Polski](./pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](./sk/USER_GUIDE.md) | 🇸🇪 [Svenska](./sv/USER_GUIDE.md) | 🇵🇭 [Filipino](./phi/USER_GUIDE.md)
## Recent note: Codex account limit policy
Documentation now includes Codex account-level quota policy behavior:
- Per-account toggles: `5h` and `Weekly` (ON/OFF).
- Threshold policy: enabled window reaching >=90% marks account as ineligible for selection.
- Auto-rotation: traffic moves to the next eligible Codex account.
- Auto-reuse: account becomes eligible again after provider `resetAt` passes.
Generated on 2026-02-26.

View File

@@ -1059,6 +1059,23 @@ Models:
cx/gpt-5.1-codex-max
```
#### Manajemen Limit Akun Codex (5h + Mingguan)
Setiap akun Codex sekarang punya toggle kebijakan di `Dashboard -> Providers`:
- `5h` (ON/OFF): menerapkan kebijakan ambang untuk jendela 5 jam.
- `Weekly` (ON/OFF): menerapkan kebijakan ambang untuk jendela mingguan.
- Perilaku ambang: saat jendela yang aktif mencapai >=90% penggunaan, akun tersebut di-skip.
- Perilaku rotasi: OmniRoute otomatis merutekan ke akun Codex berikutnya yang masih eligible.
- Perilaku reset: saat waktu `resetAt` provider sudah lewat, akun otomatis bisa dipakai lagi.
Skenario:
- `5h ON` + `Weekly ON`: akun di-skip jika salah satu jendela mencapai ambang.
- `5h OFF` + `Weekly ON`: hanya penggunaan mingguan yang bisa memblokir akun.
- `5h ON` + `Weekly OFF`: hanya penggunaan 5 jam yang bisa memblokir akun.
- `resetAt` sudah lewat: akun otomatis masuk rotasi lagi (tanpa enable manual).
### Gemini CLI (GRATIS 180K/bulan!)
```bash

View File

@@ -32,6 +32,17 @@ import {
import { getModelsByProviderId } from "@/shared/constants/models";
import { useCopyToClipboard } from "@/shared/hooks/useCopyToClipboard";
function normalizeCodexLimitPolicy(policy: unknown): { use5h: boolean; useWeekly: boolean } {
const record =
policy && typeof policy === "object" && !Array.isArray(policy)
? (policy as Record<string, unknown>)
: {};
return {
use5h: typeof record.use5h === "boolean" ? record.use5h : true,
useWeekly: typeof record.useWeekly === "boolean" ? record.useWeekly : true,
};
}
export default function ProviderDetailPage() {
const params = useParams();
const router = useRouter();
@@ -49,6 +60,7 @@ export default function ProviderDetailPage() {
const [headerImgError, setHeaderImgError] = useState(false);
const { copied, copy } = useCopyToClipboard();
const t = useTranslations("providers");
const notify = useNotificationStore();
const hasAutoOpened = useRef(false);
const userDismissed = useRef(false);
const [proxyTarget, setProxyTarget] = useState(null);
@@ -311,6 +323,63 @@ export default function ProviderDetailPage() {
}
};
const handleToggleCodexLimit = async (connectionId, field, enabled) => {
try {
const target = connections.find((connection) => connection.id === connectionId);
if (!target) return;
const providerSpecificData =
target.providerSpecificData && typeof target.providerSpecificData === "object"
? target.providerSpecificData
: {};
const existingPolicy =
providerSpecificData.codexLimitPolicy &&
typeof providerSpecificData.codexLimitPolicy === "object"
? providerSpecificData.codexLimitPolicy
: {};
const nextPolicy = {
...normalizeCodexLimitPolicy(existingPolicy),
[field]: enabled,
};
const res = await fetch(`/api/providers/${connectionId}`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
providerSpecificData: {
...providerSpecificData,
codexLimitPolicy: nextPolicy,
},
}),
});
if (!res.ok) {
const data = await res.json().catch(() => ({}));
notify.error(data.error || "Failed to update Codex limit policy");
return;
}
setConnections((prev) =>
prev.map((connection) =>
connection.id === connectionId
? {
...connection,
providerSpecificData: {
...(connection.providerSpecificData || {}),
codexLimitPolicy: nextPolicy,
},
}
: connection
)
);
notify.success("Codex limit policy updated");
} catch (error) {
console.error("Error toggling Codex quota policy:", error);
notify.error("Failed to update Codex limit policy");
}
};
const handleRetestConnection = async (connectionId) => {
if (!connectionId || retestingId) return;
setRetestingId(connectionId);
@@ -331,7 +400,6 @@ export default function ProviderDetailPage() {
// T12: Manual token refresh
const [refreshingId, setRefreshingId] = useState<string | null>(null);
const notify = useNotificationStore();
const handleRefreshToken = async (connectionId: string) => {
if (refreshingId) return;
setRefreshingId(connectionId);
@@ -941,6 +1009,11 @@ export default function ProviderDetailPage() {
onMoveDown={() => handleSwapPriority(conn, connections[index + 1])}
onToggleActive={(isActive) => handleUpdateConnectionStatus(conn.id, isActive)}
onToggleRateLimit={(enabled) => handleToggleRateLimit(conn.id, enabled)}
isCodex={providerId === "codex"}
onToggleCodex5h={(enabled) => handleToggleCodexLimit(conn.id, "use5h", enabled)}
onToggleCodexWeekly={(enabled) =>
handleToggleCodexLimit(conn.id, "useWeekly", enabled)
}
onRetest={() => handleRetestConnection(conn.id)}
isRetesting={retestingId === conn.id}
onEdit={() => {
@@ -2175,12 +2248,15 @@ function getStatusPresentation(connection, effectiveStatus, isCooldown, t) {
function ConnectionRow({
connection,
isOAuth,
isCodex,
isFirst,
isLast,
onMoveUp,
onMoveDown,
onToggleActive,
onToggleRateLimit,
onToggleCodex5h,
onToggleCodexWeekly,
onRetest,
isRetesting,
onEdit,
@@ -2242,6 +2318,16 @@ function ConnectionRow({
const statusPresentation = getStatusPresentation(connection, effectiveStatus, isCooldown, t);
const rateLimitEnabled = !!connection.rateLimitProtection;
const codexPolicy =
connection.providerSpecificData &&
typeof connection.providerSpecificData === "object" &&
connection.providerSpecificData.codexLimitPolicy &&
typeof connection.providerSpecificData.codexLimitPolicy === "object"
? connection.providerSpecificData.codexLimitPolicy
: {};
const normalizedCodexPolicy = normalizeCodexLimitPolicy(codexPolicy);
const codex5hEnabled = normalizedCodexPolicy.use5h;
const codexWeeklyEnabled = normalizedCodexPolicy.useWeekly;
return (
<div
@@ -2331,6 +2417,35 @@ function ConnectionRow({
<span className="material-symbols-outlined text-[13px]">shield</span>
{rateLimitEnabled ? t("rateLimitProtected") : t("rateLimitUnprotected")}
</button>
{isCodex && (
<>
<span className="text-text-muted/30 select-none">|</span>
<button
onClick={() => onToggleCodex5h?.(!codex5hEnabled)}
className={`inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-xs font-medium transition-all cursor-pointer ${
codex5hEnabled
? "bg-blue-500/15 text-blue-500 hover:bg-blue-500/25"
: "bg-black/[0.03] dark:bg-white/[0.03] text-text-muted/50 hover:text-text-muted hover:bg-black/[0.06] dark:hover:bg-white/[0.06]"
}`}
title="Toggle Codex 5h limit policy"
>
<span className="material-symbols-outlined text-[13px]">timer</span>
5h {codex5hEnabled ? "ON" : "OFF"}
</button>
<button
onClick={() => onToggleCodexWeekly?.(!codexWeeklyEnabled)}
className={`inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-xs font-medium transition-all cursor-pointer ${
codexWeeklyEnabled
? "bg-violet-500/15 text-violet-500 hover:bg-violet-500/25"
: "bg-black/[0.03] dark:bg-white/[0.03] text-text-muted/50 hover:text-text-muted hover:bg-black/[0.06] dark:hover:bg-white/[0.06]"
}`}
title="Toggle Codex weekly limit policy"
>
<span className="material-symbols-outlined text-[13px]">date_range</span>
Weekly {codexWeeklyEnabled ? "ON" : "OFF"}
</button>
</>
)}
{hasProxy &&
(() => {
const colorClass =
@@ -2451,14 +2566,18 @@ ConnectionRow.propTypes = {
lastErrorSource: PropTypes.string,
errorCode: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
globalPriority: PropTypes.number,
providerSpecificData: PropTypes.object,
}).isRequired,
isOAuth: PropTypes.bool.isRequired,
isCodex: PropTypes.bool,
isFirst: PropTypes.bool.isRequired,
isLast: PropTypes.bool.isRequired,
onMoveUp: PropTypes.func.isRequired,
onMoveDown: PropTypes.func.isRequired,
onToggleActive: PropTypes.func.isRequired,
onToggleRateLimit: PropTypes.func.isRequired,
onToggleCodex5h: PropTypes.func,
onToggleCodexWeekly: PropTypes.func,
onRetest: PropTypes.func.isRequired,
isRetesting: PropTypes.bool,
onEdit: PropTypes.func.isRequired,

View File

@@ -10,6 +10,30 @@ import { syncToCloud } from "@/lib/cloudSync";
import { updateProviderConnectionSchema } from "@/shared/validation/schemas";
import { isValidationFailure, validateBody } from "@/shared/validation/helpers";
function normalizeCodexLimitPolicy(
incoming: unknown,
existing: unknown
): { use5h: boolean; useWeekly: boolean } {
const incomingRecord =
incoming && typeof incoming === "object" && !Array.isArray(incoming)
? (incoming as Record<string, unknown>)
: {};
const existingRecord =
existing && typeof existing === "object" && !Array.isArray(existing)
? (existing as Record<string, unknown>)
: {};
const existingUse5h = typeof existingRecord.use5h === "boolean" ? existingRecord.use5h : true;
const existingUseWeekly =
typeof existingRecord.useWeekly === "boolean" ? existingRecord.useWeekly : true;
return {
use5h: typeof incomingRecord.use5h === "boolean" ? incomingRecord.use5h : existingUse5h,
useWeekly:
typeof incomingRecord.useWeekly === "boolean" ? incomingRecord.useWeekly : existingUseWeekly,
};
}
// GET /api/providers/[id] - Get single connection
export async function GET(request: Request, { params }: { params: Promise<{ id: string }> }) {
try {
@@ -105,7 +129,20 @@ export async function PUT(request: Request, { params }: { params: Promise<{ id:
existing.providerSpecificData && typeof existing.providerSpecificData === "object"
? existing.providerSpecificData
: {};
updateData.providerSpecificData = { ...existingPsd, ...incomingPsd };
const mergedPsd = { ...existingPsd, ...incomingPsd };
// Deep-merge and normalize Codex limit policy defaults.
if (existing.provider === "codex") {
const incomingRecord = incomingPsd as Record<string, unknown>;
if ("codexLimitPolicy" in incomingRecord || "codexLimitPolicy" in existingPsd) {
mergedPsd.codexLimitPolicy = normalizeCodexLimitPolicy(
incomingRecord.codexLimitPolicy,
(existingPsd as Record<string, unknown>).codexLimitPolicy
);
}
}
updateData.providerSpecificData = mergedPsd;
}
const updated = await updateProviderConnection(id, updateData);

View File

@@ -35,6 +35,13 @@ interface QuotaCacheEntry {
windowDurationMs?: number | null; // T08: optional rolling window duration
}
interface QuotaWindowStatus {
remainingPercentage: number;
usedPercentage: number;
resetAt: string | null;
reachedThreshold: boolean;
}
// ─── Constants ──────────────────────────────────────────────────────────────
const ACTIVE_TTL_MS = 5 * 60 * 1000; // 5 minutes for active accounts
@@ -89,6 +96,11 @@ function parseDate(value: string): number | null {
return Number.isNaN(ms) ? null : ms;
}
function clampPercent(value: number): number {
if (!Number.isFinite(value)) return 0;
return Math.max(0, Math.min(100, value));
}
function earliestResetAt(quotas: Record<string, QuotaInfo>): string | null {
let earliest: string | null = null;
let earliestMs = Infinity;
@@ -175,6 +187,45 @@ export function isAccountQuotaExhausted(connectionId: string): boolean {
return true;
}
/**
* Return quota window status for a connection (e.g., session/weekly).
* Returns null when no cache or no window data is available.
*/
export function getQuotaWindowStatus(
connectionId: string,
windowName: string,
thresholdPercent = 90
): QuotaWindowStatus | null {
const entry = cache.get(connectionId);
if (!entry) return null;
const now = Date.now();
const window = entry.quotas[windowName];
if (!window) return null;
const remainingPercentage = clampPercent(window.remainingPercentage);
const usedPercentage = clampPercent(100 - remainingPercentage);
let resetAt = window.resetAt || null;
let windowExpired = false;
if (resetAt) {
const resetMs = parseDate(resetAt);
if (resetMs !== null && resetMs <= now) {
resetAt = null;
windowExpired = true;
}
}
return {
remainingPercentage,
usedPercentage,
resetAt,
// If reset time has already passed, avoid stale cached percentages blocking selection.
reachedThreshold: windowExpired ? false : usedPercentage >= thresholdPercent,
};
}
/**
* Mark an account as quota-exhausted from a 429 response (no quota data available).
* Uses 5-minute fixed TTL since we don't know the actual resetAt.

View File

@@ -4,7 +4,7 @@ import {
updateProviderConnection,
getSettings,
} from "@/lib/localDb";
import { isAccountQuotaExhausted } from "@/domain/quotaCache";
import { getQuotaWindowStatus, isAccountQuotaExhausted } from "@/domain/quotaCache";
import {
isAccountUnavailable,
getUnavailableUntil,
@@ -39,6 +39,8 @@ interface ProviderConnectionView {
backoffLevel: number;
}
const CODEX_QUOTA_THRESHOLD_PERCENT = 90;
function asRecord(value: unknown): JsonRecord {
return value && typeof value === "object" && !Array.isArray(value) ? (value as JsonRecord) : {};
}
@@ -80,6 +82,40 @@ function toProviderConnection(value: unknown): ProviderConnectionView {
};
}
function toBooleanOrDefault(value: unknown, fallback: boolean): boolean {
return typeof value === "boolean" ? value : fallback;
}
function getCodexLimitPolicy(providerSpecificData: JsonRecord): {
use5h: boolean;
useWeekly: boolean;
} {
const policy = asRecord(providerSpecificData.codexLimitPolicy);
return {
use5h: toBooleanOrDefault(policy.use5h, true),
useWeekly: toBooleanOrDefault(policy.useWeekly, true),
};
}
function parseFutureDateMs(value: string | null): number | null {
if (!value) return null;
const ms = new Date(value).getTime();
if (!Number.isFinite(ms) || ms <= Date.now()) return null;
return ms;
}
function getEarliestFutureDate(candidates: Array<string | null>): string | null {
return (
candidates
.map((candidate) => ({
raw: candidate,
ms: parseFutureDateMs(candidate),
}))
.filter((entry) => entry.ms !== null)
.sort((a, b) => (a.ms as number) - (b.ms as number))[0]?.raw || null
);
}
// Mutex to prevent race conditions during account selection
let selectionMutex = Promise.resolve();
@@ -209,11 +245,84 @@ export async function getProviderCredentials(
return null;
}
let policyEligibleConnections = availableConnections;
if (provider === "codex") {
const blockedByPolicy: Array<{
id: string;
reasons: string[];
resetAt: string | null;
}> = [];
policyEligibleConnections = availableConnections.filter((connection) => {
const policy = getCodexLimitPolicy(connection.providerSpecificData);
const sessionStatus = policy.use5h
? getQuotaWindowStatus(connection.id, "session", CODEX_QUOTA_THRESHOLD_PERCENT)
: null;
const weeklyStatus = policy.useWeekly
? getQuotaWindowStatus(connection.id, "weekly", CODEX_QUOTA_THRESHOLD_PERCENT)
: null;
const reasons: string[] = [];
const resetCandidates: Array<string | null> = [];
if (policy.use5h && sessionStatus?.reachedThreshold) {
reasons.push(`5h usage ${Math.round(sessionStatus.usedPercentage)}%`);
resetCandidates.push(sessionStatus.resetAt);
}
if (policy.useWeekly && weeklyStatus?.reachedThreshold) {
reasons.push(`weekly usage ${Math.round(weeklyStatus.usedPercentage)}%`);
resetCandidates.push(weeklyStatus.resetAt);
}
if (reasons.length > 0) {
const nextResetAt = getEarliestFutureDate(resetCandidates);
blockedByPolicy.push({
id: connection.id,
reasons,
resetAt: nextResetAt,
});
return false;
}
return true;
});
if (blockedByPolicy.length > 0) {
log.info(
"AUTH",
`${provider} | quota policy filtered ${blockedByPolicy.length} account(s): ${blockedByPolicy
.map((entry) => `${entry.id.slice(0, 8)}(${entry.reasons.join(", ")})`)
.join("; ")}`
);
}
if (policyEligibleConnections.length === 0 && availableConnections.length > 0) {
const earliestResetAt = getEarliestFutureDate(
blockedByPolicy.map((entry) => entry.resetAt)
);
const earliestResetMs = parseFutureDateMs(earliestResetAt);
const retryAfter = earliestResetMs
? new Date(earliestResetMs).toISOString()
: new Date(Date.now() + 5 * 60 * 1000).toISOString();
return {
allRateLimited: true,
retryAfter,
retryAfterHuman: formatRetryAfter(retryAfter),
lastError: "All Codex accounts reached configured quota threshold",
lastErrorCode: 429,
};
}
}
// Quota-aware: prioritize accounts with available quota
const withQuota = availableConnections.filter((c) => !isAccountQuotaExhausted(c.id));
const exhaustedQuota = availableConnections.filter((c) => isAccountQuotaExhausted(c.id));
const withQuota = policyEligibleConnections.filter((c) => !isAccountQuotaExhausted(c.id));
const exhaustedQuota = policyEligibleConnections.filter((c) => isAccountQuotaExhausted(c.id));
const orderedConnections =
withQuota.length > 0 ? [...withQuota, ...exhaustedQuota] : availableConnections;
withQuota.length > 0 ? [...withQuota, ...exhaustedQuota] : policyEligibleConnections;
if (exhaustedQuota.length > 0) {
log.debug(