misc bugfixes for alpha.4 (#2953)

* fix lockup when stop during init

* Fix incorrect description for registry package remove command

* alpha.5

* beta.25

---------

Co-authored-by: Mariusz Kogen <k0gen@pm.me>
This commit is contained in:
Aiden McClelland
2025-05-23 11:23:29 -06:00
committed by GitHub
parent b1f9f90fec
commit 90e61989a4
19 changed files with 120 additions and 85 deletions

View File

@@ -37,7 +37,7 @@
}, },
"../sdk/dist": { "../sdk/dist": {
"name": "@start9labs/start-sdk", "name": "@start9labs/start-sdk",
"version": "0.4.0-beta.24", "version": "0.4.0-beta.25",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@iarna/toml": "^3.0.0", "@iarna/toml": "^3.0.0",

View File

@@ -324,6 +324,7 @@ export class RpcListener {
}), }),
) )
const callbacks = this.callbacks.child("init") const callbacks = this.callbacks.child("init")
console.error("Initializing...")
await system.init( await system.init(
makeEffects({ makeEffects({
procedureId: params.id, procedureId: params.id,
@@ -331,6 +332,7 @@ export class RpcListener {
}), }),
params.kind, params.kind,
) )
console.error("Initialization complete.")
this._system = system this._system = system
} }
})().then((result) => ({ result })), })().then((result) => ({ result })),

2
core/Cargo.lock generated
View File

@@ -6023,7 +6023,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]] [[package]]
name = "start-os" name = "start-os"
version = "0.4.0-alpha.4" version = "0.4.0-alpha.5"
dependencies = [ dependencies = [
"aes 0.7.5", "aes 0.7.5",
"async-acme", "async-acme",

View File

@@ -14,7 +14,7 @@ keywords = [
name = "start-os" name = "start-os"
readme = "README.md" readme = "README.md"
repository = "https://github.com/Start9Labs/start-os" repository = "https://github.com/Start9Labs/start-os"
version = "0.4.0-alpha.4" # VERSION_BUMP version = "0.4.0-alpha.5" # VERSION_BUMP
license = "MIT" license = "MIT"
[lib] [lib]

View File

@@ -31,13 +31,12 @@ pub async fn start(ctx: RpcContext, ControlParams { id }: ControlParams) -> Resu
} }
pub async fn stop(ctx: RpcContext, ControlParams { id }: ControlParams) -> Result<(), Error> { pub async fn stop(ctx: RpcContext, ControlParams { id }: ControlParams) -> Result<(), Error> {
// TODO: why did this return last_status before?
ctx.services ctx.services
.get(&id) .get(&id)
.await .await
.as_ref() .as_ref()
.ok_or_else(|| Error::new(eyre!("Manager not found"), crate::ErrorKind::InvalidRequest))? .ok_or_else(|| Error::new(eyre!("Manager not found"), crate::ErrorKind::InvalidRequest))?
.stop(Guid::new()) .stop(Guid::new(), true)
.await?; .await?;
Ok(()) Ok(())

View File

@@ -35,7 +35,7 @@ pub fn package_api<C: Context>() -> ParentHandler<C> {
"remove", "remove",
from_fn_async(add::remove_package) from_fn_async(add::remove_package)
.no_display() .no_display()
.with_about("Add package to registry index") .with_about("Remove package from registry index")
.with_call_remote::<CliContext>(), .with_call_remote::<CliContext>(),
) )
.subcommand( .subcommand(

View File

@@ -1,3 +1,5 @@
use futures::future::OptionFuture;
use crate::prelude::*; use crate::prelude::*;
use crate::rpc_continuations::Guid; use crate::rpc_continuations::Guid;
use crate::service::action::RunAction; use crate::service::action::RunAction;
@@ -26,13 +28,20 @@ impl Service {
} }
} }
struct Stop; struct Stop {
wait: bool,
}
impl Handler<Stop> for ServiceActor { impl Handler<Stop> for ServiceActor {
type Response = (); type Response = ();
fn conflicts_with(_: &Stop) -> ConflictBuilder<Self> { fn conflicts_with(_: &Stop) -> ConflictBuilder<Self> {
ConflictBuilder::everything().except::<RunAction>() ConflictBuilder::everything().except::<RunAction>()
} }
async fn handle(&mut self, _: Guid, _: Stop, _: &BackgroundJobQueue) -> Self::Response { async fn handle(
&mut self,
_: Guid,
Stop { wait }: Stop,
_: &BackgroundJobQueue,
) -> Self::Response {
let mut transition_state = None; let mut transition_state = None;
self.0.persistent_container.state.send_modify(|x| { self.0.persistent_container.state.send_modify(|x| {
x.desired_state = StartStop::Stop; x.desired_state = StartStop::Stop;
@@ -40,14 +49,19 @@ impl Handler<Stop> for ServiceActor {
transition_state = std::mem::take(&mut x.transition_state); transition_state = std::mem::take(&mut x.transition_state);
} }
}); });
let notif = if wait {
Some(self.0.synchronized.notified())
} else {
None
};
if let Some(restart) = transition_state { if let Some(restart) = transition_state {
restart.abort().await; restart.abort().await;
} }
self.0.synchronized.notified().await OptionFuture::from(notif).await;
} }
} }
impl Service { impl Service {
pub async fn stop(&self, id: Guid) -> Result<(), Error> { pub async fn stop(&self, id: Guid, wait: bool) -> Result<(), Error> {
self.actor.send(id, Stop).await self.actor.send(id, Stop { wait }).await
} }
} }

