Skip to content

Commit d33fb24

Browse files
committed
add timeout and abortsignal support for queries
1 parent 69da38d commit d33fb24

File tree

6 files changed

+91
-28
lines changed

6 files changed

+91
-28
lines changed

src/tarkov-data-manager/jobs/update-item-cache.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,14 @@ class UpdateItemCacheJob extends DataJob {
6262

6363
const priceFields = [
6464
'lastLowPrice',
65+
'lastLowAvgPrice',
6566
'avg24hPrice',
6667
'low24hPrice',
6768
'high24hPrice',
6869
'changeLast48h',
6970
'changeLast48hPercent',
7071
'lastOfferCount',
72+
'updated',
7173
];
7274
this.logger.log('Processing items...');
7375
for (const [key, value] of this.itemMap.entries()) {

src/tarkov-data-manager/modules/data-job.mjs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -371,14 +371,26 @@ class DataJob {
371371
return this.translationHelper.hasTranslation(key, langCode);
372372
}
373373

374-
query = (sql, params) => {
375-
const queryPromise = query(sql, params);
374+
query = (sql, values, options) => {
375+
if (typeof values === 'object' && !Array.isArray(values)) {
376+
options = values;
377+
values = undefined;
378+
}
379+
const queryPromise = query(sql, values, {signal: this.abortController.signal, ...options});
376380
this.queries.push(queryPromise);
377381
return queryPromise;
378382
}
379383

380-
batchQuery = (sql, params, batchCallback) => {
381-
const queryPromise = batchQuery(sql, params, batchCallback);
384+
batchQuery = (sql, values, batchCallback, options) => {
385+
if (values && !Array.isArray(values)) {
386+
batchCallback = values;
387+
values = [];
388+
}
389+
if (!options && typeof batchCallback !== 'function') {
390+
options = batchCallback;
391+
batchCallback = undefined;
392+
}
393+
const queryPromise = batchQuery(sql, values, batchCallback, {signal: this.abortController.signal, ...options});
382394
this.queries.push(queryPromise);
383395
return queryPromise;
384396
}

src/tarkov-data-manager/modules/db-connection.mjs

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -59,30 +59,58 @@ const waitForConnections = () => {
5959
const dbConnection = {
6060
connection: pool,
6161
pool,
62-
query: (sql, params) => {
62+
query: async (sql, values, options = {}) => {
63+
if (typeof values === 'object' && !Array.isArray(values)) {
64+
options = values;
65+
values = undefined;
66+
}
67+
let abortListener;
6368
return new Promise((resolve, reject) => {
69+
abortListener = () => {
70+
reject(new Error('Query aborted'));
71+
};
72+
options?.signal?.addEventListener('abort', abortListener, { once: true });
6473
try {
65-
pool.query(sql, params, (error, results) => {
74+
pool.query({sql, values, timeout: options?.timeout}, (error, results) => {
6675
if (error) {
67-
reject(error);
68-
return;
76+
return reject(error);
6977
}
70-
7178
resolve(results);
7279
});
7380
} catch (error) {
7481
reject(error);
7582
}
83+
}).finally(() => {
84+
options.signal?.removeEventListener('abort', abortListener);
7685
});
7786
},
78-
batchQuery: async (sql, params = [], batchCallback) => {
87+
batchQuery: async (sql, values = [], batchCallback, options = {}) => {
7988
const batchSize = dbConnection.maxQueryRows;
8089
let offset = 0;
8190
const results = [];
91+
const queryStart = new Date();
92+
if (values && !Array.isArray(values)) {
93+
batchCallback = values;
94+
values = [];
95+
}
96+
if (!options && typeof batchCallback !== 'function') {
97+
options = batchCallback;
98+
batchCallback = undefined;
99+
}
100+
let timeout = options.timeout;
82101
while (true) {
83-
const batchParams = [...params, offset, batchSize]
84-
const batchResults = await dbConnection.query(`${sql} LIMIT ?, ?
85-
`, batchParams);
102+
const batchValues = [...values, offset, batchSize];
103+
let batchTimeout;
104+
if (timeout) {
105+
batchTimeout = timeout - (new Date() - queryStart);
106+
if (batchTimeout <= 0) {
107+
return Promise.reject(new Error('Query inactivity timeout'));
108+
}
109+
}
110+
if (options.signal?.aborted) {
111+
return Promise.reject(new Error('Query aborted'));
112+
}
113+
const batchResults = await dbConnection.query(`${sql} LIMIT ?, ?`, batchValues, {timeout: batchTimeout, signal: options.signal});
86114
batchResults.forEach(r => results.push(r));
87115
if (batchCallback) {
88116
batchCallback(batchResults, offset);

src/tarkov-data-manager/modules/remote-data.mjs

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -130,11 +130,11 @@ const methods = {
130130
logger.timeEnd('item-24h-price-query');
131131
});
132132

133-
logger.time('item-last-low-price-query');
134-
const lastLowPricePromise = query(`
133+
logger.time('item-last-price-query');
134+
const lastPricePromise = query(`
135135
SELECT
136136
a.item_id,
137-
MIN(a.price) AS price,
137+
a.price,
138138
timestamp,
139139
a.game_mode
140140
FROM
@@ -151,10 +151,8 @@ const methods = {
151151
) b
152152
ON
153153
a.item_id = b.item_id AND a.timestamp = b.max_timestamp AND a.game_mode = b.game_mode
154-
GROUP BY
155-
a.item_id, a.timestamp, a.game_mode;
156154
`).finally(() => {
157-
logger.timeEnd('item-last-low-price-query');
155+
logger.timeEnd('item-last-price-query');
158156
});
159157

160158
logger.time('price-yesterday-query');
@@ -178,12 +176,12 @@ const methods = {
178176
const [
179177
items,
180178
price24hResults,
181-
lastLowPriceResults,
179+
lastPriceResults,
182180
avgPriceYesterday,
183181
] = await Promise.all([
184182
itemsPromise,
185183
price24hPromise,
186-
lastLowPricePromise,
184+
lastPricePromise,
187185
avgPriceYesterdayPromise,
188186
]);
189187

@@ -192,6 +190,20 @@ const methods = {
192190
1: {},
193191
};
194192

193+
const itemLastPrices = lastPriceResults.reduce((all, current) => {
194+
if (!all[current.game_mode]) {
195+
all[current.game_mode] = {};
196+
}
197+
if (!all[current.game_mode][current.item_id]) {
198+
all[current.game_mode][current.item_id] = {
199+
timestamp: current.timestamp,
200+
prices: [],
201+
};
202+
}
203+
all[current.game_mode][current.item_id].prices.push(current.price);
204+
return all;
205+
}, {});
206+
195207
price24hResults.forEach((resultRow) => {
196208
if (!item24hPrices[resultRow.game_mode][resultRow.item_id]) {
197209
item24hPrices[resultRow.game_mode][resultRow.item_id] = [];
@@ -208,12 +220,16 @@ const methods = {
208220
for (const gameMode of gameModes) {
209221
const fieldPrefix = gameMode.name === 'regular' ? '' : `${gameMode.name}_`;
210222

211-
const lastLowData = lastLowPriceResults.find(row => row.item_id === itemId && row.game_mode === gameMode.value);
212-
if (lastLowData) {
213-
item[`${fieldPrefix}lastLowPrice`] = lastLowData.price;
214-
if (gameMode.name === 'regular') {
215-
item.updated = lastLowData.timestamp;
216-
}
223+
//const lastLowData = lastLowPriceResults.find(row => row.item_id === itemId && row.game_mode === gameMode.value);
224+
const lastData = itemLastPrices[gameMode.value]?.[itemId];
225+
if (lastData) {
226+
item[`${fieldPrefix}lastLowPrice`] = lastData.prices[0];
227+
const lastLowAvgPrices = lastData.prices.slice(0, 3);
228+
item[`${fieldPrefix}lastLowAvgPrice`] = Math.round(lastLowAvgPrices.reduce((total, price) => {
229+
return total + price;
230+
}, 0) / lastLowAvgPrices.length);
231+
const updatedField = `${fieldPrefix}updated`;
232+
item[updatedField] = lastData.timestamp;
217233
}
218234

219235
item24hPrices[gameMode.value][itemId]?.sort();

src/tarkov-data-manager/modules/scanner-api.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ const scannerApi = {
279279
const oldScanners = users[user.username]?.scanners || [];
280280
user.scanners = oldScanners;
281281
users[user.username] = user;
282-
scannerQueries.push(query('SELECT * from scanner WHERE scanner_user_id = ?', user.id).then(scanners => {
282+
scannerQueries.push(query('SELECT * from scanner WHERE scanner_user_id = ?', [user.id]).then(scanners => {
283283
users[user.username].scanners = scanners;
284284
}));
285285
}

src/tarkov-data-manager/translations/en.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@
113113
"quest_zone_keeper6_kiba_kill": "Around Kiba Arms store",
114114
"quest_zone_last_flare": "Armored Convoy",
115115
"quest_zone_prod_flare": "Pinewood Hotel Courtyard",
116+
"sectantOni": "Oni",
117+
"sectantPredvestnik": "Harbinger",
118+
"sectantPrizrak": "Ghost",
116119
"SOPMOD II Flash": "SOPMOD II Flash",
117120
"ShturmanStash": "Shturman's Stash",
118121
"SPR": "SPR",
@@ -201,5 +204,7 @@
201204
"ZoneStartVillage": "Village",
202205
"ZoneSubCommand": "Command Bunker",
203206
"ZoneSubStorage": "Storage Bunker",
207+
"ZoneSW00": "Zmejskij Alley Block",
208+
"ZoneSW01": "Zmejskij Alley Block",
204209
"ZoneWoodCutter": "Lumber Mill"
205210
}

0 commit comments

Comments
 (0)