//flynt-disable disallow-direct-common-imports
syntax = "proto3";

import "google/protobuf/wrappers.proto";
import "wix/api/entity.proto";

package wix.infra.asyncjobs.v1;
option java_package = "com.wixpress.infra.asyncinfra.asyncjobservice.v1";

import "google/api/annotations.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/field_mask.proto";
import "google/protobuf/struct.proto";

import "wix/http/field_mask.proto";
import "wix/api/annotations.proto";
import "wix/api/validations.proto";
import "wix/api/callback.proto";
import "wix/api/permissions.proto";
import "wix/common/paging.proto";
import "wix/infra/asyncjobs/v1/upstream/wix/common/paging.proto";

import "wix/infra/asyncjobs/v1/AsyncJobItem.proto";
import "wix/infra/asyncjobs/v1/AsyncJob.proto";

service AsyncJobService {
  option (wix.api.service_entity).message = "wix.infra.asyncjobs.v1.AsyncJob";

  option (wix.api.event) = {
    event_type: ACTION,
    payload: "wix.infra.asyncjobs.v1.AsyncJobFinishedEvent"
  };

  option (wix.api.event) = {
    event_type: ACTION,
    payload: "wix.infra.asyncjobs.v1.AsyncJobFailedEvent"
  };

  option (wix.api.event) = {
    event_type: ACTION,
    payload: "wix.infra.asyncjobs.v1.AsyncJobItemFailedEvent"
  };

  // Creates an async job.
  rpc CreateAsyncJob (CreateAsyncJobRequest) returns (CreateAsyncJobResponse) {

    option (.wix.api.crud) = {
      method: CREATE
      create_options: {
        item_field: "job"
      }
    };

    option (google.api.http) = {
      post: "/v1/async-jobs"
    };

    option (wix.api.permission) = {
      name: "INFRA.ASYNC_JOB_MANAGE",
      type: MANUAL
    };

    option (wix.api.callback) = {
      event_type: CREATED
    };

    option (wix.api.maturity) = BETA;
    option (wix.api.exposure) = INTERNAL;

    option (wix.api.required) = "CreateAsyncJobRequest.job";
  }

  // Retrieves a job.
  rpc GetAsyncJob (GetAsyncJobRequest) returns (GetAsyncJobResponse) {

    option (.wix.api.crud) = {
      method: GET_ITEM
      get_options: {
        id_field: "job_id"
        item_field: "job"
      }
    };

    option (google.api.http) = {
      get: "/v1/async-jobs/{job_id}"
    };

    option (wix.api.permission) = {
      name: "INFRA.ASYNC_JOB_READ",
      type: MANUAL
    };

    option (wix.api.maturity) = GA;
    option (wix.api.exposure) = PUBLIC;
    option (wix.api.required) = "GetAsyncJobRequest.job_id";
  }

  // Updates a job.
  rpc UpdateAsyncJob (UpdateAsyncJobRequest) returns (UpdateAsyncJobResponse) {

    option (.wix.api.crud) = {
      method: UPDATE
      update_options: {
        item_field: "job"
        fieldmask_field: "mask"
      }
    };

    option (google.api.http) = {
      patch: "/v1/async-jobs/{job.id}"
    };

    option (wix.api.permission) = {
      name: "INFRA.ASYNC_JOB_MANAGE",
      type: MANUAL
    };

    option (wix.api.callback) = {
      event_type: UPDATED
    };

    option (wix.api.maturity) = GA;
    option (wix.api.exposure) = INTERNAL;
    option (wix.api.required) = "UpdateAsyncJobRequest.job.id";
    option (wix.http.infer_fieldmask) = {
      from: "job"
      fieldmask: "mask"
    };
  }

  // Deletes a job.
  rpc DeleteAsyncJob (DeleteAsyncJobRequest) returns (DeleteAsyncJobResponse) {

    option (.wix.api.crud) = {
      method: DELETE
      delete_options: {
        id_field: "job_id"
      }
    };

    option (google.api.http) = {
      delete: "/v1/async-jobs/{job_id}"
    };
    option (wix.api.permission) = {
      name: "INFRA.ASYNC_JOB_MANAGE",
      type: MANUAL
    };

    option (wix.api.callback) = {
      event_type: DELETED
    };

    option (wix.api.maturity) = GA;
    option (wix.api.exposure) = INTERNAL;
    option (wix.api.required) = "DeleteAsyncJobRequest.job_id";
  }

  // Completes a job.
  rpc CompleteAsyncJob (CompleteAsyncJobRequest) returns (CompleteAsyncJobResponse) {
    option (google.api.http) = {
      put: "/v1/async-jobs/{job_id}/complete"
    };

    option (wix.api.permission) = {
      name: "INFRA.ASYNC_JOB_MANAGE",
      type: MANUAL
    };

    option (wix.api.maturity) = GA;
    option (wix.api.exposure) = INTERNAL;
    option (wix.api.required) = "CompleteAsyncJobRequest.job_id";
  }

  // Reports job progress.
  rpc ReportAsyncJobProgress (ReportAsyncJobProgressRequest) returns (ReportAsyncJobProgressResponse) {
    option (google.api.http) = {
      post: "/v1/async-jobs/{job_id}/items/report"
    };

    option (wix.api.permission) = {
      name: "INFRA.ASYNC_JOB_MANAGE",
      type: MANUAL
    };

    option (wix.api.callback) = {
      event_type: ACTION
      payload: "wix.infra.asyncjobs.v1.AsyncJobItemAddedEvent"
    };
    option (wix.api.callback) = {
      event_type: UPDATED
    };

    option (wix.api.required) = "ReportAsyncJobProgressRequest.job_id";
  }

  // Retrieves a list of job items.
  rpc ListAsyncJobItems (ListAsyncJobItemsRequest) returns (ListAsyncJobItemsResponse) {
    option (google.api.http) = {
      get: "/v1/async-jobs/{job_id}/items"
    };
    option (wix.api.permission).name = "INFRA.ASYNC_JOB_READ";
    option (wix.api.required) = "ListAsyncJobItemsRequest.job_id";


    option (wix.api.maturity) = GA;
    option (wix.api.exposure) = PUBLIC;
  }

}
message CreateAsyncJobRequest {
  // Job to create.
  AsyncJob job = 1;
}