View File

@@ -262,7 +262,7 @@ async fn create_task(
None => true, None => true,
}; };
if active && task.severity == TaskSeverity::Critical { if active && task.severity == TaskSeverity::Critical {
context.stop(procedure_id).await?; context.stop(procedure_id, false).await?;
} }
context context
.seed .seed

View File

@@ -35,7 +35,7 @@ pub async fn shutdown(
ProcedureId { procedure_id }: ProcedureId, ProcedureId { procedure_id }: ProcedureId,
) -> Result<(), Error> { ) -> Result<(), Error> {
let context = context.deref()?; let context = context.deref()?;
context.stop(procedure_id).await?; context.stop(procedure_id, false).await?;
Ok(()) Ok(())
} }

View File

@@ -44,8 +44,9 @@ mod v0_4_0_alpha_1;
mod v0_4_0_alpha_2; mod v0_4_0_alpha_2;
mod v0_4_0_alpha_3; mod v0_4_0_alpha_3;
mod v0_4_0_alpha_4; mod v0_4_0_alpha_4;
mod v0_4_0_alpha_5;
pub type Current = v0_4_0_alpha_4::Version; // VERSION_BUMP pub type Current = v0_4_0_alpha_5::Version; // VERSION_BUMP
impl Current { impl Current {
#[instrument(skip(self, db))] #[instrument(skip(self, db))]
@@ -153,7 +154,8 @@ enum Version {
V0_4_0_alpha_1(Wrapper<v0_4_0_alpha_1::Version>), V0_4_0_alpha_1(Wrapper<v0_4_0_alpha_1::Version>),
V0_4_0_alpha_2(Wrapper<v0_4_0_alpha_2::Version>), V0_4_0_alpha_2(Wrapper<v0_4_0_alpha_2::Version>),
V0_4_0_alpha_3(Wrapper<v0_4_0_alpha_3::Version>), V0_4_0_alpha_3(Wrapper<v0_4_0_alpha_3::Version>),
V0_4_0_alpha_4(Wrapper<v0_4_0_alpha_4::Version>), // VERSION_BUMP V0_4_0_alpha_4(Wrapper<v0_4_0_alpha_4::Version>),
V0_4_0_alpha_5(Wrapper<v0_4_0_alpha_5::Version>), // VERSION_BUMP
Other(exver::Version), Other(exver::Version),
} }
@@ -200,7 +202,8 @@ impl Version {
Self::V0_4_0_alpha_1(v) => DynVersion(Box::new(v.0)), Self::V0_4_0_alpha_1(v) => DynVersion(Box::new(v.0)),
Self::V0_4_0_alpha_2(v) => DynVersion(Box::new(v.0)), Self::V0_4_0_alpha_2(v) => DynVersion(Box::new(v.0)),
Self::V0_4_0_alpha_3(v) => DynVersion(Box::new(v.0)), Self::V0_4_0_alpha_3(v) => DynVersion(Box::new(v.0)),
Self::V0_4_0_alpha_4(v) => DynVersion(Box::new(v.0)), // VERSION_BUMP Self::V0_4_0_alpha_4(v) => DynVersion(Box::new(v.0)),
Self::V0_4_0_alpha_5(v) => DynVersion(Box::new(v.0)), // VERSION_BUMP
Self::Other(v) => { Self::Other(v) => {
return Err(Error::new( return Err(Error::new(
eyre!("unknown version {v}"), eyre!("unknown version {v}"),
@@ -239,7 +242,8 @@ impl Version {
Version::V0_4_0_alpha_1(Wrapper(x)) => x.semver(), Version::V0_4_0_alpha_1(Wrapper(x)) => x.semver(),
Version::V0_4_0_alpha_2(Wrapper(x)) => x.semver(), Version::V0_4_0_alpha_2(Wrapper(x)) => x.semver(),
Version::V0_4_0_alpha_3(Wrapper(x)) => x.semver(), Version::V0_4_0_alpha_3(Wrapper(x)) => x.semver(),
Version::V0_4_0_alpha_4(Wrapper(x)) => x.semver(), // VERSION_BUMP Version::V0_4_0_alpha_4(Wrapper(x)) => x.semver(),
Version::V0_4_0_alpha_5(Wrapper(x)) => x.semver(), // VERSION_BUMP
Version::Other(x) => x.clone(), Version::Other(x) => x.clone(),
} }
} }

View File

@@ -0,0 +1,38 @@
use exver::{PreReleaseSegment, VersionRange};
use super::v0_3_5::V0_3_0_COMPAT;
use super::{v0_4_0_alpha_4, VersionT};
use crate::context::RpcContext;
use crate::prelude::*;
lazy_static::lazy_static! {
static ref V0_4_0_alpha_5: exver::Version = exver::Version::new(
[0, 4, 0],
[PreReleaseSegment::String("alpha".into()), 5.into()]
);
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Version;
impl VersionT for Version {
type Previous = v0_4_0_alpha_4::Version;
type PreUpRes = ();
async fn pre_up(self) -> Result<Self::PreUpRes, Error> {
Ok(())
}
fn semver(self) -> exver::Version {
V0_4_0_alpha_5.clone()
}
fn compat(self) -> &'static VersionRange {
&V0_3_0_COMPAT
}
#[instrument]
fn up(self, _db: &mut Value, _: Self::PreUpRes) -> Result<(), Error> {
Ok(())
}
fn down(self, _db: &mut Value) -> Result<(), Error> {
Ok(())
}
}

View File

@@ -51,41 +51,3 @@ export function setupOnInit(onInit: InitScriptOrFn): InitScript {
}, },
} }
} }
export function setupOnInstall(
onInstall: InitScriptOrFn<"install">,
): InitScript {
return {
init: async (effects, kind) => {
if (kind === "install") {
if ("init" in onInstall) await onInstall.init(effects, kind)
else await onInstall(effects, kind)
}
},
}
}
export function setupOnUpdate(onUpdate: InitScriptOrFn<"update">): InitScript {
return {
init: async (effects, kind) => {
if (kind === "update") {
if ("init" in onUpdate) await onUpdate.init(effects, kind)
else await onUpdate(effects, kind)
}
},
}
}
export function setupOnInstallOrUpdate(
onInstallOrUpdate: InitScriptOrFn<"install" | "update">,
): InitScript {
return {
init: async (effects, kind) => {
if (kind === "install" || kind === "update") {
if ("init" in onInstallOrUpdate)
await onInstallOrUpdate.init(effects, kind)
else await onInstallOrUpdate(effects, kind)
}
},
}
}

