syntax = "proto3";

import "common.proto";
import "server.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/struct.proto";

package controller;

service IsolateController {
    // Run the given function on the specified environment. Streams logs
    // and the result originating from that function.
    rpc Run (HostedRun) returns (stream HostedRunResult) {}
    // Run the given function on the specified environment. Streams logs
    // and the result originating from that function. Supports streaming
    // inputs to hot reload the function.
    rpc InteractiveRun (stream InteractiveRunRequest) returns (stream InteractiveRunResponse) {}
    // Run the given function in parallel with the given inputs
    rpc Map (HostedMap) returns (stream HostedRunResult) {}
    // Creates an authentication key for a user
    rpc CreateUserKey (CreateUserKeyRequest) returns (CreateUserKeyResponse) {}
    // Lists the user's authentication keys
    rpc ListUserKeys (ListUserKeysRequest) returns (ListUserKeysResponse) {}
    // Revokes an authentication key for a user
    rpc RevokeUserKey (RevokeUserKeyRequest) returns (RevokeUserKeyResponse) {}
    // Register a funtion
    rpc RegisterApplication (RegisterApplicationRequest) returns (stream RegisterApplicationResult) {};
    // Update configuration of an existing application.
    rpc UpdateApplication (UpdateApplicationRequest) returns (UpdateApplicationResult) {};
    // List functions
    rpc ListApplications (ListApplicationsRequest) returns (ListApplicationsResult) {};
    // Delete a function
    rpc DeleteApplication (DeleteApplicationRequest) returns (DeleteApplicationResult) {};
    // Rollout an application
    rpc RolloutApplication (RolloutApplicationRequest) returns (RolloutApplicationResult) {};
    // Set alias to point to an existing application.
    rpc SetAlias (SetAliasRequest) returns (SetAliasResult) {};
    // Delete an alias.
    rpc DeleteAlias (DeleteAliasRequest) returns (DeleteAliasResult) {};
    // List aliased registered functions
    rpc ListAliases (ListAliasesRequest) returns (ListAliasesResult) {};
    // Sets a user secret.
    rpc SetSecret (SetSecretRequest) returns (SetSecretResponse) {}
    // Lists all secrets
    rpc ListSecrets (ListSecretsRequest) returns (ListSecretsResponse) {}
    // List alias runners in detail
    rpc ListAliasRunners (ListAliasRunnersRequest) returns (ListAliasRunnersResponse) {}
    // Stop a runner
    rpc StopRunner (StopRunnerRequest) returns (StopRunnerResponse) {}
    // Kill a runner
    rpc KillRunner (KillRunnerRequest) returns (KillRunnerResponse) {}
    // List all runners
    rpc ListRunners (ListRunnersRequest) returns (ListRunnersResponse) {}
    // Open interactive shell in a runner
    rpc ShellRunner (stream ShellRunnerInput) returns (stream ShellRunnerOutput) {}
}

message HostedMap {
    // Environment definitions.
    repeated EnvironmentDefinition environments = 1;
    // Machine requirements
    optional MachineRequirements machine_requirements = 2;
    // Function to run.
    SerializedObject function = 3;
    // Inputs to the function
    repeated SerializedObject inputs = 4;
}

message File {
    // File contains the hash and the relative path of the local file
    string hash = 1;
    string relative_path = 2;
}

message HostedRun {
    // Environment definitions.
    repeated EnvironmentDefinition environments = 1;
    // Machine requirements
    optional MachineRequirements machine_requirements = 2;
    // Function to run.
    SerializedObject function = 3;
    // Optional setup function to pass as the first argument to the function.
    optional SerializedObject setup_func = 4;
    // Optional files to be included
    repeated File files = 5;
}

message CreateUserKeyRequest {
    enum Scope {
        ADMIN = 0;
        API = 1;
    }

    // privilege scope of the key
    Scope scope = 1;

    // optional alias of the key
    optional string alias = 2;
}

message CreateUserKeyResponse {
    string key_secret = 1;
    string key_id = 2;
}

message ListUserKeysRequest {
    // Empty. For future use.
}

message ListUserKeysResponse {
    repeated UserKeyInfo user_keys = 1;
}

message RevokeUserKeyRequest {
    string key_id = 1;
}

message RevokeUserKeyResponse {
    // Empty. For future use.
}

