mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 02:11:53 +00:00
add start/stop/restart to effects
fix: add a default always to the get status chore: Only do updates when the thing is installed. chore: Make the thing buildable for testing chore: Add in the debugging chore: Remove the bluj tracing chore: Fix the build Chore: Make these fn's instead of allways ran. chore: Fix the testing fix: The stopping/ restarting service fix: Fix the restarting.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
use std::future::Future;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::time::Duration;
|
||||
|
||||
@@ -93,6 +94,17 @@ impl<T> Future for NonDetachingJoinHandle<T> {
|
||||
this.0.poll(cx)
|
||||
}
|
||||
}
|
||||
impl<T> Deref for NonDetachingJoinHandle<T> {
|
||||
type Target = JoinHandle<T>;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
impl<T> DerefMut for NonDetachingJoinHandle<T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AtomicFile {
|
||||
tmp_path: PathBuf,
|
||||
|
||||
@@ -76,8 +76,8 @@ pub trait OsApi: Send + Sync + 'static {
|
||||
|
||||
async fn unbind_local(&self, id: InterfaceId, external: u16) -> Result<(), Report>;
|
||||
async fn unbind_onion(&self, id: InterfaceId, external: u16) -> Result<(), Report>;
|
||||
fn set_started(&self) -> Result<(), Report>;
|
||||
async fn restart(&self) -> Result<(), Report>;
|
||||
async fn start(&self) -> Result<(), Report>;
|
||||
async fn stop(&self) -> Result<(), Report>;
|
||||
fn set_started(&self);
|
||||
async fn restart(&self);
|
||||
async fn start(&self);
|
||||
async fn stop(&self);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import Deno from "/deno_global.js";
|
||||
import * as mainModule from "/embassy.js";
|
||||
|
||||
// throw new Error("I'm going crasy")
|
||||
|
||||
function requireParam(param) {
|
||||
throw new Error(`Missing required parameter ${param}`);
|
||||
}
|
||||
@@ -49,10 +47,8 @@ const writeFile = (
|
||||
) => Deno.core.opAsync("write_file", volumeId, path, toWrite);
|
||||
|
||||
const readFile = (
|
||||
{
|
||||
volumeId = requireParam("volumeId"),
|
||||
path = requireParam("path"),
|
||||
} = requireParam("options"),
|
||||
{ volumeId = requireParam("volumeId"), path = requireParam("path") } =
|
||||
requireParam("options"),
|
||||
) => Deno.core.opAsync("read_file", volumeId, path);
|
||||
|
||||
const runDaemon = (
|
||||
@@ -74,11 +70,8 @@ const runDaemon = (
|
||||
};
|
||||
};
|
||||
const runCommand = async (
|
||||
{
|
||||
command = requireParam("command"),
|
||||
args = [],
|
||||
timeoutMillis = 30000,
|
||||
} = requireParam("options"),
|
||||
{ command = requireParam("command"), args = [], timeoutMillis = 30000 } =
|
||||
requireParam("options"),
|
||||
) => {
|
||||
let id = Deno.core.opAsync(
|
||||
"start_command",
|
||||
@@ -128,10 +121,8 @@ const rename = (
|
||||
} = requireParam("options"),
|
||||
) => Deno.core.opAsync("rename", srcVolume, srcPath, dstVolume, dstPath);
|
||||
const metadata = async (
|
||||
{
|
||||
volumeId = requireParam("volumeId"),
|
||||
path = requireParam("path"),
|
||||
} = requireParam("options"),
|
||||
{ volumeId = requireParam("volumeId"), path = requireParam("path") } =
|
||||
requireParam("options"),
|
||||
) => {
|
||||
const data = await Deno.core.opAsync("metadata", volumeId, path);
|
||||
return {
|
||||
@@ -142,10 +133,8 @@ const metadata = async (
|
||||
};
|
||||
};
|
||||
const removeFile = (
|
||||
{
|
||||
volumeId = requireParam("volumeId"),
|
||||
path = requireParam("path"),
|
||||
} = requireParam("options"),
|
||||
{ volumeId = requireParam("volumeId"), path = requireParam("path") } =
|
||||
requireParam("options"),
|
||||
) => Deno.core.opAsync("remove_file", volumeId, path);
|
||||
const isSandboxed = () => Deno.core.opSync("is_sandboxed");
|
||||
|
||||
@@ -182,26 +171,20 @@ const chmod = async (
|
||||
return await Deno.core.opAsync("chmod", volumeId, path, mode);
|
||||
};
|
||||
const readJsonFile = async (
|
||||
{
|
||||
volumeId = requireParam("volumeId"),
|
||||
path = requireParam("path"),
|
||||
} = requireParam("options"),
|
||||
{ volumeId = requireParam("volumeId"), path = requireParam("path") } =
|
||||
requireParam("options"),
|
||||
) => JSON.parse(await readFile({ volumeId, path }));
|
||||
const createDir = (
|
||||
{
|
||||
volumeId = requireParam("volumeId"),
|
||||
path = requireParam("path"),
|
||||
} = requireParam("options"),
|
||||
{ volumeId = requireParam("volumeId"), path = requireParam("path") } =
|
||||
requireParam("options"),
|
||||
) => Deno.core.opAsync("create_dir", volumeId, path);
|
||||
|
||||
const readDir = (
|
||||
{ volumeId = requireParam("volumeId"), path = requireParam("path") } = requireParam("options"),
|
||||
) => Deno.core.opAsync("read_dir", volumeId, path);
|
||||
const removeDir = (
|
||||
{
|
||||
volumeId = requireParam("volumeId"),
|
||||
path = requireParam("path"),
|
||||
} = requireParam("options"),
|
||||
{ volumeId = requireParam("volumeId"), path = requireParam("path") } =
|
||||
requireParam("options"),
|
||||
) => Deno.core.opAsync("remove_dir", volumeId, path);
|
||||
const trace = (whatToTrace = requireParam("whatToTrace")) =>
|
||||
Deno.core.opAsync("log_trace", whatToTrace);
|
||||
@@ -276,15 +259,10 @@ const getServiceConfig = async (
|
||||
);
|
||||
};
|
||||
|
||||
const setPermissions = async (
|
||||
{
|
||||
volumeId = requireParam("volumeId"),
|
||||
path = requireParam("path"),
|
||||
readonly = requireParam("readonly"),
|
||||
} = requireParam("options"),
|
||||
) => {
|
||||
return await Deno.core.opAsync("set_permissions", volumeId, path, readonly);
|
||||
};
|
||||
const started = () => Deno.core.opSync("set_started");
|
||||
const restart = () => Deno.core.opAsync("restart");
|
||||
const start = () => Deno.core.opAsync("start");
|
||||
const stop = () => Deno.core.opAsync("stop");
|
||||
|
||||
const currentFunction = Deno.core.opSync("current_function");
|
||||
const input = Deno.core.opSync("get_input");
|
||||
@@ -314,13 +292,19 @@ const effects = {
|
||||
runCommand,
|
||||
runDaemon,
|
||||
runRsync,
|
||||
setPermissions,
|
||||
chmod,
|
||||
signalGroup,
|
||||
sleep,
|
||||
trace,
|
||||
warn,
|
||||
writeFile,
|
||||
writeJsonFile,
|
||||
restart,
|
||||
start,
|
||||
stop,
|
||||
};
|
||||
const fnSpecificArgs = {
|
||||
main: { started },
|
||||
};
|
||||
|
||||
const defaults = {
|
||||
@@ -337,8 +321,10 @@ function safeToString(fn, orValue = "") {
|
||||
}
|
||||
}
|
||||
|
||||
const apiVersion = mainModule?.version || defaults?.version || 0;
|
||||
const runFunction = jsonPointerValue(mainModule, currentFunction) ||
|
||||
jsonPointerValue(defaults, currentFunction);
|
||||
const extraArgs = jsonPointerValue(fnSpecificArgs, currentFunction) || {};
|
||||
(async () => {
|
||||
const answer = await (async () => {
|
||||
if (typeof runFunction !== "function") {
|
||||
@@ -346,7 +332,21 @@ const runFunction = jsonPointerValue(mainModule, currentFunction) ||
|
||||
throw new Error(`Expecting ${currentFunction} to be a function`);
|
||||
}
|
||||
})()
|
||||
.then(() => runFunction(effects, input, ...variable_args))
|
||||
.then(() => {
|
||||
switch (apiVersion) {
|
||||
case 0:
|
||||
return runFunction(effects, input, ...variable_args);
|
||||
case 1:
|
||||
return runFunction({
|
||||
effects,
|
||||
input,
|
||||
args: variable_args,
|
||||
...extraArgs,
|
||||
});
|
||||
default:
|
||||
return { error: `Unknown API version ${apiVersion}` };
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
if ("error" in e) return e;
|
||||
if ("error-code" in e) return e;
|
||||
|
||||
@@ -317,12 +317,16 @@ impl JsExecutionEnvironment {
|
||||
fns::wait_command::decl(),
|
||||
fns::sleep::decl(),
|
||||
fns::send_signal::decl(),
|
||||
fns::set_permissions::decl(),
|
||||
fns::chmod::decl(),
|
||||
fns::signal_group::decl(),
|
||||
fns::rsync::decl(),
|
||||
fns::rsync_wait::decl(),
|
||||
fns::rsync_progress::decl(),
|
||||
fns::get_service_config::decl(),
|
||||
fns::set_started::decl(),
|
||||
fns::restart::decl(),
|
||||
fns::start::decl(),
|
||||
fns::stop::decl(),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -624,6 +628,16 @@ mod fns {
|
||||
path_in: PathBuf,
|
||||
write: String,
|
||||
) -> Result<(), AnyError> {
|
||||
let sandboxed = {
|
||||
let state = state.borrow();
|
||||
let ctx: &JsContext = state.borrow();
|
||||
ctx.sandboxed
|
||||
};
|
||||
|
||||
if sandboxed {
|
||||
bail!("Will not run writeFile in sandboxed mode");
|
||||
}
|
||||
|
||||
let (volumes, volume_path) = {
|
||||
let state = state.borrow();
|
||||
let ctx: &JsContext = state.borrow();
|
||||
@@ -677,6 +691,16 @@ mod fns {
|
||||
dst_volume: VolumeId,
|
||||
dst_path: PathBuf,
|
||||
) -> Result<(), AnyError> {
|
||||
let sandboxed = {
|
||||
let state = state.borrow();
|
||||
let ctx: &JsContext = state.borrow();
|
||||
ctx.sandboxed
|
||||
};
|
||||
|
||||
if sandboxed {
|
||||
bail!("Will not run rename in sandboxed mode");
|
||||
}
|
||||
|
||||
let (volumes, volume_path, volume_path_out) = {
|
||||
let state = state.borrow();
|
||||
let ctx: &JsContext = state.borrow();
|
||||
@@ -734,6 +758,16 @@ mod fns {
|
||||
dst_path: PathBuf,
|
||||
options: RsyncOptions,
|
||||
) -> Result<usize, AnyError> {
|
||||
let sandboxed = {
|
||||
let state = state.borrow();
|
||||
let ctx: &JsContext = state.borrow();
|
||||
ctx.sandboxed
|
||||
};
|
||||
|
||||
if sandboxed {
|
||||
bail!("Will not run rsync in sandboxed mode");
|
||||
}
|
||||
|
||||
let (volumes, volume_path, volume_path_out, rsyncs) = {
|
||||
let state = state.borrow();
|
||||
let ctx: &JsContext = state.borrow();
|
||||
@@ -828,12 +862,22 @@ mod fns {
|
||||
Ok(progress)
|
||||
}
|
||||
#[op]
|
||||
async fn set_permissions(
|
||||
async fn chown(
|
||||
state: Rc<RefCell<OpState>>,
|
||||
volume_id: VolumeId,
|
||||
path_in: PathBuf,
|
||||
readonly: bool,
|
||||
ownership: u32,
|
||||
) -> Result<(), AnyError> {
|
||||
let sandboxed = {
|
||||
let state = state.borrow();
|
||||
let ctx: &JsContext = state.borrow();
|
||||
ctx.sandboxed
|
||||
};
|
||||
|
||||
if sandboxed {
|
||||
bail!("Will not run chown in sandboxed mode");
|
||||
}
|
||||
|
||||
let (volumes, volume_path) = {
|
||||
let state = state.borrow();
|
||||
let ctx: &JsContext = state.borrow();
|
||||
@@ -855,9 +899,56 @@ mod fns {
|
||||
volume_path.to_string_lossy(),
|
||||
);
|
||||
}
|
||||
let mut perms = tokio::fs::metadata(&new_file).await?.permissions();
|
||||
perms.set_readonly(readonly);
|
||||
tokio::fs::set_permissions(new_file, perms).await?;
|
||||
let output = tokio::process::Command::new("chown")
|
||||
.arg("--recursive")
|
||||
.arg(format!("{ownership}"))
|
||||
.arg(new_file.as_os_str())
|
||||
.output()
|
||||
.await?;
|
||||
if !output.status.success() {
|
||||
return Err(anyhow!("Chown Error"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
#[op]
|
||||
async fn chmod(
|
||||
state: Rc<RefCell<OpState>>,
|
||||
volume_id: VolumeId,
|
||||
path_in: PathBuf,
|
||||
mode: u32,
|
||||
) -> Result<(), AnyError> {
|
||||
let sandboxed = {
|
||||
let state = state.borrow();
|
||||
let ctx: &JsContext = state.borrow();
|
||||
ctx.sandboxed
|
||||
};
|
||||
|
||||
if sandboxed {
|
||||
bail!("Will not run chmod in sandboxed mode");
|
||||
}
|
||||
|
||||
let (volumes, volume_path) = {
|
||||
let state = state.borrow();
|
||||
let ctx: &JsContext = state.borrow();
|
||||
let volume_path = ctx
|
||||
.volumes
|
||||
.path_for(&ctx.datadir, &ctx.package_id, &ctx.version, &volume_id)
|
||||
.ok_or_else(|| anyhow!("There is no {} in volumes", volume_id))?;
|
||||
(ctx.volumes.clone(), volume_path)
|
||||
};
|
||||
if volumes.readonly(&volume_id) {
|
||||
bail!("Volume {} is readonly", volume_id);
|
||||
}
|
||||
let new_file = volume_path.join(path_in);
|
||||
// With the volume check
|
||||
if !is_subset(&volume_path, &new_file).await? {
|
||||
bail!(
|
||||
"Path '{}' has broken away from parent '{}'",
|
||||
new_file.to_string_lossy(),
|
||||
volume_path.to_string_lossy(),
|
||||
);
|
||||
}
|
||||
tokio::fs::set_permissions(new_file, Permissions::from_mode(mode)).await?;
|
||||
Ok(())
|
||||
}
|
||||
#[op]
|
||||
@@ -866,6 +957,16 @@ mod fns {
|
||||
volume_id: VolumeId,
|
||||
path_in: PathBuf,
|
||||
) -> Result<(), AnyError> {
|
||||
let sandboxed = {
|
||||
let state = state.borrow();
|
||||
let ctx: &JsContext = state.borrow();
|
||||
ctx.sandboxed
|
||||
};
|
||||
|
||||
if sandboxed {
|
||||
bail!("Will not run removeFile in sandboxed mode");
|
||||
}
|
||||
|
||||
let (volumes, volume_path) = {
|
||||
let state = state.borrow();
|
||||
let ctx: &JsContext = state.borrow();
|
||||
@@ -897,6 +998,16 @@ mod fns {
|
||||
volume_id: VolumeId,
|
||||
path_in: PathBuf,
|
||||
) -> Result<(), AnyError> {
|
||||
let sandboxed = {
|
||||
let state = state.borrow();
|
||||
let ctx: &JsContext = state.borrow();
|
||||
ctx.sandboxed
|
||||
};
|
||||
|
||||
if sandboxed {
|
||||
bail!("Will not run removeDir in sandboxed mode");
|
||||
}
|
||||
|
||||
let (volumes, volume_path) = {
|
||||
let state = state.borrow();
|
||||
let ctx: &JsContext = state.borrow();
|
||||
@@ -928,6 +1039,16 @@ mod fns {
|
||||
volume_id: VolumeId,
|
||||
path_in: PathBuf,
|
||||
) -> Result<(), AnyError> {
|
||||
let sandboxed = {
|
||||
let state = state.borrow();
|
||||
let ctx: &JsContext = state.borrow();
|
||||
ctx.sandboxed
|
||||
};
|
||||
|
||||
if sandboxed {
|
||||
bail!("Will not run createDir in sandboxed mode");
|
||||
}
|
||||
|
||||
let (volumes, volume_path) = {
|
||||
let state = state.borrow();
|
||||
let ctx: &JsContext = state.borrow();
|
||||
@@ -1251,6 +1372,16 @@ mod fns {
|
||||
pid: u32,
|
||||
signal: u32,
|
||||
) -> Result<(), AnyError> {
|
||||
let sandboxed = {
|
||||
let state = state.borrow();
|
||||
let ctx: &JsContext = state.borrow();
|
||||
ctx.sandboxed
|
||||
};
|
||||
|
||||
if sandboxed {
|
||||
bail!("Will not run sendSignal in sandboxed mode");
|
||||
}
|
||||
|
||||
if let Some(rpc_client) = {
|
||||
let state = state.borrow();
|
||||
let ctx = state.borrow::<JsContext>();
|
||||
@@ -1279,6 +1410,16 @@ mod fns {
|
||||
gid: u32,
|
||||
signal: u32,
|
||||
) -> Result<(), AnyError> {
|
||||
let sandboxed = {
|
||||
let state = state.borrow();
|
||||
let ctx: &JsContext = state.borrow();
|
||||
ctx.sandboxed
|
||||
};
|
||||
|
||||
if sandboxed {
|
||||
bail!("Will not run signalGroup in sandboxed mode");
|
||||
}
|
||||
|
||||
if let Some(rpc_client) = {
|
||||
let state = state.borrow();
|
||||
let ctx = state.borrow::<JsContext>();
|
||||
@@ -1315,6 +1456,16 @@ mod fns {
|
||||
output: OutputStrategy,
|
||||
timeout: Option<u64>,
|
||||
) -> Result<StartCommand, AnyError> {
|
||||
let sandboxed = {
|
||||
let state = state.borrow();
|
||||
let ctx: &JsContext = state.borrow();
|
||||
ctx.sandboxed
|
||||
};
|
||||
|
||||
if sandboxed {
|
||||
bail!("Will not run command in sandboxed mode");
|
||||
}
|
||||
|
||||
if let (gid, Some(rpc_client)) = {
|
||||
let state = state.borrow();
|
||||
let ctx = state.borrow::<JsContext>();
|
||||
@@ -1390,99 +1541,6 @@ mod fns {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[op]
|
||||
async fn chown(
|
||||
state: Rc<RefCell<OpState>>,
|
||||
volume_id: VolumeId,
|
||||
path_in: PathBuf,
|
||||
ownership: u32,
|
||||
) -> Result<(), AnyError> {
|
||||
let sandboxed = {
|
||||
let state = state.borrow();
|
||||
let ctx: &JsContext = state.borrow();
|
||||
ctx.sandboxed
|
||||
};
|
||||
|
||||
if sandboxed {
|
||||
bail!("Will not run chown in sandboxed mode");
|
||||
}
|
||||
|
||||
let (volumes, volume_path) = {
|
||||
let state = state.borrow();
|
||||
let ctx: &JsContext = state.borrow();
|
||||
let volume_path = ctx
|
||||
.volumes
|
||||
.path_for(&ctx.datadir, &ctx.package_id, &ctx.version, &volume_id)
|
||||
.ok_or_else(|| anyhow!("There is no {} in volumes", volume_id))?;
|
||||
(ctx.volumes.clone(), volume_path)
|
||||
};
|
||||
if volumes.readonly(&volume_id) {
|
||||
bail!("Volume {} is readonly", volume_id);
|
||||
}
|
||||
let path_in = path_in.strip_prefix("/").unwrap_or(&path_in);
|
||||
let new_file = volume_path.join(path_in);
|
||||
// With the volume check
|
||||
if !is_subset(&volume_path, &new_file).await? {
|
||||
bail!(
|
||||
"Path '{}' has broken away from parent '{}'",
|
||||
new_file.to_string_lossy(),
|
||||
volume_path.to_string_lossy(),
|
||||
);
|
||||
}
|
||||
let output = tokio::process::Command::new("chown")
|
||||
.arg("--recursive")
|
||||
.arg(format!("{ownership}"))
|
||||
.arg(new_file.as_os_str())
|
||||
.output()
|
||||
.await?;
|
||||
if !output.status.success() {
|
||||
return Err(anyhow!("Chown Error"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
#[op]
|
||||
async fn chmod(
|
||||
state: Rc<RefCell<OpState>>,
|
||||
volume_id: VolumeId,
|
||||
path_in: PathBuf,
|
||||
mode: u32,
|
||||
) -> Result<(), AnyError> {
|
||||
let sandboxed = {
|
||||
let state = state.borrow();
|
||||
let ctx: &JsContext = state.borrow();
|
||||
ctx.sandboxed
|
||||
};
|
||||
|
||||
if sandboxed {
|
||||
bail!("Will not run chmod in sandboxed mode");
|
||||
}
|
||||
|
||||
let (volumes, volume_path) = {
|
||||
let state = state.borrow();
|
||||
let ctx: &JsContext = state.borrow();
|
||||
let volume_path = ctx
|
||||
.volumes
|
||||
.path_for(&ctx.datadir, &ctx.package_id, &ctx.version, &volume_id)
|
||||
.ok_or_else(|| anyhow!("There is no {} in volumes", volume_id))?;
|
||||
(ctx.volumes.clone(), volume_path)
|
||||
};
|
||||
if volumes.readonly(&volume_id) {
|
||||
bail!("Volume {} is readonly", volume_id);
|
||||
}
|
||||
let path_in = path_in.strip_prefix("/").unwrap_or(&path_in);
|
||||
let new_file = volume_path.join(path_in);
|
||||
// With the volume check
|
||||
if !is_subset(&volume_path, &new_file).await? {
|
||||
bail!(
|
||||
"Path '{}' has broken away from parent '{}'",
|
||||
new_file.to_string_lossy(),
|
||||
volume_path.to_string_lossy(),
|
||||
);
|
||||
}
|
||||
tokio::fs::set_permissions(new_file, Permissions::from_mode(mode)).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[op]
|
||||
async fn get_service_config(
|
||||
state: Rc<RefCell<OpState>>,
|
||||
@@ -1510,6 +1568,16 @@ mod fns {
|
||||
internal_port: u16,
|
||||
address_schema: AddressSchemaOnion,
|
||||
) -> Result<helpers::Address, AnyError> {
|
||||
let sandboxed = {
|
||||
let state = state.borrow();
|
||||
let ctx: &JsContext = state.borrow();
|
||||
ctx.sandboxed
|
||||
};
|
||||
|
||||
if sandboxed {
|
||||
bail!("Will not run bindOnion in sandboxed mode");
|
||||
}
|
||||
|
||||
let os = {
|
||||
let state = state.borrow();
|
||||
let ctx = state.borrow::<JsContext>();
|
||||
@@ -1525,6 +1593,16 @@ mod fns {
|
||||
internal_port: u16,
|
||||
address_schema: AddressSchemaLocal,
|
||||
) -> Result<helpers::Address, AnyError> {
|
||||
let sandboxed = {
|
||||
let state = state.borrow();
|
||||
let ctx: &JsContext = state.borrow();
|
||||
ctx.sandboxed
|
||||
};
|
||||
|
||||
if sandboxed {
|
||||
bail!("Will not run bindLocal in sandboxed mode");
|
||||
}
|
||||
|
||||
let os = {
|
||||
let state = state.borrow();
|
||||
let ctx = state.borrow::<JsContext>();
|
||||
@@ -1536,12 +1614,12 @@ mod fns {
|
||||
}
|
||||
|
||||
#[op]
|
||||
fn set_started(state: &mut OpState) -> Result<(), AnyError> {
|
||||
fn set_started(state: &mut OpState) {
|
||||
let os = {
|
||||
let ctx = state.borrow::<JsContext>();
|
||||
ctx.os.clone()
|
||||
};
|
||||
os.set_started().map_err(|e| anyhow!("{e:?}"))
|
||||
os.set_started()
|
||||
}
|
||||
|
||||
#[op]
|
||||
@@ -1561,7 +1639,9 @@ mod fns {
|
||||
let ctx = state.borrow::<JsContext>();
|
||||
ctx.os.clone()
|
||||
};
|
||||
os.restart().await.map_err(|e| anyhow!("{e:?}"))
|
||||
os.restart().await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[op]
|
||||
@@ -1581,7 +1661,9 @@ mod fns {
|
||||
let ctx = state.borrow::<JsContext>();
|
||||
ctx.os.clone()
|
||||
};
|
||||
os.start().await.map_err(|e| anyhow!("{e:?}"))
|
||||
os.start().await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[op]
|
||||
@@ -1601,7 +1683,9 @@ mod fns {
|
||||
let ctx = state.borrow::<JsContext>();
|
||||
ctx.os.clone()
|
||||
};
|
||||
os.stop().await.map_err(|e| anyhow!("{e:?}"))
|
||||
os.stop().await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// We need to make sure that during the file accessing, we don't reach beyond our scope of control
|
||||
|
||||
Reference in New Issue
Block a user