View File

@@ -3,18 +3,34 @@ import * as T from "../../../base/lib/types"
export type UninitFn = ( export type UninitFn = (
effects: T.Effects, effects: T.Effects,
/**
* @description the target version to prepare for
*
* on update: the canMigrateFrom of the new package
* on uninstall: null
* on shutdown: the current version
*/
target: VersionRange | ExtendedVersion | null, target: VersionRange | ExtendedVersion | null,
) => Promise<void | null | undefined> ) => Promise<void | null | undefined>
export interface UninitScript { export interface UninitScript {
uninit( uninit(
effects: T.Effects, effects: T.Effects,
/**
* @description the target version to prepare for
*
* on update: the canMigrateFrom of the new package
* on uninstall: null
* on shutdown: the current version
*/
target: VersionRange | ExtendedVersion | null, target: VersionRange | ExtendedVersion | null,
): Promise<void> ): Promise<void>
} }
export type UninitScriptOrFn = UninitScript | UninitFn
export function setupUninit( export function setupUninit(
...uninits: (UninitScript | UninitFn)[] ...uninits: UninitScriptOrFn[]
): T.ExpectedExports.uninit { ): T.ExpectedExports.uninit {
return async (opts) => { return async (opts) => {
for (const uninit of uninits) { for (const uninit of uninits) {
@@ -23,3 +39,13 @@ export function setupUninit(
} }
} }
} }
export function setupOnUninit(onUninit: UninitScriptOrFn): UninitScript {
return "uninit" in onUninit
? onUninit
: {
uninit: async (effects, target) => {
await onUninit(effects, target)
},
}
}

View File

@@ -64,13 +64,11 @@ import * as fs from "node:fs/promises"
import { import {
setupInit, setupInit,
setupUninit, setupUninit,
setupOnInstall,
setupOnUpdate,
setupOnInstallOrUpdate,
setupOnInit, setupOnInit,
setupOnUninit,
} from "../../base/lib/inits" } from "../../base/lib/inits"
export const OSVersion = testTypeVersion("0.4.0-alpha.4") export const OSVersion = testTypeVersion("0.4.0-alpha.5")
// prettier-ignore // prettier-ignore
type AnyNeverCond<T extends any[], Then, Else> = type AnyNeverCond<T extends any[], Then, Else> =
@@ -506,21 +504,13 @@ export class StartSdk<Manifest extends T.SDKManifest> {
*/ */
setupDependencies: setupDependencies<Manifest>, setupDependencies: setupDependencies<Manifest>,
/** /**
* @description Use this function to create an InitScript that runs every time the service initializes * @description Use this function to create an InitScript that runs every time the service initializes (install, update, restore, rebuild, and server bootup)
*/ */
setupOnInit, setupOnInit,
/** /**
* @description Use this function to create an InitScript that runs only when the service is freshly installed * @description Use this function to create an UninitScript that runs every time the service uninitializes (update, uninstall, and server shutdown)
*/ */
setupOnInstall, setupOnUninit,
/**
* @description Use this function to create an InitScript that runs only when the service is updated
*/
setupOnUpdate,
/**
* @description Use this function to create an InitScript that runs only when the service is installed or updated
*/
setupOnInstallOrUpdate,
/** /**
* @description Use this function to setup what happens when the service initializes. * @description Use this function to setup what happens when the service initializes.
* *

View File

@@ -1,12 +1,12 @@
{ {
"name": "@start9labs/start-sdk", "name": "@start9labs/start-sdk",
"version": "0.4.0-beta.24", "version": "0.4.0-beta.25",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@start9labs/start-sdk", "name": "@start9labs/start-sdk",
"version": "0.4.0-beta.24", "version": "0.4.0-beta.25",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@iarna/toml": "^3.0.0", "@iarna/toml": "^3.0.0",

View File

@@ -1,6 +1,6 @@
{ {
"name": "@start9labs/start-sdk", "name": "@start9labs/start-sdk",
"version": "0.4.0-beta.24", "version": "0.4.0-beta.25",
"description": "Software development kit to facilitate packaging services for StartOS", "description": "Software development kit to facilitate packaging services for StartOS",
"main": "./package/lib/index.js", "main": "./package/lib/index.js",
"types": "./package/lib/index.d.ts", "types": "./package/lib/index.d.ts",

4
web/package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "startos-ui", "name": "startos-ui",
"version": "0.4.0-alpha.4", "version": "0.4.0-alpha.5",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "startos-ui", "name": "startos-ui",
"version": "0.4.0-alpha.4", "version": "0.4.0-alpha.5",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@angular/animations": "^17.3.1", "@angular/animations": "^17.3.1",

View File

@@ -1,6 +1,6 @@
{ {
"name": "startos-ui", "name": "startos-ui",
"version": "0.4.0-alpha.4", "version": "0.4.0-alpha.5",
"author": "Start9 Labs, Inc", "author": "Start9 Labs, Inc",
"homepage": "https://start9.com/", "homepage": "https://start9.com/",
"license": "MIT", "license": "MIT",

View File

@@ -101,16 +101,16 @@ export namespace Mock {
}, },
img: {}, img: {},
}, },
'0.4.0-alpha.4': { '0.4.0-alpha.5': {
headline: 'v0.4.0-alpha.4', headline: 'v0.4.0-alpha.5',
releaseNotes: '', releaseNotes: '',
sourceVersion: '>=0.3.5:0 <=0.4.0-alpha.4:0', sourceVersion: '>=0.3.5:0 <=0.4.0-alpha.5:0',
authorized: ['G24CSA5HNYEPIXJNMK7ZM4KD5SX5N6X4'], authorized: ['G24CSA5HNYEPIXJNMK7ZM4KD5SX5N6X4'],
iso: {}, iso: {},
squashfs: { squashfs: {
aarch64: { aarch64: {
publishedAt: '2025-04-21T20:58:48.140749883Z', publishedAt: '2025-04-21T20:58:48.140749883Z',
url: 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.4/startos-0.4.0-alpha.4-33ae46f~dev_aarch64.squashfs', url: 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.5/startos-0.4.0-alpha.5-33ae46f~dev_aarch64.squashfs',
commitment: { commitment: {
hash: '4elBFVkd/r8hNadKmKtLIs42CoPltMvKe2z3LRqkphk=', hash: '4elBFVkd/r8hNadKmKtLIs42CoPltMvKe2z3LRqkphk=',
size: 1343500288, size: 1343500288,
@@ -122,7 +122,7 @@ export namespace Mock {
}, },
'aarch64-nonfree': { 'aarch64-nonfree': {
publishedAt: '2025-04-21T21:07:00.249285116Z', publishedAt: '2025-04-21T21:07:00.249285116Z',
url: 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.4/startos-0.4.0-alpha.4-33ae46f~dev_aarch64-nonfree.squashfs', url: 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.5/startos-0.4.0-alpha.5-33ae46f~dev_aarch64-nonfree.squashfs',
commitment: { commitment: {
hash: 'MrCEi4jxbmPS7zAiGk/JSKlMsiuKqQy6RbYOxlGHOIQ=', hash: 'MrCEi4jxbmPS7zAiGk/JSKlMsiuKqQy6RbYOxlGHOIQ=',
size: 1653075968, size: 1653075968,
@@ -134,7 +134,7 @@ export namespace Mock {
}, },
raspberrypi: { raspberrypi: {
publishedAt: '2025-04-21T21:16:12.933319237Z', publishedAt: '2025-04-21T21:16:12.933319237Z',
url: 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.4/startos-0.4.0-alpha.4-33ae46f~dev_raspberrypi.squashfs', url: 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.5/startos-0.4.0-alpha.5-33ae46f~dev_raspberrypi.squashfs',
commitment: { commitment: {
hash: '/XTVQRCqY3RK544PgitlKu7UplXjkmzWoXUh2E4HCw0=', hash: '/XTVQRCqY3RK544PgitlKu7UplXjkmzWoXUh2E4HCw0=',
size: 1490731008, size: 1490731008,
@@ -146,7 +146,7 @@ export namespace Mock {
}, },
x86_64: { x86_64: {
publishedAt: '2025-04-21T21:14:20.246908903Z', publishedAt: '2025-04-21T21:14:20.246908903Z',
url: 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.4/startos-0.4.0-alpha.4-33ae46f~dev_x86_64.squashfs', url: 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.5/startos-0.4.0-alpha.5-33ae46f~dev_x86_64.squashfs',
commitment: { commitment: {
hash: '/6romKTVQGSaOU7FqSZdw0kFyd7P+NBSYNwM3q7Fe44=', hash: '/6romKTVQGSaOU7FqSZdw0kFyd7P+NBSYNwM3q7Fe44=',
size: 1411657728, size: 1411657728,
@@ -158,7 +158,7 @@ export namespace Mock {
}, },
'x86_64-nonfree': { 'x86_64-nonfree': {
publishedAt: '2025-04-21T21:15:17.955265284Z', publishedAt: '2025-04-21T21:15:17.955265284Z',
url: 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.4/startos-0.4.0-alpha.4-33ae46f~dev_x86_64-nonfree.squashfs', url: 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.5/startos-0.4.0-alpha.5-33ae46f~dev_x86_64-nonfree.squashfs',
commitment: { commitment: {
hash: 'HCRq9sr/0t85pMdrEgNBeM4x11zVKHszGnD1GDyZbSE=', hash: 'HCRq9sr/0t85pMdrEgNBeM4x11zVKHszGnD1GDyZbSE=',
size: 1731035136, size: 1731035136,