mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-15 04:53:00 +08:00
75 lines
2.8 KiB
Go
75 lines
2.8 KiB
Go
package daemon
|
|
|
|
import (
|
|
"github.com/matthewlu070111/smart-srun/core/internal/application"
|
|
"github.com/matthewlu070111/smart-srun/core/internal/domain"
|
|
)
|
|
|
|
// finishSwitch runs on the coordinator, after the network worker has stopped
|
|
// and before success is visible. Switches own an exclusive dispatch slot, so
|
|
// publishing a new config cannot invalidate somebody else's running auth.
|
|
func (d *Daemon) finishSwitch(action application.Action, outcome application.Outcome) application.Outcome {
|
|
request := action.Request
|
|
if request.Kind == application.KindQuietHotspot || request.Kind == application.KindQuietCampus {
|
|
// Temporary scheduling never changes the user's selected profiles.
|
|
outcome = d.finishQuietRecord(action, outcome)
|
|
if !outcome.MaintenanceDeferred {
|
|
d.configChanged(d.config.Revision())
|
|
}
|
|
return outcome
|
|
}
|
|
if request.Kind != application.KindSwitchCampus && request.Kind != application.KindSwitchHotspot {
|
|
return outcome
|
|
}
|
|
before := d.config.Snapshot()
|
|
if request.CheckRevision && request.ConfigRevision != before.Revision {
|
|
return switchSaveFailed(outcome)
|
|
}
|
|
if outcome = d.finishQuietRecord(action, outcome); outcome.State != application.StateSucceeded {
|
|
return outcome
|
|
}
|
|
selection := before.Selection
|
|
if request.Kind == application.KindSwitchCampus {
|
|
if _, ok := before.CampusAccountByID(request.AccountID); !ok {
|
|
return switchSaveFailed(outcome)
|
|
}
|
|
selection.ActiveCampusID = request.AccountID
|
|
} else {
|
|
if _, ok := before.HotspotByID(request.HotspotID); !ok {
|
|
return switchSaveFailed(outcome)
|
|
}
|
|
selection.ActiveHotspotID = request.HotspotID
|
|
}
|
|
if selection == before.Selection {
|
|
d.configChanged(before.Revision) // invalidate observations from the old line
|
|
return d.retainManualQuietReturn(action, outcome) // no persistent config write
|
|
}
|
|
updated, err := d.config.Update(before.Revision, func(cfg *domain.Config) error {
|
|
cfg.Selection = selection
|
|
return nil
|
|
})
|
|
revision := d.config.Revision()
|
|
if revision != before.Revision {
|
|
d.configChanged(revision)
|
|
}
|
|
if err != nil {
|
|
// The line may already have changed; do not claim a config write error
|
|
// undid it. In particular rename can be visible even if fsync failed.
|
|
d.onError(err)
|
|
return switchSaveFailed(outcome)
|
|
}
|
|
if outcome.Observation != nil && outcome.Observation.Revision == before.Revision {
|
|
observed := *outcome.Observation
|
|
observed.Revision = updated.Revision
|
|
outcome.Observation = &observed
|
|
}
|
|
return d.retainManualQuietReturn(action, outcome)
|
|
}
|
|
|
|
func switchSaveFailed(outcome application.Outcome) application.Outcome {
|
|
outcome.State = application.StateFailed
|
|
outcome.Code = domain.CodeRecoveryRequired
|
|
outcome.Message = "线路切换已执行,但未能确认保存所选账号或热点,请检查当前连接后重试"
|
|
return outcome
|
|
}
|