UNPKG

@ceramicnetwork/core

Version:

Typescript implementation of the Ceramic protocol

39 lines 1.95 kB
import PQueue from 'p-queue'; import { empty, from, Observable } from 'rxjs'; import { MsgType } from './pubsub-message.js'; import { whenSubscriptionDone } from '../__tests__/when-subscription-done.util.js'; const DEFAULT_WARNINGS_INTERVAL = 30 * 60 * 1000; export class PubsubRateLimit extends Observable { constructor(pubsub, logger, queriesPerSecond, rateLimitWarningsIntervalMs = DEFAULT_WARNINGS_INTERVAL) { super((subscriber) => { pubsub.subscribe(subscriber); }); this.pubsub = pubsub; this.logger = logger; this.queriesPerSecond = queriesPerSecond; this.rateLimitWarningsIntervalMs = rateLimitWarningsIntervalMs; this.queue = new PQueue({ interval: 1000, intervalCap: queriesPerSecond }); let lastWarning = 0; this.queue.on('add', () => { if (this.queue.size > 0 && Date.now() - lastWarning >= this.rateLimitWarningsIntervalMs) { this.logger.warn(`More than ${this.queriesPerSecond} query messages published in less than a second. Query messages will be rate limited`); lastWarning = Date.now(); } }); this.maxQueuedQueries = queriesPerSecond * 10; this.logger.debug(`Configuring pubsub to rate limit query messages to ${queriesPerSecond} per second`); } next(message) { if (message.typ === MsgType.QUERY) { if (this.queue.size >= this.maxQueuedQueries) { this.logger.err(`Cannot publish query message to pubsub because we have exceeded the maximum allowed rate. Cannot have more than ${this.maxQueuedQueries} queued queries.`); return empty().subscribe(); } return from(this.queue.add(() => whenSubscriptionDone(this.pubsub.next(message)))).subscribe(); } else { return this.pubsub.next(message); } } } //# sourceMappingURL=pubsub-ratelimit.js.map