Skip to content

Commit f3faac8

Browse files
committed
release: v0.0.30 — idempotent team suspension
ProcessBilling skips re-suspending an already-suspended team, avoiding repeated scale-down/orphan-pod deletion every billing cycle for overdue teams.
1 parent ff0e3ab commit f3faac8

4 files changed

Lines changed: 20 additions & 7 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ All notable changes to the Bison project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.0.30] - 2026-06-19
9+
10+
### Fixed — Idempotent suspension
11+
12+
- `ProcessBilling` now skips re-suspending a team that is already suspended. Previously every billing cycle for an overdue, grace-expired team re-ran `SuspendTeam` (scale-down + orphan-pod deletion), which was wasteful and could delete pods a user legitimately created in the namespace.
13+
814
## [0.0.29] - 2026-06-19
915

1016
### Fixed — Auto-recharge validation

api-server/internal/service/billing_service.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -201,9 +201,12 @@ func (s *BillingService) ProcessBilling(ctx context.Context) error {
201201
return err
202202
}
203203

204-
// Map namespace to team
204+
// Map namespace to team, and remember which teams are already suspended so we
205+
// don't re-run scale-down/orphan-pod cleanup for them every billing cycle.
205206
nsToTeam := make(map[string]string)
207+
suspendedByName := make(map[string]bool)
206208
for _, team := range teams {
209+
suspendedByName[team.Name] = team.Suspended
207210
projects, _ := s.projectSvc.ListByTeam(ctx, team.Name)
208211
for _, project := range projects {
209212
nsToTeam[project.Name] = team.Name
@@ -259,9 +262,13 @@ func (s *BillingService) ProcessBilling(ctx context.Context) error {
259262

260263
// Check if grace period has passed
261264
if s.isGracePeriodExpired(config, overdueAt) {
262-
logger.Warn("Grace period expired, suspending team", "team", teamName, "overdueAt", overdueAt)
263-
if err := s.SuspendTeam(ctx, teamName); err != nil {
264-
logger.Error("Failed to suspend team", "team", teamName, "error", err)
265+
if suspendedByName[teamName] {
266+
logger.Debug("Team already suspended; skipping re-suspend", "team", teamName)
267+
} else {
268+
logger.Warn("Grace period expired, suspending team", "team", teamName, "overdueAt", overdueAt)
269+
if err := s.SuspendTeam(ctx, teamName); err != nil {
270+
logger.Error("Failed to suspend team", "team", teamName, "error", err)
271+
}
265272
}
266273
} else {
267274
remaining := s.balanceSvc.CalculateGraceRemaining(overdueAt, config.GracePeriodValue, config.GracePeriodUnit)

deploy/charts/bison/Chart.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ apiVersion: v2
22
name: bison
33
description: Bison - GPU 资源计费平台,基于 Capsule 多租户 + OpenCost 成本追踪
44
type: application
5-
version: 0.0.29
6-
appVersion: "0.0.29"
5+
version: 0.0.30
6+
appVersion: "0.0.30"
77
kubeVersion: ">=1.22.0-0"
88
keywords:
99
- gpu

web-ui/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "bison-web-ui",
3-
"version": "0.0.29",
3+
"version": "0.0.30",
44
"private": true,
55
"scripts": {
66
"dev": "vite",

0 commit comments

Comments
 (0)