From 13b6d462ea92e88d07478333eaab106e1cc8c86c Mon Sep 17 00:00:00 2001 From: Adriano Santos Date: Sat, 16 Sep 2023 16:21:47 -0300 Subject: [PATCH] Update protobuf --- spawn-rs/proto/actor.proto | 46 +-- spawn-rs/proto/protocol.proto | 45 ++- spawn-rs/src/eigr/eigr.spawn.rs | 602 -------------------------------- spawn-rs/src/eigr/spawn.rs | 96 ++--- spawn-rs/src/spawn.rs | 20 +- 5 files changed, 120 insertions(+), 689 deletions(-) delete mode 100644 spawn-rs/src/eigr/eigr.spawn.rs diff --git a/spawn-rs/proto/actor.proto b/spawn-rs/proto/actor.proto index acfc094..f3d4323 100644 --- a/spawn-rs/proto/actor.proto +++ b/spawn-rs/proto/actor.proto @@ -38,27 +38,27 @@ message TimeoutStrategy { int64 timeout = 1; } -// A command represents an action that the user can perform on an Actor. -// Commands in supporting languages are represented by functions or methods. -// An Actor command has nothing to do with the semantics of Commands in a CQRS/EventSourced system. +// A action represents an action that the user can perform on an Actor. +// Actions in supporting languages are represented by functions or methods. +// An Actor action has nothing to do with the semantics of Actions in a CQRS/EventSourced system. // It just represents an action that supporting languages can invoke. -message Command { +message Action { // The name of the function or method in the supporting language that has been registered in Ator. string name = 1; } -// A FixedTimerCommand is similar to a regular Command, its main differences are that it is scheduled to run at regular intervals +// A FixedTimerAction is similar to a regular Action, its main differences are that it is scheduled to run at regular intervals // and only takes the actor's state as an argument. -// Timer Commands are good for executing loops that manipulate the actor's own state. +// Timer Actions are good for executing loops that manipulate the actor's own state. // In Elixir or other languages in BEAM it would be similar to invoking Process.send_after(self(), atom, msg, timeout) -message FixedTimerCommand { +message FixedTimerAction { - // The time to wait until the command is triggered + // The time to wait until the action is triggered int32 seconds = 1; - // See Command description Above - Command command = 2; + // See Action description Above + Action action = 2; } message ActorState { @@ -68,7 +68,7 @@ message ActorState { // TODO doc here message Metadata { - // A channel group represents a way to send commands to various actors + // A channel group represents a way to send actions to various actors // that belong to a certain semantic group. string channel_group = 1; @@ -79,17 +79,17 @@ message Metadata { // Regardless of the type of actor it is important that // all actors are registered during the proxy and host initialization phase. enum Kind { - // When no type is informed, the default to be assumed will be the Singleton pattern. + // When no type is informed, the default to be assumed will be the Named pattern. UNKNOW_KIND = 0; - // Abstract actors are used to create children of this based actor at runtime - ABSTRACT = 1; + // NAMED actors are used to create children of this based actor at runtime + NAMED = 1; - // Singleton actors as the name suggests have only one real instance of themselves running - // during their entire lifecycle. That is, they are the opposite of the Abstract type Actors. - SINGLETON = 2; + // UNAMED actors as the name suggests have only one real instance of themselves running + // during their entire lifecycle. That is, they are the opposite of the NAMED type Actors. + UNAMED = 2; - // Pooled Actors are similar to abstract actors, but unlike them, + // Pooled Actors are similar to Unamed actors, but unlike them, // their identifying name will always be the one registered at the system initialization stage. // The great advantage of Pooled actors is that they have multiple instances of themselves // acting as a request service pool. @@ -134,7 +134,7 @@ message ActorId { // Name of a ActorSystem string system = 2; - // When the Actor is of the Abstract type, + // When the Actor is of the Unamed type, // the name of the parent Actor must be informed here. string parent = 3; } @@ -152,9 +152,9 @@ message Actor { // Actor settings. ActorSettings settings = 3; - // The commands registered for an actor - repeated Command commands = 4; + // The actions registered for an actor + repeated Action actions = 4; - // The registered timer commands for an actor. - repeated FixedTimerCommand timer_commands = 5; + // The registered timer actions for an actor. + repeated FixedTimerAction timer_actions = 5; } \ No newline at end of file diff --git a/spawn-rs/proto/protocol.proto b/spawn-rs/proto/protocol.proto index f0d6823..8589a62 100644 --- a/spawn-rs/proto/protocol.proto +++ b/spawn-rs/proto/protocol.proto @@ -58,7 +58,7 @@ // // Actors are usually created at the beginning of the SDK's communication flow with the Proxy by the registration step described above. // However, some use cases require that Actors can be created ***on the fly***. -// In other words, Spawn is used to bring to life Actors previously registered as Abstracts, giving them a name and thus creating a concrete instance +// In other words, Spawn is used to bring to life Actors previously registered as Unameds, giving them a name and thus creating a concrete instance // at runtime for that Actor. Actors created with the Spawn feature are generally used when you want to share a behavior while maintaining // the isolation characteristics of the actors. // For these situations we have the Spawning flow described below. @@ -135,7 +135,7 @@ // ║ ║ ║ ║ // ║ ║ ╠───┐ ║ // ║ ║ ║ │Handle request, ║ -// ║ ║ ║ │execute command ║ +// ║ ║ ║ │execute action ║ // ║ ║ ║◀──┘ ║ // ║ ║ ║ Reply with the ║ // ║ ║ ╠────────────result and the ────────▶║ @@ -192,6 +192,12 @@ message Context { // he does not care about the input value only with the state. message Noop {} +// JSON is an alternative that some SDKs can opt in +// it will bypass any type validation in spawn actors state / payloads +message JSONType { + string content = 1; +} + message RegistrationRequest { ServiceInfo service_info = 1; @@ -271,8 +277,8 @@ message Broadcast { // Channel of target Actors string channel_group = 1; - // Command. Only Actors that have this command will run successfully - string command_name = 2; + // Action. Only Actors that have this action will run successfully + string action_name = 2; // Payload oneof payload { @@ -281,26 +287,26 @@ message Broadcast { } } -// Sends the output of a command of an Actor to the input of another command of an Actor +// Sends the output of a action of an Actor to the input of another action of an Actor // Useful for handle `pipes` pattern: // https://www.enterpriseintegrationpatterns.com/patterns/messaging/PipesAndFilters.html message Pipe { // Target Actor string actor = 1; - // Command. - string command_name = 2; + // Action. + string action_name = 2; } -// Sends the input of a command of an Actor to the input of another command of an Actor +// Sends the input of a action of an Actor to the input of another action of an Actor // Useful for handle `content-basead router` pattern // https://www.enterpriseintegrationpatterns.com/patterns/messaging/ContentBasedRouter.html message Forward { // Target Actor string actor = 1; - // Command. - string command_name = 2; + // Action. + string action_name = 2; } // Container for archicetural message patterns @@ -322,11 +328,11 @@ message Workflow { // * system: See ActorSystem message. // * actor: The target Actor, i.e. the one that the user function is calling to perform some computation. // * caller: The caller Actor -// * command_name: The function or method on the target Actor that will receive this request +// * action_name: The function or method on the target Actor that will receive this request // and perform some useful computation with the sent data. -// * value: This is the value sent by the user function to be computed by the request's target Actor command. -// * async: Indicates whether the command should be processed synchronously, where a response should be sent back to the user function, -// or whether the command should be processed asynchronously, i.e. no response sent to the caller and no waiting. +// * value: This is the value sent by the user function to be computed by the request's target Actor action. +// * async: Indicates whether the action should be processed synchronously, where a response should be sent back to the user function, +// or whether the action should be processed asynchronously, i.e. no response sent to the caller and no waiting. // * metadata: Meta information or headers message InvocationRequest { @@ -334,7 +340,7 @@ message InvocationRequest { eigr.spawn.Actor actor = 2; - string command_name = 3; + string action_name = 3; oneof payload { google.protobuf.Any value = 4; @@ -357,17 +363,17 @@ message InvocationRequest { // // Params: // * actor: The ActorId handling the InvocationRequest request, also called the target Actor. -// * command_name: The function or method on the target Actor that will receive this request +// * action_name: The function or method on the target Actor that will receive this request // and perform some useful computation with the sent data. // * current_context: The current Context with current state value of the target Actor. // That is, the same as found via matching in %Actor{name: target_actor, state: %ActorState{state: value} = actor_state}. // In this case, the Context type will contain in the value attribute the same `value` as the matching above. -// * payload: The value to be passed to the function or method corresponding to command_name. +// * payload: The value to be passed to the function or method corresponding to action_name. message ActorInvocation { eigr.spawn.ActorId actor = 1; - string command_name = 2; + string action_name = 2; Context current_context = 3; @@ -401,6 +407,8 @@ message ActorInvocationResponse { } Workflow workflow = 5; + + bool checkpoint = 7; } // InvocationResponse is the response that the proxy that received the InvocationRequest request will forward to the request's original user function. @@ -442,4 +450,3 @@ message RequestStatus { string message = 2; } - diff --git a/spawn-rs/src/eigr/eigr.spawn.rs b/spawn-rs/src/eigr/eigr.spawn.rs deleted file mode 100644 index 39fa9c4..0000000 --- a/spawn-rs/src/eigr/eigr.spawn.rs +++ /dev/null @@ -1,602 +0,0 @@ -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Registry { - #[prost(map = "string, message", tag = "1")] - pub actors: ::std::collections::HashMap<::prost::alloc::string::String, Actor>, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ActorSystem { - #[prost(string, tag = "1")] - pub name: ::prost::alloc::string::String, - #[prost(message, optional, tag = "2")] - pub registry: ::core::option::Option, -} -/// A strategy for save state. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ActorSnapshotStrategy { - #[prost(oneof = "actor_snapshot_strategy::Strategy", tags = "1")] - pub strategy: ::core::option::Option, -} -/// Nested message and enum types in `ActorSnapshotStrategy`. -pub mod actor_snapshot_strategy { - #[allow(clippy::derive_partial_eq_without_eq)] - #[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum Strategy { - /// the timeout strategy. - #[prost(message, tag = "1")] - Timeout(super::TimeoutStrategy), - } -} -/// A strategy which a user function's entity is passivated. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ActorDeactivationStrategy { - #[prost(oneof = "actor_deactivation_strategy::Strategy", tags = "1")] - pub strategy: ::core::option::Option, -} -/// Nested message and enum types in `ActorDeactivationStrategy`. -pub mod actor_deactivation_strategy { - #[allow(clippy::derive_partial_eq_without_eq)] - #[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum Strategy { - /// the timeout strategy. - #[prost(message, tag = "1")] - Timeout(super::TimeoutStrategy), - } -} -/// A strategy based on a timeout. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct TimeoutStrategy { - /// The timeout in millis - #[prost(int64, tag = "1")] - pub timeout: i64, -} -/// A command represents an action that the user can perform on an Actor. -/// Commands in supporting languages are represented by functions or methods. -/// An Actor command has nothing to do with the semantics of Commands in a CQRS/EventSourced system. -/// It just represents an action that supporting languages can invoke. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Command { - /// The name of the function or method in the supporting language that has been registered in Ator. - #[prost(string, tag = "1")] - pub name: ::prost::alloc::string::String, -} -/// A FixedTimerCommand is similar to a regular Command, its main differences are that it is scheduled to run at regular intervals -/// and only takes the actor's state as an argument. -/// Timer Commands are good for executing loops that manipulate the actor's own state. -/// In Elixir or other languages in BEAM it would be similar to invoking Process.send_after(self(), atom, msg, timeout) -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct FixedTimerCommand { - /// The time to wait until the command is triggered - #[prost(int32, tag = "1")] - pub seconds: i32, - /// See Command description Above - #[prost(message, optional, tag = "2")] - pub command: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ActorState { - #[prost(map = "string, string", tag = "1")] - pub tags: ::std::collections::HashMap< - ::prost::alloc::string::String, - ::prost::alloc::string::String, - >, - #[prost(message, optional, tag = "2")] - pub state: ::core::option::Option<::prost_types::Any>, -} -/// TODO doc here -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Metadata { - /// A channel group represents a way to send commands to various actors - /// that belong to a certain semantic group. - #[prost(string, tag = "1")] - pub channel_group: ::prost::alloc::string::String, - #[prost(map = "string, string", tag = "2")] - pub tags: ::std::collections::HashMap< - ::prost::alloc::string::String, - ::prost::alloc::string::String, - >, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ActorSettings { - /// Indicates the type of Actor to be configured. - #[prost(enumeration = "Kind", tag = "1")] - pub kind: i32, - /// Indicates whether an actor's state should be persisted in a definitive store. - #[prost(bool, tag = "2")] - pub stateful: bool, - /// Snapshot strategy - #[prost(message, optional, tag = "3")] - pub snapshot_strategy: ::core::option::Option, - /// Deactivate strategy - #[prost(message, optional, tag = "4")] - pub deactivation_strategy: ::core::option::Option, - /// When kind is POOLED this is used to define minimun actor instances - #[prost(int32, tag = "5")] - pub min_pool_size: i32, - /// When kind is POOLED this is used to define maximum actor instances - #[prost(int32, tag = "6")] - pub max_pool_size: i32, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ActorId { - /// The name of a Actor Entity. - #[prost(string, tag = "1")] - pub name: ::prost::alloc::string::String, - /// Name of a ActorSystem - #[prost(string, tag = "2")] - pub system: ::prost::alloc::string::String, - /// When the Actor is of the Abstract type, - /// the name of the parent Actor must be informed here. - #[prost(string, tag = "3")] - pub parent: ::prost::alloc::string::String, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Actor { - /// Actor Identification - #[prost(message, optional, tag = "1")] - pub id: ::core::option::Option, - /// A Actor state. - #[prost(message, optional, tag = "2")] - pub state: ::core::option::Option, - /// Actor metadata - #[prost(message, optional, tag = "6")] - pub metadata: ::core::option::Option, - /// Actor settings. - #[prost(message, optional, tag = "3")] - pub settings: ::core::option::Option, - /// The commands registered for an actor - #[prost(message, repeated, tag = "4")] - pub commands: ::prost::alloc::vec::Vec, - /// The registered timer commands for an actor. - #[prost(message, repeated, tag = "5")] - pub timer_commands: ::prost::alloc::vec::Vec, -} -/// The type that defines the runtime characteristics of the Actor. -/// Regardless of the type of actor it is important that -/// all actors are registered during the proxy and host initialization phase. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] -#[repr(i32)] -pub enum Kind { - /// When no type is informed, the default to be assumed will be the Singleton pattern. - UnknowKind = 0, - /// Abstract actors are used to create children of this based actor at runtime - Abstract = 1, - /// Singleton actors as the name suggests have only one real instance of themselves running - /// during their entire lifecycle. That is, they are the opposite of the Abstract type Actors. - Singleton = 2, - /// Pooled Actors are similar to abstract actors, but unlike them, - /// their identifying name will always be the one registered at the system initialization stage. - /// The great advantage of Pooled actors is that they have multiple instances of themselves - /// acting as a request service pool. - /// Pooled actors are also stateless actors, that is, they will not have their - /// in-memory state persisted via Statesstore. This is done to avoid problems - /// with the correctness of the stored state. - /// Pooled Actors are generally used for tasks where the Actor Model would perform worse - /// than other concurrency models and for tasks that do not require state concerns. - /// Integration flows, data caching, proxies are good examples of use cases - /// for this type of Actor. - Pooled = 3, - /// Reserved for future use - Proxy = 4, -} -impl Kind { - /// String value of the enum field names used in the ProtoBuf definition. - /// - /// The values are not transformed in any way and thus are considered stable - /// (if the ProtoBuf definition does not change) and safe for programmatic use. - pub fn as_str_name(&self) -> &'static str { - match self { - Kind::UnknowKind => "UNKNOW_KIND", - Kind::Abstract => "ABSTRACT", - Kind::Singleton => "SINGLETON", - Kind::Pooled => "POOLED", - Kind::Proxy => "PROXY", - } - } - /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { - match value { - "UNKNOW_KIND" => Some(Self::UnknowKind), - "ABSTRACT" => Some(Self::Abstract), - "SINGLETON" => Some(Self::Singleton), - "POOLED" => Some(Self::Pooled), - "PROXY" => Some(Self::Proxy), - _ => None, - } - } -} -/// Context is where current and/or updated state is stored -/// to be transmitted to/from proxy and user function -/// -/// Params: -/// * state: Actor state passed back and forth between proxy and user function. -/// * metadata: Meta information that comes in invocations -/// * tags: Meta information stored in the actor -/// * caller: ActorId of who is calling target actor -/// * self: ActorId of itself -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Context { - #[prost(message, optional, tag = "1")] - pub state: ::core::option::Option<::prost_types::Any>, - #[prost(map = "string, string", tag = "4")] - pub metadata: ::std::collections::HashMap< - ::prost::alloc::string::String, - ::prost::alloc::string::String, - >, - #[prost(map = "string, string", tag = "5")] - pub tags: ::std::collections::HashMap< - ::prost::alloc::string::String, - ::prost::alloc::string::String, - >, - /// Who is calling target actor - #[prost(message, optional, tag = "2")] - pub caller: ::core::option::Option, - /// The target actor itself - #[prost(message, optional, tag = "3")] - pub self_: ::core::option::Option, -} -/// Noop is used when the input or output value of a function or method -/// does not matter to the caller of a Workflow or when the user just wants to receive -/// the Context in the request, that is, -/// he does not care about the input value only with the state. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Noop {} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct RegistrationRequest { - #[prost(message, optional, tag = "1")] - pub service_info: ::core::option::Option, - #[prost(message, optional, tag = "2")] - pub actor_system: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct RegistrationResponse { - #[prost(message, optional, tag = "1")] - pub status: ::core::option::Option, - #[prost(message, optional, tag = "2")] - pub proxy_info: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ServiceInfo { - /// The name of the actor system, eg, "my-actor-system". - #[prost(string, tag = "1")] - pub service_name: ::prost::alloc::string::String, - /// The version of the service. - #[prost(string, tag = "2")] - pub service_version: ::prost::alloc::string::String, - /// A description of the runtime for the service. Can be anything, but examples might be: - /// - node v10.15.2 - /// - OpenJDK Runtime Environment 1.8.0_192-b12 - #[prost(string, tag = "3")] - pub service_runtime: ::prost::alloc::string::String, - /// If using a support library, the name of that library, eg "spawn-jvm" - #[prost(string, tag = "4")] - pub support_library_name: ::prost::alloc::string::String, - /// The version of the support library being used. - #[prost(string, tag = "5")] - pub support_library_version: ::prost::alloc::string::String, - /// Spawn protocol major version accepted by the support library. - #[prost(int32, tag = "6")] - pub protocol_major_version: i32, - /// Spawn protocol minor version accepted by the support library. - #[prost(int32, tag = "7")] - pub protocol_minor_version: i32, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct SpawnRequest { - #[prost(message, repeated, tag = "1")] - pub actors: ::prost::alloc::vec::Vec, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct SpawnResponse { - #[prost(message, optional, tag = "1")] - pub status: ::core::option::Option, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ProxyInfo { - #[prost(int32, tag = "1")] - pub protocol_major_version: i32, - #[prost(int32, tag = "2")] - pub protocol_minor_version: i32, - #[prost(string, tag = "3")] - pub proxy_name: ::prost::alloc::string::String, - #[prost(string, tag = "4")] - pub proxy_version: ::prost::alloc::string::String, -} -/// When a Host Function is invoked it returns the updated state and return value to the call. -/// It can also return a number of side effects to other Actors as a result of its computation. -/// These side effects will be forwarded to the respective Actors asynchronously and should not affect the Host Function's response to its caller. -/// Internally side effects is just a special kind of InvocationRequest. -/// Useful for handle handle `recipient list` and `Composed Message Processor` patterns: -/// -/// -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct SideEffect { - #[prost(message, optional, tag = "1")] - pub request: ::core::option::Option, -} -/// Broadcast a message to many Actors -/// Useful for handle `recipient list`, `publish-subscribe channel`, and `scatter-gatther` patterns: -/// -/// -/// -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Broadcast { - /// Channel of target Actors - #[prost(string, tag = "1")] - pub channel_group: ::prost::alloc::string::String, - /// Command. Only Actors that have this command will run successfully - #[prost(string, tag = "2")] - pub command_name: ::prost::alloc::string::String, - /// Payload - #[prost(oneof = "broadcast::Payload", tags = "3, 4")] - pub payload: ::core::option::Option, -} -/// Nested message and enum types in `Broadcast`. -pub mod broadcast { - /// Payload - #[allow(clippy::derive_partial_eq_without_eq)] - #[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum Payload { - #[prost(message, tag = "3")] - Value(::prost_types::Any), - #[prost(message, tag = "4")] - Noop(super::Noop), - } -} -/// Sends the output of a command of an Actor to the input of another command of an Actor -/// Useful for handle `pipes` pattern: -/// -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Pipe { - /// Target Actor - #[prost(string, tag = "1")] - pub actor: ::prost::alloc::string::String, - /// Command. - #[prost(string, tag = "2")] - pub command_name: ::prost::alloc::string::String, -} -/// Sends the input of a command of an Actor to the input of another command of an Actor -/// Useful for handle `content-basead router` pattern -/// -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Forward { - /// Target Actor - #[prost(string, tag = "1")] - pub actor: ::prost::alloc::string::String, - /// Command. - #[prost(string, tag = "2")] - pub command_name: ::prost::alloc::string::String, -} -/// Container for archicetural message patterns -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Workflow { - #[prost(message, optional, tag = "2")] - pub broadcast: ::core::option::Option, - #[prost(message, repeated, tag = "1")] - pub effects: ::prost::alloc::vec::Vec, - #[prost(oneof = "workflow::Routing", tags = "3, 4")] - pub routing: ::core::option::Option, -} -/// Nested message and enum types in `Workflow`. -pub mod workflow { - #[allow(clippy::derive_partial_eq_without_eq)] - #[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum Routing { - #[prost(message, tag = "3")] - Pipe(super::Pipe), - #[prost(message, tag = "4")] - Forward(super::Forward), - } -} -/// The user function when it wants to send a message to an Actor uses the InvocationRequest message type. -/// -/// Params: -/// * system: See ActorSystem message. -/// * actor: The target Actor, i.e. the one that the user function is calling to perform some computation. -/// * caller: The caller Actor -/// * command_name: The function or method on the target Actor that will receive this request -/// and perform some useful computation with the sent data. -/// * value: This is the value sent by the user function to be computed by the request's target Actor command. -/// * async: Indicates whether the command should be processed synchronously, where a response should be sent back to the user function, -/// or whether the command should be processed asynchronously, i.e. no response sent to the caller and no waiting. -/// * metadata: Meta information or headers -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct InvocationRequest { - #[prost(message, optional, tag = "1")] - pub system: ::core::option::Option, - #[prost(message, optional, tag = "2")] - pub actor: ::core::option::Option, - #[prost(string, tag = "3")] - pub command_name: ::prost::alloc::string::String, - #[prost(bool, tag = "5")] - pub r#async: bool, - #[prost(message, optional, tag = "6")] - pub caller: ::core::option::Option, - #[prost(map = "string, string", tag = "8")] - pub metadata: ::std::collections::HashMap< - ::prost::alloc::string::String, - ::prost::alloc::string::String, - >, - #[prost(int64, tag = "9")] - pub scheduled_to: i64, - #[prost(bool, tag = "10")] - pub pooled: bool, - #[prost(oneof = "invocation_request::Payload", tags = "4, 7")] - pub payload: ::core::option::Option, -} -/// Nested message and enum types in `InvocationRequest`. -pub mod invocation_request { - #[allow(clippy::derive_partial_eq_without_eq)] - #[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum Payload { - #[prost(message, tag = "4")] - Value(::prost_types::Any), - #[prost(message, tag = "7")] - Noop(super::Noop), - } -} -/// ActorInvocation is a translation message between a local invocation made via InvocationRequest -/// and the real Actor that intends to respond to this invocation and that can be located anywhere in the cluster. -/// -/// Params: -/// * actor: The ActorId handling the InvocationRequest request, also called the target Actor. -/// * command_name: The function or method on the target Actor that will receive this request -/// and perform some useful computation with the sent data. -/// * current_context: The current Context with current state value of the target Actor. -/// That is, the same as found via matching in %Actor{name: target_actor, state: %ActorState{state: value} = actor_state}. -/// In this case, the Context type will contain in the value attribute the same `value` as the matching above. -/// * payload: The value to be passed to the function or method corresponding to command_name. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ActorInvocation { - #[prost(message, optional, tag = "1")] - pub actor: ::core::option::Option, - #[prost(string, tag = "2")] - pub command_name: ::prost::alloc::string::String, - #[prost(message, optional, tag = "3")] - pub current_context: ::core::option::Option, - #[prost(message, optional, tag = "6")] - pub caller: ::core::option::Option, - #[prost(oneof = "actor_invocation::Payload", tags = "4, 5")] - pub payload: ::core::option::Option, -} -/// Nested message and enum types in `ActorInvocation`. -pub mod actor_invocation { - #[allow(clippy::derive_partial_eq_without_eq)] - #[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum Payload { - #[prost(message, tag = "4")] - Value(::prost_types::Any), - #[prost(message, tag = "5")] - Noop(super::Noop), - } -} -/// The user function's response after executing the action originated by the local proxy request via ActorInvocation. -/// -/// Params: -/// actor_name: The name of the Actor handling the InvocationRequest request, also called the target Actor. -/// actor_system: The name of ActorSystem registered in Registration step. -/// updated_context: The Context with updated state value of the target Actor after user function has processed a request. -/// value: The value that the original request proxy will forward in response to the InvocationRequest type request. -/// This is the final response from the point of view of the user who invoked the Actor call and its subsequent processing. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct ActorInvocationResponse { - #[prost(string, tag = "1")] - pub actor_name: ::prost::alloc::string::String, - #[prost(string, tag = "2")] - pub actor_system: ::prost::alloc::string::String, - #[prost(message, optional, tag = "3")] - pub updated_context: ::core::option::Option, - #[prost(message, optional, tag = "5")] - pub workflow: ::core::option::Option, - #[prost(oneof = "actor_invocation_response::Payload", tags = "4, 6")] - pub payload: ::core::option::Option, -} -/// Nested message and enum types in `ActorInvocationResponse`. -pub mod actor_invocation_response { - #[allow(clippy::derive_partial_eq_without_eq)] - #[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum Payload { - #[prost(message, tag = "4")] - Value(::prost_types::Any), - #[prost(message, tag = "6")] - Noop(super::Noop), - } -} -/// InvocationResponse is the response that the proxy that received the InvocationRequest request will forward to the request's original user function. -/// -/// Params: -/// status: Status of request. Could be one of [UNKNOWN, OK, ACTOR_NOT_FOUND, ERROR]. -/// system: The original ActorSystem of the InvocationRequest request. -/// actor: The target Actor originally sent in the InvocationRequest message. -/// value: The value resulting from the request processing that the target Actor made. -/// This value must be passed by the user function to the one who requested the initial request in InvocationRequest. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct InvocationResponse { - #[prost(message, optional, tag = "1")] - pub status: ::core::option::Option, - #[prost(message, optional, tag = "2")] - pub system: ::core::option::Option, - #[prost(message, optional, tag = "3")] - pub actor: ::core::option::Option, - #[prost(oneof = "invocation_response::Payload", tags = "4, 5")] - pub payload: ::core::option::Option, -} -/// Nested message and enum types in `InvocationResponse`. -pub mod invocation_response { - #[allow(clippy::derive_partial_eq_without_eq)] - #[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum Payload { - #[prost(message, tag = "4")] - Value(::prost_types::Any), - #[prost(message, tag = "5")] - Noop(super::Noop), - } -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct RequestStatus { - #[prost(enumeration = "Status", tag = "1")] - pub status: i32, - #[prost(string, tag = "2")] - pub message: ::prost::alloc::string::String, -} -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] -#[repr(i32)] -pub enum Status { - Unknown = 0, - Ok = 1, - ActorNotFound = 2, - Error = 3, -} -impl Status { - /// String value of the enum field names used in the ProtoBuf definition. - /// - /// The values are not transformed in any way and thus are considered stable - /// (if the ProtoBuf definition does not change) and safe for programmatic use. - pub fn as_str_name(&self) -> &'static str { - match self { - Status::Unknown => "UNKNOWN", - Status::Ok => "OK", - Status::ActorNotFound => "ACTOR_NOT_FOUND", - Status::Error => "ERROR", - } - } - /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { - match value { - "UNKNOWN" => Some(Self::Unknown), - "OK" => Some(Self::Ok), - "ACTOR_NOT_FOUND" => Some(Self::ActorNotFound), - "ERROR" => Some(Self::Error), - _ => None, - } - } -} diff --git a/spawn-rs/src/eigr/spawn.rs b/spawn-rs/src/eigr/spawn.rs index b92cec8..d83e964 100644 --- a/spawn-rs/src/eigr/spawn.rs +++ b/spawn-rs/src/eigr/spawn.rs @@ -54,30 +54,30 @@ pub struct TimeoutStrategy { #[prost(int64, tag = "1")] pub timeout: i64, } -/// A command represents an action that the user can perform on an Actor. -/// Commands in supporting languages are represented by functions or methods. -/// An Actor command has nothing to do with the semantics of Commands in a CQRS/EventSourced system. +/// A action represents an action that the user can perform on an Actor. +/// Actions in supporting languages are represented by functions or methods. +/// An Actor action has nothing to do with the semantics of Actions in a CQRS/EventSourced system. /// It just represents an action that supporting languages can invoke. #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] -pub struct Command { +pub struct Action { /// The name of the function or method in the supporting language that has been registered in Ator. #[prost(string, tag = "1")] pub name: ::prost::alloc::string::String, } -/// A FixedTimerCommand is similar to a regular Command, its main differences are that it is scheduled to run at regular intervals +/// A FixedTimerAction is similar to a regular Action, its main differences are that it is scheduled to run at regular intervals /// and only takes the actor's state as an argument. -/// Timer Commands are good for executing loops that manipulate the actor's own state. +/// Timer Actions are good for executing loops that manipulate the actor's own state. /// In Elixir or other languages in BEAM it would be similar to invoking Process.send_after(self(), atom, msg, timeout) #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] -pub struct FixedTimerCommand { - /// The time to wait until the command is triggered +pub struct FixedTimerAction { + /// The time to wait until the action is triggered #[prost(int32, tag = "1")] pub seconds: i32, - /// See Command description Above + /// See Action description Above #[prost(message, optional, tag = "2")] - pub command: ::core::option::Option, + pub action: ::core::option::Option, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -92,7 +92,7 @@ pub struct ActorState { #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Metadata { - /// A channel group represents a way to send commands to various actors + /// A channel group represents a way to send actions to various actors /// that belong to a certain semantic group. #[prost(string, tag = "1")] pub channel_group: ::prost::alloc::string::String, @@ -131,7 +131,7 @@ pub struct ActorId { /// Name of a ActorSystem #[prost(string, tag = "2")] pub system: ::prost::alloc::string::String, - /// When the Actor is of the Abstract type, + /// When the Actor is of the Unamed type, /// the name of the parent Actor must be informed here. #[prost(string, tag = "3")] pub parent: ::prost::alloc::string::String, @@ -151,12 +151,12 @@ pub struct Actor { /// Actor settings. #[prost(message, optional, tag = "3")] pub settings: ::core::option::Option, - /// The commands registered for an actor + /// The actions registered for an actor #[prost(message, repeated, tag = "4")] - pub commands: ::prost::alloc::vec::Vec, - /// The registered timer commands for an actor. + pub actions: ::prost::alloc::vec::Vec, + /// The registered timer actions for an actor. #[prost(message, repeated, tag = "5")] - pub timer_commands: ::prost::alloc::vec::Vec, + pub timer_actions: ::prost::alloc::vec::Vec, } /// The type that defines the runtime characteristics of the Actor. /// Regardless of the type of actor it is important that @@ -164,14 +164,14 @@ pub struct Actor { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] pub enum Kind { - /// When no type is informed, the default to be assumed will be the Singleton pattern. + /// When no type is informed, the default to be assumed will be the Named pattern. UnknowKind = 0, - /// Abstract actors are used to create children of this based actor at runtime - Abstract = 1, - /// Singleton actors as the name suggests have only one real instance of themselves running - /// during their entire lifecycle. That is, they are the opposite of the Abstract type Actors. - Singleton = 2, - /// Pooled Actors are similar to abstract actors, but unlike them, + /// NAMED actors are used to create children of this based actor at runtime + Named = 1, + /// UNAMED actors as the name suggests have only one real instance of themselves running + /// during their entire lifecycle. That is, they are the opposite of the NAMED type Actors. + Unamed = 2, + /// Pooled Actors are similar to Unamed actors, but unlike them, /// their identifying name will always be the one registered at the system initialization stage. /// The great advantage of Pooled actors is that they have multiple instances of themselves /// acting as a request service pool. @@ -194,8 +194,8 @@ impl Kind { pub fn as_str_name(&self) -> &'static str { match self { Kind::UnknowKind => "UNKNOW_KIND", - Kind::Abstract => "ABSTRACT", - Kind::Singleton => "SINGLETON", + Kind::Named => "NAMED", + Kind::Unamed => "UNAMED", Kind::Pooled => "POOLED", Kind::Proxy => "PROXY", } @@ -204,8 +204,8 @@ impl Kind { pub fn from_str_name(value: &str) -> ::core::option::Option { match value { "UNKNOW_KIND" => Some(Self::UnknowKind), - "ABSTRACT" => Some(Self::Abstract), - "SINGLETON" => Some(Self::Singleton), + "NAMED" => Some(Self::Named), + "UNAMED" => Some(Self::Unamed), "POOLED" => Some(Self::Pooled), "PROXY" => Some(Self::Proxy), _ => None, @@ -246,6 +246,14 @@ pub struct Context { #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Noop {} +/// JSON is an alternative that some SDKs can opt in +/// it will bypass any type validation in spawn actors state / payloads +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct JsonType { + #[prost(string, tag = "1")] + pub content: ::prost::alloc::string::String, +} #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct RegistrationRequest { @@ -337,9 +345,9 @@ pub struct Broadcast { /// Channel of target Actors #[prost(string, tag = "1")] pub channel_group: ::prost::alloc::string::String, - /// Command. Only Actors that have this command will run successfully + /// Action. Only Actors that have this action will run successfully #[prost(string, tag = "2")] - pub command_name: ::prost::alloc::string::String, + pub action_name: ::prost::alloc::string::String, /// Payload #[prost(oneof = "broadcast::Payload", tags = "3, 4")] pub payload: ::core::option::Option, @@ -356,7 +364,7 @@ pub mod broadcast { Noop(super::Noop), } } -/// Sends the output of a command of an Actor to the input of another command of an Actor +/// Sends the output of a action of an Actor to the input of another action of an Actor /// Useful for handle `pipes` pattern: /// #[allow(clippy::derive_partial_eq_without_eq)] @@ -365,11 +373,11 @@ pub struct Pipe { /// Target Actor #[prost(string, tag = "1")] pub actor: ::prost::alloc::string::String, - /// Command. + /// Action. #[prost(string, tag = "2")] - pub command_name: ::prost::alloc::string::String, + pub action_name: ::prost::alloc::string::String, } -/// Sends the input of a command of an Actor to the input of another command of an Actor +/// Sends the input of a action of an Actor to the input of another action of an Actor /// Useful for handle `content-basead router` pattern /// #[allow(clippy::derive_partial_eq_without_eq)] @@ -378,9 +386,9 @@ pub struct Forward { /// Target Actor #[prost(string, tag = "1")] pub actor: ::prost::alloc::string::String, - /// Command. + /// Action. #[prost(string, tag = "2")] - pub command_name: ::prost::alloc::string::String, + pub action_name: ::prost::alloc::string::String, } /// Container for archicetural message patterns #[allow(clippy::derive_partial_eq_without_eq)] @@ -410,11 +418,11 @@ pub mod workflow { /// * system: See ActorSystem message. /// * actor: The target Actor, i.e. the one that the user function is calling to perform some computation. /// * caller: The caller Actor -/// * command_name: The function or method on the target Actor that will receive this request +/// * action_name: The function or method on the target Actor that will receive this request /// and perform some useful computation with the sent data. -/// * value: This is the value sent by the user function to be computed by the request's target Actor command. -/// * async: Indicates whether the command should be processed synchronously, where a response should be sent back to the user function, -/// or whether the command should be processed asynchronously, i.e. no response sent to the caller and no waiting. +/// * value: This is the value sent by the user function to be computed by the request's target Actor action. +/// * async: Indicates whether the action should be processed synchronously, where a response should be sent back to the user function, +/// or whether the action should be processed asynchronously, i.e. no response sent to the caller and no waiting. /// * metadata: Meta information or headers #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -424,7 +432,7 @@ pub struct InvocationRequest { #[prost(message, optional, tag = "2")] pub actor: ::core::option::Option, #[prost(string, tag = "3")] - pub command_name: ::prost::alloc::string::String, + pub action_name: ::prost::alloc::string::String, #[prost(bool, tag = "5")] pub r#async: bool, #[prost(message, optional, tag = "6")] @@ -455,19 +463,19 @@ pub mod invocation_request { /// /// Params: /// * actor: The ActorId handling the InvocationRequest request, also called the target Actor. -/// * command_name: The function or method on the target Actor that will receive this request +/// * action_name: The function or method on the target Actor that will receive this request /// and perform some useful computation with the sent data. /// * current_context: The current Context with current state value of the target Actor. /// That is, the same as found via matching in %Actor{name: target_actor, state: %ActorState{state: value} = actor_state}. /// In this case, the Context type will contain in the value attribute the same `value` as the matching above. -/// * payload: The value to be passed to the function or method corresponding to command_name. +/// * payload: The value to be passed to the function or method corresponding to action_name. #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct ActorInvocation { #[prost(message, optional, tag = "1")] pub actor: ::core::option::Option, #[prost(string, tag = "2")] - pub command_name: ::prost::alloc::string::String, + pub action_name: ::prost::alloc::string::String, #[prost(message, optional, tag = "3")] pub current_context: ::core::option::Option, #[prost(message, optional, tag = "6")] @@ -505,6 +513,8 @@ pub struct ActorInvocationResponse { pub updated_context: ::core::option::Option, #[prost(message, optional, tag = "5")] pub workflow: ::core::option::Option, + #[prost(bool, tag = "7")] + pub checkpoint: bool, #[prost(oneof = "actor_invocation_response::Payload", tags = "4, 6")] pub payload: ::core::option::Option, } diff --git a/spawn-rs/src/spawn.rs b/spawn-rs/src/spawn.rs index 21470c7..df53170 100644 --- a/spawn-rs/src/spawn.rs +++ b/spawn-rs/src/spawn.rs @@ -1,18 +1,34 @@ use crate::actor::ActorDefinition; +use crate::eigr::spawn::{ActorId, ActorInvocation, ActorInvocationResponse, Context}; use crate::handler::actor_router::Handler; +use prost::Message; use rocket::post; use rocket::data::{Data, ToByteUnit}; use rocket::State; +use std::io; +use std::io::Cursor; + #[post( "/api/v1/actors/actions", format = "application/octet-stream", data = "" )] -fn handle(data: Data<'_>, _handler: &State) -> &'static str { - "Hello, world!" +async fn handle(data: Data<'_>, _handler: &State) -> io::Result> { + let bytes = data.open(2048.megabytes()).into_bytes().await?; + + let buffer = bytes.into_inner(); + let request: ActorInvocation = ActorInvocation::decode(&mut Cursor::new(buffer)).unwrap(); + let actor: ActorId = request.actor.unwrap(); + let action: String = request.action_name; + let ctx: Context = request.current_context.unwrap(); + + let mut buf: Vec = Vec::new(); + let default_response = ActorInvocationResponse::default(); + default_response.encode(&mut buf).unwrap(); + Ok(buf) } #[derive()]