fix: make target progress reflect fresh state

This commit is contained in:
proxyctl coordinator
2026-07-17 09:21:36 +08:00
parent fd113fb316
commit fb456f35e4
6 changed files with 198 additions and 40 deletions
+41 -16
View File
@@ -76,12 +76,13 @@ type ProgressiveModule interface {
}
type Application struct {
store profile.Store
state profile.State
targets []target.Target
inspections map[string]target.Inspection
mutationLock MutationLock
logger OperationLogger
store profile.Store
state profile.State
targets []target.Target
availabilities map[string]target.Availability
inspections map[string]target.Inspection
mutationLock MutationLock
logger OperationLogger
}
func New(store profile.Store) (*Application, error) {
@@ -105,7 +106,15 @@ func NewWithTargetsAndRuntime(store profile.Store, targets []target.Target, muta
if err != nil {
return nil, err
}
a := &Application{store: store, state: state, targets: append([]target.Target(nil), targets...), inspections: make(map[string]target.Inspection), mutationLock: mutationLock, logger: logger}
a := &Application{
store: store,
state: state,
targets: append([]target.Target(nil), targets...),
availabilities: make(map[string]target.Availability),
inspections: make(map[string]target.Inspection),
mutationLock: mutationLock,
logger: logger,
}
a.refreshTargets()
return a, nil
}
@@ -114,7 +123,7 @@ func (a *Application) Snapshot() Snapshot {
profiles := append([]profile.Profile(nil), a.state.Profiles...)
snapshot := Snapshot{Profiles: profiles, ActiveProfile: a.state.ActiveProfile}
for _, adapter := range a.targets {
availability := adapter.Availability(context.Background())
availability := a.availabilities[adapter.ID()]
inspection := a.inspections[adapter.ID()]
snapshot.Targets = append(snapshot.Targets, TargetSnapshot{ID: adapter.ID(), Description: adapter.Description(), Available: availability.Available, AvailabilityEvidence: availability.Evidence, State: inspection.State, Evidence: inspection.Evidence})
}
@@ -171,7 +180,7 @@ func (a *Application) dispatch(intent Intent, publish func(Result)) Result {
})
if err == nil {
a.state = next
a.refreshTargets()
a.refreshInspections()
} else {
var committed *profile.CommitError
if errors.As(err, &committed) {
@@ -243,18 +252,22 @@ func (a *Application) activateProfile(intent Intent, publish func(Result)) Resul
publish(Result{Snapshot: a.Snapshot(), Progress: []TargetProgress{{TargetID: adapter.ID(), Applying: true, State: a.inspections[adapter.ID()].State}}, Notice: "Updating " + adapter.Description().Name + " Target"})
}
operation := adapter.SetDesired(context.Background(), true, active)
a.inspections[adapter.ID()] = operation.Inspection
inspection := operation.Inspection
var safeErr error
if operation.Err != nil {
safeErr = errors.New(profile.RedactText(operation.Err.Error()))
// A failure-returned inspection may predate a partial write. Always
// inspect explicitly against the new Active Profile before publishing.
inspection = adapter.Inspect(context.Background(), active)
safeErr = fmt.Errorf("%s (fresh inspection: %s — %s)", profile.RedactText(operation.Err.Error()), inspection.State, profile.RedactText(inspection.Evidence))
}
item := TargetProgress{TargetID: adapter.ID(), State: operation.Inspection.State, Evidence: operation.Inspection.Evidence, Err: safeErr}
a.inspections[adapter.ID()] = inspection
item := TargetProgress{TargetID: adapter.ID(), State: inspection.State, Evidence: inspection.Evidence, Err: safeErr}
progress = append(progress, item)
if publish != nil {
publish(Result{Snapshot: a.Snapshot(), Progress: []TargetProgress{item}, Notice: adapter.Description().Name + " Target update completed", Err: safeErr})
}
if a.logger != nil {
outcome, detail := "success", operation.Inspection.Evidence
outcome, detail := "success", inspection.Evidence
if safeErr != nil {
outcome, detail = "failure", safeErr.Error()
}
@@ -294,6 +307,14 @@ func (a *Application) activeProfile() *profile.Profile {
}
func (a *Application) refreshTargets() {
active := a.activeProfile()
for _, adapter := range a.targets {
a.availabilities[adapter.ID()] = adapter.Availability(context.Background())
a.inspections[adapter.ID()] = adapter.Inspect(context.Background(), active)
}
}
func (a *Application) refreshInspections() {
active := a.activeProfile()
for _, adapter := range a.targets {
a.inspections[adapter.ID()] = adapter.Inspect(context.Background(), active)
@@ -319,8 +340,12 @@ func (a *Application) setTargetDesired(intent Intent) Result {
return Result{Snapshot: a.Snapshot(), Confirmation: warning}
}
result := selected.SetDesired(context.Background(), intent.Enabled, active)
a.inspections[selected.ID()] = result.Inspection
outcome, detail := "success", result.Inspection.Evidence
inspection := result.Inspection
if result.Err != nil {
inspection = selected.Inspect(context.Background(), active)
}
a.inspections[selected.ID()] = inspection
outcome, detail := "success", inspection.Evidence
if result.Err != nil {
outcome, detail = "failure", result.Err.Error()
}
@@ -333,7 +358,7 @@ func (a *Application) setTargetDesired(intent Intent) Result {
}
notice := ""
if result.Err == nil {
notice = fmt.Sprintf("%s Target is now %s", selected.Description().Name, result.Inspection.State)
notice = fmt.Sprintf("%s Target is now %s", selected.Description().Name, inspection.State)
}
return Result{Snapshot: a.Snapshot(), Notice: notice, Err: result.Err}
}