syntax = "proto3";

package nominal.iceberg.v1;

import "buf/validate/validate.proto";
import "google/api/annotations.proto";
import "google/protobuf/timestamp.proto";
import "nominal/protos/gen/v1/error.proto";
import "nominal/protos/iceberg/v1/table.proto";

option java_multiple_files = true;
option java_package = "io.nominal.iceberg.v1";

enum CompactionStatus {
  COMPACTION_STATUS_UNSPECIFIED = 0;
  COMPACTION_STATUS_PENDING = 1;
  COMPACTION_STATUS_RUNNING = 2;
  COMPACTION_STATUS_SUCCEEDED = 3;
  COMPACTION_STATUS_FAILED = 4;
  COMPACTION_STATUS_NOT_FOUND = 5;
}

// State of a per-table compaction run.
message CompactionRun {
  TableTarget target = 1;
  CompactionStatus status = 2;
  // Set once the workflow has started executing.
  optional google.protobuf.Timestamp started_at = 3;
  // Set on terminal states (succeeded, failed).
  optional google.protobuf.Timestamp finished_at = 4;
}

message CompactTableRequest {
  TableTarget target = 1 [(buf.validate.field).required = true];
  // Optional override of the compaction container image (full registry ref,
  // e.g. 123.dkr.ecr.us-east-1.amazonaws.com/iceberg-compaction:my-tag). Lets
  // operators test a new compaction build without redeploying combined-service.
  optional string image_override = 2 [(buf.validate.field).cel = {
    id: "text.non_whitespace"
    message: "string must contain at least one non-whitespace character"
    expression: "this.matches('[^\\\\s]')"
  }];
}

message CompactTableResponse {}

message GetCompactionRunRequest {
  TableTarget target = 1 [(buf.validate.field).required = true];
}

message GetCompactionRunResponse {
  CompactionRun run = 1;
}

enum CompactionErrors {
  COMPACTION_ERRORS_UNSPECIFIED = 0;
  COMPACTION_ERRORS_TABLE_NOT_FOUND = 1 [(nominal.gen.v1.error) = {
    code: "NOT_FOUND"
    message: "Table not found in Iceberg catalog"
  }];
}

// Service for programmatically starting and monitoring Iceberg compaction jobs.
service IcebergCompactionService {
  // Kick off a compaction for a specific Iceberg table. Idempotent: if a
  // compaction is already running for the target, no new workflow is started.
  rpc CompactTable(CompactTableRequest) returns (CompactTableResponse) {
    option (google.api.http) = {
      post: "/iceberg/v1/compaction"
      body: "*"
    };
  }

  // Look up the current state of a compaction run for a target. Returns
  // a run with status COMPACTION_STATUS_NOT_FOUND if no workflow is on
  // record for the target.
  rpc GetCompactionRun(GetCompactionRunRequest) returns (GetCompactionRunResponse) {
    option (google.api.http) = {
      post: "/iceberg/v1/compaction/runs/get"
      body: "*"
    };
  }
}