message CreateAsyncJobResponse {
  // Created job.
  AsyncJob job = 1;
}

message GetAsyncJobRequest {
  // Job ID.
  string job_id = 1 [(wix.api.format) = GUID];
}

message GetAsyncJobResponse {
  // Returned job.
  AsyncJob job = 1;
}


message UpdateAsyncJobRequest {
  // Job to update.
  AsyncJob job = 1;
  // Field mask.
  google.protobuf.FieldMask mask = 2;
}

message UpdateAsyncJobResponse {
  // Updated job.
  AsyncJob job = 1;
}

message DeleteAsyncJobRequest {
  // Job ID.
  string job_id = 1 [(wix.api.format) = GUID];
}

message DeleteAsyncJobResponse {
}


message ReportAsyncJobProgressRequest {
  // Job ID.
  string job_id = 1 [(wix.api.format) = GUID];

  // Job items being reported.
  repeated AsyncJobItem items = 2 [(wix.api.maxSize) = 1000];
}

message ReportAsyncJobProgressResponse {}

message ListAsyncJobItemsRequest {
  // Job ID.
  string job_id = 1 [(wix.api.format) = GUID];
  // Pagination options.
  wix.common.CursorPaging paging = 2;
  /*
    Whether to return only failed items. 
    when false, only successful items will be returned.
    when not set, all both failed and successful will be returned.
   */
  google.protobuf.BoolValue has_error = 3 [(wix.api.field_exposure) = INTERNAL,
    deprecated = true, (wix.api.field_deprecated) = {
      replaced_by: "wix.infra.asyncjobs.v1.ListAsyncJobItemsRequest.status_filter"
      target_removal_date: "2024-12-12",
    }];
  // async job item status filter.
  StatusFilter status_filter = 4;

  enum StatusFilter {
    // Return all items.
    ALL = 0;
    // Return only failed items.
    FAILED_ONLY = 1;
    // Return only successful items.
    SUCCESSFUL_ONLY = 2;
  }
}

message ListAsyncJobItemsResponse {
  // Job items.
  repeated AsyncJobItem results = 1;
  // Paging metadata.
  wix.infra.asyncjobs.v1.upstream.wix.common.PagingMetadataV2 paging_metadata = 2;
}


message CompleteAsyncJobRequest {
  // Job ID.
  string job_id = 1 [(wix.api.format) = GUID];
  // Job status.
  CompleteStatus status = 2;

  enum CompleteStatus {
    // Job is finished.
    FINISHED = 0;
    // Job has failed.
    FAILED = 1;
  }
}

message CompleteAsyncJobResponse {}

// Events
message AsyncJobFinishedEvent {
  // Job ID.
  string job_id = 1 [(wix.api.format) = GUID];
}

message AsyncJobFailedEvent {
  // Job ID.
  string job_id = 1 [(wix.api.format) = GUID];
}

message AsyncJobItemAddedEvent {
  // Job ID.
  string job_id = 1 [(wix.api.format) = GUID];
  // Job items.
  AsyncJobItem job_item = 2;
}

message AsyncJobItemFailedEvent {
  // Job ID.
  string job_id = 1 [(wix.api.format) = GUID];
  // Job items.
  AsyncJobItem job_item = 2;
}


