syntax = "proto3";

option go_package = "github.com/hatchet-dev/hatchet/internal/services/dispatcher/contracts";

import "google/protobuf/timestamp.proto";

service Dispatcher {
    rpc Register(WorkerRegisterRequest) returns (WorkerRegisterResponse) {}

    rpc Listen(WorkerListenRequest) returns (stream AssignedAction) {}

    // ListenV2 is like listen, but implementation does not include heartbeats. This should only used by SDKs
    // against engine version v0.18.1+
    rpc ListenV2(WorkerListenRequest) returns (stream AssignedAction) {}

    // Heartbeat is a method for workers to send heartbeats to the dispatcher
    rpc Heartbeat(HeartbeatRequest) returns (HeartbeatResponse) {}

    rpc SubscribeToWorkflowEvents(SubscribeToWorkflowEventsRequest) returns (stream WorkflowEvent) {}

    rpc SubscribeToWorkflowRuns(stream SubscribeToWorkflowRunsRequest) returns (stream WorkflowRunEvent) {}

    rpc SendStepActionEvent(StepActionEvent) returns (ActionEventResponse) {}

    rpc SendGroupKeyActionEvent(GroupKeyActionEvent) returns (ActionEventResponse) {}

    rpc PutOverridesData(OverridesData) returns (OverridesDataResponse) {}

    rpc Unsubscribe(WorkerUnsubscribeRequest) returns (WorkerUnsubscribeResponse) {}

    rpc RefreshTimeout(RefreshTimeoutRequest) returns (RefreshTimeoutResponse) {}

    rpc ReleaseSlot(ReleaseSlotRequest) returns (ReleaseSlotResponse) {}

    rpc RestoreEvictedTask(RestoreEvictedTaskRequest) returns (RestoreEvictedTaskResponse) {}

    rpc UpsertWorkerLabels(UpsertWorkerLabelsRequest) returns (UpsertWorkerLabelsResponse) {}

    // GetVersion returns the dispatcher protocol version as a simple integer.
    // SDKs use this to determine feature support (e.g. slot_config registration).
    // Old engines that do not implement this RPC will return UNIMPLEMENTED.
    rpc GetVersion(GetVersionRequest) returns (GetVersionResponse) {}
}

message WorkerLabels {
    // value of the label
    optional string str_value = 1;
    optional int32 int_value = 2;
}

enum SDKS {
    UNKNOWN = 0;
    GO = 1;
    PYTHON = 2;
    TYPESCRIPT = 3;
    RUBY = 4;
}

message RuntimeInfo {
    optional string sdk_version = 1;
    optional SDKS language = 2;
    optional string language_version = 3;
    optional string os = 4;
    optional string extra = 5;
}

message WorkerRegisterRequest {
    // the name of the worker
    string worker_name = 1;

    // a list of actions that this worker can run
    repeated string actions = 2;

    // (optional) the services for this worker
    repeated string services = 3;

    // (optional) the number of default slots this worker can handle
    // deprecated: use slot_config instead
    optional int32 slots = 4;

    // (optional) worker labels (i.e. state or other metadata)
    map<string, WorkerLabels> labels = 5;

    // (optional) webhookId is the id of the webhook that the worker is associated with (if any)
    optional string webhook_id = 6;

    // (optional) information regarding the runtime environment of the worker
    optional RuntimeInfo runtime_info = 7;

    // (optional) slot config for this worker (slot_type -> units)
    map<string, int32> slot_config = 9;

}

message WorkerRegisterResponse {
    // the tenant id
    string tenant_id = 1;

    // the id of the worker
    string worker_id = 2;

    // the name of the worker
    string worker_name = 3;
}

message UpsertWorkerLabelsRequest {
    // the name of the worker
    string worker_id = 1;

    // (optional) the worker labels
    map<string, WorkerLabels> labels = 2;
}


message UpsertWorkerLabelsResponse {
    // the tenant id
    string tenant_id = 1;

    // the id of the worker
    string worker_id = 2;
}

enum ActionType {
    START_STEP_RUN = 0;
    CANCEL_STEP_RUN = 1;
    START_GET_GROUP_KEY = 2;
}

message AssignedAction {
    // the tenant id
    string tenant_id = 1;

    // the workflow run id (optional)
    string workflow_run_id = 2;

    // the get group key run id (optional)
    string get_group_key_run_id = 3;

    // the job id
    string job_id = 4;

    // the job name
    string job_name = 5;

    // the job run id
    string job_run_id = 6;

    // the task id
    string task_id = 7;

    // the task external run id
    string task_run_external_id = 8;

    // the action id
    string action_id = 9;

    // the action type
    ActionType action_type = 10;

    // the action payload
    string action_payload = 11;

    // the task name
    string task_name = 12;

    // the count number of the retry attempt
    int32 retry_count = 13;

    // (optional) additional metadata set on the workflow
    optional string additional_metadata = 14;

    // (optional) the child workflow index (if this is a child workflow)
    optional int32 child_workflow_index = 15;

    // (optional) the child workflow key (if this is a child workflow)
    optional string child_workflow_key = 16;

    // (optional) the parent workflow run id (if this is a child workflow)
    optional string parent_workflow_run_id = 17;

    // (optional) the priority of the run
    int32 priority = 18;

    // (optional) the workflow id
    optional string workflow_id = 19;

    // (optional) the workflow version id
    optional string workflow_version_id = 20;

    // (optional) the invocation count for durable task events (required for durable events, otherwise null)
    optional int32 durable_task_invocation_count = 21;

    // (optional) the external id of the event that triggered this workflow run (if any)
    optional string triggering_event_external_id = 22;

    // (optional) the key of the event that triggered this workflow run (if any)
    optional string triggering_event_key = 23;
}

