UNPKG

@ceramicnetwork/core

Version:

Typescript implementation of the Ceramic protocol

127 lines 5.93 kB
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 __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 _MonotonicKey_previous, _MonotonicKey_counter, _FeedAggregationStore_keyGenerator, _FeedAggregationStore_interval; import { ObjectStore } from './object-store.js'; import { StreamID } from '@ceramicnetwork/streamid'; import { TaskQueue } from '../ancillary/task-queue.js'; import { firstValueFrom, Subject } from 'rxjs'; function serializeStreamID(streamID) { return streamID.toString(); } function deserializeStreamID(input) { return StreamID.fromString(input); } const DEFAULT_STALE_DURATION = 604800000; const DEFAULT_CLEANUP_INTERVAL = 600000; export class MonotonicKey { constructor() { _MonotonicKey_previous.set(this, Date.now()); _MonotonicKey_counter.set(this, 0); } next(now = Date.now()) { var _a, _b; if (__classPrivateFieldGet(this, _MonotonicKey_previous, "f") === now) { const counter = (__classPrivateFieldSet(this, _MonotonicKey_counter, (_b = __classPrivateFieldGet(this, _MonotonicKey_counter, "f"), _a = _b++, _b), "f"), _a); return `${__classPrivateFieldGet(this, _MonotonicKey_previous, "f")}${counter.toString().padStart(6, '0')}`; } else { __classPrivateFieldSet(this, _MonotonicKey_counter, 1, "f"); __classPrivateFieldSet(this, _MonotonicKey_previous, now, "f"); return `${__classPrivateFieldGet(this, _MonotonicKey_previous, "f")}000000`; } } } _MonotonicKey_previous = new WeakMap(), _MonotonicKey_counter = new WeakMap(); export class FeedAggregationStore extends ObjectStore { constructor(logger, staleDuration = DEFAULT_STALE_DURATION, cleanupInterval = DEFAULT_CLEANUP_INTERVAL) { super(String, serializeStreamID, deserializeStreamID); this.logger = logger; this.useCaseName = 'feed-aggregation'; _FeedAggregationStore_keyGenerator.set(this, new MonotonicKey()); _FeedAggregationStore_interval.set(this, void 0); this.staleDuration = staleDuration; this.cleanupInterval = cleanupInterval; this.tasks = new TaskQueue(); __classPrivateFieldSet(this, _FeedAggregationStore_interval, undefined, "f"); this.find = this.find.bind(this); this.onWrite = new Subject(); } findKeys(params) { return this.store.findKeys(params); } find(params) { return this.store.find(params); } async deleteStale(lessThanMs) { const keys = await this.store.findKeys({ lt: String(lessThanMs * 1000) }); if (keys.length > 0) { let batch = this.store.batch(); for (const k of keys) { batch = batch.del(k); } await batch.write(); } return keys.length; } async put(streamId, key = __classPrivateFieldGet(this, _FeedAggregationStore_keyGenerator, "f").next()) { await this.save(key, streamId); this.logger.verbose(`Inserting this streamId from LevelDB ${streamId} at ${Date.now()}`); this.onWrite.next(); } async open(factory) { await super.open(factory); if (this.cleanupInterval) { __classPrivateFieldSet(this, _FeedAggregationStore_interval, setInterval(() => { if (this.tasks.size > 0) return; this.tasks.add(async () => { const threshold = Date.now() - this.staleDuration; await this.deleteStale(threshold); }); }, this.cleanupInterval), "f"); } } streamIDs(gt) { const source = new StreamIDFeedSource(this.find, this.onWrite.asObservable(), this.logger, gt); return new ReadableStream(source); } async close() { clearInterval(__classPrivateFieldGet(this, _FeedAggregationStore_interval, "f")); await this.tasks.onIdle(); await super.close(); } } _FeedAggregationStore_keyGenerator = new WeakMap(), _FeedAggregationStore_interval = new WeakMap(); class StreamIDFeedSource { constructor(find, onWrite, logger, token = new MonotonicKey().next()) { this.find = find; this.onWrite = onWrite; this.logger = logger; this.token = token; } async pull(controller) { const entries = await this.find({ limit: controller.desiredSize, gt: this.token }); if (entries.length === 0) { await firstValueFrom(this.onWrite); return this.pull(controller); } for (const entry of entries) { this.logger.verbose(`Sending this streamId from LevelDB ${entry.value} at ${Date.now()}`); controller.enqueue({ resumeToken: entry.key, streamID: entry.value, }); } this.token = entries[entries.length - 1].key; } } //# sourceMappingURL=feed-aggregation-store.js.map