@ceramicnetwork/core
Version:
Typescript implementation of the Ceramic protocol
164 lines • 8.83 kB
JavaScript
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _AnchorRequestStore_shouldStop, _AnchorRequestStore_abortController, _AnchorRequestStore_logger, _AnchorRequestStore_infiniteListBatchTimeoutMs, _AnchorRequestStore_minLoopDurationMs, _AnchorRequestStore_minLoopJitterMs;
import { StreamID } from '@ceramicnetwork/streamid';
import { ObjectStore } from './object-store.js';
import { CID } from 'multiformats/cid';
import { ServiceMetrics as Metrics } from '@ceramicnetwork/observability';
const DEFAULT_BATCH_TIMEOUT_MS = 60 * 1000;
const ANCHOR_POLLING_PROCESSED = 'anchor_polling_processed';
const DEFAULT_MIN_LOOP_JITTER_MS = 100;
function generateKey(object) {
if (object) {
return object.toString();
}
else {
return undefined;
}
}
export function serializeAnchorRequestData(value) {
return JSON.stringify({
cid: value.cid.toString(),
timestamp: value.timestamp,
});
}
export function deserializeAnchorRequestData(serialized) {
const parsed = JSON.parse(serialized);
return {
cid: CID.parse(parsed.cid),
timestamp: parsed.timestamp,
};
}
async function sleepOrAbort(timeoutMS, abortSignal) {
let timeout;
let listener;
return new Promise((resolve) => {
if (abortSignal.aborted) {
return resolve();
}
listener = () => {
resolve();
};
abortSignal.addEventListener('abort', listener);
timeout = setTimeout(() => {
resolve();
}, timeoutMS);
}).then(() => {
clearTimeout(timeout);
abortSignal.removeEventListener('abort', listener);
});
}
export class AnchorRequestStore extends ObjectStore {
constructor(logger, minLoopDurationMs, infiniteListBatchTimeoutMs = DEFAULT_BATCH_TIMEOUT_MS, minLoopJitterMS = DEFAULT_MIN_LOOP_JITTER_MS) {
super(generateKey, serializeAnchorRequestData, deserializeAnchorRequestData);
this.useCaseName = 'anchor-requests';
_AnchorRequestStore_shouldStop.set(this, void 0);
_AnchorRequestStore_abortController.set(this, void 0);
_AnchorRequestStore_logger.set(this, void 0);
_AnchorRequestStore_infiniteListBatchTimeoutMs.set(this, void 0);
_AnchorRequestStore_minLoopDurationMs.set(this, void 0);
_AnchorRequestStore_minLoopJitterMs.set(this, void 0);
__classPrivateFieldSet(this, _AnchorRequestStore_logger, logger, "f");
__classPrivateFieldSet(this, _AnchorRequestStore_infiniteListBatchTimeoutMs, infiniteListBatchTimeoutMs, "f");
__classPrivateFieldSet(this, _AnchorRequestStore_abortController, new AbortController(), "f");
__classPrivateFieldSet(this, _AnchorRequestStore_minLoopDurationMs, minLoopDurationMs, "f");
__classPrivateFieldSet(this, _AnchorRequestStore_minLoopJitterMs, minLoopJitterMS, "f");
}
exists(key) {
return this.store.exists(generateKey(key));
}
async *list(batchSize = 1) {
let gt = undefined;
do {
const batch = await this.store.find({
limit: batchSize,
gt: generateKey(gt),
});
if (batch.length > 0) {
gt = StreamID.fromString(batch[batch.length - 1].key);
yield batch.map((item) => {
return {
key: StreamID.fromString(item.key),
value: deserializeAnchorRequestData(item.value),
};
});
}
else {
return;
}
} while (true);
}
async *infiniteList(batchSize = 1) {
let gt = undefined;
let numEntries = 0;
do {
const loopStartTime = new Date();
try {
let timeout;
const timeoutPromise = new Promise((resolve) => {
timeout = setTimeout(() => {
__classPrivateFieldGet(this, _AnchorRequestStore_logger, "f").warn(`Timed out while waiting for AnchorRequestStore to fetch a batch`);
resolve(null);
}, __classPrivateFieldGet(this, _AnchorRequestStore_infiniteListBatchTimeoutMs, "f"));
});
if (gt) {
__classPrivateFieldGet(this, _AnchorRequestStore_logger, "f").verbose(`Fetching batch from AnchorRequestStore starting at key ${gt}`);
}
else {
__classPrivateFieldGet(this, _AnchorRequestStore_logger, "f").verbose(`Fetching batch from AnchorRequestStore starting at the beginning of the keys`);
}
const batchPromise = this.store.find({
limit: batchSize,
gt: generateKey(gt),
});
const batch = await Promise.race([batchPromise, timeoutPromise]);
clearTimeout(timeout);
if (batch && batch.length > 0) {
gt = StreamID.fromString(batch[batch.length - 1].key);
for (const item of batch) {
numEntries++;
yield StreamID.fromString(item.key);
}
}
else {
__classPrivateFieldGet(this, _AnchorRequestStore_logger, "f").debug(`Anchor polling loop processed ${numEntries} entries from the AnchorRequestStore. Restarting loop.`);
Metrics.observe(ANCHOR_POLLING_PROCESSED, numEntries);
const loopEndTime = new Date();
const loopDurationMs = Math.abs(loopEndTime.getTime() - loopStartTime.getTime());
if (__classPrivateFieldGet(this, _AnchorRequestStore_minLoopDurationMs, "f") === 0) {
await sleepOrAbort(__classPrivateFieldGet(this, _AnchorRequestStore_minLoopJitterMs, "f"), __classPrivateFieldGet(this, _AnchorRequestStore_abortController, "f").signal);
}
else if (loopDurationMs < __classPrivateFieldGet(this, _AnchorRequestStore_minLoopDurationMs, "f")) {
const remainingLoopDuration = __classPrivateFieldGet(this, _AnchorRequestStore_minLoopDurationMs, "f") - loopDurationMs;
if (remainingLoopDuration > __classPrivateFieldGet(this, _AnchorRequestStore_minLoopJitterMs, "f")) {
await sleepOrAbort(remainingLoopDuration, __classPrivateFieldGet(this, _AnchorRequestStore_abortController, "f").signal);
}
}
gt = undefined;
numEntries = 0;
}
}
catch (err) {
__classPrivateFieldGet(this, _AnchorRequestStore_logger, "f").err(`Error querying the AnchorRequestStore: ${err}`);
}
} while (!__classPrivateFieldGet(this, _AnchorRequestStore_shouldStop, "f"));
__classPrivateFieldGet(this, _AnchorRequestStore_logger, "f").debug(`AnchorRequestStore processing loop shutting down`);
}
async close() {
__classPrivateFieldGet(this, _AnchorRequestStore_logger, "f").debug(`Closing AnchorRequestStore`);
__classPrivateFieldSet(this, _AnchorRequestStore_shouldStop, true, "f");
__classPrivateFieldGet(this, _AnchorRequestStore_abortController, "f").abort();
await super.close();
}
}
_AnchorRequestStore_shouldStop = new WeakMap(), _AnchorRequestStore_abortController = new WeakMap(), _AnchorRequestStore_logger = new WeakMap(), _AnchorRequestStore_infiniteListBatchTimeoutMs = new WeakMap(), _AnchorRequestStore_minLoopDurationMs = new WeakMap(), _AnchorRequestStore_minLoopJitterMs = new WeakMap();
//# sourceMappingURL=anchor-request-store.js.map