hamok
Version:
Lightweight Distributed Object Storage on RAFT consensus algorithm
141 lines (140 loc) • 7.51 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RaftMessageEmitter = void 0;
const RaftAppendEntries_1 = require("./messagetypes/RaftAppendEntries");
const RaftVote_1 = require("./messagetypes/RaftVote");
const HamokMessage_1 = require("./HamokMessage");
const events_1 = __importDefault(require("events"));
const logger_1 = require("../common/logger");
const logger = (0, logger_1.createLogger)('RaftMessageEmitter');
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
class RaftMessageEmitter extends events_1.default {
constructor() {
super();
this.setMaxListeners(Infinity);
logger.trace('RaftMessageEmitter created');
}
send(input) {
switch (input.constructor) {
case RaftVote_1.RaftVoteRequest:
this.emit('message', this.encodeRaftVoteRequest(input));
break;
case RaftVote_1.RaftVoteResponse:
this.emit('message', this.encodeRaftVoteResponse(input));
break;
case RaftAppendEntries_1.RaftAppendEntriesRequestChunk:
this.emit('message', this.encodeRaftAppendEntriesRequest(input));
break;
case RaftAppendEntries_1.RaftAppendEntriesResponse:
this.emit('message', this.encodeRaftAppendEntriesResponse(input));
break;
default:
throw new Error(`Cannot encode input ${input}`);
}
}
receive(message) {
switch (message.type) {
case HamokMessage_1.HamokMessage_MessageType.RAFT_VOTE_REQUEST:
// logger.debug('Received RaftVoteRequest %o, request: %o', message, this.decodeRaftVoteRequest(message));
this.emit('RaftVoteRequest', this.decodeRaftVoteRequest(message));
break;
case HamokMessage_1.HamokMessage_MessageType.RAFT_VOTE_RESPONSE:
this.emit('RaftVoteResponse', this.decodeRaftVoteResponse(message));
break;
case HamokMessage_1.HamokMessage_MessageType.RAFT_APPEND_ENTRIES_REQUEST_CHUNK:
this.emit('RaftAppendEntriesRequestChunk', this.decodeRaftAppendEntriesRequest(message));
break;
case HamokMessage_1.HamokMessage_MessageType.RAFT_APPEND_ENTRIES_RESPONSE:
this.emit('RaftAppendEntriesResponse', this.decodeRaftAppendEntriesResponse(message));
break;
default:
throw new Error(`Cannot decode message ${message.type}`);
}
}
encodeRaftVoteRequest(request) {
return new HamokMessage_1.HamokMessage({
protocol: HamokMessage_1.HamokMessage_MessageProtocol.RAFT_COMMUNICATION_PROTOCOL,
type: HamokMessage_1.HamokMessage_MessageType.RAFT_VOTE_REQUEST,
raftTerm: request.term,
raftPrevLogIndex: request.lastLogIndex,
raftPrevLogTerm: request.lastLogTerm,
destinationId: request.peerId,
raftCandidateId: request.candidateId,
});
}
decodeRaftVoteRequest(message) {
if (message.type !== HamokMessage_1.HamokMessage_MessageType.RAFT_VOTE_REQUEST) {
throw new Error('decodeRaftVoteRequest(): Message type must be RAFT_VOTE_REQUEST');
}
return new RaftVote_1.RaftVoteRequest(message.raftTerm, message.raftPrevLogIndex, message.raftPrevLogTerm, message.destinationId, message.raftCandidateId);
}
encodeRaftVoteResponse(response) {
return new HamokMessage_1.HamokMessage({
protocol: HamokMessage_1.HamokMessage_MessageProtocol.RAFT_COMMUNICATION_PROTOCOL,
type: HamokMessage_1.HamokMessage_MessageType.RAFT_VOTE_RESPONSE,
raftTerm: response.term,
success: response.voteGranted,
destinationId: response.destinationPeerId,
sourceId: response.sourcePeerId,
});
}
decodeRaftVoteResponse(message) {
if (message.type !== HamokMessage_1.HamokMessage_MessageType.RAFT_VOTE_RESPONSE) {
throw new Error('decodeRaftVoteResponse(): Message type must be RAFT_VOTE_RESPONSE');
}
return new RaftVote_1.RaftVoteResponse(message.raftTerm, Boolean(message.success), message.destinationId, message.sourceId);
}
encodeRaftAppendEntriesRequest(request) {
return new HamokMessage_1.HamokMessage({
protocol: HamokMessage_1.HamokMessage_MessageProtocol.RAFT_COMMUNICATION_PROTOCOL,
type: HamokMessage_1.HamokMessage_MessageType.RAFT_APPEND_ENTRIES_REQUEST_CHUNK,
requestId: request.requestId,
destinationId: request.peerId,
raftLeaderId: request.leaderId,
raftCommitIndex: request.leaderCommit,
raftLeaderNextIndex: request.leaderNextIndex,
raftPrevLogIndex: request.prevLogIndex,
raftPrevLogTerm: request.prevLogTerm,
raftTerm: request.term,
sequence: request.sequence,
lastMessage: request.lastMessage,
embeddedMessages: request.entry ? [request.entry] : undefined,
});
}
decodeRaftAppendEntriesRequest(message) {
if (message.type !== HamokMessage_1.HamokMessage_MessageType.RAFT_APPEND_ENTRIES_REQUEST_CHUNK) {
throw new Error('decodeRaftAppendEntriesRequest(): Message type must be RAFT_APPEND_ENTRIES_REQUEST_CHUNK');
}
let entry;
if (message.embeddedMessages && 0 < message.embeddedMessages.length) {
entry = message.embeddedMessages[0];
if (1 < message.embeddedMessages.length) {
throw new Error('decodeRaftAppendEntriesRequest(): More than one message received for RaftAppendRequestChunk. Only the first one will be processed');
}
}
return new RaftAppendEntries_1.RaftAppendEntriesRequestChunk(message.requestId, message.destinationId, message.raftLeaderId, message.raftCommitIndex ?? -1, message.raftLeaderNextIndex ?? -1, message.raftPrevLogIndex ?? -1, message.raftPrevLogTerm ?? -1, message.raftTerm, message.sequence ?? 0, message.lastMessage ?? false, entry);
}
encodeRaftAppendEntriesResponse(response) {
return new HamokMessage_1.HamokMessage({
protocol: HamokMessage_1.HamokMessage_MessageProtocol.RAFT_COMMUNICATION_PROTOCOL,
type: HamokMessage_1.HamokMessage_MessageType.RAFT_APPEND_ENTRIES_RESPONSE,
requestId: response.requestId,
sourceId: response.sourcePeerId,
destinationId: response.destinationPeerId,
raftTerm: response.term,
success: response.success,
raftPeerNextIndex: response.peerNextIndex,
lastMessage: response.processed,
});
}
decodeRaftAppendEntriesResponse(message) {
if (message.type !== HamokMessage_1.HamokMessage_MessageType.RAFT_APPEND_ENTRIES_RESPONSE) {
throw new Error('decodeRaftAppendEntriesResponse(): Message type must be RAFT_APPEND_ENTRIES_RESPONSE');
}
return new RaftAppendEntries_1.RaftAppendEntriesResponse(message.requestId, message.sourceId, message.destinationId, message.raftTerm, Boolean(message.success), message.raftPeerNextIndex, Boolean(message.lastMessage));
}
}
exports.RaftMessageEmitter = RaftMessageEmitter;