Add validation for service methods

Signed-off-by: Lee Smet <lee.smet@hotmail.com>
This commit is contained in:
Lee Smet
2025-08-22 14:08:41 +02:00
parent bc6cb16732
commit 7ce19f8b6d
9 changed files with 1089 additions and 154 deletions

View File

@@ -14,7 +14,10 @@ use serde_json::{Value, json};
use crate::{
dag::{DagError, FlowDag},
models::{Actor, Context, Flow, Job, Message, MessageFormatType, Runner, ScriptType},
models::{
Actor, Context, Flow, FlowStatus, Job, JobStatus, Message, MessageFormatType,
MessageStatus, Runner, ScriptType,
},
service::AppService,
time::current_timestamp,
};
@@ -114,25 +117,24 @@ pub struct ContextCreate {
pub executors: Vec<u32>,
}
impl ContextCreate {
pub fn into_domain(self) -> Result<Context, String> {
pub fn into_domain(self) -> Context {
let ts = current_timestamp();
let mut v = serde_json::Map::new();
v.insert("id".to_string(), Value::from(self.id));
v.insert(
"admins".to_string(),
serde_json::to_value(self.admins).unwrap(),
);
v.insert(
"readers".to_string(),
serde_json::to_value(self.readers).unwrap(),
);
v.insert(
"executors".to_string(),
serde_json::to_value(self.executors).unwrap(),
);
v.insert("created_at".to_string(), Value::from(ts));
v.insert("updated_at".to_string(), Value::from(ts));
serde_json::from_value(Value::Object(v)).map_err(|e| e.to_string())
let ContextCreate {
id,
admins,
readers,
executors,
} = self;
Context {
id,
admins,
readers,
executors,
created_at: ts,
updated_at: ts,
}
}
}
@@ -145,18 +147,26 @@ pub struct RunnerCreate {
pub local: bool,
}
impl RunnerCreate {
pub fn into_domain(self) -> Result<Runner, String> {
pub fn into_domain(self) -> Runner {
let ts = current_timestamp();
let v = json!({
"id": self.id,
"pubkey": self.pubkey,
"address": self.address,
"topic": self.topic,
"local": self.local,
"created_at": ts,
"updated_at": ts,
});
serde_json::from_value(v).map_err(|e| e.to_string())
let RunnerCreate {
id,
pubkey,
address,
topic,
local,
} = self;
Runner {
id,
pubkey,
address,
topic,
local,
created_at: ts,
updated_at: ts,
}
}
}
@@ -167,24 +177,31 @@ pub struct FlowCreate {
pub context_id: u32,
pub jobs: Vec<u32>,
pub env_vars: HashMap<String, String>,
#[serde(default)]
pub result: Option<HashMap<String, String>>,
}
impl FlowCreate {
pub fn into_domain(self) -> Result<Flow, String> {
pub fn into_domain(self) -> Flow {
let ts = current_timestamp();
let v = json!({
"id": self.id,
"caller_id": self.caller_id,
"context_id": self.context_id,
"jobs": self.jobs,
"env_vars": self.env_vars,
"result": self.result.unwrap_or_default(),
"created_at": ts,
"updated_at": ts,
"status": "Dispatched",
});
serde_json::from_value(v).map_err(|e| e.to_string())
let FlowCreate {
id,
caller_id,
context_id,
jobs,
env_vars,
} = self;
Flow {
id,
caller_id,
context_id,
jobs,
env_vars,
result: HashMap::new(),
created_at: ts,
updated_at: ts,
status: FlowStatus::Created,
}
}
}
@@ -198,31 +215,43 @@ pub struct JobCreate {
pub timeout: u32,
pub retries: u8,
pub env_vars: HashMap<String, String>,
#[serde(default)]
pub result: Option<HashMap<String, String>>,
pub prerequisites: Vec<String>,
pub depends: Vec<u32>,
}
impl JobCreate {
pub fn into_domain(self) -> Result<Job, String> {
pub fn into_domain(self) -> Job {
let ts = current_timestamp();
let v = json!({
"id": self.id,
"caller_id": self.caller_id,
"context_id": self.context_id,
"script": self.script,
"script_type": self.script_type,
"timeout": self.timeout,
"retries": self.retries,
"env_vars": self.env_vars,
"result": self.result.unwrap_or_default(),
"prerequisites": self.prerequisites,
"depends": self.depends,
"created_at": ts,
"updated_at": ts,
"status": "Dispatched",
});
serde_json::from_value(v).map_err(|e| e.to_string())
let JobCreate {
id,
caller_id,
context_id,
script,
script_type,
timeout,
retries,
env_vars,
prerequisites,
depends,
} = self;
Job {
id,
caller_id,
context_id,
script,
script_type,
timeout,
retries,
env_vars,
result: HashMap::new(),
prerequisites,
depends,
created_at: ts,
updated_at: ts,
status: JobStatus::WaitingForPrerequisites,
}
}
}
@@ -238,37 +267,40 @@ pub struct MessageCreate {
pub timeout_ack: u32,
pub timeout_result: u32,
pub job: Vec<JobCreate>,
#[serde(default)]
pub logs: Option<Vec<String>>,
}
impl MessageCreate {
pub fn into_domain(self) -> Result<Message, String> {
pub fn into_domain(self) -> Message {
let ts = current_timestamp();
let jobs: Result<Vec<Value>, String> = self
.job
.into_iter()
.map(|j| {
let jd: Job = j.into_domain()?;
serde_json::to_value(jd).map_err(|e| e.to_string())
})
.collect();
let v = json!({
"id": self.id,
"caller_id": self.caller_id,
"context_id": self.context_id,
"message": self.message,
"message_type": self.message_type,
"message_format_type": self.message_format_type, // "Html" | "Text" | "Md"
"timeout": self.timeout,
"timeout_ack": self.timeout_ack,
"timeout_result": self.timeout_result,
"job": jobs?,
"logs": self.logs.unwrap_or_default(),
"created_at": ts,
"updated_at": ts,
"status": "Dispatched",
});
serde_json::from_value(v).map_err(|e| e.to_string())
let MessageCreate {
id,
caller_id,
context_id,
message,
message_type,
message_format_type,
timeout,
timeout_ack,
timeout_result,
job,
} = self;
Message {
id,
caller_id,
context_id,
message,
message_type,
message_format_type,
timeout,
timeout_ack,
timeout_result,
job: job.into_iter().map(JobCreate::into_domain).collect(),
logs: Vec::new(),
created_at: ts,
updated_at: ts,
status: MessageStatus::Dispatched,
}
}
}
@@ -390,7 +422,7 @@ pub fn build_module(state: Arc<AppState>) -> RpcModule<()> {
let state = state.clone();
async move {
let p: ContextCreateParams = params.parse().map_err(invalid_params_err)?;
let ctx = p.context.into_domain().map_err(invalid_params_err)?;
let ctx = p.context.into_domain();
let ctx = state
.service
.create_context(ctx)
@@ -427,7 +459,7 @@ pub fn build_module(state: Arc<AppState>) -> RpcModule<()> {
let state = state.clone();
async move {
let p: RunnerCreateParams = params.parse().map_err(invalid_params_err)?;
let runner = p.runner.into_domain().map_err(invalid_params_err)?;
let runner = p.runner.into_domain();
let runner = state
.service
.create_runner(p.context_id, runner)
@@ -464,7 +496,7 @@ pub fn build_module(state: Arc<AppState>) -> RpcModule<()> {
let state = state.clone();
async move {
let p: FlowCreateParams = params.parse().map_err(invalid_params_err)?;
let flow = p.flow.into_domain().map_err(invalid_params_err)?;
let flow = p.flow.into_domain();
let flow = state
.service
.create_flow(p.context_id, flow)
@@ -518,7 +550,7 @@ pub fn build_module(state: Arc<AppState>) -> RpcModule<()> {
let state = state.clone();
async move {
let p: JobCreateParams = params.parse().map_err(invalid_params_err)?;
let job = p.job.into_domain().map_err(invalid_params_err)?;
let job = p.job.into_domain();
let job = state
.service
.create_job(p.context_id, job)
@@ -555,7 +587,7 @@ pub fn build_module(state: Arc<AppState>) -> RpcModule<()> {
let state = state.clone();
async move {
let p: MessageCreateParams = params.parse().map_err(invalid_params_err)?;
let message = p.message.into_domain().map_err(invalid_params_err)?;
let message = p.message.into_domain();
let message = state
.service
.create_message(p.context_id, message)