syntax = "proto3";

package databroker;
option go_package = "github.com/pomerium/pomerium/pkg/grpc/databroker";

import "google/protobuf/any.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/field_mask.proto";
import "google/protobuf/struct.proto";
import "google/protobuf/timestamp.proto";

message Record {
  uint64 version = 1;
  string type = 2;
  string id = 3;
  google.protobuf.Any data = 4;
  google.protobuf.Timestamp modified_at = 5;
  google.protobuf.Timestamp deleted_at = 6;
}
message Versions {
  // the server version indicates the version of the server storing the data
  uint64 server_version = 1;
  uint64 latest_record_version = 2;
}

// Options are the options for a type stored in the databroker.
message Options {
  // capacity sets a maximum size for the given type. Once the capacity is
  // reached the oldest records will be removed.
  optional uint64 capacity = 1;
}

message GetRequest {
  string type = 1;
  string id = 2;
}
message GetResponse { Record record = 1; }

message ListTypesResponse { repeated string types = 1; }

message QueryRequest {
  string type = 1;
  string query = 2;
  int64 offset = 3;
  int64 limit = 4;
  google.protobuf.Struct filter = 5;
  optional uint64 minimum_record_version_hint = 6;
}
message QueryResponse {
  repeated Record records = 1;
  int64 total_count = 2;
  uint64 server_version = 3;
  uint64 record_version = 4;
}

message PutRequest { repeated Record records = 1; }
message PutResponse {
  uint64 server_version = 1;
  repeated Record records = 2;
}

message PatchRequest {
  repeated Record records = 1;
  google.protobuf.FieldMask field_mask = 2;
}
message PatchResponse {
  uint64 server_version = 1;
  repeated Record records = 2;
}

message SetOptionsRequest {
  string type = 1;
  Options options = 2;
}
message SetOptionsResponse { Options options = 1; }

message SyncRequest {
  uint64 server_version = 1;
  uint64 record_version = 2;
  string type = 3;
}
message SyncResponse { Record record = 1; }

message SyncLatestRequest { string type = 1; }
message SyncLatestResponse {
  oneof response {
    Record record = 1;
    Versions versions = 2;
  }
}

message AcquireLeaseRequest {
  // Name is the name of the lease. Only a single client can hold the lease on
  // the specified name at any one time.
  string name = 1;
  // Duration is the duration of the lease. After the duration is reached the
  // lease can be acquired by other clients.
  google.protobuf.Duration duration = 2;
}
message AcquireLeaseResponse {
  // Id is the id of the acquired lease. Subsequent calls to release or renew
  // will need both the lease name and the lease id.
  string id = 1;
}
message ReleaseLeaseRequest {
  string name = 1;
  string id = 2;
}
message RenewLeaseRequest {
  string name = 1;
  string id = 2;
  google.protobuf.Duration duration = 3;
}

// The DataBrokerService stores key-value data.
service DataBrokerService {
  // AcquireLease acquires a distributed mutex lease.
  rpc AcquireLease(AcquireLeaseRequest) returns (AcquireLeaseResponse);
  // Get gets a record.
  rpc Get(GetRequest) returns (GetResponse);
  // ListTypes lists all the known record types.
  rpc ListTypes(google.protobuf.Empty) returns (ListTypesResponse);
  // Put saves a record.
  rpc Put(PutRequest) returns (PutResponse);
  // Patch updates specific fields of an existing record.
  rpc Patch(PatchRequest) returns (PatchResponse);
  // Query queries for records.
  rpc Query(QueryRequest) returns (QueryResponse);
  // ReleaseLease releases a distributed mutex lease.
  rpc ReleaseLease(ReleaseLeaseRequest) returns (google.protobuf.Empty);
  // RenewLease renews a distributed mutex lease.
  rpc RenewLease(RenewLeaseRequest) returns (google.protobuf.Empty);
  // SetOptions sets the options for a type in the databroker.
  rpc SetOptions(SetOptionsRequest) returns (SetOptionsResponse);
  // Sync streams changes to records after the specified version.
  rpc Sync(SyncRequest) returns (stream SyncResponse);
  // SyncLatest streams the latest version of every record.
  rpc SyncLatest(SyncLatestRequest) returns (stream SyncLatestResponse);
}