Skip to main content

acktor_ipc/node/
command.rs

1//! Commands which can be used to interact with a node.
2//!
3
4use std::fmt::{self, Debug};
5use std::marker::PhantomData;
6
7use acktor::{Actor, Address, Message, utils::ShortName};
8
9use crate::actor_ref::ActorRef;
10use crate::error::NodeError;
11use crate::ipc_method::{IpcConnection, IpcListener};
12use crate::remote::{RemoteAddressable, RemoteSpawnable};
13use crate::session::Session;
14
15type Result<T> = std::result::Result<T, NodeError>;
16
17/// A command which is used to add an IPC listener to a node.
18///
19/// A node can hold multiple listeners so that it can accept inbound connections on several local
20/// endpoints in parallel. Returns `false` if the listener is already registered.
21pub struct AddListener<L>(pub L)
22where
23    L: IpcListener;
24
25impl<L> Debug for AddListener<L>
26where
27    L: IpcListener,
28{
29    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30        f.debug_tuple(&ShortName::of::<Self>().to_string())
31            .field(&self.0.local_endpoint())
32            .finish()
33    }
34}
35
36impl<L> Message for AddListener<L>
37where
38    L: IpcListener,
39{
40    type Result = bool;
41}
42
43/// A command which is used to remove an IPC listener from a node.
44///
45/// The listener is identified by its local endpoint. Returns `false` if no listener with the
46/// given endpoint is found.
47#[derive(Debug)]
48pub struct RemoveListener(pub String);
49
50impl Message for RemoveListener {
51    type Result = bool;
52}
53
54/// A command which is used to actively connect to another node like a client.
55///
56/// A new session will be created if the operation is successful. The user can provide a
57/// `session_label` as an alias to the session, and it can be used to refer to the session actor
58/// in other commands. If `session_label` is not provided, the endpoint of the connection will be
59/// used as the alias of the new session actor.
60///
61/// The command will return the address of the session actor if it succeeds.
62pub struct Connect<C>
63where
64    C: IpcConnection,
65{
66    pub endpoint: String,
67    pub session_label: Option<String>,
68    _marker: PhantomData<fn(C) -> C>,
69}
70
71impl<C> Debug for Connect<C>
72where
73    C: IpcConnection,
74{
75    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76        f.debug_tuple(&ShortName::of::<Self>().to_string())
77            .field(&self.endpoint)
78            .field(&self.session_label)
79            .finish()
80    }
81}
82
83impl<C> Message for Connect<C>
84where
85    C: IpcConnection,
86{
87    type Result = Result<Address<Session>>;
88}
89
90impl<C> Connect<C>
91where
92    C: IpcConnection,
93{
94    /// Constructs a new [`Connect`] command for the connection type `C`.
95    pub fn new<S1, S2>(endpoint: S1, label: S2) -> Self
96    where
97        S1: AsRef<str>,
98        S2: AsRef<str>,
99    {
100        Self {
101            endpoint: endpoint.as_ref().to_string(),
102            session_label: Some(label.as_ref().to_string()),
103            _marker: PhantomData,
104        }
105    }
106
107    /// Constructs a new [`Connect`] command for the connection type `C` without a session label.
108    pub fn no_label<S>(endpoint: S) -> Self
109    where
110        S: AsRef<str>,
111    {
112        Self {
113            endpoint: endpoint.as_ref().to_string(),
114            session_label: None,
115            _marker: PhantomData,
116        }
117    }
118}
119
120/// A command which is used to add a remote addressable actor to a node.
121///
122/// The `label` is registered alongside the address so the actor can later be looked up by label
123/// from a remote node. Returns `false` if either the label or the actor is already registered.
124pub struct AddActor<A>
125where
126    A: Actor + RemoteAddressable,
127{
128    pub label: String,
129    pub address: Address<A>,
130    _marker: PhantomData<fn(A) -> A>,
131}
132
133impl<A> Debug for AddActor<A>
134where
135    A: Actor + RemoteAddressable,
136{
137    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
138        f.debug_tuple(&ShortName::of::<Self>().to_string())
139            .field(&self.label)
140            .field(&self.address.index())
141            .finish()
142    }
143}
144
145impl<A> Message for AddActor<A>
146where
147    A: Actor + RemoteAddressable,
148{
149    type Result = bool;
150}
151
152impl<A> AddActor<A>
153where
154    A: Actor + RemoteAddressable,
155{
156    /// Constructs a new [`AddActor`] command.
157    pub fn new<S>(label: S, address: Address<A>) -> Self
158    where
159        S: AsRef<str>,
160    {
161        Self {
162            label: label.as_ref().to_string(),
163            address,
164            _marker: PhantomData,
165        }
166    }
167}
168
169/// A command which is used to remove an actor from a node.
170///
171/// The actor is identified by its index or label. Returns `false` if no actor is found.
172pub struct RemoveActor(pub ActorRef);
173
174impl Debug for RemoveActor {
175    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
176        f.debug_tuple("RemoveActor")
177            .field(match &self.0 {
178                ActorRef::Index(index) => index,
179                ActorRef::Label(label) => label,
180            })
181            .finish()
182    }
183}
184
185impl Message for RemoveActor {
186    type Result = bool;
187}
188
189/// A command which is used to create an actor in a remote node.
190///
191/// The actor type should have been registered in the remote node's factory registry. If the
192/// operation is successful, the provided `label` will be used as the actor label of the new actor
193/// created in the remote node.
194#[derive(Debug)]
195pub struct RemoteCreateActor<A>
196where
197    A: Actor + RemoteSpawnable,
198{
199    pub session: ActorRef,
200    pub label: String,
201    pub config: Option<String>,
202    _marker: PhantomData<fn(A) -> A>,
203}
204
205impl<A> Message for RemoteCreateActor<A>
206where
207    A: Actor + RemoteSpawnable,
208{
209    type Result = Result<Address<A>>;
210}
211
212impl<A> RemoteCreateActor<A>
213where
214    A: Actor + RemoteSpawnable,
215{
216    /// Constructs a new [`RemoteCreateActor`] command for the actor type `A`.
217    pub fn new<S>(session: ActorRef, label: S, config: Option<String>) -> Self
218    where
219        S: AsRef<str>,
220    {
221        Self {
222            session,
223            label: label.as_ref().to_string(),
224            config,
225            _marker: PhantomData,
226        }
227    }
228}
229
230/// A command which is used to get the address of an actor in a remote node.
231#[derive(Debug)]
232pub struct RemoteGetActor<A>
233where
234    A: Actor + RemoteAddressable,
235{
236    pub session: ActorRef,
237    pub actor: ActorRef,
238    _marker: PhantomData<fn(A) -> A>,
239}
240
241impl<A> Message for RemoteGetActor<A>
242where
243    A: Actor + RemoteAddressable,
244{
245    type Result = Result<Address<A>>;
246}
247
248impl<A> RemoteGetActor<A>
249where
250    A: Actor + RemoteAddressable,
251{
252    /// Constructs a new [`RemoteGetActor`] command for the actor type `A`.
253    pub fn new(session: ActorRef, actor: ActorRef) -> Self {
254        Self {
255            session,
256            actor,
257            _marker: PhantomData,
258        }
259    }
260}