UNPKG

@atproto/sync

Version:
57 lines 1.96 kB
import PQueue from 'p-queue'; import { ConsecutiveList } from './consecutive-list.js'; // A queue with arbitrarily many partitions, each processing work sequentially. // Partitions are created lazily and taken out of memory when they go idle. export class MemoryRunner { constructor(opts = {}) { this.opts = opts; this.consecutive = new ConsecutiveList(); this.partitions = new Map(); this.mainQueue = new PQueue({ concurrency: opts.concurrency ?? Infinity }); this.cursor = opts.startCursor; } getCursor() { return this.cursor; } async addTask(partitionId, task) { if (this.mainQueue.isPaused) return; return this.mainQueue.add(() => { return this.getPartition(partitionId).add(task); }); } getPartition(partitionId) { let partition = this.partitions.get(partitionId); if (!partition) { partition = new PQueue({ concurrency: 1 }); partition.once('idle', () => this.partitions.delete(partitionId)); this.partitions.set(partitionId, partition); } return partition; } async trackEvent(did, seq, handler) { if (this.mainQueue.isPaused) return; const item = this.consecutive.push(seq); await this.addTask(did, async () => { await handler(); const latest = item.complete().at(-1); if (latest !== undefined) { this.cursor = latest; if (this.opts.setCursor) { await this.opts.setCursor(this.cursor); } } }); } async processAll() { await this.mainQueue.onIdle(); } async destroy() { this.mainQueue.pause(); this.mainQueue.clear(); this.partitions.forEach((p) => p.clear()); await this.mainQueue.onIdle(); } } //# sourceMappingURL=memory-runner.js.map