From b01e5d9f09188876e4e7f6d9554f03dcee189ecd Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Sat, 28 Mar 2026 23:13:59 -0600 Subject: [PATCH] refactor: move restart field from ServerInfo to ServerStatus The restart reason belongs with other server state (shutting_down, restarting, update_progress) rather than on the top-level ServerInfo. Co-Authored-By: Claude Opus 4.6 (1M context) --- core/src/db/model/public.rs | 6 +++--- core/src/hostname.rs | 2 +- core/src/init.rs | 4 ++-- core/src/system/mod.rs | 6 +++--- core/src/update/mod.rs | 5 +++-- core/src/version/v0_4_0_alpha_23.rs | 11 ++++++----- sdk/base/lib/osBindings/ServerInfo.ts | 2 -- sdk/base/lib/osBindings/ServerStatus.ts | 2 ++ .../ui/src/app/routes/portal/portal.component.ts | 4 +++- web/projects/ui/src/app/services/api/api.fixures.ts | 1 + .../src/app/services/api/embassy-mock-api.service.ts | 8 ++++---- web/projects/ui/src/app/services/api/mock-patch.ts | 2 +- 12 files changed, 29 insertions(+), 24 deletions(-) diff --git a/core/src/db/model/public.rs b/core/src/db/model/public.rs index ebd067abb..6f108f894 100644 --- a/core/src/db/model/public.rs +++ b/core/src/db/model/public.rs @@ -128,6 +128,7 @@ impl Public { update_progress: None, shutting_down: false, restarting: false, + restart: None, }, unread_notification_count: 0, password_hash: account.password.clone(), @@ -151,7 +152,6 @@ impl Public { kiosk: Some(kiosk).filter(|_| &*PLATFORM != "raspberrypi"), language, keyboard, - restart: None, }, package_data: AllPackageData::default(), ui: serde_json::from_str(*DB_UI_SEED_CELL.get().unwrap_or(&"null")) @@ -218,8 +218,6 @@ pub struct ServerInfo { pub kiosk: Option, pub language: Option, pub keyboard: Option, - #[serde(default)] - pub restart: Option, } #[derive(Debug, Clone, Deserialize, Serialize, TS)] @@ -381,6 +379,8 @@ pub struct ServerStatus { pub shutting_down: bool, #[serde(default)] pub restarting: bool, + #[serde(default)] + pub restart: Option, } #[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)] diff --git a/core/src/hostname.rs b/core/src/hostname.rs index f8bd003a3..2dbba37b7 100644 --- a/core/src/hostname.rs +++ b/core/src/hostname.rs @@ -272,7 +272,7 @@ pub async fn set_hostname_rpc( } if let Some(hostname) = &hostname { hostname.save(server_info)?; - server_info.as_restart_mut().ser(&Some(RestartReason::Mdns))?; + server_info.as_status_info_mut().as_restart_mut().ser(&Some(RestartReason::Mdns))?; } ServerHostnameInfo::load(server_info) }) diff --git a/core/src/init.rs b/core/src/init.rs index 7795d313c..af0106552 100644 --- a/core/src/init.rs +++ b/core/src/init.rs @@ -16,7 +16,7 @@ use crate::account::AccountInfo; use crate::context::config::ServerConfig; use crate::context::{CliContext, InitContext, RpcContext}; use crate::db::model::Database; -use crate::db::model::public::{RestartReason, ServerStatus}; +use crate::db::model::public::ServerStatus; use crate::developer::OS_DEVELOPER_KEY_PATH; use crate::hostname::ServerHostname; use crate::middleware::auth::local::LocalAuthContext; @@ -375,10 +375,10 @@ pub async fn init( backup_progress: None, shutting_down: false, restarting: false, + restart: None, }; db.mutate(|v| { let server_info = v.as_public_mut().as_server_info_mut(); - server_info.as_restart_mut().ser(&None::)?; server_info.as_ntp_synced_mut().ser(&ntp_synced)?; server_info.as_ram_mut().ser(&ram)?; server_info.as_devices_mut().ser(&devices)?; diff --git a/core/src/system/mod.rs b/core/src/system/mod.rs index 66afd84a7..4c4a86a4d 100644 --- a/core/src/system/mod.rs +++ b/core/src/system/mod.rs @@ -354,7 +354,7 @@ pub fn kiosk() -> ParentHandler { .mutate(|db| { let server_info = db.as_public_mut().as_server_info_mut(); server_info.as_kiosk_mut().ser(&Some(true))?; - server_info.as_restart_mut().ser(&Some(RestartReason::Kiosk)) + server_info.as_status_info_mut().as_restart_mut().ser(&Some(RestartReason::Kiosk)) }) .await .result?; @@ -371,7 +371,7 @@ pub fn kiosk() -> ParentHandler { .mutate(|db| { let server_info = db.as_public_mut().as_server_info_mut(); server_info.as_kiosk_mut().ser(&Some(false))?; - server_info.as_restart_mut().ser(&Some(RestartReason::Kiosk)) + server_info.as_status_info_mut().as_restart_mut().ser(&Some(RestartReason::Kiosk)) }) .await .result?; @@ -1370,7 +1370,7 @@ pub async fn set_language( server_info .as_language_mut() .ser(&Some(language.clone()))?; - server_info.as_restart_mut().ser(&Some(RestartReason::Language)) + server_info.as_status_info_mut().as_restart_mut().ser(&Some(RestartReason::Language)) }) .await .result?; diff --git a/core/src/update/mod.rs b/core/src/update/mod.rs index ce17ed95c..2fd6b90c6 100644 --- a/core/src/update/mod.rs +++ b/core/src/update/mod.rs @@ -81,6 +81,7 @@ pub async fn update_system( .await .into_public() .into_server_info() + .into_status_info() .into_restart() .de()? .is_some() @@ -286,7 +287,7 @@ async fn maybe_do_update( .mutate(|db| { let server_info = db.as_public_mut().as_server_info_mut(); - if server_info.as_restart().de()?.is_some() { + if server_info.as_status_info().as_restart().de()?.is_some() { return Err(Error::new( eyre!("{}", t!("update.already-updated-restart-required")), crate::ErrorKind::InvalidRequest, @@ -342,7 +343,7 @@ async fn maybe_do_update( .as_status_info_mut() .as_update_progress_mut() .ser(&None)?; - server_info.as_restart_mut().ser(&Some(RestartReason::Update)) + server_info.as_status_info_mut().as_restart_mut().ser(&Some(RestartReason::Update)) }) .await .result?; diff --git a/core/src/version/v0_4_0_alpha_23.rs b/core/src/version/v0_4_0_alpha_23.rs index 0d8b4059a..230dedc29 100644 --- a/core/src/version/v0_4_0_alpha_23.rs +++ b/core/src/version/v0_4_0_alpha_23.rs @@ -29,11 +29,12 @@ impl VersionT for Version { } #[instrument(skip_all)] fn up(self, db: &mut Value, _: Self::PreUpRes) -> Result { - db["public"]["serverInfo"]["statusInfo"] - .as_object_mut() - .map(|m| m.remove("updated")); - - db["public"]["serverInfo"]["restart"] = Value::Null; + let status_info = db["public"]["serverInfo"]["statusInfo"] + .as_object_mut(); + if let Some(m) = status_info { + m.remove("updated"); + m.insert("restart".into(), Value::Null); + } Ok(Value::Null) } diff --git a/sdk/base/lib/osBindings/ServerInfo.ts b/sdk/base/lib/osBindings/ServerInfo.ts index 7caa724e5..540110109 100644 --- a/sdk/base/lib/osBindings/ServerInfo.ts +++ b/sdk/base/lib/osBindings/ServerInfo.ts @@ -3,7 +3,6 @@ import type { Governor } from './Governor' import type { KeyboardOptions } from './KeyboardOptions' import type { LshwDevice } from './LshwDevice' import type { NetworkInfo } from './NetworkInfo' -import type { RestartReason } from './RestartReason' import type { ServerStatus } from './ServerStatus' import type { SmtpValue } from './SmtpValue' @@ -33,5 +32,4 @@ export type ServerInfo = { kiosk: boolean | null language: string | null keyboard: KeyboardOptions | null - restart: RestartReason | null } diff --git a/sdk/base/lib/osBindings/ServerStatus.ts b/sdk/base/lib/osBindings/ServerStatus.ts index 9d754d267..c40f1bbd3 100644 --- a/sdk/base/lib/osBindings/ServerStatus.ts +++ b/sdk/base/lib/osBindings/ServerStatus.ts @@ -2,10 +2,12 @@ import type { BackupProgress } from './BackupProgress' import type { FullProgress } from './FullProgress' import type { PackageId } from './PackageId' +import type { RestartReason } from './RestartReason' export type ServerStatus = { backupProgress: { [key: PackageId]: BackupProgress } | null updateProgress: FullProgress | null shuttingDown: boolean restarting: boolean + restart: RestartReason | null } diff --git a/web/projects/ui/src/app/routes/portal/portal.component.ts b/web/projects/ui/src/app/routes/portal/portal.component.ts index 10da593b2..cc5e746b5 100644 --- a/web/projects/ui/src/app/routes/portal/portal.component.ts +++ b/web/projects/ui/src/app/routes/portal/portal.component.ts @@ -149,7 +149,9 @@ export class PortalComponent { readonly name = toSignal(this.patch.watch$('serverInfo', 'name')) readonly update = toSignal(inject(OSService).updating$) - readonly restartReason = toSignal(this.patch.watch$('serverInfo', 'restart')) + readonly restartReason = toSignal( + this.patch.watch$('serverInfo', 'statusInfo', 'restart'), + ) readonly bar = signal(true) getProgress(size: number, downloaded: number): number { diff --git a/web/projects/ui/src/app/services/api/api.fixures.ts b/web/projects/ui/src/app/services/api/api.fixures.ts index e7bd71a1a..436dcced9 100644 --- a/web/projects/ui/src/app/services/api/api.fixures.ts +++ b/web/projects/ui/src/app/services/api/api.fixures.ts @@ -26,6 +26,7 @@ export namespace Mock { updateProgress: null, restarting: false, shuttingDown: false, + restart: null, } export const RegistryOSUpdate: T.OsVersionInfoMap = { diff --git a/web/projects/ui/src/app/services/api/embassy-mock-api.service.ts b/web/projects/ui/src/app/services/api/embassy-mock-api.service.ts index 74c3503b2..ea871b0ff 100644 --- a/web/projects/ui/src/app/services/api/embassy-mock-api.service.ts +++ b/web/projects/ui/src/app/services/api/embassy-mock-api.service.ts @@ -445,7 +445,7 @@ export class MockApiService extends ApiService { this.mockRevision([ { op: PatchOp.REPLACE, - path: '/serverInfo/restart', + path: '/serverInfo/statusInfo/restart', value: 'kiosk', }, ]) @@ -471,7 +471,7 @@ export class MockApiService extends ApiService { this.mockRevision([ { op: PatchOp.REPLACE, - path: '/serverInfo/restart', + path: '/serverInfo/statusInfo/restart', value: 'mdns', }, ]) @@ -507,7 +507,7 @@ export class MockApiService extends ApiService { this.mockRevision([ { op: PatchOp.REPLACE, - path: '/serverInfo/restart', + path: '/serverInfo/statusInfo/restart', value: 'language', }, ]) @@ -1852,7 +1852,7 @@ export class MockApiService extends ApiService { const patch3: Operation[] = [ { op: PatchOp.REPLACE, - path: '/serverInfo/restart', + path: '/serverInfo/statusInfo/restart', value: 'update', }, { diff --git a/web/projects/ui/src/app/services/api/mock-patch.ts b/web/projects/ui/src/app/services/api/mock-patch.ts index 5a166dd46..1eb61067e 100644 --- a/web/projects/ui/src/app/services/api/mock-patch.ts +++ b/web/projects/ui/src/app/services/api/mock-patch.ts @@ -231,8 +231,8 @@ export const mockPatchData: DataModel = { restarting: false, shuttingDown: false, backupProgress: null, + restart: null, }, - restart: null, name: 'Random Words', hostname: 'random-words', pubkey: 'npub1sg6plzptd64u62a878hep2kev88swjh3tw00gjsfl8f237lmu63q0uf63m',