@tramvai/module-request-limiter 2.70.1 → 2.72.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/browser.js CHANGED
@@ -1,10 +1,6 @@
1
1
  import { __decorate } from 'tslib';
2
2
  import { Module } from '@tramvai/core';
3
- import { createToken } from '@tinkoff/dippy';
4
-
5
- const REQUESTS_LIMITER_TOKEN = createToken('requestsLimiterToken');
6
- const REQUESTS_LIMITER_ACTIVATE_TOKEN = createToken('requestsLimiterActivateToken');
7
- const REQUESTS_LIMITER_OPTIONS_TOKEN = createToken('requestsLimiterOptionsToken');
3
+ export { REQUESTS_LIMITER_ACTIVATE_TOKEN, REQUESTS_LIMITER_OPTIONS_TOKEN, REQUESTS_LIMITER_TOKEN } from './tokens.browser.js';
8
4
 
9
5
  let RequestLimiterModule = class RequestLimiterModule {
10
6
  };
@@ -14,4 +10,4 @@ RequestLimiterModule = __decorate([
14
10
  })
15
11
  ], RequestLimiterModule);
16
12
 
17
- export { REQUESTS_LIMITER_ACTIVATE_TOKEN, REQUESTS_LIMITER_OPTIONS_TOKEN, REQUESTS_LIMITER_TOKEN, RequestLimiterModule };
13
+ export { RequestLimiterModule };
@@ -0,0 +1,85 @@
1
+ import fp from 'fastify-plugin';
2
+ import { HttpError } from '@tinkoff/errors';
3
+ import onFinished from 'on-finished';
4
+ import { monitorEventLoopDelay } from 'perf_hooks';
5
+ import { DoubleLinkedList } from './utils/doubleLinkedList.es.js';
6
+
7
+ const DEFAULT_OPTIONS = {
8
+ limit: 10,
9
+ queue: 100,
10
+ maxEventLoopDelay: 150,
11
+ error: { httpStatus: 429, message: 'Too Many Requests' },
12
+ };
13
+ const resolution = 10;
14
+ class RequestLimiter {
15
+ constructor(options) {
16
+ this.currentActive = 0;
17
+ this.eventLoopDelay = 0;
18
+ this.queue = new DoubleLinkedList();
19
+ const { limit, queue, maxEventLoopDelay, error } = options;
20
+ this.activeRequestLimit = limit;
21
+ this.minimalActiveRequestLimit = Math.round(limit / 3);
22
+ this.queueLimit = queue;
23
+ this.error = error;
24
+ this.maxEventLoopDelay = maxEventLoopDelay;
25
+ this.eventLoopHistogram = monitorEventLoopDelay({ resolution });
26
+ this.eventLoopHistogram.enable();
27
+ const timer = setInterval(() => this.nextTick(), 1000);
28
+ timer.unref();
29
+ }
30
+ onResponse() {
31
+ this.currentActive--;
32
+ this.loop();
33
+ }
34
+ // General idea is change limits every second. Because if DDOS was happened we need some time to get problem with event loop. And better if we slowly adapt
35
+ nextTick() {
36
+ this.eventLoopDelay = Math.max(0, this.eventLoopHistogram.mean / 1e6 - resolution);
37
+ if (Number.isNaN(this.eventLoopDelay))
38
+ this.eventLoopDelay = Infinity;
39
+ this.eventLoopHistogram.reset();
40
+ if (this.currentActive >= this.activeRequestLimit) {
41
+ if (this.eventLoopDelay <= this.maxEventLoopDelay) {
42
+ this.activeRequestLimit++;
43
+ // We need to have minimalActiveRequestLimit
44
+ }
45
+ else if (this.activeRequestLimit > this.minimalActiveRequestLimit) {
46
+ this.activeRequestLimit--;
47
+ }
48
+ }
49
+ }
50
+ add(request) {
51
+ if (this.currentActive < this.activeRequestLimit) {
52
+ this.run(request);
53
+ return;
54
+ }
55
+ if (this.queue.length >= this.queueLimit) {
56
+ const lastNode = this.queue.shift();
57
+ lastNode.next(new HttpError(this.error));
58
+ }
59
+ this.queue.push(request);
60
+ }
61
+ loop() {
62
+ while (this.queue.length > 0 && this.currentActive < this.activeRequestLimit) {
63
+ // better if we start with new requests. Because more opportunity to answer before client cancel request
64
+ this.run(this.queue.pop());
65
+ }
66
+ }
67
+ run({ next, res }) {
68
+ this.currentActive++;
69
+ // onFinished doesn't work OK in DEV mode. Just stuck with high load without any reasons
70
+ // fastify: it only works this way with on-finished, as using hook `onRequest` is not enough to handle all of the requests
71
+ // and some of the failed requests are getting disappeared
72
+ // and other hooks useless as well. [related issue](https://github.com/fastify/fastify/issues/1352)
73
+ onFinished(res.raw, () => {
74
+ this.onResponse();
75
+ });
76
+ next();
77
+ }
78
+ }
79
+ const fastifyRequestsLimiter = fp(async (fastify, { requestsLimiter }) => {
80
+ fastify.addHook('onRequest', (req, res, next) => {
81
+ requestsLimiter.add({ req, res, next });
82
+ });
83
+ });
84
+
85
+ export { DEFAULT_OPTIONS, RequestLimiter, fastifyRequestsLimiter };
@@ -0,0 +1,96 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var fp = require('fastify-plugin');
6
+ var errors = require('@tinkoff/errors');
7
+ var onFinished = require('on-finished');
8
+ var perf_hooks = require('perf_hooks');
9
+ var doubleLinkedList = require('./utils/doubleLinkedList.js');
10
+
11
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
12
+
13
+ var fp__default = /*#__PURE__*/_interopDefaultLegacy(fp);
14
+ var onFinished__default = /*#__PURE__*/_interopDefaultLegacy(onFinished);
15
+
16
+ const DEFAULT_OPTIONS = {
17
+ limit: 10,
18
+ queue: 100,
19
+ maxEventLoopDelay: 150,
20
+ error: { httpStatus: 429, message: 'Too Many Requests' },
21
+ };
22
+ const resolution = 10;
23
+ class RequestLimiter {
24
+ constructor(options) {
25
+ this.currentActive = 0;
26
+ this.eventLoopDelay = 0;
27
+ this.queue = new doubleLinkedList.DoubleLinkedList();
28
+ const { limit, queue, maxEventLoopDelay, error } = options;
29
+ this.activeRequestLimit = limit;
30
+ this.minimalActiveRequestLimit = Math.round(limit / 3);
31
+ this.queueLimit = queue;
32
+ this.error = error;
33
+ this.maxEventLoopDelay = maxEventLoopDelay;
34
+ this.eventLoopHistogram = perf_hooks.monitorEventLoopDelay({ resolution });
35
+ this.eventLoopHistogram.enable();
36
+ const timer = setInterval(() => this.nextTick(), 1000);
37
+ timer.unref();
38
+ }
39
+ onResponse() {
40
+ this.currentActive--;
41
+ this.loop();
42
+ }
43
+ // General idea is change limits every second. Because if DDOS was happened we need some time to get problem with event loop. And better if we slowly adapt
44
+ nextTick() {
45
+ this.eventLoopDelay = Math.max(0, this.eventLoopHistogram.mean / 1e6 - resolution);
46
+ if (Number.isNaN(this.eventLoopDelay))
47
+ this.eventLoopDelay = Infinity;
48
+ this.eventLoopHistogram.reset();
49
+ if (this.currentActive >= this.activeRequestLimit) {
50
+ if (this.eventLoopDelay <= this.maxEventLoopDelay) {
51
+ this.activeRequestLimit++;
52
+ // We need to have minimalActiveRequestLimit
53
+ }
54
+ else if (this.activeRequestLimit > this.minimalActiveRequestLimit) {
55
+ this.activeRequestLimit--;
56
+ }
57
+ }
58
+ }
59
+ add(request) {
60
+ if (this.currentActive < this.activeRequestLimit) {
61
+ this.run(request);
62
+ return;
63
+ }
64
+ if (this.queue.length >= this.queueLimit) {
65
+ const lastNode = this.queue.shift();
66
+ lastNode.next(new errors.HttpError(this.error));
67
+ }
68
+ this.queue.push(request);
69
+ }
70
+ loop() {
71
+ while (this.queue.length > 0 && this.currentActive < this.activeRequestLimit) {
72
+ // better if we start with new requests. Because more opportunity to answer before client cancel request
73
+ this.run(this.queue.pop());
74
+ }
75
+ }
76
+ run({ next, res }) {
77
+ this.currentActive++;
78
+ // onFinished doesn't work OK in DEV mode. Just stuck with high load without any reasons
79
+ // fastify: it only works this way with on-finished, as using hook `onRequest` is not enough to handle all of the requests
80
+ // and some of the failed requests are getting disappeared
81
+ // and other hooks useless as well. [related issue](https://github.com/fastify/fastify/issues/1352)
82
+ onFinished__default["default"](res.raw, () => {
83
+ this.onResponse();
84
+ });
85
+ next();
86
+ }
87
+ }
88
+ const fastifyRequestsLimiter = fp__default["default"](async (fastify, { requestsLimiter }) => {
89
+ fastify.addHook('onRequest', (req, res, next) => {
90
+ requestsLimiter.add({ req, res, next });
91
+ });
92
+ });
93
+
94
+ exports.DEFAULT_OPTIONS = DEFAULT_OPTIONS;
95
+ exports.RequestLimiter = RequestLimiter;
96
+ exports.fastifyRequestsLimiter = fastifyRequestsLimiter;
package/lib/server.es.js CHANGED
@@ -2,153 +2,10 @@ import { __decorate } from 'tslib';
2
2
  import { Module, provide, Scope } from '@tramvai/core';
