libp2p-gossipsub
Version:
A typescript implementation of gossipsub
124 lines (123 loc) • 3.99 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MessageCache = void 0;
const utils_1 = require("./utils");
class MessageCache {
/**
* @param {Number} gossip
* @param {Number} history
* @param {msgIdFn} msgIdFn a function that returns message id from a message
*
* @constructor
*/
constructor(gossip, history) {
/**
* @type {Map<string, RPC.Message>}
*/
this.msgs = new Map();
this.peertx = new Map();
/**
* @type {Array<Array<CacheEntry>>}
*/
this.history = [];
for (let i = 0; i < history; i++) {
this.history[i] = [];
}
/**
* @type {Number}
*/
this.gossip = gossip;
}
/**
* Adds a message to the current window and the cache
*
* @param {string} msgIdStr
* @param {RPC.Message} msg
* @returns {Promise<void>}
*/
put(msg, msgIdStr) {
return __awaiter(this, void 0, void 0, function* () {
this.msgs.set(msgIdStr, msg);
const msgId = utils_1.messageIdFromString(msgIdStr);
this.history[0].push({ msgId: msgId, topics: msg.topicIDs });
});
}
/**
* Retrieves a message from the cache by its ID, if it is still present
*
* @param {Uint8Array} msgId
* @returns {Message}
*/
get(msgId) {
return this.msgs.get(utils_1.messageIdToString(msgId));
}
/**
* Retrieves a message from the cache by its ID, if it is present
* for a specific peer.
* Returns the message and the number of times the peer has requested the message
*
* @param {string} msgIdStr
* @param {string} p
* @returns {[InMessage | undefined, number]}
*/
getForPeer(msgIdStr, p) {
const msg = this.msgs.get(msgIdStr);
if (!msg) {
return [undefined, 0];
}
let peertx = this.peertx.get(msgIdStr);
if (!peertx) {
peertx = new Map();
this.peertx.set(msgIdStr, peertx);
}
const count = (peertx.get(p) || 0) + 1;
peertx.set(p, count);
return [msg, count];
}
/**
* Retrieves a list of message IDs for a given topic
*
* @param {String} topic
*
* @returns {Array<Uint8Array>}
*/
getGossipIDs(topic) {
const msgIds = [];
for (let i = 0; i < this.gossip; i++) {
this.history[i].forEach((entry) => {
for (const t of entry.topics) {
if (t === topic) {
msgIds.push(entry.msgId);
break;
}
}
});
}
return msgIds;
}
/**
* Shifts the current window, discarding messages older than this.history.length of the cache
*
* @returns {void}
*/
shift() {
const last = this.history[this.history.length - 1];
last.forEach((entry) => {
const msgIdStr = utils_1.messageIdToString(entry.msgId);
this.msgs.delete(msgIdStr);
this.peertx.delete(msgIdStr);
});
this.history.pop();
this.history.unshift([]);
}
}
exports.MessageCache = MessageCache;