UNPKG

hamok

Version:

Lightweight Distributed Object Storage on RAFT consensus algorithm

135 lines (116 loc) 3.46 kB
import { HamokMessage } from '../messages/HamokMessage'; import { RaftAppendEntriesRequestChunk } from '../messages/messagetypes/RaftAppendEntries'; export class RaftAppendEntriesRequest { private _peerId?: string; private _term = -1; private _leaderId?: string; private _prevLogIndex = -1; private _prevLogTerm = -1; private _leaderCommit = -1; private _leaderNextIndex = -1; private _entries = new Map<number, HamokMessage>(); private _ready = false; private _endSeq = -1; private _created = Date.now(); private _received = 0; private _entriesList: HamokMessage[] = []; public readonly requestId: string; public constructor(requestId: string) { this.requestId = requestId; } public add(requestChunk: RaftAppendEntriesRequestChunk): void { if (requestChunk.requestId !== this.requestId) { throw new Error(`Request id mismatch. Expected ${this.requestId}, got ${requestChunk.requestId}`); } if (this._peerId == null) { this._peerId = requestChunk.peerId; } if (this._term < 0) { this._term = requestChunk.term; } if (this._leaderId == null) { this._leaderId = requestChunk.leaderId; } if (this._prevLogIndex < 0) { this._prevLogIndex = requestChunk.prevLogIndex; } if (this._prevLogTerm < 0) { this._prevLogTerm = requestChunk.prevLogTerm; } if (this._leaderCommit < 0) { this._leaderCommit = requestChunk.leaderCommit; } if (this._leaderNextIndex < 0) { this._leaderNextIndex = requestChunk.leaderNextIndex; } if (requestChunk.entry != undefined) { const removedEntry = this._entries.get(requestChunk.sequence); this._entries.set(requestChunk.sequence, requestChunk.entry); if (removedEntry != null) { throw new Error(`Overwritten log entry for requestChunk: ${ requestChunk }. removedEntry: ${ removedEntry}`); } } if (requestChunk.lastMessage) { this._endSeq = requestChunk.sequence; } if (this._endSeq == 0) { // in this case the first message is the last, // so its immediately ready this._ready = true; } else if (0 < this._endSeq) { // in this case the saved number of entries have to be equal to the endseq this._ready = (this._entries.size - 1) == this._endSeq; } if (this._ready) { const entriesList: HamokMessage[] = []; for (let index = 0; index < this._entries.size; ++index) { const entry = this._entries.get(index); if (!entry) { continue; } entriesList.push(entry); } this._entriesList = entriesList; } } public get peerId(): string | undefined { return this._peerId; } public get term(): number { return this._term; } public get leaderId(): string | undefined { return this._leaderId; } public get prevLogIndex(): number { return this._prevLogIndex; } public get prevLogTerm(): number { return this._prevLogTerm; } public get leaderCommit(): number { return this._leaderCommit; } public get leaderNextIndex(): number { return this._leaderNextIndex; } public get entries(): HamokMessage[] { return this._entriesList; } public get ready(): boolean { return this._ready; } public toString(): string { return JSON.stringify({ peerId: this._peerId, term: this._term, leaderId: this._leaderId, prevLogIndex: this._prevLogIndex, prevLogTerm: this._prevLogTerm, leaderCommit: this._leaderCommit, leaderNextIndex: this._leaderNextIndex, endSeq: this._endSeq, ready: this._ready }, null, 2); } }