diff --git a/docs/source/books/hyperactor-book/src/SUMMARY.md b/docs/source/books/hyperactor-book/src/SUMMARY.md index 334b01176..717c99555 100644 --- a/docs/source/books/hyperactor-book/src/SUMMARY.md +++ b/docs/source/books/hyperactor-book/src/SUMMARY.md @@ -47,6 +47,6 @@ - [`#[derive(Named)]`](macros/named.md) - [`#[export]`](macros/export.md) - [`#[forward]`](macros/forward.md) - - [`#[alias]`](macros/alias.md) + - [`#[behavior]`](macros/behavior.md) - [Appendix](appendix/index.md) - [Typed Message Lifecycle](appendix/lifecycle.md) diff --git a/docs/source/books/hyperactor-book/src/macros/alias.md b/docs/source/books/hyperactor-book/src/macros/behavior.md similarity index 72% rename from docs/source/books/hyperactor-book/src/macros/alias.md rename to docs/source/books/hyperactor-book/src/macros/behavior.md index 3e69d399c..531d90b57 100644 --- a/docs/source/books/hyperactor-book/src/macros/alias.md +++ b/docs/source/books/hyperactor-book/src/macros/behavior.md @@ -1,11 +1,12 @@ -# `#[alias]` +# `#[behavior]` -The `#[alias]` macro defines a façade actor type that exposes only a selected set of messages. -This allows you to hand out **stable or restricted APIs** without tying clients to the full concrete actor type. +The `#[behavior]` macro defines a type which represents an actor that handles a set of messages. +Behaviors allows you to define and hand out **stable or restricted APIs** without tying clients +to the full concrete actor type. -### Defining an alias +### Defining a behavior -An alias groups together one or more message enums or structs: +A behavior groups together one or more message enums or structs: ```rust #[derive(Handler)] @@ -28,8 +29,8 @@ struct GetItemCount { reply: OncePortRef, } -// Define an alias actor `ShoppingApi` that exposes exactly these messages. -hyperactor::alias!( +// Define a behavior `ShoppingApi` that exposes exactly these messages. +hyperactor::behavior!( ShoppingApi, ShoppingList, ClearList, @@ -37,14 +38,14 @@ hyperactor::alias!( ); ``` -The alias can include: +The behavior can include any type of message: - Enums (e.g. `ShoppingList`) - Struct messages (e.g. `ClearList`, `GetItemCount`) - Generic messages, with concrete type parameters bound at the alias site. -### Using an alias +### Using a behavior -After spawning the real actor, re-type its id as the alias: +After spawning the real actor, re-type its id as the behavior: ```rust let mut proc = Proc::local(); @@ -69,14 +70,14 @@ println!("items containing 'dairy': {n}"); shopping_api.clear_list(&client, "end of session".into()).await?; ``` -> **Note:** `alias!` does *not* rename methods. It authorizes those calls on +> **Note:** `behavior!` does *not* rename methods. It authorizes those calls on > `ActorRef` if and only if the message type was included. > **Note:** `attest` is a low-level escape hatch. It asserts that a raw -> `ActorId` is valid for the alias type. This example uses it only because +> `ActorId` is valid for the behavior. This example uses it only because > we just spawned the actor and know the id is safe. > In general, prefer higher-level APIs (such as `Proc` utilities) for -> constructing alias references, and use `attest` sparingly. +> constructing behavior references, and use `attest` sparingly. ### Generated code (excerpt) @@ -108,12 +109,12 @@ impl hyperactor::actor::RemoteHandles> for ShoppingApi {} ### Capability slicing -If a message type is not listed in the alias, trying to call it will fail at compile time: +If a message type is not listed in the behavior, trying to call it will fail at compile time: ```rust -// If ClearList were omitted from the alias: +// If ClearList were omitted from the behavior: shopping_api.clear_list(&client, "...").await?; // ^ error: the trait bound `ShoppingApi: RemoteHandles` is not satisfied ``` -This makes `alias!` a useful tool for **compile-time capability control**. +This makes `behavior!` a useful tool for **compile-time capability control**. diff --git a/hyperactor/example/derive.rs b/hyperactor/example/derive.rs index feaa2417c..f9b92b5d3 100644 --- a/hyperactor/example/derive.rs +++ b/hyperactor/example/derive.rs @@ -129,10 +129,10 @@ impl GetItemCountHandler for ShoppingListActor { } } -// Define an alias actor `ShoppingApi`. Clients can use +// Define a behavior `ShoppingApi`. Clients can use // `ActorRef` instead of referencing the concrete // `ShoppingListActor` directly. -hyperactor::alias!(ShoppingApi, ShoppingList, ClearList, GetItemCount,); +hyperactor::behavior!(ShoppingApi, ShoppingList, ClearList, GetItemCount,); #[tokio::main] async fn main() -> Result<(), anyhow::Error> { diff --git a/hyperactor/src/actor.rs b/hyperactor/src/actor.rs index 20f370b0b..5d711f459 100644 --- a/hyperactor/src/actor.rs +++ b/hyperactor/src/actor.rs @@ -689,7 +689,7 @@ impl Clone for ActorHandle { /// remote references across process boundaries. /// /// It is not limited to concrete [`Actor`] implementations. For -/// example, façade types generated by [`alias!`] implement +/// example, façade types generated by [`behavior!`] implement /// `Referable` so that you can hand out restricted or stable APIs /// while still using the same remote messaging machinery. /// @@ -700,7 +700,7 @@ impl Clone for ActorHandle { /// boundaries. /// /// In contrast, [`RemotableActor`] is the trait that marks *actors* -/// that can actually be **spawned remotely**. An alias type may be a +/// that can actually be **spawned remotely**. A behavior may be a /// `Referable` but is never a `RemotableActor`. pub trait Referable: Named + Send + Sync {} @@ -1033,15 +1033,15 @@ mod tests { } #[tokio::test] - async fn test_ref_alias() { + async fn test_ref_behavior() { let test = MultiValuesTest::new().await; test.send(123u64); test.send("foo".to_string()); - hyperactor::alias!(MyActorAlias, u64, String); + hyperactor::behavior!(MyActorBehavior, u64, String); - let myref: ActorRef = test.handle.bind(); + let myref: ActorRef = test.handle.bind(); myref.port().send(&test.client, "biz".to_string()).unwrap(); myref.port().send(&test.client, 999u64).unwrap(); diff --git a/hyperactor/src/lib.rs b/hyperactor/src/lib.rs index 8c0caf458..4e9c4596d 100644 --- a/hyperactor/src/lib.rs +++ b/hyperactor/src/lib.rs @@ -128,7 +128,7 @@ pub use hyperactor_macros::RefClient; #[doc(inline)] pub use hyperactor_macros::Unbind; #[doc(inline)] -pub use hyperactor_macros::alias; +pub use hyperactor_macros::behavior; #[doc(inline)] pub use hyperactor_macros::export; #[doc(inline)] diff --git a/hyperactor_macros/src/lib.rs b/hyperactor_macros/src/lib.rs index 6e4a909ad..20e41b214 100644 --- a/hyperactor_macros/src/lib.rs +++ b/hyperactor_macros/src/lib.rs @@ -1603,31 +1603,31 @@ pub fn export(attr: TokenStream, item: TokenStream) -> TokenStream { TokenStream::from(expanded) } -/// Represents the full input to [`fn alias`]. -struct AliasInput { - alias: Ident, +/// Represents the full input to [`fn behavior`]. +struct BehaviorInput { + behavior: Ident, handlers: Vec, } -impl syn::parse::Parse for AliasInput { +impl syn::parse::Parse for BehaviorInput { fn parse(input: syn::parse::ParseStream) -> syn::Result { - let alias: Ident = input.parse()?; + let behavior: Ident = input.parse()?; let _: Token![,] = input.parse()?; let raw_handlers = input.parse_terminated(HandlerSpec::parse, Token![,])?; let handlers = raw_handlers.into_iter().collect(); - Ok(AliasInput { alias, handlers }) + Ok(BehaviorInput { behavior, handlers }) } } -/// Create a [`Referable`] handling a specific set of message types. -/// This is used to create an [`ActorRef`] without having to depend on the +/// Create a [`Referable`] definition, handling a specific set of message types. +/// Behaviors are used to create an [`ActorRef`] without having to depend on the /// actor's implementation. If the message type need to be cast, add `castable` -/// flag to those types. e.g. the following example creats an alias with 5 +/// flag to those types. e.g. the following example creates a behavior with 5 /// message types, and 4 of which need to be cast. /// /// ``` -/// hyperactor::alias!( -/// TestActorAlias, +/// hyperactor::behavior!( +/// TestActorBehavior, /// TestMessage { castable = true }, /// () {castable = true }, /// MyGeneric<()> {castable = true }, @@ -1635,17 +1635,20 @@ impl syn::parse::Parse for AliasInput { /// ); /// ``` #[proc_macro] -pub fn alias(input: TokenStream) -> TokenStream { - let AliasInput { alias, handlers } = parse_macro_input!(input as AliasInput); +pub fn behavior(input: TokenStream) -> TokenStream { + let BehaviorInput { + behavior: behavior, + handlers, + } = parse_macro_input!(input as BehaviorInput); let tys = HandlerSpec::add_indexed(handlers); let expanded = quote! { - #[doc = "The generated alias struct."] + #[doc = "The generated behavior struct."] #[derive(Debug, hyperactor::Named, serde::Serialize, serde::Deserialize)] - pub struct #alias; - impl hyperactor::actor::Referable for #alias {} + pub struct #behavior; + impl hyperactor::actor::Referable for #behavior {} - impl hyperactor::actor::Binds for #alias + impl hyperactor::actor::Binds for #behavior where A: hyperactor::Actor #(+ hyperactor::Handler<#tys>)* { fn bind(ports: &hyperactor::proc::Ports) { @@ -1656,7 +1659,7 @@ pub fn alias(input: TokenStream) -> TokenStream { } #( - impl hyperactor::actor::RemoteHandles<#tys> for #alias {} + impl hyperactor::actor::RemoteHandles<#tys> for #behavior {} )* }; diff --git a/hyperactor_macros/tests/export.rs b/hyperactor_macros/tests/export.rs index 82c4c5aef..81d22d4f8 100644 --- a/hyperactor_macros/tests/export.rs +++ b/hyperactor_macros/tests/export.rs @@ -85,7 +85,7 @@ impl Handler for TestActor { } } -hyperactor::alias!( +hyperactor::behavior!( TestActorAlias, TestMessage { cast = true }, () { cast = true }, diff --git a/hyperactor_multiprocess/src/supervision.rs b/hyperactor_multiprocess/src/supervision.rs index bbb08fc1e..ded8f44fe 100644 --- a/hyperactor_multiprocess/src/supervision.rs +++ b/hyperactor_multiprocess/src/supervision.rs @@ -133,6 +133,6 @@ impl ProcSupervisionState { } } -hyperactor::alias!(ProcSupervisor, ProcSupervisionMessage); // For proc supervisor to implement (e.g. system actor) -hyperactor::alias!(WorldSupervisor, WorldSupervisionMessage); // For world supervisor to implement (e.g. system actor) -hyperactor::alias!(SupervisionClient, WorldSupervisionState); // For the end receiver of supervision events to implement (e.g. client) +hyperactor::behavior!(ProcSupervisor, ProcSupervisionMessage); // For proc supervisor to implement (e.g. system actor) +hyperactor::behavior!(WorldSupervisor, WorldSupervisionMessage); // For world supervisor to implement (e.g. system actor) +hyperactor::behavior!(SupervisionClient, WorldSupervisionState); // For the end receiver of supervision events to implement (e.g. client) diff --git a/monarch_messages/src/client.rs b/monarch_messages/src/client.rs index c50376843..d0a961b89 100644 --- a/monarch_messages/src/client.rs +++ b/monarch_messages/src/client.rs @@ -95,4 +95,4 @@ pub enum ClientMessage { }, } -hyperactor::alias!(ClientActor, ClientMessage); +hyperactor::behavior!(ClientActor, ClientMessage); diff --git a/monarch_messages/src/controller.rs b/monarch_messages/src/controller.rs index 7c40130f5..8d59ca592 100644 --- a/monarch_messages/src/controller.rs +++ b/monarch_messages/src/controller.rs @@ -237,4 +237,4 @@ pub enum ControllerMessage { }, } -hyperactor::alias!(ControllerActor, ControllerMessage); +hyperactor::behavior!(ControllerActor, ControllerMessage); diff --git a/monarch_messages/src/debugger.rs b/monarch_messages/src/debugger.rs index 633e38cfc..7794cf53b 100644 --- a/monarch_messages/src/debugger.rs +++ b/monarch_messages/src/debugger.rs @@ -55,7 +55,7 @@ pub enum DebuggerMessage { Action { action: DebuggerAction }, } -hyperactor::alias!( +hyperactor::behavior!( DebuggerActor, DebuggerMessage { cast = true }, ); diff --git a/monarch_messages/src/worker.rs b/monarch_messages/src/worker.rs index b9d7f1a06..255571b90 100644 --- a/monarch_messages/src/worker.rs +++ b/monarch_messages/src/worker.rs @@ -941,7 +941,7 @@ pub struct WorkerParams { pub controller_actor: ActorRef, } -hyperactor::alias!( +hyperactor::behavior!( WorkerActor, WorkerMessage { cast = true }, );