Throttler: log jail triggers

This commit is contained in:
Alice Gaudon 2020-11-15 15:16:18 +01:00
parent da38fdaf72
commit 6eacfdcffa
2 changed files with 14 additions and 6 deletions

View File

@ -69,11 +69,11 @@ export class NotFoundHttpError extends BadRequestError {
} }
export class TooManyRequestsHttpError extends BadRequestError { export class TooManyRequestsHttpError extends BadRequestError {
public constructor(retryIn: number, cause?: Error) { public constructor(retryIn: number, jailName: string, cause?: Error) {
super( super(
`You're making too many requests!`, `You're making too many requests!`,
`We need some rest. Please retry in ${Math.floor(retryIn / 1000)} seconds.`, `We need some rest. Please retry in ${Math.floor(retryIn / 1000)} seconds.`,
'', jailName,
cause, cause,
); );
} }

View File

@ -1,4 +1,5 @@
import {TooManyRequestsHttpError} from "./HttpError"; import {TooManyRequestsHttpError} from "./HttpError";
import {log} from "./Logger";
export default class Throttler { export default class Throttler {
private static readonly throttles: Record<string, Throttle | undefined> = {}; private static readonly throttles: Record<string, Throttle | undefined> = {};
@ -25,7 +26,8 @@ export default class Throttler {
jailPeriod: number = 30 * 1000, jailPeriod: number = 30 * 1000,
): void { ): void {
let throttle = this.throttles[action]; let throttle = this.throttles[action];
if (!throttle) throttle = this.throttles[action] = new Throttle(max, resetPeriod, holdPeriod, jailPeriod); if (!throttle)
throttle = this.throttles[action] = new Throttle(action, max, resetPeriod, holdPeriod, jailPeriod);
throttle.trigger(id); throttle.trigger(id);
} }
@ -35,6 +37,7 @@ export default class Throttler {
} }
class Throttle { class Throttle {
private readonly jailName: string;
private readonly max: number; private readonly max: number;
private readonly resetPeriod: number; private readonly resetPeriod: number;
private readonly holdPeriod: number; private readonly holdPeriod: number;
@ -45,7 +48,8 @@ class Throttle {
jailed?: number; jailed?: number;
} | undefined> = {}; } | undefined> = {};
public constructor(max: number, resetPeriod: number, holdPeriod: number, jailPeriod: number) { public constructor(jailName: string, max: number, resetPeriod: number, holdPeriod: number, jailPeriod: number) {
this.jailName = jailName;
this.max = max; this.max = max;
this.resetPeriod = resetPeriod; this.resetPeriod = resetPeriod;
this.holdPeriod = holdPeriod; this.holdPeriod = holdPeriod;
@ -75,11 +79,15 @@ class Throttle {
if (trigger.count > this.max) { if (trigger.count > this.max) {
trigger.jailed = currentDate; trigger.jailed = currentDate;
return this.throw(trigger.jailed + this.jailPeriod - currentDate);
const unjailedIn = trigger.jailed + this.jailPeriod - currentDate;
log.info(`Jail ${this.jailName} triggered by ${id} and will be unjailed in ${unjailedIn}ms.`);
return this.throw(unjailedIn);
} }
} }
protected throw(unjailedIn: number) { protected throw(unjailedIn: number) {
throw new TooManyRequestsHttpError(unjailedIn); throw new TooManyRequestsHttpError(unjailedIn, this.jailName);
} }
} }