syntax = "proto3";

package eigr.functions.protocol.actors;

import "google/protobuf/any.proto";

option java_package = "io.eigr.functions.protocol.actors";
option go_package = "github.com/eigr/go-support/eigr/actors;actors";

message Registry {
    map<string, Actor> actors = 1;
}

message ActorSystem {
    string name = 1;
    Registry registry = 2;
}

// A strategy for save state.
message ActorSnapshotStrategy {
    oneof strategy {
        // the timeout strategy.
        TimeoutStrategy timeout = 1;
    }
}

// A strategy which a user function's entity is passivated.
message ActorDeactivationStrategy {
    oneof strategy {
        // the timeout strategy.
        TimeoutStrategy timeout = 1;
    }
}

// A strategy based on a timeout. 
message TimeoutStrategy {
    // The timeout in millis
    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. 
// It just represents an action that supporting languages can invoke.
message Command {

    // 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 
// 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)
message FixedTimerCommand {

    // The time to wait until the command is triggered
    int32 seconds = 1;

    // See Command description Above
    Command command = 2;
}

message ActorState {
    map<string, string> tags = 1;
    google.protobuf.Any state = 2;
}

// TODO doc here
message Metadata {
    // A channel group represents a way to send commands to various actors 
    // that belong to a certain semantic group.
    string channel_group = 1;

    map<string, string> tags = 2;
}

message ActorSettings {

    // Indicates if actor´s is abstract or non abstract.
    bool abstract = 1;

    // Indicates whether an actor's state should be persisted in a definitive store.
    bool persistent = 2;

    // Snapshot strategy
    ActorSnapshotStrategy snapshot_strategy = 3;

    // Deactivate strategy
    ActorDeactivationStrategy deactivation_strategy = 4;
}

message ActorId {
    // The name of a Actor Entity.
    string name = 1;

    // Name of a ActorSystem
    string system = 2;

    // When the Actor is of the Abstract type, 
    // the name of the parent Actor must be informed here.
    string parent = 3;
}

message Actor {
    // Actor Identification
    ActorId id = 1;

    // A Actor state.
    ActorState state = 2;

    // Actor metadata
    Metadata metadata = 6;

    // Actor settings.
    ActorSettings settings = 3;

    // The commands registered for an actor
    repeated Command commands = 4;

    // The registered timer commands for an actor.
    repeated FixedTimerCommand timer_commands = 5;
}