Files
start-os/core/src/service/rpc.rs
Aiden McClelland 96ae532879 Refactor/project structure (#3085)
* refactor project structure

* environment-based default registry

* fix tests

* update build container

* use docker platform for iso build emulation

* simplify compat

* Fix docker platform spec in run-compat.sh

* handle riscv compat

* fix bug with dep error exists attr

* undo removal of sorting

* use qemu for iso stage

---------

Co-authored-by: Mariusz Kogen <k0gen@pm.me>
Co-authored-by: Matt Hill <mattnine@protonmail.com>
2025-12-22 13:39:38 -07:00

281 lines
6.6 KiB
Rust

use std::collections::BTreeSet;
use std::str::FromStr;
use std::sync::{Arc, Weak};
use std::time::Duration;
use clap::builder::ValueParserFactory;
use exver::{ExtendedVersion, VersionRange};
use imbl::Vector;
use imbl_value::{InternedString, Value};
use rpc_toolkit::Empty;
use rpc_toolkit::yajrc::RpcMethod;
use ts_rs::TS;
use crate::prelude::*;
use crate::rpc_continuations::Guid;
use crate::service::ProcedureName;
use crate::service::persistent_container::PersistentContainer;
use crate::util::{FromStrParser, Never};
#[derive(Clone, serde::Deserialize, serde::Serialize, TS)]
#[serde(rename_all = "kebab-case")]
pub enum InitKind {
Install,
Update,
Restore,
}
#[derive(Clone, serde::Deserialize, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
pub struct InitParams {
pub id: Guid,
pub kind: Option<InitKind>,
}
#[derive(Clone)]
pub struct Init;
impl RpcMethod for Init {
type Params = InitParams;
type Response = ();
fn as_str<'a>(&'a self) -> &'a str {
"init"
}
}
impl serde::Serialize for Init {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(self.as_str())
}
}
#[derive(Clone)]
pub struct Start;
impl RpcMethod for Start {
type Params = Empty;
type Response = ();
fn as_str<'a>(&'a self) -> &'a str {
"start"
}
}
impl serde::Serialize for Start {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(self.as_str())
}
}
#[derive(Clone)]
pub struct Stop;
impl RpcMethod for Stop {
type Params = Empty;
type Response = ();
fn as_str<'a>(&'a self) -> &'a str {
"stop"
}
}
impl serde::Serialize for Stop {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(self.as_str())
}
}
#[derive(Clone, serde::Deserialize, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
pub struct ExitParams {
id: Guid,
/// VersionRange or ExtendedVersion
#[ts(type = "string | null")]
target: Option<InternedString>,
}
impl ExitParams {
pub fn target_version(version: &ExtendedVersion) -> Self {
Self {
id: Guid::new(),
target: Some(InternedString::from_display(version)),
}
}
pub fn target_range(range: &VersionRange) -> Self {
Self {
id: Guid::new(),
target: Some(InternedString::from_display(range)),
}
}
pub fn uninstall() -> Self {
Self {
id: Guid::new(),
target: None,
}
}
pub fn is_uninstall(&self) -> bool {
self.target.is_none()
}
}
#[derive(Clone)]
pub struct Exit;
impl RpcMethod for Exit {
type Params = ExitParams;
type Response = ();
fn as_str<'a>(&'a self) -> &'a str {
"exit"
}
}
impl serde::Serialize for Exit {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(self.as_str())
}
}
#[derive(Clone, serde::Deserialize, serde::Serialize, TS)]
pub struct ExecuteParams {
id: Guid,
procedure: String,
#[ts(type = "any")]
input: Value,
timeout: Option<u128>,
}
impl ExecuteParams {
pub fn new(
id: Guid,
procedure: ProcedureName,
input: Value,
timeout: Option<Duration>,
) -> Self {
Self {
id,
procedure: procedure.js_function_name(),
input,
timeout: timeout.map(|d| d.as_millis()),
}
}
}
#[derive(Clone)]
pub struct Execute;
impl RpcMethod for Execute {
type Params = ExecuteParams;
type Response = Value;
fn as_str<'a>(&'a self) -> &'a str {
"execute"
}
}
impl serde::Serialize for Execute {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(self.as_str())
}
}
#[derive(Clone)]
pub struct Sandbox;
impl RpcMethod for Sandbox {
type Params = ExecuteParams;
type Response = Value;
fn as_str<'a>(&'a self) -> &'a str {
"sandbox"
}
}
impl serde::Serialize for Sandbox {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(self.as_str())
}
}
#[derive(
Clone, Copy, Debug, serde::Deserialize, serde::Serialize, TS, PartialEq, Eq, PartialOrd, Ord,
)]
#[ts(type = "number")]
pub struct CallbackId(u64);
impl CallbackId {
pub fn register(self, container: &PersistentContainer) -> CallbackHandle {
let this = Arc::new(self);
let res = Arc::downgrade(&this);
container
.state
.send_if_modified(|s| s.callbacks.insert(this));
CallbackHandle(res)
}
}
impl FromStr for CallbackId {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
u64::from_str(s).map_err(Error::from).map(Self)
}
}
impl ValueParserFactory for CallbackId {
type Parser = FromStrParser<Self>;
fn value_parser() -> Self::Parser {
FromStrParser::new()
}
}
pub struct CallbackHandle(Weak<CallbackId>);
impl CallbackHandle {
pub fn is_active(&self) -> bool {
self.0.strong_count() > 0
}
pub fn params(
self,
registered: &mut BTreeSet<Arc<CallbackId>>,
args: Vector<Value>,
) -> Option<CallbackParams> {
if let Some(id) = self.0.upgrade() {
if let Some(strong) = registered.get(&id) {
if Arc::ptr_eq(strong, &id) {
registered.remove(&id);
return Some(CallbackParams::new(&*id, args));
}
}
}
None
}
pub fn take(&mut self) -> Self {
Self(std::mem::take(&mut self.0))
}
}
#[derive(Clone, serde::Deserialize, serde::Serialize, TS)]
pub struct CallbackParams {
id: u64,
#[ts(type = "any[]")]
args: Vector<Value>,
}
impl CallbackParams {
fn new(id: &CallbackId, args: Vector<Value>) -> Self {
Self { id: id.0, args }
}
}
#[derive(Clone)]
pub struct Callback;
impl RpcMethod for Callback {
type Params = CallbackParams;
type Response = Never;
fn as_str<'a>(&'a self) -> &'a str {
"callback"
}
}
impl serde::Serialize for Callback {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(self.as_str())
}
}