UNPKG

@ceramicnetwork/core

Version:

Typescript implementation of the Ceramic protocol

164 lines • 8.83 kB
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