cleanup: ota state

This commit is contained in:
Siyuan 2025-10-31 16:15:42 +00:00
parent 0a98a73275
commit 2b3f392f0f
6 changed files with 84 additions and 56 deletions

View File

@ -27,14 +27,14 @@ func (s *State) updateApp(ctx context.Context, appUpdate *componentUpdateStatus)
l := s.l.With().Str("path", appUpdatePath).Logger() l := s.l.With().Str("path", appUpdatePath).Logger()
if err := s.downloadFile(ctx, appUpdatePath, appUpdate.url, &appUpdate.downloadProgress); err != nil { if err := s.downloadFile(ctx, appUpdatePath, appUpdate.url, "app"); err != nil {
return s.componentUpdateError("Error downloading app update", err, &l) return s.componentUpdateError("Error downloading app update", err, &l)
} }
downloadFinished := time.Now() downloadFinished := time.Now()
appUpdate.downloadFinishedAt = downloadFinished appUpdate.downloadFinishedAt = downloadFinished
appUpdate.downloadProgress = 1 appUpdate.downloadProgress = 1
s.triggerStateUpdate() s.triggerComponentUpdateState("app", appUpdate)
if err := s.verifyFile( if err := s.verifyFile(
appUpdatePath, appUpdatePath,
@ -48,7 +48,7 @@ func (s *State) updateApp(ctx context.Context, appUpdate *componentUpdateStatus)
appUpdate.verificationProgress = 1 appUpdate.verificationProgress = 1
appUpdate.updatedAt = verifyFinished appUpdate.updatedAt = verifyFinished
appUpdate.updateProgress = 1 appUpdate.updateProgress = 1
s.triggerStateUpdate() s.triggerComponentUpdateState("app", appUpdate)
l.Info().Msg("App update downloaded") l.Info().Msg("App update downloaded")

View File

@ -92,6 +92,11 @@ func (s *State) triggerStateUpdate() {
s.onStateUpdate(s.ToRPCState()) s.onStateUpdate(s.ToRPCState())
} }
func (s *State) triggerComponentUpdateState(component string, update *componentUpdateStatus) {
s.componentUpdateStatuses[component] = *update
s.triggerStateUpdate()
}
func (s *State) doUpdate(ctx context.Context, params UpdateParams) error { func (s *State) doUpdate(ctx context.Context, params UpdateParams) error {
scopedLogger := s.l.With(). scopedLogger := s.l.With().
Interface("params", params). Interface("params", params).
@ -102,32 +107,35 @@ func (s *State) doUpdate(ctx context.Context, params UpdateParams) error {
return fmt.Errorf("update already in progress") return fmt.Errorf("update already in progress")
} }
if !params.CheckOnly {
s.updating = true s.updating = true
s.triggerStateUpdate() s.triggerStateUpdate()
defer func() { defer func() {
s.updating = false s.updating = false
s.triggerStateUpdate() s.triggerStateUpdate()
}() }()
}
appUpdate, systemUpdate, err := s.getUpdateStatus(ctx, params) appUpdate, systemUpdate, err := s.getUpdateStatus(ctx, params)
if err != nil { if err != nil {
return s.componentUpdateError("Error checking for updates", err, &scopedLogger) return s.componentUpdateError("Error checking for updates", err, &scopedLogger)
} }
s.metadataFetchedAt = time.Now()
s.triggerStateUpdate()
if params.CheckOnly { if params.CheckOnly {
return nil return nil
} }
s.metadataFetchedAt = time.Now()
s.triggerStateUpdate()
if appUpdate.available || appUpdate.downgradeAvailable { if appUpdate.available || appUpdate.downgradeAvailable {
appUpdate.pending = true appUpdate.pending = true
s.triggerComponentUpdateState("app", appUpdate)
} }
if systemUpdate.available || systemUpdate.downgradeAvailable { if systemUpdate.available || systemUpdate.downgradeAvailable {
systemUpdate.pending = true systemUpdate.pending = true
s.triggerComponentUpdateState("system", systemUpdate)
} }
if appUpdate.pending { if appUpdate.pending {

View File

@ -69,23 +69,23 @@ type componentUpdateStatus struct {
type RPCState struct { type RPCState struct {
Updating bool `json:"updating"` Updating bool `json:"updating"`
Error string `json:"error,omitempty"` Error string `json:"error,omitempty"`
MetadataFetchedAt time.Time `json:"metadataFetchedAt,omitempty"` MetadataFetchedAt *time.Time `json:"metadataFetchedAt,omitempty"`
AppUpdatePending bool `json:"appUpdatePending"` AppUpdatePending bool `json:"appUpdatePending"`
SystemUpdatePending bool `json:"systemUpdatePending"` SystemUpdatePending bool `json:"systemUpdatePending"`
AppDownloadProgress float32 `json:"appDownloadProgress,omitempty"` //TODO: implement for progress bar AppDownloadProgress *float32 `json:"appDownloadProgress,omitempty"` //TODO: implement for progress bar
AppDownloadFinishedAt time.Time `json:"appDownloadFinishedAt,omitempty"` AppDownloadFinishedAt *time.Time `json:"appDownloadFinishedAt,omitempty"`
SystemDownloadProgress float32 `json:"systemDownloadProgress,omitempty"` //TODO: implement for progress bar SystemDownloadProgress *float32 `json:"systemDownloadProgress,omitempty"` //TODO: implement for progress bar
SystemDownloadFinishedAt time.Time `json:"systemDownloadFinishedAt,omitempty"` SystemDownloadFinishedAt *time.Time `json:"systemDownloadFinishedAt,omitempty"`
AppVerificationProgress float32 `json:"appVerificationProgress,omitempty"` AppVerificationProgress *float32 `json:"appVerificationProgress,omitempty"`
AppVerifiedAt time.Time `json:"appVerifiedAt,omitempty"` AppVerifiedAt *time.Time `json:"appVerifiedAt,omitempty"`
SystemVerificationProgress float32 `json:"systemVerificationProgress,omitempty"` SystemVerificationProgress *float32 `json:"systemVerificationProgress,omitempty"`
SystemVerifiedAt time.Time `json:"systemVerifiedAt,omitempty"` SystemVerifiedAt *time.Time `json:"systemVerifiedAt,omitempty"`
AppUpdateProgress float32 `json:"appUpdateProgress,omitempty"` //TODO: implement for progress bar AppUpdateProgress *float32 `json:"appUpdateProgress,omitempty"` //TODO: implement for progress bar
AppUpdatedAt time.Time `json:"appUpdatedAt,omitempty"` AppUpdatedAt *time.Time `json:"appUpdatedAt,omitempty"`
SystemUpdateProgress float32 `json:"systemUpdateProgress,omitempty"` //TODO: port rk_ota, then implement SystemUpdateProgress *float32 `json:"systemUpdateProgress,omitempty"` //TODO: port rk_ota, then implement
SystemUpdatedAt time.Time `json:"systemUpdatedAt,omitempty"` SystemUpdatedAt *time.Time `json:"systemUpdatedAt,omitempty"`
SystemTargetVersion string `json:"systemTargetVersion,omitempty"` SystemTargetVersion *string `json:"systemTargetVersion,omitempty"`
AppTargetVersion string `json:"appTargetVersion,omitempty"` AppTargetVersion *string `json:"appTargetVersion,omitempty"`
} }
// HwRebootFunc is a function that reboots the hardware // HwRebootFunc is a function that reboots the hardware
@ -221,35 +221,48 @@ func NewState(opts Options) *State {
} }
// ToRPCState converts the State to the RPCState // ToRPCState converts the State to the RPCState
// probably we need a generator for this ...
func (s *State) ToRPCState() *RPCState { func (s *State) ToRPCState() *RPCState {
r := &RPCState{ r := &RPCState{
Updating: s.updating, Updating: s.updating,
Error: s.error, Error: s.error,
MetadataFetchedAt: s.metadataFetchedAt, MetadataFetchedAt: &s.metadataFetchedAt,
} }
app, ok := s.componentUpdateStatuses["app"] app, ok := s.componentUpdateStatuses["app"]
if ok { if ok {
r.AppUpdatePending = app.pending r.AppUpdatePending = app.pending
r.AppDownloadProgress = app.downloadProgress r.AppDownloadProgress = &app.downloadProgress
r.AppDownloadFinishedAt = app.downloadFinishedAt if !app.downloadFinishedAt.IsZero() {
r.AppVerificationProgress = app.verificationProgress r.AppDownloadFinishedAt = &app.downloadFinishedAt
r.AppVerifiedAt = app.verifiedAt }
r.AppUpdateProgress = app.updateProgress r.AppVerificationProgress = &app.verificationProgress
r.AppUpdatedAt = app.updatedAt if !app.verifiedAt.IsZero() {
r.AppTargetVersion = app.targetVersion r.AppVerifiedAt = &app.verifiedAt
}
r.AppUpdateProgress = &app.updateProgress
if !app.updatedAt.IsZero() {
r.AppUpdatedAt = &app.updatedAt
}
r.AppTargetVersion = &app.targetVersion
} }
system, ok := s.componentUpdateStatuses["system"] system, ok := s.componentUpdateStatuses["system"]
if ok { if ok {
r.SystemUpdatePending = system.pending r.SystemUpdatePending = system.pending
r.SystemDownloadProgress = system.downloadProgress r.SystemDownloadProgress = &system.downloadProgress
r.SystemDownloadFinishedAt = system.downloadFinishedAt if !system.downloadFinishedAt.IsZero() {
r.SystemVerificationProgress = system.verificationProgress r.SystemDownloadFinishedAt = &system.downloadFinishedAt
r.SystemVerifiedAt = system.verifiedAt }
r.SystemUpdateProgress = system.updateProgress r.SystemVerificationProgress = &system.verificationProgress
r.SystemUpdatedAt = system.updatedAt if !system.verifiedAt.IsZero() {
r.SystemTargetVersion = system.targetVersion r.SystemVerifiedAt = &system.verifiedAt
}
r.SystemUpdateProgress = &system.updateProgress
if !system.updatedAt.IsZero() {
r.SystemUpdatedAt = &system.updatedAt
}
r.SystemTargetVersion = &system.targetVersion
} }
return r return r

View File

@ -17,14 +17,14 @@ func (s *State) updateSystem(ctx context.Context, systemUpdate *componentUpdateS
l := s.l.With().Str("path", systemUpdatePath).Logger() l := s.l.With().Str("path", systemUpdatePath).Logger()
if err := s.downloadFile(ctx, systemUpdatePath, systemUpdate.url, &systemUpdate.downloadProgress); err != nil { if err := s.downloadFile(ctx, systemUpdatePath, systemUpdate.url, "system"); err != nil {
return s.componentUpdateError("Error downloading system update", err, &l) return s.componentUpdateError("Error downloading system update", err, &l)
} }
downloadFinished := time.Now() downloadFinished := time.Now()
systemUpdate.downloadFinishedAt = downloadFinished systemUpdate.downloadFinishedAt = downloadFinished
systemUpdate.downloadProgress = 1 systemUpdate.downloadProgress = 1
s.triggerStateUpdate() s.triggerComponentUpdateState("system", systemUpdate)
if err := s.verifyFile( if err := s.verifyFile(
systemUpdatePath, systemUpdatePath,
@ -38,7 +38,7 @@ func (s *State) updateSystem(ctx context.Context, systemUpdate *componentUpdateS
systemUpdate.verificationProgress = 1 systemUpdate.verificationProgress = 1
systemUpdate.updatedAt = verifyFinished systemUpdate.updatedAt = verifyFinished
systemUpdate.updateProgress = 1 systemUpdate.updateProgress = 1
s.triggerStateUpdate() s.triggerComponentUpdateState("system", systemUpdate)
l.Info().Msg("System update downloaded") l.Info().Msg("System update downloaded")
@ -68,7 +68,7 @@ func (s *State) updateSystem(ctx context.Context, systemUpdate *componentUpdateS
if systemUpdate.updateProgress > 0.99 { if systemUpdate.updateProgress > 0.99 {
systemUpdate.updateProgress = 0.99 systemUpdate.updateProgress = 0.99
} }
s.triggerStateUpdate() s.triggerComponentUpdateState("system", systemUpdate)
case <-ctx.Done(): case <-ctx.Done():
return return
} }
@ -86,7 +86,7 @@ func (s *State) updateSystem(ctx context.Context, systemUpdate *componentUpdateS
rkLogger.Info().Msg("rk_ota success") rkLogger.Info().Msg("rk_ota success")
systemUpdate.updateProgress = 1 systemUpdate.updateProgress = 1
systemUpdate.updatedAt = verifyFinished systemUpdate.updatedAt = verifyFinished
s.triggerStateUpdate() s.triggerComponentUpdateState("system", systemUpdate)
return nil return nil
} }

View File

@ -25,7 +25,14 @@ func syncFilesystem() error {
return nil return nil
} }
func (s *State) downloadFile(ctx context.Context, path string, url string, downloadProgress *float32) error { func (s *State) downloadFile(ctx context.Context, path string, url string, component string) error {
componentUpdate, ok := s.componentUpdateStatuses[component]
if !ok {
return fmt.Errorf("component %s not found", component)
}
downloadProgress := componentUpdate.downloadProgress
if _, err := os.Stat(path); err == nil { if _, err := os.Stat(path); err == nil {
if err := os.Remove(path); err != nil { if err := os.Remove(path); err != nil {
return fmt.Errorf("error removing existing file: %w", err) return fmt.Errorf("error removing existing file: %w", err)
@ -80,9 +87,9 @@ func (s *State) downloadFile(ctx context.Context, path string, url string, downl
return fmt.Errorf("error writing to file: %w", ew) return fmt.Errorf("error writing to file: %w", ew)
} }
progress := float32(written) / float32(totalSize) progress := float32(written) / float32(totalSize)
if progress-*downloadProgress >= 0.01 { if progress-downloadProgress >= 0.01 {
*downloadProgress = progress componentUpdate.downloadProgress = progress
s.triggerStateUpdate() s.triggerComponentUpdateState(component, &componentUpdate)
} }
} }
if er != nil { if er != nil {

View File

@ -200,7 +200,7 @@ export default function SettingsAdvancedRoute() {
// Navigate to update page // Navigate to update page
navigateTo("/settings/general/update"); navigateTo("/settings/general/update");
}); });
}, [updateTarget, appVersion, systemVersion, devChannel, send, navigateTo]); }, [appVersion, systemVersion, devChannel, send, navigateTo]);
return ( return (
<div className="space-y-4"> <div className="space-y-4">