3
3
  import { ENV_USED_TOKEN, ENV_MANAGER_TOKEN } from '@tramvai/tokens-common';
4
4
  import { WEB_FASTIFY_APP_LIMITER_TOKEN } from '@tramvai/tokens-server-private';
5
- import fp from 'fastify-plugin';
6
- import { HttpError } from '@tinkoff/errors';
7
- import onFinished from 'on-finished';
8
- import { monitorEventLoopDelay } from 'perf_hooks';
9
- import { createToken } from '@tinkoff/dippy';
10
-
11
- class DoubleLinkedList {
12
- constructor() {
13
- this.length = 0;
14
- this.start = null;
15
- this.end = null;
16
- }
17
- push(value) {
18
- const newNode = {
19
- value,
20
- next: null,
21
- prev: null,
22
- };
23
- this.length++;
24
- if (this.start === null) {
25
- this.start = newNode;
26
- this.end = newNode;
27
- return;
28
- }
29
- const currentEnd = this.end;
30
- this.end = newNode;
31
- this.end.prev = currentEnd;
32
- currentEnd.next = this.end;
33
- }
34
- pop() {
35
- if (this.end === null) {
36
- return null;
37
- }
38
- this.length--;
39
- // if equal we have only 1 node, so we just remove start
40
- if (this.end === this.start) {
41
- this.start = null;
42
- }
43
- const { value } = this.end;
44
- this.end = this.end.prev;
45
- if (this.end) {
46
- this.end.next = null;
47
- }
48
- return value;
49
- }
50
- shift() {
51
- if (this.start === null) {
52
- return null;
53
- }
54
- this.length--;
55
- // if equal we have only 1 node, so we just remove end
56
- if (this.end === this.start) {
57
- this.end = null;
58
- }
59
- const { value } = this.start;
60
- this.start = this.start.next;
61
- if (this.start) {
62
- this.start.prev = null;
63
- }
64
- return value;
65
- }
66
- size() {
67
- return this.length;
68
- }
69
- }
70
-
71
- const DEFAULT_OPTIONS = {
72
- limit: 10,
73
- queue: 100,
74
- maxEventLoopDelay: 150,
75
- error: { httpStatus: 429, message: 'Too Many Requests' },
76
- };
77
- const resolution = 10;
78
- class RequestLimiter {
79
- constructor(options) {
80
- this.currentActive = 0;
81
- this.eventLoopDelay = 0;
82
- this.queue = new DoubleLinkedList();
83
- const { limit, queue, maxEventLoopDelay, error } = options;
84
- this.activeRequestLimit = limit;
85
- this.minimalActiveRequestLimit = Math.round(limit / 3);
86
- this.queueLimit = queue;
87
- this.error = error;
88
- this.maxEventLoopDelay = maxEventLoopDelay;
89
- this.eventLoopHistogram = monitorEventLoopDelay({ resolution });
90
- this.eventLoopHistogram.enable();
91
- const timer = setInterval(() => this.nextTick(), 1000);
92
- timer.unref();
93
- }
94
- onResponse() {
95
- this.currentActive--;
96
- this.loop();
97
- }
98
- // General idea is change limits every second. Because if DDOS was happened we need some time to get problem with event loop. And better if we slowly adapt
99
- nextTick() {
100
- this.eventLoopDelay = Math.max(0, this.eventLoopHistogram.mean / 1e6 - resolution);
101
- if (Number.isNaN(this.eventLoopDelay))
102
- this.eventLoopDelay = Infinity;
103
- this.eventLoopHistogram.reset();
104
- if (this.currentActive >= this.activeRequestLimit) {
105
- if (this.eventLoopDelay <= this.maxEventLoopDelay) {
106
- this.activeRequestLimit++;
107
- // We need to have minimalActiveRequestLimit
108
- }
109
- else if (this.activeRequestLimit > this.minimalActiveRequestLimit) {
110
- this.activeRequestLimit--;
111
- }
112
- }
113
- }
114
- add(request) {
115
- if (this.currentActive < this.activeRequestLimit) {
116
- this.run(request);
117
- return;
118
- }
119
- if (this.queue.length >= this.queueLimit) {
120
- const lastNode = this.queue.shift();
121
- lastNode.next(new HttpError(this.error));
122
- }
123
- this.queue.push(request);
124
- }
125
- loop() {
126
- while (this.queue.length > 0 && this.currentActive < this.activeRequestLimit) {
127
- // better if we start with new requests. Because more opportunity to answer before client cancel request
128
- this.run(this.queue.pop());
129
- }
130
- }
131
- run({ next, res }) {
132
- this.currentActive++;
133
- // onFinished doesn't work OK in DEV mode. Just stuck with high load without any reasons
134
- // fastify: it only works this way with on-finished, as using hook `onRequest` is not enough to handle all of the requests
135
- // and some of the failed requests are getting disappeared
136
- // and other hooks useless as well. [related issue](https://github.com/fastify/fastify/issues/1352)
137
- onFinished(res.raw, () => {
138
- this.onResponse();
139
- });
140
- next();
141
- }
142
- }
143
- const fastifyRequestsLimiter = fp(async (fastify, { requestsLimiter }) => {
144
- fastify.addHook('onRequest', (req, res, next) => {
145
- requestsLimiter.add({ req, res, next });
146
- });
147
- });
148
-
149
- const REQUESTS_LIMITER_TOKEN = createToken('requestsLimiterToken');
150
- const REQUESTS_LIMITER_ACTIVATE_TOKEN = createToken('requestsLimiterActivateToken');
151
- const REQUESTS_LIMITER_OPTIONS_TOKEN = createToken('requestsLimiterOptionsToken');
5
+ import { DEFAULT_OPTIONS, RequestLimiter, fastifyRequestsLimiter } from './requestLimiter.es.js';
6
+ export { DEFAULT_OPTIONS, RequestLimiter, fastifyRequestsLimiter } from './requestLimiter.es.js';
7
+ import { REQUESTS_LIMITER_OPTIONS_TOKEN, REQUESTS_LIMITER_TOKEN, REQUESTS_LIMITER_ACTIVATE_TOKEN } from './tokens.es.js';
8
+ export { REQUESTS_LIMITER_ACTIVATE_TOKEN, REQUESTS_LIMITER_OPTIONS_TOKEN, REQUESTS_LIMITER_TOKEN } from './tokens.es.js';
152
9
 