message UserKeyInfo {
    string key_id = 1;
    google.protobuf.Timestamp created_at = 2;
    CreateUserKeyRequest.Scope scope = 3;
    string alias = 4;
}

message ServiceURLs {
    string playground = 1;
    string run = 2;
    string queue = 3;
    string ws = 4;
}

message HostedRunResult {
    // Unique run id / token.
    string run_id = 1;

    // Optionally the status of the current run (in terms of
    // fal cloud).
    optional HostedRunStatus status = 2;

    // The most recent logs from the run.
    repeated Log logs = 3;

    // The result of the run, if it is complete (indicated by
    // status.is_complete).
    optional SerializedObject return_value = 4;

    // Service URLs for the run
    optional ServiceURLs service_urls = 5;
}

message InteractiveRunRequest {
    HostedRun hosted_run = 1;
}

message InteractiveRunResponse {
    HostedRunResult hosted_run_result = 1;
}

message HostedRunStatus {
    enum State {
        // The run is in progress.
        IN_PROGRESS = 0;
        // The run has completed successfully.
        SUCCESS = 1;
        // The run has failed because of isolate.
        INTERNAL_FAILURE = 2;
        // TODO: probably QUEUED, etc.
    }

    // The state of the run.
    State state = 1;

    // TODO: probably a free form struct for more detailed
    // information (how it crashed, position in queue, etc).
}

message MachineRequirements {
    // Machine type. It is not an enum because we want to be able
    // to dynamically add new machine types without regenerating
    // both the client and the server. Validation is done at the
    // server side.
    // If machine_types is set, machine_type is ignored.
    optional string machine_type = 1 [deprecated = true]; // deprecated
    optional int32 keep_alive = 2;
    optional string base_image = 3;
    optional int32 exposed_port = 4;
    optional string scheduler = 5;
    optional google.protobuf.Struct scheduler_options = 8;
    optional int32 max_multiplexing = 6;
    optional int32 max_concurrency = 9;
    optional int32 min_concurrency = 10;
    repeated string machine_types = 11; // machine_type alternative
    optional int32 num_gpus = 12;
    optional int32 request_timeout = 13;
    optional int32 startup_timeout = 14;
    optional int32 concurrency_buffer = 15;
    optional int32 concurrency_buffer_perc = 16;
    optional int32 scaling_delay_seconds = 17;
}

enum ApplicationAuthMode {
    PRIVATE = 0;
    PUBLIC = 1;
    SHARED = 2;
}

enum DeploymentStrategy {
    RECREATE = 0;
    ROLLING = 1;
}



message RegisterApplicationRequest {
    // Environment definitions.
    repeated EnvironmentDefinition environments = 1;
    // Machine requirements
    optional MachineRequirements machine_requirements = 2;
    // Function to run.
    SerializedObject function = 3;
    // Optional setup function to pass as the first argument to the function.
    optional SerializedObject setup_func = 4;
    // Name of the application
    optional string application_name = 5;
    // If application has alias: auth mode to use
    optional ApplicationAuthMode auth_mode = 6;
    // Max concurrency in gateway
    optional int32 max_concurrency = 7 [deprecated = true];
    // metadata to store with the application
    optional google.protobuf.Struct metadata = 8;
    // Deployment strategy
    optional DeploymentStrategy deployment_strategy = 9;
    // To ignore/respect the scaling settings of the application
    // when re-deploying an existing application.
    optional bool scale = 10;
    // To make all logs generated from the app private
    optional bool private_logs = 11;
    // Optional files to be included
    repeated File files = 12;
    // Source code of the app implementation
    optional string source_code = 13;
}

message RegisterApplicationResultType {
    string application_id = 1;
}

message RegisterApplicationResult {
    repeated Log logs = 1;
    optional RegisterApplicationResultType result = 2;
    optional ServiceURLs service_urls = 3;
}

message UpdateApplicationRequest {
    string application_name = 1;
    optional int32 keep_alive = 2;
    optional int32 max_multiplexing = 3;
    optional int32 max_concurrency = 4;
    optional int32 min_concurrency = 5;
    repeated string valid_regions = 6;
    repeated string machine_types = 7;
    optional int32 request_timeout = 8;
    optional int32 startup_timeout = 9;
    optional int32 concurrency_buffer = 10;
    optional int32 concurrency_buffer_perc = 11;
    optional int32 scaling_delay_seconds = 12;
}