message WorkerListenRequest {
    // the id of the worker
    string worker_id = 1;
}

message WorkerUnsubscribeRequest {
    // the id of the worker
    string worker_id = 1;
}

message WorkerUnsubscribeResponse {
    // the tenant id to unsubscribe from
    string tenant_id = 1;

    // the id of the worker
    string worker_id = 2;
}

enum GroupKeyActionEventType {
    GROUP_KEY_EVENT_TYPE_UNKNOWN = 0;
    GROUP_KEY_EVENT_TYPE_STARTED = 1;
    GROUP_KEY_EVENT_TYPE_COMPLETED = 2;
    GROUP_KEY_EVENT_TYPE_FAILED = 3;
}

message GroupKeyActionEvent {
    // the id of the worker
    string worker_id = 1;

    // the id of the job
    string workflow_run_id = 2;

    string get_group_key_run_id = 3;

    // the action id
    string action_id = 4;

    google.protobuf.Timestamp event_timestamp = 5;

    // the task event type
    GroupKeyActionEventType event_type = 6;

    // the event payload
    string event_payload = 7;
}

enum StepActionEventType {
    STEP_EVENT_TYPE_UNKNOWN = 0;
    STEP_EVENT_TYPE_STARTED = 1;
    STEP_EVENT_TYPE_COMPLETED = 2;
    STEP_EVENT_TYPE_FAILED = 3;
    STEP_EVENT_TYPE_ACKNOWLEDGED = 4;
}

message StepActionEvent {
    // the id of the worker
    string worker_id = 1;

    // the id of the job
    string job_id = 2;

    // the job run id
    string job_run_id = 3;

    // the id of the task
    string task_id = 4;

    // the task external run id
    string task_run_external_id = 5;

    // the action id
    string action_id = 6;

    google.protobuf.Timestamp event_timestamp = 7;

    // the task event type
    StepActionEventType event_type = 8;

    // the event payload
    string event_payload = 9;

    // the retry count
    optional int32 retry_count = 10;

    // a flag indicating if the task should _not_ be retried
    optional bool should_not_retry = 11;
}

message ActionEventResponse {
    // the tenant id
    string tenant_id = 1;

    // the id of the worker
    string worker_id = 2;
}

message SubscribeToWorkflowEventsRequest {
    // the id of the workflow run
    optional string workflow_run_id = 1;

    // the key of the additional meta field to subscribe to
    optional string additional_meta_key = 2;

    // the value of the additional meta field to subscribe to
    optional string additional_meta_value = 3;
}

message SubscribeToWorkflowRunsRequest {
    // the id of the workflow run
    string workflow_run_id = 1;
}

enum ResourceType {
    RESOURCE_TYPE_UNKNOWN = 0;
    RESOURCE_TYPE_STEP_RUN = 1;
    RESOURCE_TYPE_WORKFLOW_RUN = 2;
}

enum ResourceEventType {
    RESOURCE_EVENT_TYPE_UNKNOWN = 0;
    RESOURCE_EVENT_TYPE_STARTED = 1;
    RESOURCE_EVENT_TYPE_COMPLETED = 2;
    RESOURCE_EVENT_TYPE_FAILED = 3;
    RESOURCE_EVENT_TYPE_CANCELLED = 4;
    RESOURCE_EVENT_TYPE_TIMED_OUT = 5;
    RESOURCE_EVENT_TYPE_STREAM = 6;
}

message WorkflowEvent {
    // the id of the workflow run
    string workflow_run_id = 1;

    ResourceType resource_type = 2;

    ResourceEventType event_type = 3;

    string resource_id = 4;

    google.protobuf.Timestamp event_timestamp = 5;

    // the event payload
    string event_payload = 6;

    // whether this is the last event for the workflow run - server
    // will hang up the connection but clients might want to case
    bool hangup = 7;

    // (optional) the max number of retries this task can handle
    optional int32 task_retries = 8;

    // (optional) the retry count of this task
    optional int32 retry_count = 9;

    optional int64 event_index = 10;
}

enum WorkflowRunEventType {
    WORKFLOW_RUN_EVENT_TYPE_FINISHED = 0;
}

message WorkflowRunEvent {
    // the id of the workflow run
    string workflow_run_id = 1;

    WorkflowRunEventType event_type = 2;

    google.protobuf.Timestamp event_timestamp = 3;

    repeated StepRunResult results = 4;
}

message StepRunResult {
    string task_run_external_id = 1;

    string task_name = 2;

    string job_run_id = 3;

    optional string error = 4;

    optional string output = 5;
}

message OverridesData {
    // the task run id
    string task_run_external_id = 1;

    // the path of the data to set
    string path = 2;

    // the value to set
    string value = 3;

    // the filename of the caller
    string caller_filename = 4;
}

message OverridesDataResponse {}

message HeartbeatRequest {
    // the id of the worker
    string worker_id = 1;

    // heartbeatAt is the time the worker sent the heartbeat
    google.protobuf.Timestamp heartbeat_at = 2;
}

message HeartbeatResponse {}

message RefreshTimeoutRequest {
    // the id of the task run to release
    string task_run_external_id = 1;

    string increment_timeout_by = 2;
}

message RefreshTimeoutResponse {
    google.protobuf.Timestamp timeout_at = 1;

}
message ReleaseSlotRequest {
    // the id of the task run to release
    string task_run_external_id = 1;
}

message ReleaseSlotResponse {}

message RestoreEvictedTaskRequest {
    string task_run_external_id = 1;
}

message RestoreEvictedTaskResponse {
    bool requeued = 1;
}

message GetVersionRequest {}

message GetVersionResponse {
    string version = 1;
}
