syntax = "proto3";

import "google/protobuf/timestamp.proto";
import "google/protobuf/any.proto";

package obelisk;

service Scheduler {
    rpc Submit(SubmitRequest) returns (SubmitResponse);
    rpc GetStatus(GetStatusRequest) returns (stream GetStatusResponse);
}

service FunctionRepository {
    rpc ListComponents(ListComponentsRequest) returns (ListComponentsResponse);
}

message ListComponentsRequest {
    optional FunctionName function = 1;
    optional ConfigId config_id = 2;
    bool extensions = 3;
}

message ListComponentsResponse {
    repeated Component components = 1;
}

message Component {
    ConfigId config_id = 1;
    string digest = 2;
    string name = 3;
    string type = 4;
    reserved 5;
    repeated FunctionDetails exports = 6;
    repeated FunctionDetails imports = 7;
}

message FunctionDetails {
    FunctionName function = 1;
    repeated FunctionParameter params = 2;
    optional WitType return_type = 3;

}

message FunctionParameter {
    WitType type = 1;
    optional string name = 2;
}

message WitType {
    optional string wit_type = 1;
    google.protobuf.Any internal = 2;
}

message ExecutionId {
    string id = 1;
}

message RunId {
    string id = 1;
}

message JoinSetId {
    string id = 1;
}

// Identifier for given configuration.
// Uniqueness is not guaranteed.
// The id is not persisted, only appears in logs and traces and gRPC responses.
message ConfigId {
    string id = 1;
}

message FunctionName {
    // `namespace:pkg_name/ifc_name` or `namespace:pkg_name/ifc_name@version`
    string interface_name = 1;
    string function_name = 2;
}

message SubmitRequest {
    FunctionName function = 1;
    google.protobuf.Any params = 2;
    optional ExecutionId execution_id = 3;      // Generated if not set
    reserved 4;
}

message SubmitResponse {
    ExecutionId execution_id = 1;
}

message GetStatusRequest {
    ExecutionId execution_id = 1;
    bool follow = 2;
}

message ExecutionStatus {
    message Locked {
        RunId run_id = 2;
        google.protobuf.Timestamp lock_expires_at = 3;
    }
    message PendingAt {
        google.protobuf.Timestamp scheduled_at = 1;
    }
    message BlockedByJoinSet {
        JoinSetId join_set_id = 1;
        google.protobuf.Timestamp lock_expires_at = 2;
    }
    message Finished {
        google.protobuf.Any result = 1;
        google.protobuf.Timestamp created_at = 2;
        google.protobuf.Timestamp finished_at = 4;
    }
    oneof status {
        Locked locked = 1;
        PendingAt pending_at = 2;
        BlockedByJoinSet blocked_by_join_set = 3;
        Finished finished = 4;
    }
}

message GetStatusResponse {
    message ExecutionSummary {
        FunctionName function_name = 1;
        ExecutionStatus current_status = 2;
    }

    oneof message {
        // First message in the stream
        ExecutionSummary summary = 1;
        // Remaining messages
        ExecutionStatus current_status = 2;
    }
}