message UpdateApplicationResult {
    AliasInfo alias_info = 1;
}

message ListApplicationsRequest {
    optional string application_name = 1;
}

message ApplicationInfo {
    string application_id = 1;
    google.protobuf.Timestamp created_at = 13;
    int32 max_concurrency = 2;
    int32 max_multiplexing = 3;
    int32 keep_alive = 4;
    int32 active_runners = 6;
    int32 min_concurrency = 7;
    repeated string machine_types = 8;
    optional int32 request_timeout = 9;
    optional int32 startup_timeout = 10;
    repeated string valid_regions = 11;
    optional int32 concurrency_buffer = 12;
    optional int32 concurrency_buffer_perc = 14;
    optional int32 scaling_delay_seconds = 15;
}

message ListApplicationsResult {
    repeated ApplicationInfo applications = 1;
}

message DeleteApplicationRequest {
    string application_id = 1;
}

message DeleteApplicationResult {
    // Empty. For future use.
}

message RolloutApplicationRequest {
    string application_name = 1;
    optional bool force = 2;
}

message RolloutApplicationResult {
    // Empty. For future use.
}

message SetAliasRequest {
    string alias = 1;
    string revision = 2;
    optional ApplicationAuthMode auth_mode = 3;
}

message SetAliasResult {
    // Empty. For future use.
    AliasInfo alias_info = 1;
}

message DeleteAliasRequest {
    string alias = 1;
}

message DeleteAliasResult {
    string revision = 1;
}

message ListAliasesRequest {
    // Empty. For future use.
}

message ListAliasesResult {
    repeated AliasInfo aliases = 1;
}

message AliasInfo {
    string alias = 1;
    string revision = 2;
    ApplicationAuthMode auth_mode = 3;
    int32 max_concurrency = 4;
    int32 max_multiplexing = 5;
    int32 keep_alive = 6;
    int32 active_runners = 7;
    int32 min_concurrency = 8;
    repeated string machine_types = 9;
    optional int32 request_timeout = 10;
    optional int32 startup_timeout = 11;
    repeated string valid_regions = 12;
    optional int32 concurrency_buffer = 13;
    optional int32 concurrency_buffer_perc = 14;
    optional int32 scaling_delay_seconds = 15;
}

message SetSecretRequest {
    string name = 1;
    optional string value = 2;
}

message SetSecretResponse {
    // Empty. For future use.
}

message ListSecretsRequest {
    // Empty. For future use.
}

message Secret {
    string name = 1;
    optional google.protobuf.Timestamp created_time = 2;
    // Could also include the value/scope of the secret in the future.
}

message ListSecretsResponse {
    repeated Secret secrets = 1;
}

message ListAliasRunnersRequest {
    string alias = 1;
    optional bool list_pending = 2;
    optional google.protobuf.Timestamp start_time = 3;
}

message ListAliasRunnersResponse {
    repeated RunnerInfo runners = 1;
}

message RunnerInfo {
    string runner_id = 1;
    int32 in_flight_requests = 2;
    optional int32 expiration_countdown = 3;
    float uptime = 4;
    string revision = 6;
    string alias = 7;
    optional google.protobuf.Struct external_metadata = 5;

    enum State {
        RUNNING = 0;
        PENDING = 1;
        SETUP = 2;
        DEAD = 3; // TERMINATED
        DOCKER_PULL = 4;
        DRAINING = 5;
        STOPPING = 6;
        STOPPED = 7;
    }

    optional State state = 8;
}

message StopRunnerRequest {
    string runner_id = 1;
}

message StopRunnerResponse {
    // Empty. For future use.
}


message KillRunnerRequest {
    string runner_id = 1;
}

message ListRunnersRequest {
    optional bool list_pending = 1;
    optional google.protobuf.Timestamp start_time = 2;
}

message ListRunnersResponse {
    repeated RunnerInfo runners = 1;
}

message KillRunnerResponse {
    // Empty. For future use.
}

message TerminalSize {
    int32 height = 1;
    int32 width = 2;
}

message ShellRunnerInput {
    string runner_id = 1;
    bytes data = 2;
    bool close = 3;
    optional TerminalSize tty_size = 4;
}

message ShellRunnerOutput {
    bytes data = 1;
    bool close = 2;
    optional int32 exit_code = 3;
}
