From 98d9f9f1fc8e942c2ec7ecddca4734adf24e3dad Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Tue, 7 Nov 2023 22:19:23 -0700 Subject: [PATCH 1/3] extend `server-info` --- backend/src/db/model.rs | 6 ++++++ backend/src/init.rs | 2 ++ backend/src/shutdown.rs | 19 ++++++++++++++++++- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/backend/src/db/model.rs b/backend/src/db/model.rs index 6ce3f8add..72231c020 100644 --- a/backend/src/db/model.rs +++ b/backend/src/db/model.rs @@ -57,6 +57,8 @@ impl Database { backup_progress: None, updated: false, update_progress: None, + shutting_down: false, + restarting: false, }, wifi: WifiInfo { ssids: Vec::new(), @@ -166,6 +168,10 @@ pub struct ServerStatus { pub backup_progress: Option>, pub updated: bool, pub update_progress: Option, + #[serde(default)] + pub shutting_down: bool, + #[serde(default)] + pub restarting: bool, } #[derive(Debug, Deserialize, Serialize, HasModel)] diff --git a/backend/src/init.rs b/backend/src/init.rs index dc98dae42..288149f37 100644 --- a/backend/src/init.rs +++ b/backend/src/init.rs @@ -406,6 +406,8 @@ pub async fn init(cfg: &RpcContextConfig) -> Result { updated: false, update_progress: None, backup_progress: None, + shutting_down: false, + restarting: false, }; server_info.ntp_synced = if time_not_synced { diff --git a/backend/src/shutdown.rs b/backend/src/shutdown.rs index 93e5cc3d2..3196bc580 100644 --- a/backend/src/shutdown.rs +++ b/backend/src/shutdown.rs @@ -6,10 +6,11 @@ use rpc_toolkit::command; use crate::context::RpcContext; use crate::disk::main::export; use crate::init::{STANDBY_MODE_PATH, SYSTEM_REBUILD_PATH}; +use crate::prelude::*; use crate::sound::SHUTDOWN; use crate::util::docker::CONTAINER_TOOL; use crate::util::{display_none, Invoke}; -use crate::{Error, PLATFORM}; +use crate::PLATFORM; #[derive(Debug, Clone)] pub struct Shutdown { @@ -90,6 +91,14 @@ impl Shutdown { #[command(display(display_none))] pub async fn shutdown(#[context] ctx: RpcContext) -> Result<(), Error> { + ctx.db + .mutate(|db| { + db.as_server_info_mut() + .as_status_info_mut() + .as_shutting_down() + .ser(&true) + }) + .await?; ctx.shutdown .send(Some(Shutdown { export_args: Some((ctx.disk_guid.clone(), ctx.datadir.clone())), @@ -102,6 +111,14 @@ pub async fn shutdown(#[context] ctx: RpcContext) -> Result<(), Error> { #[command(display(display_none))] pub async fn restart(#[context] ctx: RpcContext) -> Result<(), Error> { + ctx.db + .mutate(|db| { + db.as_server_info_mut() + .as_status_info_mut() + .as_restarting() + .ser(&true) + }) + .await?; ctx.shutdown .send(Some(Shutdown { export_args: Some((ctx.disk_guid.clone(), ctx.datadir.clone())), From 299623d230a2cd4ffd17a42450352fc4a2cb92d8 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Tue, 7 Nov 2023 22:41:28 -0700 Subject: [PATCH 2/3] add restarting, shutting down to FE status bar --- .../projects/ui/src/app/app.component.html | 10 +--- frontend/projects/ui/src/app/app.component.ts | 15 +++++- .../connection-bar.component.ts | 26 +++++++++- .../server-show/server-show.page.ts | 21 -------- .../ui/src/app/services/api/api.fixures.ts | 2 + .../services/api/embassy-mock-api.service.ts | 49 +++++++++++++++++-- .../ui/src/app/services/api/mock-patch.ts | 2 + .../src/app/services/patch-db/data-model.ts | 2 + 8 files changed, 91 insertions(+), 36 deletions(-) diff --git a/frontend/projects/ui/src/app/app.component.html b/frontend/projects/ui/src/app/app.component.html index 29c7e11a3..0506d5214 100644 --- a/frontend/projects/ui/src/app/app.component.html +++ b/frontend/projects/ui/src/app/app.component.html @@ -26,10 +26,7 @@ type="overlay" side="end" class="right-menu container" - [class.container_offline]=" - (authService.isVerified$ | async) && - !(connection.connected$ | async) - " + [class.container_offline]="offline$ | async" [class.right-menu_hidden]="!drawer.open" [style.--side-width.px]="drawer.width" > @@ -47,10 +44,7 @@ [responsiveColViewport]="viewport" id="main-content" class="container" - [class.container_offline]=" - (authService.isVerified$ | async) && - !(connection.connected$ | async) - " + [class.container_offline]="offline$ | async" > + verified && + (!connected || status.restarting || status['shutting-down']), + ), + ) constructor( private readonly titleService: Title, diff --git a/frontend/projects/ui/src/app/components/connection-bar/connection-bar.component.ts b/frontend/projects/ui/src/app/components/connection-bar/connection-bar.component.ts index dc5388b04..9c4b07b7f 100644 --- a/frontend/projects/ui/src/app/components/connection-bar/connection-bar.component.ts +++ b/frontend/projects/ui/src/app/components/connection-bar/connection-bar.component.ts @@ -1,6 +1,8 @@ import { ChangeDetectionStrategy, Component } from '@angular/core' +import { PatchDB } from 'patch-db-client' import { combineLatest, map, Observable, startWith } from 'rxjs' import { ConnectionService } from 'src/app/services/connection.service' +import { DataModel } from 'src/app/services/patch-db/data-model' @Component({ selector: 'connection-bar', @@ -19,8 +21,11 @@ export class ConnectionBarComponent { }> = combineLatest([ this.connectionService.networkConnected$, this.websocket$.pipe(startWith(false)), + this.patch + .watch$('server-info', 'status-info') + .pipe(startWith({ restarting: false, 'shutting-down': false })), ]).pipe( - map(([network, websocket]) => { + map(([network, websocket, status]) => { if (!network) return { message: 'No Internet', @@ -35,6 +40,20 @@ export class ConnectionBarComponent { icon: 'cloud-offline-outline', dots: true, } + if (status['shutting-down']) + return { + message: 'Shutting Down', + color: 'dark', + icon: 'power', + dots: true, + } + if (status.restarting) + return { + message: 'Restarting', + color: 'dark', + icon: 'power', + dots: true, + } return { message: 'Connected', @@ -45,5 +64,8 @@ export class ConnectionBarComponent { }), ) - constructor(private readonly connectionService: ConnectionService) {} + constructor( + private readonly connectionService: ConnectionService, + private readonly patch: PatchDB, + ) {} } diff --git a/frontend/projects/ui/src/app/pages/server-routes/server-show/server-show.page.ts b/frontend/projects/ui/src/app/pages/server-routes/server-show/server-show.page.ts index 401dc19c0..2b64fcf1c 100644 --- a/frontend/projects/ui/src/app/pages/server-routes/server-show/server-show.page.ts +++ b/frontend/projects/ui/src/app/pages/server-routes/server-show/server-show.page.ts @@ -352,7 +352,6 @@ export class ServerShowPage { try { await this.embassyApi.restartServer({}) - this.presentAlertInProgress(action, ` until ${action} completes.`) } catch (e: any) { this.errToast.present(e) } finally { @@ -370,10 +369,6 @@ export class ServerShowPage { try { await this.embassyApi.shutdownServer({}) - this.presentAlertInProgress( - action, - '.

You will need to physically power cycle the device to regain connectivity.', - ) } catch (e: any) { this.errToast.present(e) } finally { @@ -391,7 +386,6 @@ export class ServerShowPage { try { await this.embassyApi.systemRebuild({}) - this.presentAlertInProgress(action, ` until ${action} completes.`) } catch (e: any) { this.errToast.present(e) } finally { @@ -437,21 +431,6 @@ export class ServerShowPage { alert.present() } - private async presentAlertInProgress(verb: string, message: string) { - const alert = await this.alertCtrl.create({ - header: `${verb} In Progress...`, - message: `Stopping all services gracefully. This can take a while.

If you have a speaker, your server will ♫ play a melody ♫ before shutting down. Your server will then become unreachable${message}`, - buttons: [ - { - text: 'OK', - role: 'cancel', - cssClass: 'enter-click', - }, - ], - }) - alert.present() - } - settings: ServerSettings = { Backups: [ { diff --git a/frontend/projects/ui/src/app/services/api/api.fixures.ts b/frontend/projects/ui/src/app/services/api/api.fixures.ts index 67ddbd8d6..c4db1225d 100644 --- a/frontend/projects/ui/src/app/services/api/api.fixures.ts +++ b/frontend/projects/ui/src/app/services/api/api.fixures.ts @@ -17,6 +17,8 @@ export module Mock { 'backup-progress': null, 'update-progress': null, updated: true, + restarting: false, + 'shutting-down': false, } export const MarketplaceEos: RR.GetMarketplaceEosRes = { version: '0.3.5', diff --git a/frontend/projects/ui/src/app/services/api/embassy-mock-api.service.ts b/frontend/projects/ui/src/app/services/api/embassy-mock-api.service.ts index 96cc2941c..c98a4bd87 100644 --- a/frontend/projects/ui/src/app/services/api/embassy-mock-api.service.ts +++ b/frontend/projects/ui/src/app/services/api/embassy-mock-api.service.ts @@ -302,6 +302,27 @@ export class MockApiService extends ApiService { params: RR.RestartServerReq, ): Promise { await pauseFor(2000) + + const patch = [ + { + op: PatchOp.REPLACE, + path: '/server-info/status-info/restarting', + value: true, + }, + ] + this.mockRevision(patch) + + setTimeout(() => { + const patch2 = [ + { + op: PatchOp.REPLACE, + path: '/server-info/status-info/restarting', + value: false, + }, + ] + this.mockRevision(patch2) + }, 2000) + return null } @@ -309,14 +330,34 @@ export class MockApiService extends ApiService { params: RR.ShutdownServerReq, ): Promise { await pauseFor(2000) + + const patch = [ + { + op: PatchOp.REPLACE, + path: '/server-info/status-info/shutting-down', + value: true, + }, + ] + this.mockRevision(patch) + + setTimeout(() => { + const patch2 = [ + { + op: PatchOp.REPLACE, + path: '/server-info/status-info/shutting-down', + value: false, + }, + ] + this.mockRevision(patch2) + }, 2000) + return null } async systemRebuild( - params: RR.RestartServerReq, - ): Promise { - await pauseFor(2000) - return null + params: RR.SystemRebuildReq, + ): Promise { + return this.restartServer(params) } async repairDisk(params: RR.RestartServerReq): Promise { diff --git a/frontend/projects/ui/src/app/services/api/mock-patch.ts b/frontend/projects/ui/src/app/services/api/mock-patch.ts index 02faddeb7..0c930aa8f 100644 --- a/frontend/projects/ui/src/app/services/api/mock-patch.ts +++ b/frontend/projects/ui/src/app/services/api/mock-patch.ts @@ -66,6 +66,8 @@ export const mockPatchData: DataModel = { 'backup-progress': null, updated: false, 'update-progress': null, + restarting: false, + 'shutting-down': false, }, hostname: 'random-words', pubkey: 'npub1sg6plzptd64u62a878hep2kev88swjh3tw00gjsfl8f237lmu63q0uf63m', diff --git a/frontend/projects/ui/src/app/services/patch-db/data-model.ts b/frontend/projects/ui/src/app/services/patch-db/data-model.ts index ba2dd4de7..e4ea729d9 100644 --- a/frontend/projects/ui/src/app/services/patch-db/data-model.ts +++ b/frontend/projects/ui/src/app/services/patch-db/data-model.ts @@ -96,6 +96,8 @@ export interface ServerStatusInfo { } updated: boolean 'update-progress': { size: number | null; downloaded: number } | null + restarting: boolean + 'shutting-down': boolean } export enum ServerStatus { From 44643cbf0fa99a62134b60ffae9093b75a31e892 Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Tue, 7 Nov 2023 23:10:07 -0700 Subject: [PATCH 3/3] fix build --- backend/src/shutdown.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/shutdown.rs b/backend/src/shutdown.rs index 3196bc580..7a34d1e94 100644 --- a/backend/src/shutdown.rs +++ b/backend/src/shutdown.rs @@ -95,7 +95,7 @@ pub async fn shutdown(#[context] ctx: RpcContext) -> Result<(), Error> { .mutate(|db| { db.as_server_info_mut() .as_status_info_mut() - .as_shutting_down() + .as_shutting_down_mut() .ser(&true) }) .await?; @@ -115,7 +115,7 @@ pub async fn restart(#[context] ctx: RpcContext) -> Result<(), Error> { .mutate(|db| { db.as_server_info_mut() .as_status_info_mut() - .as_restarting() + .as_restarting_mut() .ser(&true) }) .await?;