153
10
  let RequestLimiterModule = class RequestLimiterModule {
154
11
  };
@@ -234,4 +91,4 @@ RequestLimiterModule = __decorate([
234
91
  })
235
92
  ], RequestLimiterModule);
236
93
 
237
- export { DEFAULT_OPTIONS, REQUESTS_LIMITER_ACTIVATE_TOKEN, REQUESTS_LIMITER_OPTIONS_TOKEN, REQUESTS_LIMITER_TOKEN, RequestLimiter, RequestLimiterModule, fastifyRequestsLimiter };
94
+ export { RequestLimiterModule };
package/lib/server.js CHANGED
@@ -6,158 +6,8 @@ var tslib = require('tslib');
6
6
  var core = require('@tramvai/core');
7
7
  var tokensCommon = require('@tramvai/tokens-common');
8
8
  var tokensServerPrivate = require('@tramvai/tokens-server-private');
9
- var fp = require('fastify-plugin');
10
- var errors = require('@tinkoff/errors');
11
- var onFinished = require('on-finished');
12
- var perf_hooks = require('perf_hooks');
13
- var dippy = require('@tinkoff/dippy');
14
-
15
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
16
-
17
- var fp__default = /*#__PURE__*/_interopDefaultLegacy(fp);
18
- var onFinished__default = /*#__PURE__*/_interopDefaultLegacy(onFinished);
19
-
20
- class DoubleLinkedList {
21
- constructor() {
22
- this.length = 0;
23
- this.start = null;
24
- this.end = null;
25
- }
26
- push(value) {
27
- const newNode = {
28
- value,
29
- next: null,
30
- prev: null,
31
- };
32
- this.length++;
33
- if (this.start === null) {
34
- this.start = newNode;
35
- this.end = newNode;
36
- return;
37
- }
38
- const currentEnd = this.end;
39
- this.end = newNode;
40
- this.end.prev = currentEnd;
41
- currentEnd.next = this.end;
42
- }
43
- pop() {
44
- if (this.end === null) {
45
- return null;
46
- }
47
- this.length--;
48
- // if equal we have only 1 node, so we just remove start
49
- if (this.end === this.start) {
50
- this.start = null;
51
- }
52
- const { value } = this.end;
53
- this.end = this.end.prev;
54
- if (this.end) {
55
- this.end.next = null;
56
- }
57
- return value;
58
- }
59
- shift() {
60
- if (this.start === null) {
61
- return null;
62
- }
63
- this.length--;
64
- // if equal we have only 1 node, so we just remove end
65
- if (this.end === this.start) {
66
- this.end = null;
67
- }
68
- const { value } = this.start;
69
- this.start = this.start.next;
70
- if (this.start) {
71
- this.start.prev = null;
72
- }
73
- return value;
74
- }
75
- size() {
76
- return this.length;
77
- }
78
- }
79
-
80
- const DEFAULT_OPTIONS = {
81
- limit: 10,
82
- queue: 100,
83
- maxEventLoopDelay: 150,
84
- error: { httpStatus: 429, message: 'Too Many Requests' },
85
- };
86
- const resolution = 10;
87
- class RequestLimiter {
88
- constructor(options) {
89
- this.currentActive = 0;
90
- this.eventLoopDelay = 0;
91
- this.queue = new DoubleLinkedList();
92
- const { limit, queue, maxEventLoopDelay, error } = options;
93
- this.activeRequestLimit = limit;
94
- this.minimalActiveRequestLimit = Math.round(limit / 3);
95
- this.queueLimit = queue;
96
- this.error = error;
97
- this.maxEventLoopDelay = maxEventLoopDelay;
98
- this.eventLoopHistogram = perf_hooks.monitorEventLoopDelay({ resolution });
99
- this.eventLoopHistogram.enable();
100
- const timer = setInterval(() => this.nextTick(), 1000);
101
- timer.unref();
102
- }
103
- onResponse() {
104
- this.currentActive--;
105
- this.loop();
106
- }
107
- // General idea is change limits every second. Because if DDOS was happened we need some time to get problem with event loop. And better if we slowly adapt
108
- nextTick() {
109
- this.eventLoopDelay = Math.max(0, this.eventLoopHistogram.mean / 1e6 - resolution);
110
- if (Number.isNaN(this.eventLoopDelay))
111
- this.eventLoopDelay = Infinity;
112
- this.eventLoopHistogram.reset();
113
- if (this.currentActive >= this.activeRequestLimit) {
114
- if (this.eventLoopDelay <= this.maxEventLoopDelay) {
115
- this.activeRequestLimit++;
116
- // We need to have minimalActiveRequestLimit
117
- }
118
- else if (this.activeRequestLimit > this.minimalActiveRequestLimit) {
119
- this.activeRequestLimit--;
120
- }
121
- }
122
- }
123
- add(request) {
124
- if (this.currentActive < this.activeRequestLimit) {
125
- this.run(request);
126
- return;
127
- }
128
- if (this.queue.length >= this.queueLimit) {
129
- const lastNode = this.queue.shift();
130
- lastNode.next(new errors.HttpError(this.error));
131
- }
132
- this.queue.push(request);
133
- }
134
- loop() {
135
- while (this.queue.length > 0 && this.currentActive < this.activeRequestLimit) {
136
- // better if we start with new requests. Because more opportunity to answer before client cancel request
137
- this.run(this.queue.pop());
138
- }
139
- }
140
- run({ next, res }) {
141
- this.currentActive++;
142
- // onFinished doesn't work OK in DEV mode. Just stuck with high load without any reasons
143
- // fastify: it only works this way with on-finished, as using hook `onRequest` is not enough to handle all of the requests
144
- // and some of the failed requests are getting disappeared
145
- // and other hooks useless as well. [related issue](https://github.com/fastify/fastify/issues/1352)
146
- onFinished__default["default"](res.raw, () => {
147
- this.onResponse();
148
- });
149
- next();
150
- }
151
- }
152
- const fastifyRequestsLimiter = fp__default["default"](async (fastify, { requestsLimiter }) => {
153
- fastify.addHook('onRequest', (req, res, next) => {
154
- requestsLimiter.add({ req, res, next });
155
- });
156
- });
157
-
158
- const REQUESTS_LIMITER_TOKEN = dippy.createToken('requestsLimiterToken');
159
- const REQUESTS_LIMITER_ACTIVATE_TOKEN = dippy.createToken('requestsLimiterActivateToken');
160
- const REQUESTS_LIMITER_OPTIONS_TOKEN = dippy.createToken('requestsLimiterOptionsToken');
9
+ var requestLimiter = require('./requestLimiter.js');
10
+ var tokens = require('./tokens.js');
161
11
 
