syntax = "proto3";

import "google/protobuf/empty.proto";
import "google/protobuf/struct.proto";



// Request to allocate a slot for a call
message TryCall {
    string models_call_json = 1;
    string slot_hash_id = 2;
    map<string,string> extensions = 3;
}

// Data sent C2S and S2C - as soon as the runner sees the first of these it
// will start running. If empty content, there must be one of these with eof.
// The runner will send these for the body of the response, AFTER it has sent
// a CallEnding message.
message DataFrame {
    bytes data = 1;
    bool eof = 2;
}

message HttpHeader {
    string key = 1;
    string value = 2;
}

message HttpRespMeta {
    int32 status_code = 1;
    repeated HttpHeader headers = 2;
}

// Call has started to finish - data might not be here yet and it will be sent
// as DataFrames.
message CallResultStart {
    oneof meta {
        HttpRespMeta http = 100;
    }
}

// Call has really finished, it might have completed or crashed
message CallFinished {
    bool success = 1;
    string details = 2;
    int32 errorCode = 3;
    string errorStr = 4;
    string createdAt = 5;
    string startedAt = 6;
    string completedAt = 7;
    int64 schedulerDuration = 8;
    int64 executionDuration = 9;
    bool errorUser = 10;
    string image = 11;
    int64 imagePullWaitDuration = 12;
    int64 ctrPrepDuration = 13;
    int64 ctrCreateDuration = 14;
    int64 initStartTime = 15;
}

message ClientMsg {
    oneof body {
        TryCall try = 1;
        DataFrame data = 2;
    }
}

message RunnerMsg {
    oneof body {
        CallResultStart result_start = 1;
        DataFrame data = 2;
        CallFinished finished = 3;
    }
}

message RunnerStatus {
    int32 active = 2;  // Number of currently inflight responses
    bool failed = 3; // if status was successful or not
    string id = 4; // call id if status image was used
    string details = 5; // response from status image
    int32 errorCode = 6; // error code if not successful
    string errorStr = 7; // error description if not successful
    string createdAt = 8; // call latency details: initialization time
    string startedAt = 9; // call latency details: start time in container
    string completedAt = 10; // call latency details: end time
    bool cached = 11; // true if status response was provided from cache
    uint64 requestsReceived = 12; // number of requests received by runner
    uint64 requestsHandled = 13; // number of requests processed by runner without NACK
    uint64 kdumpsOnDisk = 14; // number of kdumps on local disk
    int64 schedulerDuration = 15; // the amount of time for scheduler execution
    int64 executionDuration = 16; // the amount of time for function execution
    bool isNetworkDisabled = 17; // returns true if runner network is not ready
    map<string,string> customStatus = 18; // returns any user defined healthcheck status
    int64 imagePullWaitDuration = 19;
    int64 ctrPrepDuration = 20;
    int64 ctrCreateDuration = 21;
    int64 initStartTime = 22;
}

message ConfigMsg {
    map<string,string> config = 1;
}

message ConfigStatus {
}

// Collector to Runner messages
message LogRequestMsg {
    // Initial Logging session message sent by Collectors to Runners
    message Start {
        map<string,string> config = 1;
    }

    // Acknowledgement of last data in stream: a message sent by Collectors to Runners
    message Ack {
    }

    // Enable stream readiness for push: a message sent by Collectors to Runners
    message Ready {
    }

    oneof body {
        Start start = 1;
        Ack ack = 2;
        Ready ready = 3;
    }
}

// Runners to Collectors
message LogResponseMsg {
    // Per container log data
    message Container {
        string applicationId = 1;     // application id
        string functionId = 2;        // function id
        string containerId = 3;       // container id

        // Per request log data
        message Request {
            string requestId = 1;     // call request id

            // Log lines
            message Line {
                int64 timestamp = 1; // utc unix time msecs
                enum Source {
                    STDOUT = 0;
                    STDERR = 1;
                }
                Source source = 2;    // stderr or stdout
                bytes data = 3;       // opaque log data
            }
            repeated Line data = 2;   // log lines
        }
        repeated Request data = 4;    // request logs
    }
    repeated Container data = 1;      // container logs
}

service RunnerProtocol {
    rpc Engage (stream ClientMsg) returns (stream RunnerMsg);

    // Rather than rely on Prometheus for this, expose status that's specific to the runner lifecycle through this.
    rpc Status(google.protobuf.Empty) returns (RunnerStatus) {
        option deprecated = true;
    };

    // Configure the remote runner by passing config data.
    rpc ConfigureRunner(ConfigMsg) returns (ConfigStatus);

    // Logging Interface
    rpc StreamLogs(stream LogRequestMsg) returns (stream LogResponseMsg);

    // If a status image container is configured (for handling custom statuses)
    /// the supplied opaque JSON is passed as an input to that image.
    // Output from the container is sent back via RunnerStatus.Details
    // as before.
    rpc Status2(google.protobuf.Struct) returns (RunnerStatus);
}
