syntax = "proto3";

package chainfire.internal;

// Internal Raft RPC service for node-to-node communication
service RaftService {
    // Vote requests a vote from a peer
    rpc Vote(VoteRequest) returns (VoteResponse);

    // AppendEntries sends log entries to followers
    rpc AppendEntries(AppendEntriesRequest) returns (AppendEntriesResponse);

    // InstallSnapshot sends a snapshot to a follower
    rpc InstallSnapshot(stream InstallSnapshotRequest) returns (InstallSnapshotResponse);
}

message VoteRequest {
    // term is the candidate's term
    uint64 term = 1;
    // candidate_id is the candidate requesting the vote
    uint64 candidate_id = 2;
    // last_log_index is index of candidate's last log entry
    uint64 last_log_index = 3;
    // last_log_term is term of candidate's last log entry
    uint64 last_log_term = 4;
}

message VoteResponse {
    // term is the current term for the voter
    uint64 term = 1;
    // vote_granted is true if the candidate received the vote
    bool vote_granted = 2;
    // last_log_id is the voter's last log ID
    uint64 last_log_index = 3;
    uint64 last_log_term = 4;
}

message AppendEntriesRequest {
    // term is the leader's term
    uint64 term = 1;
    // leader_id is the leader's ID
    uint64 leader_id = 2;
    // prev_log_index is index of log entry immediately preceding new ones
    uint64 prev_log_index = 3;
    // prev_log_term is term of prev_log_index entry
    uint64 prev_log_term = 4;
    // entries are log entries to append
    repeated LogEntry entries = 5;
    // leader_commit is leader's commit index
    uint64 leader_commit = 6;
}

message LogEntry {
    // index is the log entry index
    uint64 index = 1;
    // term is the term when entry was received
    uint64 term = 2;
    // data is the command data
    bytes data = 3;
}

message AppendEntriesResponse {
    // term is the current term
    uint64 term = 1;
    // success is true if follower contained entry matching prevLogIndex
    bool success = 2;
    // conflict_index is the first conflicting index (for optimization)
    uint64 conflict_index = 3;
    // conflict_term is the term of the conflicting entry
    uint64 conflict_term = 4;
}

message InstallSnapshotRequest {
    // term is the leader's term
    uint64 term = 1;
    // leader_id is the leader's ID
    uint64 leader_id = 2;
    // last_included_index is the snapshot replaces all entries up through and including this index
    uint64 last_included_index = 3;
    // last_included_term is term of last_included_index
    uint64 last_included_term = 4;
    // offset is byte offset where chunk is positioned in the snapshot file
    uint64 offset = 5;
    // data is raw bytes of the snapshot chunk
    bytes data = 6;
    // done is true if this is the last chunk
    bool done = 7;
}

message InstallSnapshotResponse {
    // term is the current term
    uint64 term = 1;
}
