Skip to content

refactor(combo): god-file split D7a — round-robin sticky state to combo/rrState.ts (QG v2 Fase 9 T5) - #4196

Merged
diegosouzapw merged 2 commits into
release/v3.8.29from
refactor/combo-split-4
Jun 18, 2026
Merged

diegosouzapw merged 2 commits into
release/v3.8.29from
refactor/combo-split-4

Conversation

@diegosouzapw

Copy link
Copy Markdown
Collaborator

O que

Continuação do split do god-file open-sse/services/combo.ts (Quality Gate v2 / Fase 9 T5), D7a — primeira metade do D7 (estado de roteamento). Extrai o bloco de estado round-robin para o novo leaf open-sse/services/combo/rrState.ts. Move byte-idêntico, zero mudança de comportamento.

  • combo.ts 3431 → 3388 LOC (−43); rrState.ts 71 LOC.

Movido para combo/rrState.ts (6 símbolos)

MAX_RR_COUNTERS, rrCounters (Map), rrStickyTargets (Map), clampStickyRoundRobinTargetLimit, getStickyRoundRobinStartIndex, recordStickyRoundRobinSuccess.

⭐ Coesão de estado (o ponto do D7)

rrCounters/rrStickyTargets são mutados em vários lugares — os 3 helpers movidos e código que fica no combo.ts (orderTargetsByResetAwareQuota, orderTargetsByResetWindow, handleRoundRobinCombo). Após o move, cada Map permanece instância única definida 1× em rrState.ts; o combo.ts importa as mesmas referências de volta e muta direto. Verificado: new Map de rrCounters/rrStickyTargets = 0 no combo.ts, 2 no rrState.ts.

rrState.ts é leaf puro — importa só ResolvedComboTarget de ./types.ts, nada do barrel ../combo (sem ciclo).

O bloco quota (reset-aware/reset-window + 2 caches, ~800 linhas) vem no D7b (quotaScoring.ts + quotaStrategies.ts, que importarão rrCounters deste módulo).

Validação

  • typecheck:core rc=0 (0 erros TS) · lint escopado rc=0
  • ⭐ combo-routing-e2e.test.ts (sticky-3) PASS — guarda decisiva de que o estado round-robin sobreviveu como instância única
  • outros testes de combo (round-robin-streaming-lock + strategy-fallbacks + routing-engine) PASS
  • check:cycles rc=0 · check:file-size rc=0 (baseline combo.ts → 3389)
  • Auditoria trust-but-verify: Maps com new Map count 0 no combo.ts, cada símbolo def 1×, sem barrel, diff move-only.

Refactor puro — testes existentes são a guarda de regressão.

🤖 Generated with Claude Code

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the round-robin sticky state and its associated helpers from open-sse/services/combo.ts into a new dedicated module open-sse/services/combo/rrState.ts. The review feedback recommends adding defensive checks in getStickyRoundRobinStartIndex and recordStickyRoundRobinSuccess to handle empty or undefined inputs, preventing potential runtime issues such as division by zero or type errors.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +35 to +50
export function getStickyRoundRobinStartIndex(
comboName: string,
targets: ResolvedComboTarget[],
stickyLimit: number
): { startIndex: number; counter: number } {
const sticky = rrStickyTargets.get(comboName);
const stickyIndex = sticky
? targets.findIndex((target) => target.executionKey === sticky.executionKey)
: -1;
if (stickyLimit > 1 && sticky && stickyIndex >= 0 && sticky.successCount < stickyLimit) {
return { startIndex: stickyIndex, counter: rrCounters.get(comboName) || 0 };
}

const counter = rrCounters.get(comboName) || 0;
return { startIndex: counter % targets.length, counter };
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Para aplicar programação defensiva e evitar possíveis erros em tempo de execução (como um erro de tipo se targets for nulo/indefinido, ou NaN se targets estiver vazio devido à divisão por zero em counter % targets.length), é recomendável adicionar uma verificação defensiva no início da função.

export function getStickyRoundRobinStartIndex(
  comboName: string,
  targets: ResolvedComboTarget[],
  stickyLimit: number
): { startIndex: number; counter: number } {
  const counter = rrCounters.get(comboName) || 0;
  if (!targets || targets.length === 0) {
    return { startIndex: 0, counter };
  }

  const sticky = rrStickyTargets.get(comboName);
  const stickyIndex = sticky
    ? targets.findIndex((target) => target.executionKey === sticky.executionKey)
    : -1;
  if (stickyLimit > 1 && sticky && stickyIndex >= 0 && sticky.successCount < stickyLimit) {
    return { startIndex: stickyIndex, counter };
  }

  return { startIndex: counter % targets.length, counter };
}

Comment on lines +52 to +71
export function recordStickyRoundRobinSuccess(
comboName: string,
target: ResolvedComboTarget,
stickyLimit: number,
targets: ResolvedComboTarget[]
): void {
const sticky = rrStickyTargets.get(comboName);
const successCount = sticky?.executionKey === target.executionKey ? sticky.successCount + 1 : 1;
if (successCount >= stickyLimit) {
const servedIndex = targets.findIndex((entry) => entry.executionKey === target.executionKey);
rrCounters.set(
comboName,
servedIndex >= 0 ? servedIndex + 1 : (rrCounters.get(comboName) || 0) + 1
);
rrStickyTargets.delete(comboName);
return;
}

rrStickyTargets.set(comboName, { executionKey: target.executionKey, successCount });
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Para aplicar programação defensiva, devemos adicionar uma verificação para lidar com casos em que target ou targets sejam nulos/indefinidos ou vazios, evitando possíveis falhas em tempo de execução (como um erro de tipo ao acessar target.executionKey ou ao chamar targets.findIndex).

export function recordStickyRoundRobinSuccess(
  comboName: string,
  target: ResolvedComboTarget,
  stickyLimit: number,
  targets: ResolvedComboTarget[]
): void {
  if (!target || !targets || targets.length === 0) return;

  const sticky = rrStickyTargets.get(comboName);
  const successCount = sticky?.executionKey === target.executionKey ? sticky.successCount + 1 : 1;
  if (successCount >= stickyLimit) {
    const servedIndex = targets.findIndex((entry) => entry.executionKey === target.executionKey);
    rrCounters.set(
      comboName,
      servedIndex >= 0 ? servedIndex + 1 : (rrCounters.get(comboName) || 0) + 1
    );
    rrStickyTargets.delete(comboName);
    return;
  }

  rrStickyTargets.set(comboName, { executionKey: target.executionKey, successCount });
}

@diegosouzapw
diegosouzapw merged commit f06a90d into release/v3.8.29 Jun 18, 2026
4 checks passed
@diegosouzapw
diegosouzapw deleted the refactor/combo-split-4 branch June 19, 2026 12:07
tkgo11 pushed a commit to tkgo11/OmniRoute that referenced this pull request Sep 23, 2026
… (QG v2 Fase 9 T5 D7a) (cheaper-inference#4196)

Integrated into release/v3.8.29 — D7a round-robin sticky state extracted byte-identically to combo/rrState.ts; reconciled with cheaper-inference#4194 (baseline combo.ts -> 3398, resolving the over-cap left by cheaper-inference#4194).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant