syntax = "proto3";
package v3electionpb;

import "gogoproto/gogo.proto";
import "etcd/etcdserver/etcdserverpb/rpc.proto";
import "etcd/mvcc/mvccpb/kv.proto";

// for grpc-gateway
import "google/api/annotations.proto";

option (gogoproto.marshaler_all) = true;
option (gogoproto.unmarshaler_all) = true;

// The election service exposes client-side election facilities as a gRPC interface.
service Election {
  // Campaign waits to acquire leadership in an election, returning a LeaderKey
  // representing the leadership if successful. The LeaderKey can then be used
  // to issue new values on the election, transactionally guard API requests on
  // leadership still being held, and resign from the election.
  rpc Campaign(CampaignRequest) returns (CampaignResponse) {
      option (google.api.http) = {
        post: "/v3beta/election/campaign"
        body: "*"
    };
  }
  // Proclaim updates the leader's posted value with a new value.
  rpc Proclaim(ProclaimRequest) returns (ProclaimResponse) {
      option (google.api.http) = {
        post: "/v3beta/election/proclaim"
        body: "*"
    };
  }
  // Leader returns the current election proclamation, if any.
  rpc Leader(LeaderRequest) returns (LeaderResponse) {
      option (google.api.http) = {
        post: "/v3beta/election/leader"
        body: "*"
    };
  }
  // Observe streams election proclamations in-order as made by the election's
  // elected leaders.
  rpc Observe(LeaderRequest) returns (stream LeaderResponse) {
      option (google.api.http) = {
        post: "/v3beta/election/observe"
        body: "*"
    };
  }
  // Resign releases election leadership so other campaigners may acquire
  // leadership on the election.
  rpc Resign(ResignRequest) returns (ResignResponse) {
      option (google.api.http) = {
        post: "/v3beta/election/resign"
        body: "*"
    };
  }
}

message CampaignRequest {
  // name is the election's identifier for the campaign.
  bytes name = 1;
  // lease is the ID of the lease attached to leadership of the election. If the
  // lease expires or is revoked before resigning leadership, then the
  // leadership is transferred to the next campaigner, if any.
  int64 lease = 2;
  // value is the initial proclaimed value set when the campaigner wins the
  // election.
  bytes value = 3;
}

message CampaignResponse {
  etcdserverpb.ResponseHeader header = 1;
  // leader describes the resources used for holding leadereship of the election.
  LeaderKey leader = 2;
}

message LeaderKey {
  // name is the election identifier that correponds to the leadership key.
  bytes name = 1;
  // key is an opaque key representing the ownership of the election. If the key
  // is deleted, then leadership is lost.
  bytes key = 2;
  // rev is the creation revision of the key. It can be used to test for ownership
  // of an election during transactions by testing the key's creation revision
  // matches rev.
  int64 rev = 3;
  // lease is the lease ID of the election leader.
  int64 lease = 4;
}

message LeaderRequest {
  // name is the election identifier for the leadership information.
  bytes name = 1;
}

message LeaderResponse {
  etcdserverpb.ResponseHeader header = 1;
  // kv is the key-value pair representing the latest leader update.
  mvccpb.KeyValue kv = 2;
}

message ResignRequest {
  // leader is the leadership to relinquish by resignation.
  LeaderKey leader = 1;
}

message ResignResponse {
  etcdserverpb.ResponseHeader header = 1;
}

message ProclaimRequest {
  // leader is the leadership hold on the election.
  LeaderKey leader = 1;
  // value is an update meant to overwrite the leader's current value.
  bytes value = 2;
}

message ProclaimResponse {
  etcdserverpb.ResponseHeader header = 1;
}
