syntax = "proto3";
package eraftpb;

enum EntryType {
    EntryNormal = 0;
    EntryConfChange = 1;
}

// The entry is a type of change that needs to be applied. It contains two data fields.
// While the fields are built into the model; their usage is determined by the entry_type.
//
// For normal entries, the data field should contain the data change that should be applied.
// The context field can be used for any contextual data that might be relevant to the
// application of the data.
//
// For configuration changes, the data will contain the ConfChange message and the
// context will provide anything needed to assist the configuration change. The context
// is for the user to set and use in this case.
message Entry {
    EntryType entry_type = 1;
    uint64 term = 2;
    uint64 index = 3;
    bytes data = 4;
}

// SnapshotMetadata contains the log index and term of the last log applied to this
// Snapshot, along with the membership information of the time the last log applied.
message SnapshotMetadata {
    ConfState conf_state = 1;
    uint64 index = 2;
    uint64 term = 3;
}

message Snapshot {
    bytes data = 1;
    SnapshotMetadata metadata = 2;
}

// Some MessageType defined here are local messages which not come from the network, but should
// also use the Step method to handle
enum MessageType {
    // 'MessageType_MsgHup' is a local message used for election. If an election timeout happened,
    // the node should pass 'MessageType_MsgHup' to its Step method and start a new election.
    MsgHup = 0;
    // 'MessageType_MsgBeat' is a local message that signals the leader to send a heartbeat
    // of the 'MessageType_MsgHeartbeat' type to its followers.
    MsgBeat = 1;
    // 'MessageType_MsgPropose' is a local message that proposes to append data to the leader's log entries.
    MsgPropose = 2;
    // 'MessageType_MsgAppend' contains log entries to replicate.
    MsgAppend = 3;
    // 'MessageType_MsgAppendResponse' is response to log replication request('MessageType_MsgAppend').
    MsgAppendResponse = 4;
    // 'MessageType_MsgRequestVote' requests votes for election.
    MsgRequestVote = 5;
    // 'MessageType_MsgRequestVoteResponse' contains responses from voting request.
    MsgRequestVoteResponse = 6;
    // 'MessageType_MsgSnapshot' requests to install a snapshot message.
    MsgSnapshot = 7;
    // 'MessageType_MsgHeartbeat' sends heartbeat from leader to its followers.
    MsgHeartbeat = 8;
    // 'MessageType_MsgHeartbeatResponse' is a response to 'MessageType_MsgHeartbeat'.
    MsgHeartbeatResponse = 9;
    // 'MessageType_MsgTransferLeader' requests the leader to transfer its leadership.
    MsgTransferLeader = 11;
    // 'MessageType_MsgTimeoutNow' send from the leader to the leadership transfer target, to let
    // the transfer target timeout immediately and start a new election.
    MsgTimeoutNow = 12;
}

message Message {
    MessageType msg_type = 1;
    uint64 to = 2;
    uint64 from = 3;
    uint64 term = 4;
    uint64 log_term = 5;
    uint64 index = 6;
    repeated Entry entries = 7;
    uint64 commit = 8;
    Snapshot snapshot = 9;
    bool reject = 10;
}

// HardState contains the state of a node need to be peristed, including the current term, commit index 
// and the vote record
message HardState {
    uint64 term = 1;
    uint64 vote = 2;
    uint64 commit = 3;
}

// ConfState contains the current membership information of the raft group
message ConfState {
    // all node id
    repeated uint64 nodes = 1;
}

enum ConfChangeType {
    AddNode    = 0;
    RemoveNode = 1;
}

// ConfChange is the data that attach on entry with EntryConfChange type
message ConfChange {
    ConfChangeType change_type = 1;
    // node will be add/remove
    uint64 node_id = 2;
    bytes context = 3;
}