162
12
  exports.RequestLimiterModule = class RequestLimiterModule {
163
13
  };
@@ -171,22 +21,22 @@ exports.RequestLimiterModule = tslib.__decorate([
171
21
  {
172
22
  key: 'REQUEST_LIMITER_MELD',
173
23
  optional: true,
174
- value: String(DEFAULT_OPTIONS.maxEventLoopDelay),
24
+ value: String(requestLimiter.DEFAULT_OPTIONS.maxEventLoopDelay),
175
25
  },
176
26
  {
177
27
  key: 'REQUEST_LIMITER_QUEUE',
178
28
  optional: true,
179
- value: String(DEFAULT_OPTIONS.queue),
29
+ value: String(requestLimiter.DEFAULT_OPTIONS.queue),
180
30
  },
181
31
  {
182
32
  key: 'REQUEST_LIMITER_LIMIT',
183
33
  optional: true,
184
- value: String(DEFAULT_OPTIONS.limit),
34
+ value: String(requestLimiter.DEFAULT_OPTIONS.limit),
185
35
  },
186
36
  ],
187
37
  }),
188
38
  core.provide({
189
- provide: REQUESTS_LIMITER_OPTIONS_TOKEN,
39
+ provide: tokens.REQUESTS_LIMITER_OPTIONS_TOKEN,
190
40
  useFactory: ({ envManager }) => ({
191
41
  maxEventLoopDelay: Number(envManager.get('REQUEST_LIMITER_MELD')),
192
42
  queue: Number(envManager.get('REQUEST_LIMITER_QUEUE')),
@@ -197,7 +47,7 @@ exports.RequestLimiterModule = tslib.__decorate([
197
47
  },
198
48
  }),
199
49
  core.provide({
200
- provide: REQUESTS_LIMITER_TOKEN,
50
+ provide: tokens.REQUESTS_LIMITER_TOKEN,
201
51
  scope: core.Scope.SINGLETON,
202
52
  useFactory: ({ options, featureEnable, envManager }) => {
203
53
  var _a, _b, _c, _d;
@@ -208,18 +58,18 @@ exports.RequestLimiterModule = tslib.__decorate([
208
58
  const queue = envManager.get('REQUEST_LIMITER_QUEUE');
209
59
  const limit = envManager.get('REQUEST_LIMITER_LIMIT');
210
60
  const resultOptions = {
211
- limit: limit ? Number(limit) : (_a = options === null || options === void 0 ? void 0 : options.limit) !== null && _a !== void 0 ? _a : DEFAULT_OPTIONS.limit,
212
- queue: queue ? Number(queue) : (_b = options === null || options === void 0 ? void 0 : options.queue) !== null && _b !== void 0 ? _b : DEFAULT_OPTIONS.queue,
61
+ limit: limit ? Number(limit) : (_a = options === null || options === void 0 ? void 0 : options.limit) !== null && _a !== void 0 ? _a : requestLimiter.DEFAULT_OPTIONS.limit,
62
+ queue: queue ? Number(queue) : (_b = options === null || options === void 0 ? void 0 : options.queue) !== null && _b !== void 0 ? _b : requestLimiter.DEFAULT_OPTIONS.queue,
213
63
  maxEventLoopDelay: meld
214
64
  ? Number(meld)
215
- : (_c = options === null || options === void 0 ? void 0 : options.maxEventLoopDelay) !== null && _c !== void 0 ? _c : DEFAULT_OPTIONS.maxEventLoopDelay,
216
- error: (_d = options === null || options === void 0 ? void 0 : options.error) !== null && _d !== void 0 ? _d : DEFAULT_OPTIONS.error,
65
+ : (_c = options === null || options === void 0 ? void 0 : options.maxEventLoopDelay) !== null && _c !== void 0 ? _c : requestLimiter.DEFAULT_OPTIONS.maxEventLoopDelay,
66
+ error: (_d = options === null || options === void 0 ? void 0 : options.error) !== null && _d !== void 0 ? _d : requestLimiter.DEFAULT_OPTIONS.error,
217
67
  };
218
- return new RequestLimiter(resultOptions);
68
+ return new requestLimiter.RequestLimiter(resultOptions);
219
69
  },
220
70
  deps: {
221
- options: { token: REQUESTS_LIMITER_OPTIONS_TOKEN, optional: true },
222
- featureEnable: { token: REQUESTS_LIMITER_ACTIVATE_TOKEN, optional: true },
71
+ options: { token: tokens.REQUESTS_LIMITER_OPTIONS_TOKEN, optional: true },
72
+ featureEnable: { token: tokens.REQUESTS_LIMITER_ACTIVATE_TOKEN, optional: true },
223
73
  envManager: tokensCommon.ENV_MANAGER_TOKEN,
224
74
  },
225
75
  }),
@@ -231,21 +81,21 @@ exports.RequestLimiterModule = tslib.__decorate([
231
81
  if (featureEnable === false) {
232
82
  return;
233
83
  }
234
- await fastifyRequestsLimiter(app, { requestsLimiter });
84
+ await requestLimiter.fastifyRequestsLimiter(app, { requestsLimiter });
235
85
  };
236
86
  },
237
87
  deps: {
238
- requestsLimiter: REQUESTS_LIMITER_TOKEN,
239
- featureEnable: { token: REQUESTS_LIMITER_ACTIVATE_TOKEN, optional: true },
88
+ requestsLimiter: tokens.REQUESTS_LIMITER_TOKEN,
89
+ featureEnable: { token: tokens.REQUESTS_LIMITER_ACTIVATE_TOKEN, optional: true },
240
90
  },
241
91
  }),
242
92
  ],
243
93
  })
