@k03mad/request 2.1.0 → 3.0.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/app/lib/curl.js +0 -3
- package/app/lib/queue.js +30 -44
- package/app/lib/request.js +41 -35
- package/package.json +2 -2
package/app/lib/curl.js
CHANGED
|
@@ -4,7 +4,6 @@ import prettyBytes from 'pretty-bytes';
|
|
|
4
4
|
const {bgWhite, black, blue, dim, green, magenta, red, white, yellow} = chalk;
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Сформировать curl-строку из опций got
|
|
8
7
|
* @param {string} url
|
|
9
8
|
* @param {object} [opts]
|
|
10
9
|
* @param {string} [opts.method]
|
|
@@ -25,12 +24,10 @@ export default (url, {
|
|
|
25
24
|
}, res) => {
|
|
26
25
|
const msg = [];
|
|
27
26
|
|
|
28
|
-
// если третий параметр — объект ошибки, то все необходимое на уровень ниже, в ключе response
|
|
29
27
|
if (res?.response) {
|
|
30
28
|
res = res.response;
|
|
31
29
|
}
|
|
32
30
|
|
|
33
|
-
// 200 [800 ms] [3.15 kB]
|
|
34
31
|
if (res?.statusCode) {
|
|
35
32
|
msg.push(bgWhite(black(res.statusCode)));
|
|
36
33
|
}
|
package/app/lib/queue.js
CHANGED
|
@@ -3,27 +3,24 @@ import PQueue from 'p-queue';
|
|
|
3
3
|
|
|
4
4
|
const debug = _debug('mad:queue');
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
const intervals = {
|
|
7
|
+
concurrency: num => ({concurrency: num}),
|
|
8
|
+
rpm: num => ({intervalCap: num, interval: 60_000}),
|
|
9
|
+
rps: num => ({intervalCap: num, interval: 1000}),
|
|
10
|
+
};
|
|
8
11
|
|
|
9
|
-
//
|
|
10
|
-
// второй уровень — метод (* — любой, кроме уже перечисленных)
|
|
11
|
-
// третий уровень — настройки очереди из p-queue
|
|
12
|
+
// host: p-queue options
|
|
12
13
|
const requestQueue = {
|
|
13
|
-
'*':
|
|
14
|
-
'*': concurrency(3),
|
|
15
|
-
},
|
|
14
|
+
'*': intervals.concurrency(3),
|
|
16
15
|
};
|
|
17
16
|
|
|
18
17
|
/**
|
|
19
|
-
* Поставить логирование и вернуть очередь
|
|
20
18
|
* @param {string} host
|
|
21
|
-
* @param {string} method
|
|
22
19
|
* @param {object} opts
|
|
23
20
|
* @returns {object}
|
|
24
21
|
*/
|
|
25
|
-
const getLoggedQueue = (host,
|
|
26
|
-
const queue = requestQueue[host]
|
|
22
|
+
const getLoggedQueue = (host, opts) => {
|
|
23
|
+
const queue = requestQueue[host];
|
|
27
24
|
|
|
28
25
|
queue.on('active', () => {
|
|
29
26
|
const {pending, size} = queue;
|
|
@@ -33,9 +30,7 @@ const getLoggedQueue = (host, method, opts) => {
|
|
|
33
30
|
? `${concurrent} concurrent`
|
|
34
31
|
: `${intervalCap} rp ${interval} ms`;
|
|
35
32
|
|
|
36
|
-
const logMessage = `[${
|
|
37
|
-
method === '*' ? '' : `${method}: `
|
|
38
|
-
}${host}] ${parallel} | queue: ${size} | running: ${pending}`;
|
|
33
|
+
const logMessage = `[${host}] ${parallel} | queue: ${size} | running: ${pending}`;
|
|
39
34
|
|
|
40
35
|
debug(logMessage);
|
|
41
36
|
});
|
|
@@ -44,43 +39,34 @@ const getLoggedQueue = (host, method, opts) => {
|
|
|
44
39
|
};
|
|
45
40
|
|
|
46
41
|
/**
|
|
47
|
-
* Получить очередь по хосту и методу
|
|
48
42
|
* @param {string} host
|
|
49
|
-
* @param {
|
|
43
|
+
* @param {object} params
|
|
44
|
+
* @param {number} params.concurrency
|
|
45
|
+
* @param {number} params.rpm
|
|
46
|
+
* @param {number} params.rps
|
|
50
47
|
* @returns {object}
|
|
51
48
|
*/
|
|
52
|
-
export default (host,
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (requestQueue[host]?.[elem]?._events) {
|
|
57
|
-
return requestQueue[host][elem];
|
|
58
|
-
}
|
|
49
|
+
export default (host, params) => {
|
|
50
|
+
if (requestQueue[host]?._events) {
|
|
51
|
+
return requestQueue[host];
|
|
52
|
+
}
|
|
59
53
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
54
|
+
if (Object.keys(params).length > 0) {
|
|
55
|
+
for (const [key, value] of Object.entries(params)) {
|
|
56
|
+
if (intervals[key]) {
|
|
57
|
+
requestQueue[host] = intervals[key](value);
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
65
60
|
}
|
|
66
61
|
}
|
|
67
62
|
|
|
68
|
-
// инициализация очереди для хоста без текущего метода в предустановках
|
|
69
63
|
if (requestQueue[host]) {
|
|
70
|
-
const opts = requestQueue[
|
|
71
|
-
requestQueue[host]
|
|
72
|
-
return getLoggedQueue(host,
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// инициализация очереди для хоста с методом из предустановок для всех очередей
|
|
76
|
-
if (requestQueue['*'][method]) {
|
|
77
|
-
const opts = requestQueue['*'][method];
|
|
78
|
-
requestQueue[host] = {[method]: new PQueue(opts)};
|
|
79
|
-
return getLoggedQueue(host, method, opts);
|
|
64
|
+
const opts = requestQueue[host];
|
|
65
|
+
requestQueue[host] = new PQueue(opts);
|
|
66
|
+
return getLoggedQueue(host, opts);
|
|
80
67
|
}
|
|
81
68
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
return getLoggedQueue(host, '*', opts);
|
|
69
|
+
const opts = requestQueue['*'];
|
|
70
|
+
requestQueue[host] = new PQueue(opts);
|
|
71
|
+
return getLoggedQueue(host, opts);
|
|
86
72
|
};
|
package/app/lib/request.js
CHANGED
|
@@ -8,21 +8,37 @@ import getQueue from './queue.js';
|
|
|
8
8
|
const {blue, cyan, dim, green, red, yellow} = chalk;
|
|
9
9
|
const debug = _debug('mad:request');
|
|
10
10
|
|
|
11
|
-
const
|
|
11
|
+
const gotCache = new Map();
|
|
12
|
+
|
|
13
|
+
const cacheGotResponseKeys = [
|
|
14
|
+
'body',
|
|
15
|
+
'headers',
|
|
16
|
+
'method',
|
|
17
|
+
'statusCode',
|
|
18
|
+
'statusMessage',
|
|
19
|
+
'timings',
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
const gotDefaultOpts = got.extend({
|
|
12
23
|
dnsCache: true,
|
|
13
24
|
timeout: {request: 15_000},
|
|
14
|
-
headers: {'user-agent': 'curl/
|
|
25
|
+
headers: {'user-agent': 'curl/7.81.0'},
|
|
15
26
|
});
|
|
16
27
|
|
|
28
|
+
const cacheDebug = msgArr => {
|
|
29
|
+
if (process.env.DEBUG) {
|
|
30
|
+
debug(msgArr.join(' :: '));
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
17
34
|
/**
|
|
18
|
-
* Отправить запрос
|
|
19
35
|
* @param {string} url
|
|
20
36
|
* @param {object} opts
|
|
21
37
|
* @returns {object}
|
|
22
38
|
*/
|
|
23
39
|
const sendRequest = async (url, opts) => {
|
|
24
40
|
try {
|
|
25
|
-
const response = await
|
|
41
|
+
const response = await gotDefaultOpts(url, opts);
|
|
26
42
|
|
|
27
43
|
if (!opts.responseType) {
|
|
28
44
|
try {
|
|
@@ -65,22 +81,17 @@ const sendRequest = async (url, opts) => {
|
|
|
65
81
|
}
|
|
66
82
|
};
|
|
67
83
|
|
|
68
|
-
export const cache = new Map();
|
|
69
|
-
|
|
70
84
|
/**
|
|
71
|
-
* Отправить запрос c выбором использования очереди
|
|
72
85
|
* @param {string} url
|
|
73
86
|
* @param {object} [opts]
|
|
74
87
|
* @param {object} [params]
|
|
75
|
-
* @param {
|
|
88
|
+
* @param {number} [params.concurrency]
|
|
89
|
+
* @param {number} [params.rpm]
|
|
90
|
+
* @param {number} [params.rps]
|
|
76
91
|
* @returns {Promise<object>}
|
|
77
92
|
*/
|
|
78
|
-
export const request = (url, opts = {},
|
|
79
|
-
|
|
80
|
-
return sendRequest(url, opts);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const queue = getQueue(new URL(url).host, opts.method);
|
|
93
|
+
export const request = (url, opts = {}, params = {}) => {
|
|
94
|
+
const queue = getQueue(new URL(url).host, params);
|
|
84
95
|
return queue.add(() => sendRequest(url, opts));
|
|
85
96
|
};
|
|
86
97
|
|
|
@@ -90,45 +101,40 @@ export const request = (url, opts = {}, {skipQueue} = {}) => {
|
|
|
90
101
|
* @param {object} [params]
|
|
91
102
|
* @param {number} [params.expire] seconds
|
|
92
103
|
* @param {object} [params.cacheBy]
|
|
104
|
+
* @param {number} [params.concurrency]
|
|
105
|
+
* @param {number} [params.rpm]
|
|
106
|
+
* @param {number} [params.rps]
|
|
93
107
|
* @returns {Promise<object>}
|
|
94
108
|
*/
|
|
95
|
-
export const requestCache = (url, opts = {}, {cacheBy, expire = 43_200} = {}) => {
|
|
96
|
-
const queue = getQueue(new URL(url).host,
|
|
109
|
+
export const requestCache = (url, opts = {}, {cacheBy, expire = 43_200, ...params} = {}) => {
|
|
110
|
+
const queue = getQueue(new URL(url).host, params);
|
|
97
111
|
|
|
98
112
|
return queue.add(async () => {
|
|
99
|
-
const cacheGotResponseKeys = [
|
|
100
|
-
'body',
|
|
101
|
-
'headers',
|
|
102
|
-
'method',
|
|
103
|
-
'statusCode',
|
|
104
|
-
'statusMessage',
|
|
105
|
-
'timings',
|
|
106
|
-
];
|
|
107
|
-
|
|
108
113
|
const cacheKey = `${url}::${JSON.stringify(cacheBy || opts)}`;
|
|
109
|
-
const
|
|
114
|
+
const urlLog = `${blue(url)}\n${dim(cacheKey)}`;
|
|
110
115
|
|
|
111
116
|
try {
|
|
112
|
-
if (
|
|
113
|
-
const {cachedResponse, date} =
|
|
117
|
+
if (gotCache.has(cacheKey)) {
|
|
118
|
+
const {cachedResponse, date} = gotCache.get(cacheKey);
|
|
114
119
|
|
|
115
120
|
const measurement = 'seconds';
|
|
116
121
|
const currentDiff = Math.round((Date.now() - date) / 1000);
|
|
122
|
+
const diffLog = `${currentDiff}/${expire} ${measurement} left`;
|
|
117
123
|
|
|
118
124
|
if (currentDiff < expire) {
|
|
119
|
-
|
|
125
|
+
cacheDebug([green('FROM CACHE'), diffLog, urlLog]);
|
|
120
126
|
return {cacheKey, ...cachedResponse};
|
|
121
127
|
}
|
|
122
128
|
|
|
123
|
-
|
|
129
|
+
cacheDebug([yellow('CACHE EXPIRED'), diffLog, urlLog]);
|
|
124
130
|
} else {
|
|
125
|
-
|
|
131
|
+
cacheDebug([blue('CACHE NOT FOUND'), urlLog]);
|
|
126
132
|
}
|
|
127
133
|
} catch (err) {
|
|
128
|
-
|
|
134
|
+
cacheDebug([red('CACHE ERROR'), dim(err), urlLog]);
|
|
129
135
|
}
|
|
130
136
|
|
|
131
|
-
const res = await
|
|
137
|
+
const res = await sendRequest(url, opts);
|
|
132
138
|
|
|
133
139
|
const cachedResponse = {};
|
|
134
140
|
|
|
@@ -136,8 +142,8 @@ export const requestCache = (url, opts = {}, {cacheBy, expire = 43_200} = {}) =>
|
|
|
136
142
|
cachedResponse[key] = res[key];
|
|
137
143
|
});
|
|
138
144
|
|
|
139
|
-
|
|
140
|
-
|
|
145
|
+
gotCache.set(cacheKey, {date: Date.now(), cachedResponse});
|
|
146
|
+
cacheDebug([cyan('CACHE SAVED'), urlLog]);
|
|
141
147
|
|
|
142
148
|
return res;
|
|
143
149
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@k03mad/request",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Request library",
|
|
5
5
|
"maintainers": [
|
|
6
6
|
"Kirill Molchanov <k03.mad@gmail.com"
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"pretty-bytes": "6.1.1"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@k03mad/eslint-config": "12.0.
|
|
23
|
+
"@k03mad/eslint-config": "12.0.6",
|
|
24
24
|
"@microsoft/eslint-formatter-sarif": "3.0.0",
|
|
25
25
|
"eslint": "8.46.0",
|
|
26
26
|
"eslint-plugin-import": "2.28.0",
|