@ceramicnetwork/core
Version:
Typescript implementation of the Ceramic protocol
39 lines • 1.95 kB
JavaScript
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