#[client_task]Expand description
§#[client_task]
The #[client_task] attribute macro is used on a struct to designate it as a client-side RPC task.
It simplifies implementation by generating boilerplate code for several traits.
The macro always generates:
DerefandDerefMutto the field marked#[field(common)].ClientTaskEncodefor the#[field(req)]and#[field(req_blob)]fields.ClientTaskDecodefor the#[field(resp)]and#[field(resp_blob)]fields.
The macro can also conditionally generate:
ClientTaskAction: Generated if a static action is provided (e.g.,#[client_task(1)]) or if a field is marked#[field(action)].ClientTaskDone: Generated if both#[field(res)]and#[field(noti)]are present. If not generated, you must implement this trait manually.
§Field Attributes:
-
#[field(common)]: (Mandatory) Marks a field that holds common task information (e.g.,ClientTaskCommon). Allows direct access to members likeseqviaDeref. -
#[field(action)]: Specifies a field that dynamically provides the RPC action. Mutually exclusive with a static action in#[client_task(...). -
#[field(req)]: (Mandatory) Designates the field for the request payload. -
#[field(resp)]: (Mandatory) Designates the field for the response payload, which must be anOption<T>. -
#[field(req_blob)]: (Optional) Marks a field for an optional request blob. Must implementAsRef<[u8]>. -
#[field(resp_blob)]: (Optional) Marks a field for an optional response blob. Must beOption<T>whereTimplementsrazor_stream::buffer::AllocateBuf. -
#[field(res)]: (Optional) When used with#[field(noti)], triggers automaticClientTaskDoneimplementation. Must be of typeOption<Result<(), RpcError<E>>>whereEimplementsrazor_stream::error::RpcErrCodec. Stores the final result of the task. -
#[field(noti)]: (Optional) When used with#[field(res)], triggers automaticClientTaskDoneimplementation. Must be anOptionwrapping a crossfire list channel MTx sender (e.g.,Option<crossfire::MTx<crossfire::mpsc::List<ParentTask>>>) to notify of task completion. where the task has implIntoasParentTaskextracted withcrossfire::flavor::Queue::Item
§Example of Automatic ClientTaskDone
use razor_stream::error::RpcError;
use nix::errno::Errno;
use razor_stream_macros::client_task;
use serde_derive::{Deserialize, Serialize};
use crossfire::{mpsc, MTx};
use razor_stream::client::task::*;
#[derive(Debug, Default, Deserialize, Serialize)]
pub struct FileReadReq {
pub path: String,
pub offset: u64,
pub len: u64,
}
#[derive(Debug, Default, Deserialize, Serialize)]
pub struct FileReadResp {
pub bytes_read: u64,
}
// A task with automatic `ClientTaskDone` implementation.
#[client_task(1, debug)]
pub struct FileReadTask {
#[field(common)]
common: ClientTaskCommon,
#[field(req)]
req: FileReadReq,
#[field(resp)]
resp: Option<FileReadResp>,
#[field(res)]
res: Option<Result<(), RpcError<Errno>>>,
#[field(noti)]
noti: Option<MTx<mpsc::List<Self>>>,
}
// Usage
let (tx, rx) = mpsc::unbounded_blocking::<FileReadTask>();
let mut task = FileReadTask {
common: ClientTaskCommon { seq: 1, ..Default::default() },
req: FileReadReq { path: "/path/to/file".to_string(), offset: 0, len: 1024 },
resp: None,
res: None,
noti: Some(tx),
};
task.set_ok();
task.done();
let completed_task = rx.recv().unwrap();
assert_eq!(completed_task.common.seq, 1);
assert!(completed_task.res.is_some() && completed_task.res.as_ref().unwrap().is_ok());