Packages
spawn
0.5.0-rc.10
2.0.0-RC9
2.0.0-RC8
2.0.0-RC7
2.0.0-RC6
2.0.0-RC5
2.0.0-RC4
2.0.0-RC3
2.0.0-RC2
2.0.0-RC14
2.0.0-RC13
2.0.0-RC12
2.0.0-RC11
2.0.0-RC10
2.0.0-RC1
1.4.3
1.4.2
1.4.1
1.4.0
1.3.3
1.3.2
1.3.1
1.3.0
1.2.1
1.2.0
1.1.1
1.1.0
1.0.1
1.0.0
1.0.0-rc3
1.0.0-rc16
1.0.0-rc1
1.0.0-rc.38
1.0.0-rc.37
1.0.0-rc.36
1.0.0-rc.35
1.0.0-rc.34
1.0.0-rc.33
1.0.0-rc.32
1.0.0-rc.31
1.0.0-rc.30
1.0.0-rc.29
1.0.0-rc.28
1.0.0-rc.27
1.0.0-rc.26
1.0.0-rc.25
1.0.0-rc.24
1.0.0-rc.23
1.0.0-rc.22
1.0.0-rc.21
1.0.0-rc.20
1.0.0-rc.19
1.0.0-rc.18
1.0.0-rc.17
1.0.0-rc.2
0.6.3
0.6.2
0.6.1
0.6.0
0.5.5
0.5.4
0.5.3
0.5.1
0.5.0
0.5.0-rc.13
0.5.0-rc.12
0.5.0-rc.11
0.5.0-rc.10
0.5.0-rc.9
0.5.0-rc.8
0.5.0-rc.7
0.5.0-rc.6
0.5.0-rc.5
0.5.0-rc.3
0.5.0-alpha.13
0.5.0-alpha.12
0.5.0-alpha.11
0.5.0-alpha.10
0.5.0-alpha.9
0.5.0-alpha.8
0.5.0-alpha.7
0.5.0-alpha.6
0.5.0-alpha.5
0.5.0-alpha.4
0.5.0-alpha.3
0.5.0-alpha.2
0.5.0-alpha.1
0.1.0
Spawn is the core lib for Spawn Actors System
Current section
Files
Jump to
Current section
Files
priv/protos/eigr/functions/protocol/actors/protocol.proto
// The Spawn Protocol
//
// Spawn is divided into two main parts namely:
//
// 1. A sidecar proxy that exposes the server part of the Spawn Protocol in the form of an HTTP API.
// 2. A user function, written in any language that supports HTTP, that exposes the client part of the Spawn Protocol.
//
// Both are client and server of their counterparts.
//
// In turn, the proxy exposes an HTTP endpoint for registering a user function a.k.a ActorSystem.
//
// A user function that wants to register actors in Proxy Spawn must proceed by making a POST request to the following endpoint:
//
// `
// POST /api/v1/system HTTP 1.1
// HOST: localhost
// User-Agent: user-function-client/0.1.0 (this is just example)
// Accept: application/octet-stream
// Content-Type: application/octet-stream
//
// registration request type bytes encoded here :-)
// `
//
// The general flow of a registration action is as follows:
//
//╔═══════════════════╗ ╔═══════════════════╗ ╔═══════════════════╗
//║ User Function ║ ║Local Spawn Sidecar║ ║ Actor ║
//╚═══════════════════╝ ╚═══════════════════╝ ╚═══════════════════╝
// ║ ║ ║
// ║ ║ ║
// ║ HTTP POST ║ ║
// ║ Registration ║ ║
// ║ Request ║ ║
// ╠─────────────────────────────────────▶║ ║
// ║ ║ Upfront start Actors with ║
// ║ ╠───────BEAM Distributed Protocol─────▶║
// ║ ║ ║
// ║ ║ ╠───┐Initialize
// ║ ║ ║ │ State
// ║ ║ ║ │ Store
// ║ ║ ║◀──┘
// ║ HTTP Registration ║ ║
// ║ Response ║ ║
// ║◀─────────────────────────────────────╣ ║
// ║ ║ ║
// ║ ║ ║
// ║ ║ ║
// ║ ║ ║
// ║ ║ ║
// ║ ║ ║
// ║ ║ ║
// ║ ║ ║
//
// ███████████ ███████████ ███████████
//
//
// ## Spawning Actors
//
// 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
// 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.
//
// A user function that wants to Spawning new Actors in Proxy Spawn must proceed by making a POST request to the following endpoint:
//
// ```
// POST /system/:system_name/actors/spawn HTTP 1.1
// HOST: localhost
// User-Agent: user-function-client/0.1.0 (this is just example)
// Accept: application/octet-stream
// Content-Type: application/octet-stream
//
// SpawnRequest type bytes encoded here :-)
// ```
//
// The general flow of a Spawning Actors is as follows:
//
// ```
// +----------------+ +---------------------+ +-------+
// | User Function | | Local Spawn Sidecar | | Actor |
// +----------------+ +---------------------+ +-------+
// | | |
// | HTTP POST SpawnRequest | |
// |------------------------------------------------------>| |
// | | |
// | | Upfront start Actors with BEAM Distributed Protocol |
// | |---------------------------------------------------->|
// | | |
// | | |Initialize Statestore
// | | |----------------------
// | | | |
// | | |<---------------------
// | | |
// | HTTP SpawnResponse | |
// |<------------------------------------------------------| |
// | | |
// ```
//
// Once the system has been initialized, that is, the registration step has been successfully completed,
// then the user function will be able to make requests to the System Actors.
// This is done through a post request to the Proxy at the `/system/:name/actors/:actor_name/invoke` endpoint.
//
// A user function that wants to call actors in Proxy Spawn must proceed by making a POST request as the follow:
//
// `
// POST /system/:name/actors/:actor_name/invoke HTTP 1.1
// HOST: localhost
// User-Agent: user-function-client/0.1.0 (this is just example)
// Accept: application/octet-stream
// Content-Type: application/octet-stream
//
// invocation request type bytes encoded here :-)
// `
//
// Assuming that two user functions were registered in different separate Proxies, the above request would go the following way:
//
//╔═══════════════════╗ ╔═══════════════════╗ ╔═════════════════════════╗ ╔═════════════════════════════╗
//║ User Function ║ ║Local Spawn Sidecar║ ║ Remote User Function B ║ ║Remote Spawn Sidecar/Actor B ║
//╚═══════════════════╝ ╚═══════════════════╝ ╚═════════════════════════╝ ╚═════════════════════════════╝
// ║ HTTP POST ║ ║ ║
// ║ Registration ║ ║ ║
// ║ Request ║ ║ ║
// ╠─────────────────────────────────────▶║ ║ ║
// ║ ╠───┐ ║ ║
// ║ ║ │Lookup for ║ ║
// ║ ║ │ Actor ║ ║
// ║ ║◀──┘ ║ ║
// ║ ║ ║ BEAM Distributed ║
// ║ ╠─────────────────────────────────────╬────────────protocol call──────────▶║
// ║ ║ ║ ║
// ║ ║ ║ HTTP POST: ║
// ║ ║ ║◀──────/api/v1/actors/actions───────╣
// ║ ║ ║ ║
// ║ ║ ╠───┐ ║
// ║ ║ ║ │Handle request, ║
// ║ ║ ║ │execute command ║
// ║ ║ ║◀──┘ ║
// ║ ║ ║ Reply with the ║
// ║ ║ ╠────────────result and the ────────▶║
// ║ ║ ║ new state of ║────┐
// ║ ║ ║ ║ │
// ║ ║ ║ ║ │Store new State
// ║ ║ Send response to the ║ ║ ◀──┘
// ║ Respond to user with ║◀─────────Spawn Sidecar A────────────╬────────────────────────────────────╣
// ║ result value ║ ║ ║
// ║◀─────────────────────────────────────╣ ║ ║
// ║ ║ ║ ║
// ║ ║ ║ ║
//
// ███████████ ████████████ ███████████ ███████████
//
//
syntax = "proto3";
package eigr.functions.protocol;
import "actor.proto";
import "google/protobuf/any.proto";
option java_package = "io.eigr.functions.protocol";
option go_package = "github.com/eigr/go-support/eigr/protocol;protocol";
// 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 or headers
// * caller: ActorId of who is calling target actor
// * self: ActorId of itself
message Context {
google.protobuf.Any state = 1;
map<string, string> metadata = 4;
// Who is calling target actor
eigr.functions.protocol.actors.ActorId caller = 2;
// The target actor itself
eigr.functions.protocol.actors.ActorId self = 3;
}
// 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.
message Noop {}
message RegistrationRequest {
ServiceInfo service_info = 1;
eigr.functions.protocol.actors.ActorSystem actor_system = 2;
}
message RegistrationResponse {
RequestStatus status = 1;
ProxyInfo proxy_info = 2;
}
message ServiceInfo {
// The name of the actor system, eg, "my-actor-system".
string service_name = 1;
// The version of the service.
string service_version = 2;
// 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
string service_runtime = 3;
// If using a support library, the name of that library, eg "spawn-jvm"
string support_library_name = 4;
// The version of the support library being used.
string support_library_version = 5;
// Spawn protocol major version accepted by the support library.
int32 protocol_major_version = 6;
// Spawn protocol minor version accepted by the support library.
int32 protocol_minor_version = 7;
}
message SpawnRequest {
repeated eigr.functions.protocol.actors.ActorId actors = 1;
}
message SpawnResponse {
RequestStatus status = 1;
}
message ProxyInfo {
int32 protocol_major_version = 1;
int32 protocol_minor_version = 2;
string proxy_name = 3;
string proxy_version = 4;
}
// 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:
// https://www.enterpriseintegrationpatterns.com/patterns/messaging/RecipientList.html
// https://www.enterpriseintegrationpatterns.com/patterns/messaging/DistributionAggregate.html
message SideEffect {
InvocationRequest request = 1;
}
// Broadcast a message to many Actors
// Useful for handle `recipient list`, `publish-subscribe channel`, and `scatter-gatther` patterns:
// https://www.enterpriseintegrationpatterns.com/patterns/messaging/RecipientList.html
// https://www.enterpriseintegrationpatterns.com/patterns/messaging/PublishSubscribeChannel.html
// https://www.enterpriseintegrationpatterns.com/patterns/messaging/BroadcastAggregate.html
message Broadcast {
// Channel of target Actors
string channel_group = 1;
// Command. Only Actors that have this command will run successfully
string command_name = 2;
// Payload
oneof payload {
google.protobuf.Any value = 3;
Noop noop = 4;
}
}
// Sends the output of a command of an Actor to the input of another command 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;
}
// 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
// https://www.enterpriseintegrationpatterns.com/patterns/messaging/ContentBasedRouter.html
message Forward {
// Target Actor
string actor = 1;
// Command.
string command_name = 2;
}
// Container for archicetural message patterns
message Workflow {
Broadcast broadcast = 2;
repeated SideEffect effects = 1;
oneof routing {
Pipe pipe = 3;
Forward forward = 4;
}
}
// 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
message InvocationRequest {
eigr.functions.protocol.actors.ActorSystem system = 1;
eigr.functions.protocol.actors.Actor actor = 2;
string command_name = 3;
oneof payload {
google.protobuf.Any value = 4;
Noop noop = 7;
}
bool async = 5;
eigr.functions.protocol.actors.ActorId caller = 6;
map<string, string> metadata = 8;
int64 scheduled_to = 9;
bool pooled = 10;
}
// 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.
message ActorInvocation {
eigr.functions.protocol.actors.ActorId actor = 1;
string command_name = 2;
Context current_context = 3;
oneof payload {
google.protobuf.Any value = 4;
Noop noop = 5;
}
eigr.functions.protocol.actors.ActorId caller = 6;
}
// 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.
message ActorInvocationResponse {
string actor_name = 1;
string actor_system = 2;
Context updated_context = 3;
oneof payload {
google.protobuf.Any value = 4;
Noop noop = 6;
}
Workflow workflow = 5;
}
// 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.
message InvocationResponse {
RequestStatus status = 1;
eigr.functions.protocol.actors.ActorSystem system = 2;
eigr.functions.protocol.actors.Actor actor = 3;
oneof payload {
google.protobuf.Any value = 4;
Noop noop = 5;
}
}
enum Status {
UNKNOWN = 0;
OK = 1;
ACTOR_NOT_FOUND = 2;
ERROR = 3;
}
message RequestStatus {
Status status = 1;
string message = 2;
}