Skip to content

fix(llmodels): keep the scaling baseline in sync with list replica actions - #1413

Merged
hibig merged 1 commit into
mainfrom
issue/6257-scaling-baseline-list-actions
Sep 24, 2026
Merged

hibig merged 1 commit into
mainfrom
issue/6257-scaling-baseline-list-actions

Conversation

@hibig

@hibig hibig commented Sep 24, 2026 •

Copy link
Copy Markdown
Collaborator

With scheduled scaling on, replicas is the live count the scheduler writes and scaling_schedule.baseline_replicas is the idle count the user declared. The deploy form keeps the two equal, but the list page never learned the contract: the inline replica edit and start/stop spread the row and overrode replicas alone, so the baseline went out with its old value and compute_desired_replicas drove the count straight back to it on the next tick. The request returned 200 and the UI showed a success toast, so the action looked like it had simply done nothing.

getReplicasUpdate now carries the baseline along with every replica change on a schedule-enabled row; rows without a schedule send the same payload as before. All three entry points route through it, and both batch start/stop reuse the same handlers.

Start no longer falls back to a hardcoded 1. A stopped row reports replicas: 0, so the fallback is what actually picks the count — it is now the declared baseline, with 1 only when there is none. A baseline of 0 is deliberately excluded: stopping from this list writes exactly that, and honouring it would make the next start a no-op.

scaling_schedule was added to ListItem; the API already returns it on the row.

No UI content changes — this is the bug fix only.

Not covered, pending a backend decision: inside an active window compute_desired_replicas returns the rule's replica count without consulting the baseline at all, so an explicit stop there is still reverted. That is questions 1 and 3 in gpustack/gpustack#6257 (comment) — either the backend suppresses the window on an explicit stop / baseline_replicas: 0, or the UI withholds the stop action while a window is active.

ref #6257

🤖 Generated with Claude Code

Copilot AI balanced review requested due to automatic review settings September 24, 2026 02:07

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

A zero baseline is incorrectly treated as missing during Start, contradicting the stated behavior.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)
What changed in this PR

Synchronizes scheduled-scaling baselines with model-list replica actions to address #6257.

Changes:

  • Updates baselines during inline edit and start/stop actions.
  • Adds scheduled-scaling context to list rows.
  • Adds localized schedule indicators and tooltips.
File Description
src/​pages/​llmodels/​components/​table-list.tsx Synchronizes replica and baseline updates.
src/​pages/​llmodels/​config/​types.ts Adds schedule data to list rows.
src/​pages/​llmodels/​hooks/​use-models-columns.tsx Displays the scheduled-scaling marker.
src/​locales/​en-US/​models.ts Adds English labels.
src/​locales/​ja-JP/​models.ts Adds Japanese labels.
src/​locales/​ru-RU/​models.ts Adds Russian labels.
src/​locales/​tr-TR/​models.ts Adds Turkish labels.
src/​locales/​zh-CN/​models.ts Adds Chinese labels.

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

const baseline = record.scaling_schedule?.enabled
? record.scaling_schedule.baseline_replicas
: null;
return baseline || 1;

@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 introduces support for scheduled scaling in the model list view. It adds necessary localization strings, updates the ListItem type definition, and implements helper functions in table-list.tsx to ensure that replica updates and start/stop actions correctly handle the baseline replica count when a schedule is enabled. The UI is also updated to display a 'Scheduled' tag with a tooltip explaining the scaling behavior. The reviewer suggested improving type safety by replacing the any type with ListItem in the newly added helper functions, which is a valid improvement opportunity.

Comment on lines +118 to +140
const getReplicasUpdate = (record: any, replicas: number) => {
const schedule = record.scaling_schedule;
if (!schedule?.enabled) {
return { replicas };
}
return {
replicas,
scaling_schedule: { ...schedule, baseline_replicas: replicas }
};
};

// A stopped row reports `replicas: 0`, so the fallback is what actually decides
// the count on start. Under a schedule that is the baseline the user declared,
// not a hardcoded 1 — which is all the row's own `replicas` could ever give us.
const getStartReplicas = (record: any) => {
if (record.replicas) {
return record.replicas;
}
const baseline = record.scaling_schedule?.enabled
? record.scaling_schedule.baseline_replicas
: null;
return baseline || 1;
};

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

To improve type safety and maintainability, avoid using any for the record parameter in getReplicasUpdate and getStartReplicas. Since ListItem is already imported in this file, you can type record as ListItem directly.

const getReplicasUpdate = (record: ListItem, replicas: number) => {
  const schedule = record.scaling_schedule;
  if (!schedule?.enabled) {
    return { replicas };
  }
  return {
    replicas,
    scaling_schedule: { ...schedule, baseline_replicas: replicas }
  };
};

// A stopped row reports replicas: 0, so the fallback is what actually decides
// the count on start. Under a schedule that is the baseline the user declared,
// not a hardcoded 1 — which is all the row's own replicas could ever give us.
const getStartReplicas = (record: ListItem) => {
  if (record.replicas) {
    return record.replicas;
  }
  const baseline = record.scaling_schedule?.enabled
    ? record.scaling_schedule.baseline_replicas
    : null;
  return baseline || 1;
};

…tions

The inline replica edit and start/stop sent only `replicas`, leaving
`baseline_replicas` stale, so the scheduler reconciled the count straight
back and the action silently did nothing. Start also fell back to a
hardcoded 1 instead of the declared baseline.

Refs #6257
@hibig
hibig force-pushed the issue/6257-scaling-baseline-list-actions branch from 8b0020e to 84a6c64 Compare September 24, 2026 08:55
@hibig
hibig merged commit f658798 into main Sep 24, 2026
4 checks passed
@hibig
hibig deleted the issue/6257-scaling-baseline-list-actions branch September 24, 2026 09:04
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.

2 participants