From b590a40891dcf843a2f3ca23d930aca4363e7ffe Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Sun, 12 Oct 2025 18:15:36 +0800 Subject: feat: Add Clone implementation for ActionContext This enables ActionContext to be cloned when setting up process begin callbacks, resolving lifetime issues in callback registration. --- crates/system_action/src/action.rs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'crates/system_action/src/action.rs') diff --git a/crates/system_action/src/action.rs b/crates/system_action/src/action.rs index 562a142..c8d7a18 100644 --- a/crates/system_action/src/action.rs +++ b/crates/system_action/src/action.rs @@ -1,6 +1,12 @@ +use serde::{Serialize, de::DeserializeOwned}; use tcp_connection::{error::TcpTargetError, instance::ConnectionInstance}; +use tokio::net::TcpStream; -pub trait Action { +pub trait Action +where + Args: Serialize + DeserializeOwned + Send, + Return: Serialize + DeserializeOwned + Send, +{ fn action_name() -> &'static str; fn is_remote_action() -> bool; @@ -13,7 +19,7 @@ pub trait Action { #[derive(Default)] pub struct ActionContext { - // Whether the action is executed locally or remotely + /// Whether the action is executed locally or remotely local: bool, /// The connection instance in the current context, @@ -35,6 +41,18 @@ impl ActionContext { ctx.local = false; ctx } + + /// Build connection instance from TcpStream + pub fn build_instance(mut self, stream: TcpStream) -> Self { + self.instance = Some(ConnectionInstance::from(stream)); + self + } + + /// Insert connection instance into context + pub fn insert_instance(mut self, instance: ConnectionInstance) -> Self { + self.instance = Some(instance); + self + } } impl ActionContext { -- cgit From 67fb8ec01b351c6c9fd2af321166bb92250b1218 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Mon, 13 Oct 2025 13:34:39 +0800 Subject: feat: Implement JSON-based type-erased action invocation - Add process_json method to ActionPool for type-agnostic calls using JSON serialization - Extend ActionContext with action_name and action_args fields and setter methods - Update action_gen macro to use process_json instead of typed process method - Implement remote action invocation framework in client_registry and action_service - Add protocol definitions for remote action communication - Enable flexible action execution without explicit type specifications --- crates/system_action/src/action.rs | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'crates/system_action/src/action.rs') diff --git a/crates/system_action/src/action.rs b/crates/system_action/src/action.rs index c8d7a18..e7d2d8c 100644 --- a/crates/system_action/src/action.rs +++ b/crates/system_action/src/action.rs @@ -22,6 +22,12 @@ pub struct ActionContext { /// Whether the action is executed locally or remotely local: bool, + /// The name of the action being executed + action_name: String, + + /// The JSON-serialized arguments for the action + action_args_json: String, + /// The connection instance in the current context, /// used to interact with the machine on the other end instance: Option, @@ -53,6 +59,11 @@ impl ActionContext { self.instance = Some(instance); self } + + /// Pop connection instance from context + pub fn pop_instance(&mut self) -> Option { + self.instance.take() + } } impl ActionContext { @@ -70,4 +81,31 @@ impl ActionContext { pub fn instance(&self) -> &Option { &self.instance } + + /// Get a mutable reference to the connection instance in the current context + pub fn instance_mut(&mut self) -> &mut Option { + &mut self.instance + } + + /// Get the action name from the context + pub fn action_name(&self) -> &str { + &self.action_name + } + + /// Get the action arguments from the context + pub fn action_args_json(&self) -> &String { + &self.action_args_json + } + + /// Set the action name in the context + pub fn set_action_name(mut self, action_name: String) -> Self { + self.action_name = action_name; + self + } + + /// Set the action arguments in the context + pub fn set_action_args_json(mut self, action_args: String) -> Self { + self.action_args_json = action_args; + self + } } -- cgit From acf0804b5f9bdc2796d847919a8ae20103be600a Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Mon, 13 Oct 2025 14:17:51 +0800 Subject: feat: implement asynchronous action call system - Add async callback support with proper argument passing - Implement remote action invocation via TCP connection - Add hello_world_action example demonstrating async communication - Improve ActionPool with type-safe async processing - Update client registry for remote action handling - Enhance ActionContext with better instance management - Support both local and remote action execution modes --- crates/system_action/src/action.rs | 70 +++++++++++++++++++++++++++++++++----- 1 file changed, 61 insertions(+), 9 deletions(-) (limited to 'crates/system_action/src/action.rs') diff --git a/crates/system_action/src/action.rs b/crates/system_action/src/action.rs index e7d2d8c..3ae5711 100644 --- a/crates/system_action/src/action.rs +++ b/crates/system_action/src/action.rs @@ -1,6 +1,9 @@ use serde::{Serialize, de::DeserializeOwned}; +use std::any::{Any, TypeId}; +use std::collections::HashMap; +use std::sync::Arc; use tcp_connection::{error::TcpTargetError, instance::ConnectionInstance}; -use tokio::net::TcpStream; +use tokio::{net::TcpStream, sync::Mutex}; pub trait Action where @@ -29,8 +32,10 @@ pub struct ActionContext { action_args_json: String, /// The connection instance in the current context, - /// used to interact with the machine on the other end - instance: Option, + instance: Option>>, + + /// Generic data storage for arbitrary types + data: HashMap>, } impl ActionContext { @@ -50,18 +55,18 @@ impl ActionContext { /// Build connection instance from TcpStream pub fn build_instance(mut self, stream: TcpStream) -> Self { - self.instance = Some(ConnectionInstance::from(stream)); + self.instance = Some(Arc::new(Mutex::new(ConnectionInstance::from(stream)))); self } /// Insert connection instance into context pub fn insert_instance(mut self, instance: ConnectionInstance) -> Self { - self.instance = Some(instance); + self.instance = Some(Arc::new(Mutex::new(instance))); self } /// Pop connection instance from context - pub fn pop_instance(&mut self) -> Option { + pub fn pop_instance(&mut self) -> Option>> { self.instance.take() } } @@ -78,12 +83,12 @@ impl ActionContext { } /// Get the connection instance in the current context - pub fn instance(&self) -> &Option { + pub fn instance(&self) -> &Option>> { &self.instance } /// Get a mutable reference to the connection instance in the current context - pub fn instance_mut(&mut self) -> &mut Option { + pub fn instance_mut(&mut self) -> &mut Option>> { &mut self.instance } @@ -104,8 +109,55 @@ impl ActionContext { } /// Set the action arguments in the context - pub fn set_action_args_json(mut self, action_args: String) -> Self { + pub fn set_action_args(mut self, action_args: String) -> Self { self.action_args_json = action_args; self } + + /// Insert arbitrary data in the context + pub fn insert(mut self, value: T) -> Self { + self.data.insert(TypeId::of::(), Arc::new(value)); + self + } + + /// Insert arbitrary data as Arc in the context + pub fn insert_arc(mut self, value: Arc) -> Self { + self.data.insert(TypeId::of::(), value); + self + } + + /// Get arbitrary data from the context + pub fn get(&self) -> Option<&T> { + self.data + .get(&TypeId::of::()) + .and_then(|arc| arc.downcast_ref::()) + } + + /// Get arbitrary data as Arc from the context + pub fn get_arc(&self) -> Option> { + self.data + .get(&TypeId::of::()) + .and_then(|arc| Arc::clone(arc).downcast::().ok()) + } + + /// Remove and return arbitrary data from the context + pub fn remove(&mut self) -> Option> { + self.data + .remove(&TypeId::of::()) + .and_then(|arc| arc.downcast::().ok()) + } + + /// Check if the context contains data of a specific type + pub fn contains(&self) -> bool { + self.data.contains_key(&TypeId::of::()) + } + + /// Take ownership of the context and extract data of a specific type + pub fn take(mut self) -> (Self, Option>) { + let value = self + .data + .remove(&TypeId::of::()) + .and_then(|arc| arc.downcast::().ok()); + (self, value) + } } -- cgit From 4810f56e6a49b60923eb850d5944457650c81c75 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Mon, 13 Oct 2025 14:27:01 +0800 Subject: Fix Clippy warnings and optimize code - Fix let_underscore_future warning by properly awaiting async functions - Make accept_import function async to match add_mapping usage - Propagate errors properly with ? operator instead of ignoring them - Replace manual Default implementation with derive attribute - Replace vec! with array literal to avoid useless_vec warning - All tests pass and code is now Clippy clean --- crates/system_action/src/action.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'crates/system_action/src/action.rs') diff --git a/crates/system_action/src/action.rs b/crates/system_action/src/action.rs index 3ae5711..8a6180a 100644 --- a/crates/system_action/src/action.rs +++ b/crates/system_action/src/action.rs @@ -41,16 +41,18 @@ pub struct ActionContext { impl ActionContext { /// Generate local context pub fn local() -> Self { - let mut ctx = ActionContext::default(); - ctx.local = true; - ctx + ActionContext { + local: true, + ..Default::default() + } } /// Generate remote context pub fn remote() -> Self { - let mut ctx = ActionContext::default(); - ctx.local = false; - ctx + ActionContext { + local: false, + ..Default::default() + } } /// Build connection instance from TcpStream -- cgit