UNPKG

hamok

Version:

Lightweight Distributed Object Storage on RAFT consensus algorithm

141 lines (140 loc) 7.51 kB
"use strict"; 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;