129 lines
3.1 KiB
Python
129 lines
3.1 KiB
Python
""" This module holds the messages for raft to use.
|
|
|
|
Message -- Base message class
|
|
|
|
AppendEntries -- Message representing raft append entries.
|
|
|
|
RequestVote -- Message representing raft request vote.
|
|
|
|
RequestVoteReponse -- Message for responding to a request vote.
|
|
|
|
Response -- Response to an append entries message.
|
|
"""
|
|
import umsgpack
|
|
from enum import Enum
|
|
|
|
class Messages(Enum):
|
|
AppendEntries = 1
|
|
RequestVote = 2
|
|
RequestVoteResponse = 3
|
|
AppendEntriesResponse = 4
|
|
|
|
class Message:
|
|
"""The base class of all messages used in raft"""
|
|
_type = None
|
|
|
|
def __init__(self, sender, data = {}, term = 0):
|
|
self._sender = sender
|
|
self._data = data
|
|
self._term = term
|
|
|
|
@property
|
|
def sender(self):
|
|
return self._sender
|
|
|
|
@property
|
|
def type(self):
|
|
return self._type
|
|
|
|
def serialise(self):
|
|
"""Serialises a Message object into a message pack byte array"""
|
|
raise NotImplementedError
|
|
|
|
@staticmethod
|
|
def deserialise(message):
|
|
"""Deserialises from a byte array into a Message object
|
|
|
|
message -- Message to deserialise.
|
|
|
|
Returns -- Deserialised message object, None if incorrect input message.
|
|
"""
|
|
m = None
|
|
try:
|
|
m = umsgpack.unpackb(m)
|
|
except:
|
|
print("Could not decode message")
|
|
return m
|
|
|
|
m = Message('tbd')
|
|
raise NotImplementedError
|
|
|
|
def __eq__(self, other):
|
|
if not isinstance(other, Message):
|
|
return False
|
|
|
|
if other.type != self.type:
|
|
return False
|
|
|
|
if other._data != self._data:
|
|
return False
|
|
|
|
if other._sender != self._sender:
|
|
return False
|
|
|
|
return True
|
|
|
|
class AppendEntries(Message):
|
|
_type = "AppendEntries"
|
|
|
|
def __init__(self, term, leaderId, prevLogIndex, prevLogTerm, leaderCommit, entries = None):
|
|
self._data["term"] = term
|
|
self._data["leaderId"] = leaderId
|
|
self._data["prevLogIndex"] = prevLogIndex
|
|
self._data["prevLogTerm"] = prevLogTerm
|
|
self._data["entries"] = entries
|
|
self._data["leaderCommit"] = leaderCommit # Leader's commit index.
|
|
|
|
|
|
class RequestVote(Message):
|
|
_type = "RequestVote"
|
|
|
|
def __init__(self, term, candidate_id, last_log_index, last_log_term):
|
|
self._data["candidateId"] = candidate_id
|
|
self._data["lastLogIndex"] = last_log_index
|
|
self._data["lastLogTerm"] = last_log_term
|
|
|
|
@property
|
|
def candidate_id(self):
|
|
return self._data["candidateId"]
|
|
|
|
@property
|
|
def last_log_index(self):
|
|
return self._data["lastLogIndex"]
|
|
|
|
@property
|
|
def last_log_term(self):
|
|
return self._data["lastLogTerm"]
|
|
|
|
|
|
class RequestVoteResponse(Message):
|
|
_type = "RequestVoteResponse"
|
|
|
|
def __init__(self, term, vote_granted):
|
|
self._data["voteGranted"] = vote_granted
|
|
|
|
@property
|
|
def vote_granted(self):
|
|
return self._data["voteGranted"]
|
|
|
|
class Response(Message):
|
|
_type = "Response"
|
|
|
|
def __init__(self, term, success):
|
|
self._data["success"] = success
|
|
|
|
@property
|
|
def success(self):
|
|
return self._data["success"]
|
|
|
|
|