UNPKG

hamok

Version:

Lightweight Distributed Object Storage on RAFT consensus algorithm

226 lines (225 loc) 11.4 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.HamokGridCodec = void 0; const HamokCodec_1 = require("../common/HamokCodec"); const logger_1 = require("../common/logger"); const SubmitMessage_1 = require("./messagetypes/SubmitMessage"); const HamokMessage_1 = require("./HamokMessage"); const OngoingRequests_1 = require("./messagetypes/OngoingRequests"); const Collections = __importStar(require("../common/Collections")); const EndpointNotification_1 = require("./messagetypes/EndpointNotification"); const HelloNotification_1 = require("./messagetypes/HelloNotification"); const JoinNotification_1 = require("./messagetypes/JoinNotification"); const logger = (0, logger_1.createLogger)('GridCodec'); const EMPTY_ARRAY = []; const strCodec = (0, HamokCodec_1.createStrToUint8ArrayCodec)(); function setToArray(set) { if (!set) return; return Array.from(set); } function arrayToSet(array) { if (!array) return; return new Set(array); } class HamokGridCodec { encode(input) { switch (input.constructor) { case HelloNotification_1.HelloNotification: return this.encodeHelloNotification(input); case JoinNotification_1.JoinNotification: return this.encodeJoinNotification(input); case EndpointNotification_1.EndpointStatesNotification: return this.encodeEndpointStateNotification(input); case OngoingRequests_1.OngoingRequestsNotification: return this.encodeOngoingRequestsNotification(input); case SubmitMessage_1.SubmitMessageRequest: return this.encodeSubmitMessageRequest(input); case SubmitMessage_1.SubmitMessageResponse: return this.encodeSubmitMessageResponse(input); default: throw new Error(`Cannot encode input${input}`); } } decode(message) { switch (message.type) { case HamokMessage_1.HamokMessage_MessageType.HELLO_NOTIFICATION: return this.decodeHelloNotification(message); case HamokMessage_1.HamokMessage_MessageType.JOIN_NOTIFICATION: return this.decodeJoinNotification(message); case HamokMessage_1.HamokMessage_MessageType.ENDPOINT_STATES_NOTIFICATION: return this.decodeEndpointStateNotification(message); case HamokMessage_1.HamokMessage_MessageType.ONGOING_REQUESTS_NOTIFICATION: return this.decodeOngoingRequestsNotification(message); case HamokMessage_1.HamokMessage_MessageType.SUBMIT_MESSAGE_REQUEST: return this.decodeSubmitMessageRequest(message); case HamokMessage_1.HamokMessage_MessageType.SUBMIT_MESSAGE_RESPONSE: return this.decodeSubmitMessageResponse(message); default: throw new Error(`Cannot decode message${message}`); } } encodeHelloNotification(notification) { logger.trace('encodeHelloNotification(): notification.customData %o', notification); return new HamokMessage_1.HamokMessage({ // eslint-disable-next-line camelcase protocol: HamokMessage_1.HamokMessage_MessageProtocol.GRID_COMMUNICATION_PROTOCOL, type: HamokMessage_1.HamokMessage_MessageType.HELLO_NOTIFICATION, sourceId: notification.sourcePeerId, destinationId: notification.destinationPeerId, raftLeaderId: notification.raftLeaderId, keys: notification.customData ? [strCodec.encode(notification.customData)] : [], requestId: notification.requestId, }); } decodeHelloNotification(message) { if (message.type !== HamokMessage_1.HamokMessage_MessageType.HELLO_NOTIFICATION) { throw new Error('decodeHelloNotification(): Message type must be HELLO_NOTIFICATION'); } const customData = message.keys.length === 1 ? strCodec.decode(message.keys[0]) : undefined; return new HelloNotification_1.HelloNotification(message.sourceId, message.destinationId, message.raftLeaderId, customData, message.requestId); } encodeJoinNotification(notification) { return new HamokMessage_1.HamokMessage({ // eslint-disable-next-line camelcase protocol: HamokMessage_1.HamokMessage_MessageProtocol.GRID_COMMUNICATION_PROTOCOL, type: HamokMessage_1.HamokMessage_MessageType.JOIN_NOTIFICATION, sourceId: notification.sourcePeerId, destinationId: notification.destinationPeerId, }); } decodeJoinNotification(message) { if (message.type !== HamokMessage_1.HamokMessage_MessageType.JOIN_NOTIFICATION) { throw new Error('decodeJoinNotification(): Message type must be JOIN_NOTIFICATION'); } return new JoinNotification_1.JoinNotification(message.sourceId, message.destinationId); } encodeEndpointStateNotification(notification) { const activeEndpointIds = setToArray(notification.activeEndpointIds); const snapshot = notification.snapshot ? strCodec.encode(notification.snapshot) : undefined; logger.trace('encodeEndpointStateNotification(): activeEndpointIds %s', activeEndpointIds); return new HamokMessage_1.HamokMessage({ // eslint-disable-next-line camelcase protocol: HamokMessage_1.HamokMessage_MessageProtocol.GRID_COMMUNICATION_PROTOCOL, type: HamokMessage_1.HamokMessage_MessageType.ENDPOINT_STATES_NOTIFICATION, sourceId: notification.sourceEndpointId, destinationId: notification.destinationEndpointId, raftTerm: notification.term, raftCommitIndex: notification.commitIndex, raftLeaderNextIndex: notification.leaderNextIndex, raftNumberOfLogs: notification.numberOfLogs, activeEndpointIds, snapshot, requestId: notification.requestId, }); } decodeEndpointStateNotification(message) { if (message.type !== HamokMessage_1.HamokMessage_MessageType.ENDPOINT_STATES_NOTIFICATION) { throw new Error('decodeEndpointStateNotification(): Message type must be ENDPOINT_STATES_NOTIFICATION'); } logger.trace('decodeEndpointStateNotification(): activeEndpointIds %s', message.activeEndpointIds); const activeEndpointIds = arrayToSet(message.activeEndpointIds); const snapshot = message.snapshot ? strCodec.decode(message.snapshot) : undefined; return new EndpointNotification_1.EndpointStatesNotification(message.sourceId, message.destinationId, message.raftTerm, message.raftCommitIndex, message.raftLeaderNextIndex, message.raftNumberOfLogs, activeEndpointIds, snapshot, message.requestId); } encodeOngoingRequestsNotification(notification) { const keys = HamokGridCodec._encodeSet(notification.requestIds, strCodec); return new HamokMessage_1.HamokMessage({ type: HamokMessage_1.HamokMessage_MessageType.ONGOING_REQUESTS_NOTIFICATION, destinationId: notification.destinationEndpointId, keys, }); } decodeOngoingRequestsNotification(message) { if (message.type !== HamokMessage_1.HamokMessage_MessageType.ONGOING_REQUESTS_NOTIFICATION) { throw new Error('decodeOngoingRequestsNotification(): Message type must be ONGOING_REQUESTS_NOTIFICATION'); } const requestIds = HamokGridCodec._decodeSet(message.keys, strCodec); return new OngoingRequests_1.OngoingRequestsNotification(requestIds, message.destinationId); } encodeSubmitMessageRequest(request) { return new HamokMessage_1.HamokMessage({ type: HamokMessage_1.HamokMessage_MessageType.SUBMIT_MESSAGE_REQUEST, requestId: request.requestId, embeddedMessages: [request.entry], sourceId: request.sourceEndpointId, destinationId: request.destinationEndpointId, }); } decodeSubmitMessageRequest(message) { if (message.type !== HamokMessage_1.HamokMessage_MessageType.SUBMIT_MESSAGE_REQUEST) { throw new Error('decodeSubmitMessageRequest(): Message type must be SUBMIT_MESSAGE_REQUEST'); } let entry; if (message.embeddedMessages && 0 < message.embeddedMessages.length) { entry = message.embeddedMessages[0]; if (1 < message.embeddedMessages.length) { logger.warn('decodeSubmitMessageRequest(): More than one message received for SubmitMessageRequest. Only the first one will be processed'); } } return new SubmitMessage_1.SubmitMessageRequest(message.requestId, message.sourceId, entry, message.destinationId); } encodeSubmitMessageResponse(response) { return new HamokMessage_1.HamokMessage({ type: HamokMessage_1.HamokMessage_MessageType.SUBMIT_MESSAGE_RESPONSE, requestId: response.requestId, success: response.success, destinationId: response.destinationEndpointId, raftLeaderId: response.leaderId, }); } decodeSubmitMessageResponse(message) { if (message.type !== HamokMessage_1.HamokMessage_MessageType.SUBMIT_MESSAGE_RESPONSE) { throw new Error('decodeSubmitMessageResponse(): Message type must be SUBMIT_MESSAGE_RESPONSE'); } return new SubmitMessage_1.SubmitMessageResponse(message.requestId, Boolean(message.success), message.destinationId, message.raftLeaderId); } static _encodeSet(keys, encoder) { if (keys.size < 1) { return EMPTY_ARRAY; } const result = []; for (const key of keys) { const encodedKey = encoder.encode(key); result.push(encodedKey); } return result; } static _decodeSet(keys, decoder) { if (keys.length < 1) { return Collections.EMPTY_SET; } const result = new Set(); for (let i = 0; i < keys.length; ++i) { const key = keys[i]; const decodedKey = decoder.decode(key); result.add(decodedKey); } return result; } } exports.HamokGridCodec = HamokGridCodec;