244
94
  ], exports.RequestLimiterModule);
245
95
 
246
- exports.DEFAULT_OPTIONS = DEFAULT_OPTIONS;
247
- exports.REQUESTS_LIMITER_ACTIVATE_TOKEN = REQUESTS_LIMITER_ACTIVATE_TOKEN;
248
- exports.REQUESTS_LIMITER_OPTIONS_TOKEN = REQUESTS_LIMITER_OPTIONS_TOKEN;
249
- exports.REQUESTS_LIMITER_TOKEN = REQUESTS_LIMITER_TOKEN;
250
- exports.RequestLimiter = RequestLimiter;
251
- exports.fastifyRequestsLimiter = fastifyRequestsLimiter;
96
+ exports.DEFAULT_OPTIONS = requestLimiter.DEFAULT_OPTIONS;
97
+ exports.RequestLimiter = requestLimiter.RequestLimiter;
98
+ exports.fastifyRequestsLimiter = requestLimiter.fastifyRequestsLimiter;
99
+ exports.REQUESTS_LIMITER_ACTIVATE_TOKEN = tokens.REQUESTS_LIMITER_ACTIVATE_TOKEN;
100
+ exports.REQUESTS_LIMITER_OPTIONS_TOKEN = tokens.REQUESTS_LIMITER_OPTIONS_TOKEN;
101
+ exports.REQUESTS_LIMITER_TOKEN = tokens.REQUESTS_LIMITER_TOKEN;
@@ -0,0 +1,7 @@
1
+ import { createToken } from '@tinkoff/dippy';
2
+
3
+ const REQUESTS_LIMITER_TOKEN = createToken('requestsLimiterToken');
4
+ const REQUESTS_LIMITER_ACTIVATE_TOKEN = createToken('requestsLimiterActivateToken');
5
+ const REQUESTS_LIMITER_OPTIONS_TOKEN = createToken('requestsLimiterOptionsToken');
6
+
7
+ export { REQUESTS_LIMITER_ACTIVATE_TOKEN, REQUESTS_LIMITER_OPTIONS_TOKEN, REQUESTS_LIMITER_TOKEN };
@@ -0,0 +1,7 @@
1
+ import { createToken } from '@tinkoff/dippy';
2
+
3
+ const REQUESTS_LIMITER_TOKEN = createToken('requestsLimiterToken');
4
+ const REQUESTS_LIMITER_ACTIVATE_TOKEN = createToken('requestsLimiterActivateToken');
5
+ const REQUESTS_LIMITER_OPTIONS_TOKEN = createToken('requestsLimiterOptionsToken');
6
+
7
+ export { REQUESTS_LIMITER_ACTIVATE_TOKEN, REQUESTS_LIMITER_OPTIONS_TOKEN, REQUESTS_LIMITER_TOKEN };
package/lib/tokens.js ADDED
@@ -0,0 +1,13 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var dippy = require('@tinkoff/dippy');
6
+
7
+ const REQUESTS_LIMITER_TOKEN = dippy.createToken('requestsLimiterToken');
8
+ const REQUESTS_LIMITER_ACTIVATE_TOKEN = dippy.createToken('requestsLimiterActivateToken');
9
+ const REQUESTS_LIMITER_OPTIONS_TOKEN = dippy.createToken('requestsLimiterOptionsToken');
10
+
11
+ exports.REQUESTS_LIMITER_ACTIVATE_TOKEN = REQUESTS_LIMITER_ACTIVATE_TOKEN;
12
+ exports.REQUESTS_LIMITER_OPTIONS_TOKEN = REQUESTS_LIMITER_OPTIONS_TOKEN;
13
+ exports.REQUESTS_LIMITER_TOKEN = REQUESTS_LIMITER_TOKEN;
@@ -0,0 +1,61 @@
1
+ class DoubleLinkedList {
2
+ constructor() {
3
+ this.length = 0;
4
+ this.start = null;
5
+ this.end = null;
6
+ }
7
+ push(value) {
8
+ const newNode = {
9
+ value,
10
+ next: null,
11
+ prev: null,
12
+ };
13
+ this.length++;
14
+ if (this.start === null) {
15
+ this.start = newNode;
16
+ this.end = newNode;
17
+ return;
18
+ }
19
+ const currentEnd = this.end;
20
+ this.end = newNode;
21
+ this.end.prev = currentEnd;
22
+ currentEnd.next = this.end;
23
+ }
24
+ pop() {
25
+ if (this.end === null) {
26
+ return null;
27
+ }
28
+ this.length--;
29
+ // if equal we have only 1 node, so we just remove start
30
+ if (this.end === this.start) {
31
+ this.start = null;
32
+ }
33
+ const { value } = this.end;
34
+ this.end = this.end.prev;
35
+ if (this.end) {
36
+ this.end.next = null;
37
+ }
38
+ return value;
39
+ }
40
+ shift() {
41
+ if (this.start === null) {
42
+ return null;
43
+ }
44
+ this.length--;
45
+ // if equal we have only 1 node, so we just remove end
46
+ if (this.end === this.start) {
47
+ this.end = null;
48
+ }
49
+ const { value } = this.start;
50
+ this.start = this.start.next;
51
+ if (this.start) {
52
+ this.start.prev = null;
53
+ }
54
+ return value;
55
+ }
56
+ size() {
57
+ return this.length;
58
+ }
59
+ }
60
+
61
+ export { DoubleLinkedList };
@@ -0,0 +1,65 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ class DoubleLinkedList {
6
+ constructor() {
7
+ this.length = 0;
8
+ this.start = null;
9
+ this.end = null;
10
+ }
11
+ push(value) {
12
+ const newNode = {
13
+ value,
14
+ next: null,
15
+ prev: null,
16
+ };
17
+ this.length++;
18
+ if (this.start === null) {
19
+ this.start = newNode;
20
+ this.end = newNode;
21
+ return;
22
+ }
23
+ const currentEnd = this.end;
24
+ this.end = newNode;
25
+ this.end.prev = currentEnd;
26
+ currentEnd.next = this.end;
27
+ }
28
+ pop() {
29
+ if (this.end === null) {
30
+ return null;
31
+ }
32
+ this.length--;
33
+ // if equal we have only 1 node, so we just remove start
34
+ if (this.end === this.start) {
35
+ this.start = null;
36
+ }
37
+ const { value } = this.end;
38
+ this.end = this.end.prev;
39
+ if (this.end) {
40
+ this.end.next = null;
41
+ }
42
+ return value;
43
+ }
44
+ shift() {
45
+ if (this.start === null) {
46
+ return null;
47
+ }
48
+ this.length--;
49
+ // if equal we have only 1 node, so we just remove end
50
+ if (this.end === this.start) {
51
+ this.end = null;
52
+ }
53
+ const { value } = this.start;
54
+ this.start = this.start.next;
55
+ if (this.start) {
56
+ this.start.prev = null;
57
+ }
58
+ return value;
59
+ }
60
+ size() {
61
+ return this.length;
62
+ }
63
+ }
64
+
65
+ exports.DoubleLinkedList = DoubleLinkedList;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tramvai/module-request-limiter",
3
- "version": "2.70.1",
3
+ "version": "2.72.0",
4
4
  "description": "Enable different rendering modes for pages",
