mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 04:01:58 +00:00
Feature/callbacks (#2678)
* wip * initialize callbacks * wip * smtp * list_service_interfaces * wip * wip * fix domains * fix hostname handling in NetService * misc fixes * getInstalledPackages * misc fixes * publish v6 lib * refactor service effects * fix import * fix container runtime * fix tests * apply suggestions from review
This commit is contained in:
@@ -3,8 +3,8 @@ import * as fs from "fs/promises"
|
||||
|
||||
import { polyfillEffects } from "./polyfillEffects"
|
||||
import { Duration, duration, fromDuration } from "../../../Models/Duration"
|
||||
import { System } from "../../../Interfaces/System"
|
||||
import { matchManifest, Manifest, Procedure } from "./matchManifest"
|
||||
import { System, Procedure } from "../../../Interfaces/System"
|
||||
import { matchManifest, Manifest } from "./matchManifest"
|
||||
import * as childProcess from "node:child_process"
|
||||
import { DockerProcedureContainer } from "./DockerProcedureContainer"
|
||||
import { promisify } from "node:util"
|
||||
@@ -27,7 +27,6 @@ import {
|
||||
Parser,
|
||||
array,
|
||||
} from "ts-matches"
|
||||
import { hostSystemStartOs } from "../../HostSystemStartOs"
|
||||
import { JsonPath, unNestPath } from "../../../Models/JsonPath"
|
||||
import { RpcResult, matchRpcResult } from "../../RpcListener"
|
||||
import { CT } from "@start9labs/start-sdk"
|
||||
@@ -48,6 +47,7 @@ import {
|
||||
transformConfigSpec,
|
||||
transformOldConfigToNew,
|
||||
} from "./transformConfigSpec"
|
||||
import { MainEffects } from "@start9labs/start-sdk/cjs/lib/StartSdk"
|
||||
|
||||
type Optional<A> = A | undefined | null
|
||||
function todo(): never {
|
||||
@@ -203,16 +203,39 @@ export class SystemForEmbassy implements System {
|
||||
readonly manifest: Manifest,
|
||||
readonly moduleCode: Partial<U.ExpectedExports>,
|
||||
) {}
|
||||
|
||||
async init(): Promise<void> {}
|
||||
|
||||
async exit(): Promise<void> {
|
||||
if (this.currentRunning) await this.currentRunning.clean()
|
||||
delete this.currentRunning
|
||||
}
|
||||
|
||||
async start(effects: MainEffects): Promise<void> {
|
||||
if (!!this.currentRunning) return
|
||||
|
||||
this.currentRunning = await MainLoop.of(this, effects)
|
||||
}
|
||||
callCallback(_callback: number, _args: any[]): void {}
|
||||
async stop(): Promise<void> {
|
||||
const { currentRunning } = this
|
||||
this.currentRunning?.clean()
|
||||
delete this.currentRunning
|
||||
if (currentRunning) {
|
||||
await currentRunning.clean({
|
||||
timeout: fromDuration(this.manifest.main["sigterm-timeout"] || "30s"),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async execute(
|
||||
effectCreator: ReturnType<typeof hostSystemStartOs>,
|
||||
effects: Effects,
|
||||
options: {
|
||||
id: string
|
||||
procedure: JsonPath
|
||||
input: unknown
|
||||
timeout?: number | undefined
|
||||
},
|
||||
): Promise<RpcResult> {
|
||||
const effects = effectCreator(options.id)
|
||||
return this._execute(effects, options)
|
||||
.then((x) =>
|
||||
matches(x)
|
||||
@@ -267,10 +290,6 @@ export class SystemForEmbassy implements System {
|
||||
}
|
||||
})
|
||||
}
|
||||
async exit(): Promise<void> {
|
||||
if (this.currentRunning) await this.currentRunning.clean()
|
||||
delete this.currentRunning
|
||||
}
|
||||
async _execute(
|
||||
effects: Effects,
|
||||
options: {
|
||||
@@ -294,7 +313,7 @@ export class SystemForEmbassy implements System {
|
||||
case "/actions/metadata":
|
||||
return todo()
|
||||
case "/init":
|
||||
return this.init(
|
||||
return this.initProcedure(
|
||||
effects,
|
||||
string.optional().unsafeCast(input),
|
||||
options.timeout || null,
|
||||
@@ -305,10 +324,6 @@ export class SystemForEmbassy implements System {
|
||||
string.optional().unsafeCast(input),
|
||||
options.timeout || null,
|
||||
)
|
||||
case "/main/start":
|
||||
return this.mainStart(effects, options.timeout || null)
|
||||
case "/main/stop":
|
||||
return this.mainStop(effects, options.timeout || null)
|
||||
default:
|
||||
const procedures = unNestPath(options.procedure)
|
||||
switch (true) {
|
||||
@@ -345,7 +360,14 @@ export class SystemForEmbassy implements System {
|
||||
}
|
||||
throw new Error(`Could not find the path for ${options.procedure}`)
|
||||
}
|
||||
private async init(
|
||||
async sandbox(
|
||||
effects: Effects,
|
||||
options: { procedure: Procedure; input: unknown; timeout?: number },
|
||||
): Promise<RpcResult> {
|
||||
return this.execute(effects, options)
|
||||
}
|
||||
|
||||
private async initProcedure(
|
||||
effects: Effects,
|
||||
previousVersion: Optional<string>,
|
||||
timeoutMs: number | null,
|
||||
@@ -470,42 +492,22 @@ export class SystemForEmbassy implements System {
|
||||
// TODO Do a migration down if the version exists
|
||||
await effects.setMainStatus({ status: "stopped" })
|
||||
}
|
||||
private async mainStart(
|
||||
effects: Effects,
|
||||
timeoutMs: number | null,
|
||||
): Promise<void> {
|
||||
if (!!this.currentRunning) return
|
||||
|
||||
this.currentRunning = new MainLoop(this, effects)
|
||||
}
|
||||
private async mainStop(
|
||||
effects: Effects,
|
||||
timeoutMs: number | null,
|
||||
): Promise<void> {
|
||||
try {
|
||||
const { currentRunning } = this
|
||||
this.currentRunning?.clean()
|
||||
delete this.currentRunning
|
||||
if (currentRunning) {
|
||||
await currentRunning.clean({
|
||||
timeout: utils.inMs(this.manifest.main["sigterm-timeout"]),
|
||||
})
|
||||
}
|
||||
return
|
||||
} finally {
|
||||
await effects.setMainStatus({ status: "stopped" })
|
||||
}
|
||||
}
|
||||
private async createBackup(
|
||||
effects: Effects,
|
||||
timeoutMs: number | null,
|
||||
): Promise<void> {
|
||||
const backup = this.manifest.backup.create
|
||||
if (backup.type === "docker") {
|
||||
const container = await DockerProcedureContainer.of(effects, backup, {
|
||||
...this.manifest.volumes,
|
||||
BACKUP: { type: "backup", readonly: false },
|
||||
})
|
||||
const container = await DockerProcedureContainer.of(
|
||||
effects,
|
||||
this.manifest.id,
|
||||
backup,
|
||||
{
|
||||
...this.manifest.volumes,
|
||||
BACKUP: { type: "backup", readonly: false },
|
||||
},
|
||||
)
|
||||
await container.execFail([backup.entrypoint, ...backup.args], timeoutMs)
|
||||
} else {
|
||||
const moduleCode = await this.moduleCode
|
||||
@@ -520,6 +522,7 @@ export class SystemForEmbassy implements System {
|
||||
if (restoreBackup.type === "docker") {
|
||||
const container = await DockerProcedureContainer.of(
|
||||
effects,
|
||||
this.manifest.id,
|
||||
restoreBackup,
|
||||
{
|
||||
...this.manifest.volumes,
|
||||
@@ -552,6 +555,7 @@ export class SystemForEmbassy implements System {
|
||||
if (config.type === "docker") {
|
||||
const container = await DockerProcedureContainer.of(
|
||||
effects,
|
||||
this.manifest.id,
|
||||
config,
|
||||
this.manifest.volumes,
|
||||
)
|
||||
@@ -594,6 +598,7 @@ export class SystemForEmbassy implements System {
|
||||
if (setConfigValue.type === "docker") {
|
||||
const container = await DockerProcedureContainer.of(
|
||||
effects,
|
||||
this.manifest.id,
|
||||
setConfigValue,
|
||||
this.manifest.volumes,
|
||||
)
|
||||
@@ -702,6 +707,7 @@ export class SystemForEmbassy implements System {
|
||||
if (procedure.type === "docker") {
|
||||
const container = await DockerProcedureContainer.of(
|
||||
effects,
|
||||
this.manifest.id,
|
||||
procedure,
|
||||
this.manifest.volumes,
|
||||
)
|
||||
@@ -744,6 +750,7 @@ export class SystemForEmbassy implements System {
|
||||
if (setConfigValue.type === "docker") {
|
||||
const container = await DockerProcedureContainer.of(
|
||||
effects,
|
||||
this.manifest.id,
|
||||
setConfigValue,
|
||||
this.manifest.volumes,
|
||||
)
|
||||
@@ -785,6 +792,7 @@ export class SystemForEmbassy implements System {
|
||||
if (actionProcedure.type === "docker") {
|
||||
const container = await DockerProcedureContainer.of(
|
||||
effects,
|
||||
this.manifest.id,
|
||||
actionProcedure,
|
||||
this.manifest.volumes,
|
||||
)
|
||||
@@ -825,6 +833,7 @@ export class SystemForEmbassy implements System {
|
||||
if (actionProcedure.type === "docker") {
|
||||
const container = await DockerProcedureContainer.of(
|
||||
effects,
|
||||
this.manifest.id,
|
||||
actionProcedure,
|
||||
this.manifest.volumes,
|
||||
)
|
||||
@@ -1039,15 +1048,15 @@ async function updateConfig(
|
||||
}
|
||||
}
|
||||
const url: string =
|
||||
filled === null
|
||||
filled === null || filled.addressInfo === null
|
||||
? ""
|
||||
: catchFn(() =>
|
||||
utils.hostnameInfoToAddress(
|
||||
specValue.target === "lan-address"
|
||||
? filled.addressInfo.localHostnames[0] ||
|
||||
filled.addressInfo.onionHostnames[0]
|
||||
: filled.addressInfo.onionHostnames[0] ||
|
||||
filled.addressInfo.localHostnames[0],
|
||||
? filled.addressInfo!.localHostnames[0] ||
|
||||
filled.addressInfo!.onionHostnames[0]
|
||||
: filled.addressInfo!.onionHostnames[0] ||
|
||||
filled.addressInfo!.localHostnames[0],
|
||||
),
|
||||
) || ""
|
||||
mutConfigValue[key] = url
|
||||
|
||||
Reference in New Issue
Block a user