@cubejs-backend/query-orchestrator 0.23.3 → 0.24.2
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/CHANGELOG.md +38 -0
- package/README.md +2 -2
- package/dist/src/driver/BaseDriver.d.ts +36 -0
- package/dist/src/driver/BaseDriver.d.ts.map +1 -0
- package/dist/src/driver/BaseDriver.js +175 -0
- package/dist/src/driver/BaseDriver.js.map +1 -0
- package/dist/src/driver/index.d.ts +3 -0
- package/dist/src/driver/index.d.ts.map +1 -0
- package/dist/src/driver/index.js +15 -0
- package/dist/src/driver/index.js.map +1 -0
- package/dist/src/driver/utils.d.ts +2 -0
- package/dist/src/driver/utils.d.ts.map +1 -0
- package/dist/src/driver/utils.js +17 -0
- package/dist/src/driver/utils.js.map +1 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +15 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/orchestrator/BaseQueueDriver.d.ts +4 -0
- package/dist/src/orchestrator/BaseQueueDriver.d.ts.map +1 -0
- package/dist/src/orchestrator/BaseQueueDriver.js +16 -0
- package/dist/src/orchestrator/BaseQueueDriver.js.map +1 -0
- package/dist/src/orchestrator/ContinueWaitError.d.ts +3 -0
- package/dist/src/orchestrator/ContinueWaitError.d.ts.map +1 -0
- package/dist/src/orchestrator/ContinueWaitError.js +10 -0
- package/dist/src/orchestrator/ContinueWaitError.js.map +1 -0
- package/dist/src/orchestrator/LocalCacheDriver.d.ts +8 -0
- package/dist/src/orchestrator/LocalCacheDriver.d.ts.map +1 -0
- package/dist/src/orchestrator/LocalCacheDriver.js +30 -0
- package/dist/src/orchestrator/LocalCacheDriver.js.map +1 -0
- package/dist/src/orchestrator/LocalQueueDriver.d.ts +57 -0
- package/dist/src/orchestrator/LocalQueueDriver.d.ts.map +1 -0
- package/dist/src/orchestrator/LocalQueueDriver.js +230 -0
- package/dist/src/orchestrator/LocalQueueDriver.js.map +1 -0
- package/dist/src/orchestrator/PreAggregations.d.ts +26 -0
- package/dist/src/orchestrator/PreAggregations.d.ts.map +1 -0
- package/dist/src/orchestrator/PreAggregations.js +565 -0
- package/dist/src/orchestrator/PreAggregations.js.map +1 -0
- package/dist/src/orchestrator/QueryCache.d.ts +51 -0
- package/dist/src/orchestrator/QueryCache.d.ts.map +1 -0
- package/dist/src/orchestrator/QueryCache.js +293 -0
- package/dist/src/orchestrator/QueryCache.js.map +1 -0
- package/dist/src/orchestrator/QueryOrchestrator.d.ts +27 -0
- package/dist/src/orchestrator/QueryOrchestrator.d.ts.map +1 -0
- package/dist/src/orchestrator/QueryOrchestrator.js +79 -0
- package/dist/src/orchestrator/QueryOrchestrator.js.map +1 -0
- package/dist/src/orchestrator/QueryQueue.d.ts +36 -0
- package/dist/src/orchestrator/QueryQueue.d.ts.map +1 -0
- package/dist/src/orchestrator/QueryQueue.js +351 -0
- package/dist/src/orchestrator/QueryQueue.js.map +1 -0
- package/dist/src/orchestrator/RedisCacheDriver.d.ts +12 -0
- package/dist/src/orchestrator/RedisCacheDriver.d.ts.map +1 -0
- package/dist/src/orchestrator/RedisCacheDriver.js +50 -0
- package/dist/src/orchestrator/RedisCacheDriver.js.map +1 -0
- package/dist/src/orchestrator/RedisFactory.d.ts +3 -0
- package/dist/src/orchestrator/RedisFactory.d.ts.map +1 -0
- package/dist/src/orchestrator/RedisFactory.js +45 -0
- package/dist/src/orchestrator/RedisFactory.js.map +1 -0
- package/dist/src/orchestrator/RedisPool.d.ts +10 -0
- package/dist/src/orchestrator/RedisPool.d.ts.map +1 -0
- package/dist/src/orchestrator/RedisPool.js +57 -0
- package/dist/src/orchestrator/RedisPool.js.map +1 -0
- package/dist/src/orchestrator/RedisQueueDriver.d.ts +47 -0
- package/dist/src/orchestrator/RedisQueueDriver.d.ts.map +1 -0
- package/dist/src/orchestrator/RedisQueueDriver.js +253 -0
- package/dist/src/orchestrator/RedisQueueDriver.js.map +1 -0
- package/dist/src/orchestrator/TimeoutError.d.ts +4 -0
- package/dist/src/orchestrator/TimeoutError.d.ts.map +1 -0
- package/dist/src/orchestrator/TimeoutError.js +7 -0
- package/dist/src/orchestrator/TimeoutError.js.map +1 -0
- package/dist/src/orchestrator/index.d.ts +14 -0
- package/dist/src/orchestrator/index.d.ts.map +1 -0
- package/dist/src/orchestrator/index.js +26 -0
- package/dist/src/orchestrator/index.js.map +1 -0
- package/driver/BaseDriver.js +5 -221
- package/driver/README.md +3 -0
- package/driver/utils.js +8 -12
- package/orchestrator/BaseQueueDriver.js +5 -8
- package/orchestrator/ContinueWaitError.js +6 -5
- package/orchestrator/LocalCacheDriver.js +5 -29
- package/orchestrator/LocalQueueDriver.js +5 -256
- package/orchestrator/PreAggregations.js +4 -764
- package/orchestrator/QueryCache.js +5 -381
- package/orchestrator/QueryOrchestrator.js +5 -100
- package/orchestrator/QueryQueue.js +5 -378
- package/orchestrator/README.md +3 -0
- package/orchestrator/RedisCacheDriver.js +5 -45
- package/orchestrator/RedisFactory.js +6 -46
- package/orchestrator/RedisPool.js +5 -49
- package/orchestrator/RedisQueueDriver.js +5 -283
- package/orchestrator/TimeoutError.js +6 -1
- package/package.json +29 -10
- package/test/integration/PreAggregations.test.js +0 -337
- package/test/integration/QueryQueueRedis.test.js +0 -6
- package/test/unit/QueryOrchestrator.test.js +0 -301
- package/test/unit/QueryQueue.test.js +0 -249
|
@@ -1,381 +1,8 @@
|
|
|
1
|
-
const
|
|
2
|
-
const TimeoutError = require('./TimeoutError');
|
|
3
|
-
const ContinueWaitError = require('./ContinueWaitError');
|
|
4
|
-
const RedisQueueDriver = require('./RedisQueueDriver');
|
|
5
|
-
const LocalQueueDriver = require('./LocalQueueDriver');
|
|
1
|
+
const { QueryQueue } = require('../dist/src/orchestrator/QueryQueue');
|
|
6
2
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
this.continueWaitTimeout = options.continueWaitTimeout || 5;
|
|
12
|
-
this.executionTimeout = options.executionTimeout || 600;
|
|
13
|
-
this.orphanedTimeout = options.orphanedTimeout || 120;
|
|
14
|
-
this.heartBeatInterval = options.heartBeatInterval || 30;
|
|
15
|
-
this.sendProcessMessageFn = options.sendProcessMessageFn || ((queryKey) => { this.processQuery(queryKey); });
|
|
16
|
-
this.sendCancelMessageFn = options.sendCancelMessageFn || ((query) => { this.processCancel(query); });
|
|
17
|
-
this.queryHandlers = options.queryHandlers;
|
|
18
|
-
this.cancelHandlers = options.cancelHandlers;
|
|
19
|
-
this.logger = options.logger || ((message, event) => console.log(`${message} ${JSON.stringify(event)}`));
|
|
20
|
-
const queueDriverOptions = {
|
|
21
|
-
redisQueuePrefix: this.redisQueuePrefix,
|
|
22
|
-
concurrency: this.concurrency,
|
|
23
|
-
continueWaitTimeout: this.continueWaitTimeout,
|
|
24
|
-
orphanedTimeout: this.orphanedTimeout,
|
|
25
|
-
heartBeatTimeout: this.heartBeatInterval * 4,
|
|
26
|
-
redisPool: options.redisPool
|
|
27
|
-
};
|
|
28
|
-
this.queueDriver = options.cacheAndQueueDriver === 'redis' ?
|
|
29
|
-
new RedisQueueDriver(queueDriverOptions) :
|
|
30
|
-
new LocalQueueDriver(queueDriverOptions);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async executeInQueue(queryHandler, queryKey, query, priority, options) {
|
|
34
|
-
options = options || {};
|
|
35
|
-
const redisClient = await this.queueDriver.createConnection();
|
|
36
|
-
try {
|
|
37
|
-
if (priority == null) {
|
|
38
|
-
priority = 0;
|
|
39
|
-
}
|
|
40
|
-
if (!(priority >= -10000 && priority <= 10000)) {
|
|
41
|
-
throw new Error('Priority should be between -10000 and 10000');
|
|
42
|
-
}
|
|
43
|
-
let result = await redisClient.getResult(queryKey);
|
|
44
|
-
if (result) {
|
|
45
|
-
return this.parseResult(result);
|
|
46
|
-
}
|
|
47
|
-
const time = new Date().getTime();
|
|
48
|
-
const keyScore = time + (10000 - priority) * 1E14;
|
|
49
|
-
|
|
50
|
-
// eslint-disable-next-line no-unused-vars
|
|
51
|
-
const [added, b, c, queueSize] = await redisClient.addToQueue(
|
|
52
|
-
keyScore, queryKey, time, queryHandler, query, priority, options
|
|
53
|
-
);
|
|
54
|
-
|
|
55
|
-
if (added > 0) {
|
|
56
|
-
this.logger('Added to queue', {
|
|
57
|
-
priority,
|
|
58
|
-
queueSize,
|
|
59
|
-
queryKey,
|
|
60
|
-
queuePrefix: this.redisQueuePrefix,
|
|
61
|
-
requestId: options.requestId,
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
await this.reconcileQueue();
|
|
66
|
-
|
|
67
|
-
const queryDef = await redisClient.getQueryDef(queryKey);
|
|
68
|
-
const [active, toProcess] = await redisClient.getQueryStageState(true);
|
|
69
|
-
|
|
70
|
-
if (queryDef) {
|
|
71
|
-
this.logger('Waiting for query', {
|
|
72
|
-
queueSize,
|
|
73
|
-
queryKey: queryDef.queryKey,
|
|
74
|
-
queuePrefix: this.redisQueuePrefix,
|
|
75
|
-
requestId: options.requestId,
|
|
76
|
-
activeQueryKeys: active,
|
|
77
|
-
toProcessQueryKeys: toProcess,
|
|
78
|
-
active: active.indexOf(redisClient.redisHash(queryKey)) !== -1,
|
|
79
|
-
queueIndex: toProcess.indexOf(redisClient.redisHash(queryKey)),
|
|
80
|
-
waitingForRequestId: queryDef.requestId
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
result = await redisClient.getResultBlocking(queryKey);
|
|
85
|
-
if (!result) {
|
|
86
|
-
throw new ContinueWaitError();
|
|
87
|
-
}
|
|
88
|
-
return this.parseResult(result);
|
|
89
|
-
} finally {
|
|
90
|
-
this.queueDriver.release(redisClient);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
parseResult(result) {
|
|
95
|
-
if (!result) {
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
if (result.error) {
|
|
99
|
-
throw new Error(result.error); // TODO
|
|
100
|
-
} else {
|
|
101
|
-
// eslint-disable-next-line consistent-return
|
|
102
|
-
return result.result;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
async reconcileQueue() {
|
|
107
|
-
if (!this.reconcilePromise) {
|
|
108
|
-
this.reconcileAgain = false;
|
|
109
|
-
this.reconcilePromise = this.reconcileQueueImpl().then(() => {
|
|
110
|
-
this.reconcilePromise = null;
|
|
111
|
-
if (this.reconcileAgain) {
|
|
112
|
-
return this.reconcileQueue();
|
|
113
|
-
}
|
|
114
|
-
return null;
|
|
115
|
-
});
|
|
116
|
-
} else {
|
|
117
|
-
this.reconcileAgain = true;
|
|
118
|
-
}
|
|
119
|
-
return this.reconcilePromise;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
async reconcileQueueImpl() {
|
|
123
|
-
const redisClient = await this.queueDriver.createConnection();
|
|
124
|
-
try {
|
|
125
|
-
const toCancel = (
|
|
126
|
-
await redisClient.getStalledQueries()
|
|
127
|
-
).concat(
|
|
128
|
-
await redisClient.getOrphanedQueries()
|
|
129
|
-
);
|
|
130
|
-
|
|
131
|
-
await Promise.all(toCancel.map(async queryKey => {
|
|
132
|
-
const [query] = await redisClient.getQueryAndRemove(queryKey);
|
|
133
|
-
if (query) {
|
|
134
|
-
this.logger('Removing orphaned query', {
|
|
135
|
-
queryKey: query.queryKey,
|
|
136
|
-
queuePrefix: this.redisQueuePrefix,
|
|
137
|
-
requestId: query.requestId
|
|
138
|
-
});
|
|
139
|
-
await this.sendCancelMessageFn(query);
|
|
140
|
-
}
|
|
141
|
-
}));
|
|
142
|
-
|
|
143
|
-
const active = await redisClient.getActiveQueries();
|
|
144
|
-
const toProcess = await redisClient.getToProcessQueries();
|
|
145
|
-
await Promise.all(
|
|
146
|
-
R.pipe(
|
|
147
|
-
R.filter(p => active.indexOf(p) === -1),
|
|
148
|
-
R.take(this.concurrency),
|
|
149
|
-
R.map(this.sendProcessMessageFn)
|
|
150
|
-
)(toProcess)
|
|
151
|
-
);
|
|
152
|
-
} finally {
|
|
153
|
-
this.queueDriver.release(redisClient);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
queryTimeout(promise) {
|
|
158
|
-
let timeout;
|
|
159
|
-
const { executionTimeout } = this;
|
|
160
|
-
|
|
161
|
-
return Promise.race([
|
|
162
|
-
promise,
|
|
163
|
-
new Promise((resolve, reject) => {
|
|
164
|
-
timeout = setTimeout(() => {
|
|
165
|
-
reject(new TimeoutError(`Query execution timeout after ${executionTimeout / 60} min of waiting`));
|
|
166
|
-
}, executionTimeout * 1000);
|
|
167
|
-
}),
|
|
168
|
-
]).then((v) => {
|
|
169
|
-
clearTimeout(timeout);
|
|
170
|
-
return v;
|
|
171
|
-
}, (err) => {
|
|
172
|
-
clearTimeout(timeout);
|
|
173
|
-
throw err;
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
async fetchQueryStageState() {
|
|
178
|
-
const redisClient = await this.queueDriver.createConnection();
|
|
179
|
-
try {
|
|
180
|
-
return redisClient.getQueryStageState();
|
|
181
|
-
} finally {
|
|
182
|
-
this.queueDriver.release(redisClient);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
async getQueryStage(stageQueryKey, priorityFilter, queryStageState) {
|
|
187
|
-
const [active, toProcess, allQueryDefs] = queryStageState || await this.fetchQueryStageState();
|
|
188
|
-
|
|
189
|
-
const queryDefs = toProcess.map(k => allQueryDefs[k]).filter(q => !!q);
|
|
190
|
-
const queryInQueue = queryDefs.find(q => this.redisHash(q.stageQueryKey) === this.redisHash(stageQueryKey) &&
|
|
191
|
-
(priorityFilter != null ? q.priority === priorityFilter : true));
|
|
192
|
-
|
|
193
|
-
if (queryInQueue) {
|
|
194
|
-
if (active.indexOf(this.redisHash(queryInQueue.queryKey)) !== -1) {
|
|
195
|
-
return {
|
|
196
|
-
stage: 'Executing query',
|
|
197
|
-
timeElapsed: queryInQueue.startQueryTime ? new Date().getTime() - queryInQueue.startQueryTime : undefined
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
const index = queryDefs.filter(q => active.indexOf(this.redisHash(q.queryKey)) === -1).indexOf(queryInQueue);
|
|
201
|
-
if (index !== -1) {
|
|
202
|
-
return index !== -1 ? { stage: `#${index + 1} in queue` } : undefined;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
return undefined;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
async processQuery(queryKey) {
|
|
210
|
-
const redisClient = await this.queueDriver.createConnection();
|
|
211
|
-
let insertedCount;
|
|
212
|
-
// eslint-disable-next-line no-unused-vars
|
|
213
|
-
let removedCount;
|
|
214
|
-
let activeKeys;
|
|
215
|
-
let queueSize;
|
|
216
|
-
let query;
|
|
217
|
-
let processingLockAcquired;
|
|
218
|
-
try {
|
|
219
|
-
const processingId = await redisClient.getNextProcessingId();
|
|
220
|
-
const retrieveResult = await redisClient.retrieveForProcessing(queryKey, processingId);
|
|
221
|
-
if (retrieveResult) {
|
|
222
|
-
[insertedCount, removedCount, activeKeys, queueSize, query, processingLockAcquired] = retrieveResult;
|
|
223
|
-
}
|
|
224
|
-
const activated = activeKeys && activeKeys.indexOf(this.redisHash(queryKey)) !== -1;
|
|
225
|
-
if (!query) {
|
|
226
|
-
query = await redisClient.getQueryDef(this.redisHash(queryKey));
|
|
227
|
-
}
|
|
228
|
-
if (query && insertedCount && activated && processingLockAcquired) {
|
|
229
|
-
let executionResult;
|
|
230
|
-
const startQueryTime = (new Date()).getTime();
|
|
231
|
-
const timeInQueue = (new Date()).getTime() - query.addedToQueueTime;
|
|
232
|
-
this.logger('Performing query', {
|
|
233
|
-
processingId,
|
|
234
|
-
queueSize,
|
|
235
|
-
queryKey: query.queryKey,
|
|
236
|
-
queuePrefix: this.redisQueuePrefix,
|
|
237
|
-
requestId: query.requestId,
|
|
238
|
-
timeInQueue
|
|
239
|
-
});
|
|
240
|
-
await redisClient.optimisticQueryUpdate(queryKey, { startQueryTime }, processingId);
|
|
241
|
-
|
|
242
|
-
const heartBeatTimer = setInterval(
|
|
243
|
-
() => redisClient.updateHeartBeat(queryKey),
|
|
244
|
-
this.heartBeatInterval * 1000
|
|
245
|
-
);
|
|
246
|
-
try {
|
|
247
|
-
executionResult = {
|
|
248
|
-
result: await this.queryTimeout(
|
|
249
|
-
this.queryHandlers[query.queryHandler](
|
|
250
|
-
query.query,
|
|
251
|
-
async (cancelHandler) => {
|
|
252
|
-
try {
|
|
253
|
-
return redisClient.optimisticQueryUpdate(queryKey, { cancelHandler }, processingId);
|
|
254
|
-
} catch (e) {
|
|
255
|
-
this.logger('Error while query update', {
|
|
256
|
-
queryKey: query.queryKey,
|
|
257
|
-
error: e.stack || e,
|
|
258
|
-
queuePrefix: this.redisQueuePrefix,
|
|
259
|
-
requestId: query.requestId
|
|
260
|
-
});
|
|
261
|
-
}
|
|
262
|
-
return null;
|
|
263
|
-
}
|
|
264
|
-
)
|
|
265
|
-
)
|
|
266
|
-
};
|
|
267
|
-
this.logger('Performing query completed', {
|
|
268
|
-
processingId,
|
|
269
|
-
queueSize,
|
|
270
|
-
duration: ((new Date()).getTime() - startQueryTime),
|
|
271
|
-
queryKey: query.queryKey,
|
|
272
|
-
queuePrefix: this.redisQueuePrefix,
|
|
273
|
-
requestId: query.requestId,
|
|
274
|
-
timeInQueue
|
|
275
|
-
});
|
|
276
|
-
} catch (e) {
|
|
277
|
-
executionResult = {
|
|
278
|
-
error: (e.message || e).toString() // TODO error handling
|
|
279
|
-
};
|
|
280
|
-
this.logger('Error while querying', {
|
|
281
|
-
processingId,
|
|
282
|
-
queueSize,
|
|
283
|
-
duration: ((new Date()).getTime() - startQueryTime),
|
|
284
|
-
queryKey: query.queryKey,
|
|
285
|
-
queuePrefix: this.redisQueuePrefix,
|
|
286
|
-
requestId: query.requestId,
|
|
287
|
-
timeInQueue,
|
|
288
|
-
error: (e.stack || e).toString()
|
|
289
|
-
});
|
|
290
|
-
if (e instanceof TimeoutError) {
|
|
291
|
-
const queryWithCancelHandle = await redisClient.getQueryDef(queryKey);
|
|
292
|
-
if (queryWithCancelHandle) {
|
|
293
|
-
this.logger('Cancelling query due to timeout', {
|
|
294
|
-
processingId,
|
|
295
|
-
queryKey: queryWithCancelHandle.queryKey,
|
|
296
|
-
queuePrefix: this.redisQueuePrefix,
|
|
297
|
-
requestId: queryWithCancelHandle.requestId
|
|
298
|
-
});
|
|
299
|
-
await this.sendCancelMessageFn(queryWithCancelHandle);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
clearInterval(heartBeatTimer);
|
|
305
|
-
|
|
306
|
-
if (!(await redisClient.setResultAndRemoveQuery(queryKey, executionResult, processingId))) {
|
|
307
|
-
this.logger('Orphaned execution result', {
|
|
308
|
-
processingId,
|
|
309
|
-
warn: 'Result for query was not set due to processing lock wasn\'t acquired',
|
|
310
|
-
queryKey: query.queryKey,
|
|
311
|
-
queuePrefix: this.redisQueuePrefix,
|
|
312
|
-
requestId: query.requestId
|
|
313
|
-
});
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
await this.reconcileQueue();
|
|
317
|
-
} else {
|
|
318
|
-
this.logger('Skip processing', {
|
|
319
|
-
processingId,
|
|
320
|
-
queryKey: query && query.queryKey || queryKey,
|
|
321
|
-
requestId: query && query.requestId,
|
|
322
|
-
queuePrefix: this.redisQueuePrefix,
|
|
323
|
-
processingLockAcquired,
|
|
324
|
-
query,
|
|
325
|
-
insertedCount,
|
|
326
|
-
activeKeys,
|
|
327
|
-
activated,
|
|
328
|
-
queryExists: !!query
|
|
329
|
-
});
|
|
330
|
-
const currentProcessingId = await redisClient.freeProcessingLock(queryKey, processingId, activated);
|
|
331
|
-
if (currentProcessingId) {
|
|
332
|
-
this.logger('Skipping free processing lock', {
|
|
333
|
-
processingId,
|
|
334
|
-
currentProcessingId,
|
|
335
|
-
queryKey: query && query.queryKey || queryKey,
|
|
336
|
-
requestId: query && query.requestId,
|
|
337
|
-
queuePrefix: this.redisQueuePrefix,
|
|
338
|
-
processingLockAcquired,
|
|
339
|
-
query,
|
|
340
|
-
insertedCount,
|
|
341
|
-
activeKeys,
|
|
342
|
-
activated,
|
|
343
|
-
queryExists: !!query
|
|
344
|
-
});
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
} catch (e) {
|
|
348
|
-
this.logger('Queue storage error', {
|
|
349
|
-
queryKey: query && query.queryKey || queryKey,
|
|
350
|
-
requestId: query && query.requestId,
|
|
351
|
-
error: (e.stack || e).toString(),
|
|
352
|
-
queuePrefix: this.redisQueuePrefix
|
|
353
|
-
});
|
|
354
|
-
} finally {
|
|
355
|
-
this.queueDriver.release(redisClient);
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
async processCancel(query) {
|
|
360
|
-
const { queryHandler } = query;
|
|
361
|
-
try {
|
|
362
|
-
if (!this.cancelHandlers[queryHandler]) {
|
|
363
|
-
throw new Error(`No cancel handler for ${queryHandler}`);
|
|
364
|
-
}
|
|
365
|
-
await this.cancelHandlers[queryHandler](query);
|
|
366
|
-
} catch (e) {
|
|
367
|
-
this.logger('Error while cancel', {
|
|
368
|
-
queryKey: query.queryKey,
|
|
369
|
-
error: e.stack || e,
|
|
370
|
-
queuePrefix: this.redisQueuePrefix,
|
|
371
|
-
requestId: query.requestId
|
|
372
|
-
});
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
redisHash(queryKey) {
|
|
377
|
-
return this.queueDriver.redisHash(queryKey);
|
|
378
|
-
}
|
|
379
|
-
}
|
|
3
|
+
process.emitWarning(
|
|
4
|
+
'Using absolute import with @cubejs-backend/query-orchestrator is deprecated',
|
|
5
|
+
'DeprecationWarning'
|
|
6
|
+
);
|
|
380
7
|
|
|
381
8
|
module.exports = QueryQueue;
|
|
@@ -1,48 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
constructor({ pool }) {
|
|
3
|
-
this.redisPool = pool;
|
|
4
|
-
}
|
|
1
|
+
const { RedisCacheDriver } = require('../dist/src/orchestrator/RedisCacheDriver');
|
|
5
2
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
async get(key) {
|
|
11
|
-
const client = await this.getClient();
|
|
12
|
-
try {
|
|
13
|
-
const res = await client.getAsync(key);
|
|
14
|
-
return res && JSON.parse(res);
|
|
15
|
-
} finally {
|
|
16
|
-
this.redisPool.release(client);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
async set(key, value, expiration) {
|
|
21
|
-
const client = await this.getClient();
|
|
22
|
-
try {
|
|
23
|
-
return await client.setAsync(key, JSON.stringify(value), 'EX', expiration);
|
|
24
|
-
} finally {
|
|
25
|
-
this.redisPool.release(client);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
async remove(key) {
|
|
30
|
-
const client = await this.getClient();
|
|
31
|
-
try {
|
|
32
|
-
return await client.delAsync(key);
|
|
33
|
-
} finally {
|
|
34
|
-
this.redisPool.release(client);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
async keysStartingWith(prefix) {
|
|
39
|
-
const client = await this.getClient();
|
|
40
|
-
try {
|
|
41
|
-
return await client.keysAsync(`${prefix}*`);
|
|
42
|
-
} finally {
|
|
43
|
-
this.redisPool.release(client);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
3
|
+
process.emitWarning(
|
|
4
|
+
'Using absolute import with @cubejs-backend/query-orchestrator is deprecated',
|
|
5
|
+
'DeprecationWarning'
|
|
6
|
+
);
|
|
47
7
|
|
|
48
8
|
module.exports = RedisCacheDriver;
|
|
@@ -1,48 +1,8 @@
|
|
|
1
|
-
const
|
|
2
|
-
const { promisify } = require('util');
|
|
1
|
+
const { createRedisClient } = require('../dist/src/orchestrator/RedisFactory');
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
)));
|
|
9
|
-
};
|
|
3
|
+
process.emitWarning(
|
|
4
|
+
'Using absolute import with @cubejs-backend/query-orchestrator is deprecated',
|
|
5
|
+
'DeprecationWarning'
|
|
6
|
+
);
|
|
10
7
|
|
|
11
|
-
|
|
12
|
-
url,
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
if (process.env.REDIS_TLS === 'true') {
|
|
16
|
-
options.tls = {};
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
if (process.env.REDIS_PASSWORD) {
|
|
20
|
-
options.password = process.env.REDIS_PASSWORD;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const client = redis.createClient(options);
|
|
24
|
-
|
|
25
|
-
[
|
|
26
|
-
'brpop',
|
|
27
|
-
'del',
|
|
28
|
-
'get',
|
|
29
|
-
'hget',
|
|
30
|
-
'rpop',
|
|
31
|
-
'set',
|
|
32
|
-
'zadd',
|
|
33
|
-
'zrange',
|
|
34
|
-
'zrangebyscore',
|
|
35
|
-
'keys',
|
|
36
|
-
'watch',
|
|
37
|
-
'unwatch',
|
|
38
|
-
'incr',
|
|
39
|
-
'decr',
|
|
40
|
-
'lpush'
|
|
41
|
-
].forEach(
|
|
42
|
-
k => {
|
|
43
|
-
client[`${k}Async`] = promisify(client[k]);
|
|
44
|
-
}
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
return client;
|
|
48
|
-
};
|
|
8
|
+
module.exports = createRedisClient;
|
|
@@ -1,52 +1,8 @@
|
|
|
1
|
-
const
|
|
2
|
-
const createRedisClient = require('./RedisFactory');
|
|
1
|
+
const { RedisPool } = require('../dist/src/orchestrator/RedisPool');
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const defaultMax = process.env.CUBEJS_REDIS_POOL_MAX ? parseInt(process.env.CUBEJS_REDIS_POOL_MAX, 10) : 1000;
|
|
9
|
-
const min = (typeof options.poolMin !== 'undefined') ? options.poolMin : defaultMin;
|
|
10
|
-
const max = (typeof options.poolMax !== 'undefined') ? options.poolMax : defaultMax;
|
|
11
|
-
const create = options.createClient || (() => createRedisClient(process.env.REDIS_URL));
|
|
12
|
-
const destroy = options.destroyClient || (client => client.end(true));
|
|
13
|
-
const opts = {
|
|
14
|
-
min,
|
|
15
|
-
max,
|
|
16
|
-
acquireTimeoutMillis: 5000,
|
|
17
|
-
idleTimeoutMillis: 5000,
|
|
18
|
-
evictionRunIntervalMillis: 5000
|
|
19
|
-
};
|
|
20
|
-
if (max > 0) {
|
|
21
|
-
this.pool = genericPool.createPool({ create, destroy }, opts);
|
|
22
|
-
} else {
|
|
23
|
-
// fallback to un-pooled behavior if pool max is 0
|
|
24
|
-
this.create = create;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async getClient() {
|
|
29
|
-
if (this.pool) {
|
|
30
|
-
return this.pool.acquire();
|
|
31
|
-
} else {
|
|
32
|
-
return this.create();
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
release(client) {
|
|
37
|
-
if (this.pool) {
|
|
38
|
-
this.pool.release(client);
|
|
39
|
-
} else if (client) {
|
|
40
|
-
client.quit();
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
async cleanup() {
|
|
45
|
-
if (this.pool) {
|
|
46
|
-
await this.pool.drain();
|
|
47
|
-
this.pool.clear();
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
3
|
+
process.emitWarning(
|
|
4
|
+
'Using absolute import with @cubejs-backend/query-orchestrator is deprecated',
|
|
5
|
+
'DeprecationWarning'
|
|
6
|
+
);
|
|
51
7
|
|
|
52
8
|
module.exports = RedisPool;
|