hamok
Version:
Lightweight Distributed Object Storage on RAFT consensus algorithm
226 lines (225 loc) • 11.4 kB
JavaScript
;
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;