Packages
spawn
2.0.0-RC1
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/spawn/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 Unnameds,
// 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 action ║ ║ ║
// ║◀──┘ ║ ║ ║ ║ 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 spawn;
import "spawn/actors/actor.proto";
import "google/protobuf/any.proto";
import "google/protobuf/timestamp.proto";
option java_package = "io.spawn";
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 that comes in invocations
// * tags: Meta information stored in the actor
// * caller: ActorId of who is calling target actor
// * self: ActorId of itself
message Context {
google.protobuf.Any state = 1;
map<string, string> metadata = 4;
map<string, string> tags = 5;
// Who is calling target actor
spawn.actors.ActorId caller = 2;
// The target actor itself
spawn.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 {}
// 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;
spawn.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 spawn.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 {
// Target topic or channel
// Change this to channel
string channel_group = 1;
// Payload
oneof payload {
google.protobuf.Any value = 3;
Noop noop = 4;
}
}
// 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;
// Action.
string action_name = 2;
}
// 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;
// Action.
string action_name = 2;
}
// Facts are emitted by actions and represent the internal state of the moment
// at that moment. These are treated by Projections so that visualizations can
// be built around these states.
message Fact {
string uuid = 1;
google.protobuf.Any state = 2;
map<string, string> metadata = 3;
google.protobuf.Timestamp timestamp = 4;
}
// 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
// * 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 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
// * register_ref: If the invocation should register the specific actor with
// the given name without having to call register before
message InvocationRequest {
spawn.actors.ActorSystem system = 1;
spawn.actors.Actor actor = 2;
string action_name = 3;
oneof payload {
google.protobuf.Any value = 4;
Noop noop = 7;
}
bool async = 5;
spawn.actors.ActorId caller = 6;
map<string, string> metadata = 8;
int64 scheduled_to = 9;
bool pooled = 10;
string register_ref = 11;
}
// 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.
// * 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 action_name.
message ActorInvocation {
spawn.actors.ActorId actor = 1;
string action_name = 2;
Context current_context = 3;
oneof payload {
google.protobuf.Any value = 4;
Noop noop = 5;
}
spawn.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;
bool checkpoint = 7;
}
// 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;
spawn.actors.ActorSystem system = 2;
spawn.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;
}