5
5
  "main": "lib/server.js",
6
6
  "module": "lib/server.es.js",
@@ -16,24 +16,23 @@
16
16
  },
17
17
  "license": "Apache-2.0",
18
18
  "scripts": {
19
- "build": "tramvai-build --for-publish",
20
- "watch": "tsc -w",
21
- "build-for-publish": "true"
19
+ "build": "tramvai-build --forPublish --preserveModules",
20
+ "watch": "tsc -w"
22
21
  },
23
22
  "publishConfig": {
24
23
  "registry": "https://registry.npmjs.org/"
25
24
  },
26
25
  "dependencies": {
27
- "@tinkoff/errors": "0.3.5",
26
+ "@tinkoff/errors": "0.3.6",
28
27
  "fastify-plugin": "^4.2.1",
29
28
  "on-finished": "^2.3.0"
30
29
  },
31
30
  "devDependencies": {},
32
31
  "peerDependencies": {
33
- "@tinkoff/dippy": "0.8.12",
34
- "@tramvai/core": "2.70.1",
35
- "@tramvai/tokens-common": "2.70.1",
36
- "@tramvai/tokens-server-private": "2.70.1",
32
+ "@tinkoff/dippy": "0.8.13",
33
+ "@tramvai/core": "2.72.0",
34
+ "@tramvai/tokens-common": "2.72.0",
35
+ "@tramvai/tokens-server-private": "2.72.0",
37
36
  "fastify": "^4.6.0",
38
37
  "tslib": "^2.4.0"
39
38
  }