Harden host deletion and test stability

This commit is contained in:
phamnazage-jpg
2026-05-25 07:30:07 +08:00
parent 916569ccc5
commit 5e76fb20d0
12 changed files with 240 additions and 61 deletions

View File

@@ -2,6 +2,7 @@ package sqlite
import (
"context"
"database/sql"
"fmt"
"strings"
)
@@ -158,6 +159,49 @@ func (r *HostsRepo) ListAll(ctx context.Context) ([]Host, error) {
}
return hosts, nil
}
func (r *HostsRepo) RuntimeDependencyCountsByHostID(ctx context.Context, hostID string) (HostDeleteBlocker, error) {
hostID = strings.TrimSpace(hostID)
if hostID == "" {
return HostDeleteBlocker{}, fmt.Errorf("host_id is required")
}
host, err := r.GetByHostID(ctx, hostID)
if err != nil {
return HostDeleteBlocker{}, err
}
blocker := HostDeleteBlocker{HostID: host.HostID}
if err := r.db.QueryRowContext(ctx, `SELECT COUNT(1) FROM import_batches WHERE host_id = ?`, host.ID).Scan(&blocker.ImportBatchCount); err != nil {
return HostDeleteBlocker{}, fmt.Errorf("count import batches for host %q: %w", hostID, err)
}
if err := r.db.QueryRowContext(ctx, `SELECT COUNT(1) FROM managed_resources WHERE host_id = ?`, host.ID).Scan(&blocker.ManagedResourceCount); err != nil {
return HostDeleteBlocker{}, fmt.Errorf("count managed resources for host %q: %w", hostID, err)
}
if err := r.db.QueryRowContext(ctx, `SELECT COUNT(1) FROM reconcile_runs WHERE host_id = ?`, host.ID).Scan(&blocker.ReconcileRunCount); err != nil {
return HostDeleteBlocker{}, fmt.Errorf("count reconcile runs for host %q: %w", hostID, err)
}
return blocker, nil
}
type HostDeleteBlocker struct {
HostID string
ImportBatchCount int
ManagedResourceCount int
ReconcileRunCount int
}
func (e *HostDeleteBlocker) Error() string {
if e == nil {
return "host delete is blocked"
}
return fmt.Sprintf(
"host %q cannot be deleted while runtime state exists (import_batches=%d managed_resources=%d reconcile_runs=%d)",
e.HostID,
e.ImportBatchCount,
e.ManagedResourceCount,
e.ReconcileRunCount,
)
}
func (r *HostsRepo) DeleteByHostID(ctx context.Context, hostID string) error {
hostID = strings.TrimSpace(hostID)
@@ -165,6 +209,17 @@ func (r *HostsRepo) DeleteByHostID(ctx context.Context, hostID string) error {
return fmt.Errorf("host_id is required")
}
blocker, err := r.RuntimeDependencyCountsByHostID(ctx, hostID)
if err != nil {
if err == sql.ErrNoRows {
return fmt.Errorf("host %q not found", hostID)
}
return fmt.Errorf("resolve host %q runtime dependencies: %w", hostID, err)
}
if blocker.ImportBatchCount > 0 || blocker.ManagedResourceCount > 0 || blocker.ReconcileRunCount > 0 {
return &blocker
}
result, err := r.db.ExecContext(ctx, `DELETE FROM hosts WHERE host_id = ?`, hostID)
if err != nil {
return fmt.Errorf("delete host %q: %w", hostID, err)