@cubejs-backend/query-orchestrator 0.24.0 → 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.
Files changed (96) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/src/driver/BaseDriver.d.ts +36 -0
  3. package/dist/src/driver/BaseDriver.d.ts.map +1 -0
  4. package/dist/src/driver/BaseDriver.js +175 -0
  5. package/dist/src/driver/BaseDriver.js.map +1 -0
  6. package/dist/src/driver/index.d.ts +3 -0
  7. package/dist/src/driver/index.d.ts.map +1 -0
  8. package/dist/src/driver/index.js +15 -0
  9. package/dist/src/driver/index.js.map +1 -0
  10. package/dist/src/driver/utils.d.ts +2 -0
  11. package/dist/src/driver/utils.d.ts.map +1 -0
  12. package/dist/src/driver/utils.js +17 -0
  13. package/dist/src/driver/utils.js.map +1 -0
  14. package/dist/src/index.d.ts +3 -0
  15. package/dist/src/index.d.ts.map +1 -0
  16. package/dist/src/index.js +15 -0
  17. package/dist/src/index.js.map +1 -0
  18. package/dist/src/orchestrator/BaseQueueDriver.d.ts +4 -0
  19. package/dist/src/orchestrator/BaseQueueDriver.d.ts.map +1 -0
  20. package/dist/src/orchestrator/BaseQueueDriver.js +16 -0
  21. package/dist/src/orchestrator/BaseQueueDriver.js.map +1 -0
  22. package/dist/src/orchestrator/ContinueWaitError.d.ts +3 -0
  23. package/dist/src/orchestrator/ContinueWaitError.d.ts.map +1 -0
  24. package/dist/src/orchestrator/ContinueWaitError.js +10 -0
  25. package/dist/src/orchestrator/ContinueWaitError.js.map +1 -0
  26. package/dist/src/orchestrator/LocalCacheDriver.d.ts +8 -0
  27. package/dist/src/orchestrator/LocalCacheDriver.d.ts.map +1 -0
  28. package/dist/src/orchestrator/LocalCacheDriver.js +30 -0
  29. package/dist/src/orchestrator/LocalCacheDriver.js.map +1 -0
  30. package/dist/src/orchestrator/LocalQueueDriver.d.ts +57 -0
  31. package/dist/src/orchestrator/LocalQueueDriver.d.ts.map +1 -0
  32. package/dist/src/orchestrator/LocalQueueDriver.js +230 -0
  33. package/dist/src/orchestrator/LocalQueueDriver.js.map +1 -0
  34. package/dist/src/orchestrator/PreAggregations.d.ts +26 -0
  35. package/dist/src/orchestrator/PreAggregations.d.ts.map +1 -0
  36. package/dist/src/orchestrator/PreAggregations.js +565 -0
  37. package/dist/src/orchestrator/PreAggregations.js.map +1 -0
  38. package/dist/src/orchestrator/QueryCache.d.ts +51 -0
  39. package/dist/src/orchestrator/QueryCache.d.ts.map +1 -0
  40. package/dist/src/orchestrator/QueryCache.js +293 -0
  41. package/dist/src/orchestrator/QueryCache.js.map +1 -0
  42. package/dist/src/orchestrator/QueryOrchestrator.d.ts +27 -0
  43. package/dist/src/orchestrator/QueryOrchestrator.d.ts.map +1 -0
  44. package/dist/src/orchestrator/QueryOrchestrator.js +79 -0
  45. package/dist/src/orchestrator/QueryOrchestrator.js.map +1 -0
  46. package/dist/src/orchestrator/QueryQueue.d.ts +36 -0
  47. package/dist/src/orchestrator/QueryQueue.d.ts.map +1 -0
  48. package/dist/src/orchestrator/QueryQueue.js +351 -0
  49. package/dist/src/orchestrator/QueryQueue.js.map +1 -0
  50. package/dist/src/orchestrator/RedisCacheDriver.d.ts +12 -0
  51. package/dist/src/orchestrator/RedisCacheDriver.d.ts.map +1 -0
  52. package/dist/src/orchestrator/RedisCacheDriver.js +50 -0
  53. package/dist/src/orchestrator/RedisCacheDriver.js.map +1 -0
  54. package/dist/src/orchestrator/RedisFactory.d.ts +3 -0
  55. package/dist/src/orchestrator/RedisFactory.d.ts.map +1 -0
  56. package/dist/src/orchestrator/RedisFactory.js +45 -0
  57. package/dist/src/orchestrator/RedisFactory.js.map +1 -0
  58. package/dist/src/orchestrator/RedisPool.d.ts +10 -0
  59. package/dist/src/orchestrator/RedisPool.d.ts.map +1 -0
  60. package/dist/src/orchestrator/RedisPool.js +57 -0
  61. package/dist/src/orchestrator/RedisPool.js.map +1 -0
  62. package/dist/src/orchestrator/RedisQueueDriver.d.ts +47 -0
  63. package/dist/src/orchestrator/RedisQueueDriver.d.ts.map +1 -0
  64. package/dist/src/orchestrator/RedisQueueDriver.js +253 -0
  65. package/dist/src/orchestrator/RedisQueueDriver.js.map +1 -0
  66. package/dist/src/orchestrator/TimeoutError.d.ts +4 -0
  67. package/dist/src/orchestrator/TimeoutError.d.ts.map +1 -0
  68. package/dist/src/orchestrator/TimeoutError.js +7 -0
  69. package/dist/src/orchestrator/TimeoutError.js.map +1 -0
  70. package/dist/src/orchestrator/index.d.ts +14 -0
  71. package/dist/src/orchestrator/index.d.ts.map +1 -0
  72. package/dist/src/orchestrator/index.js +26 -0
  73. package/dist/src/orchestrator/index.js.map +1 -0
  74. package/driver/BaseDriver.js +5 -221
  75. package/driver/README.md +3 -0
  76. package/driver/utils.js +8 -12
  77. package/orchestrator/BaseQueueDriver.js +5 -8
  78. package/orchestrator/ContinueWaitError.js +6 -5
  79. package/orchestrator/LocalCacheDriver.js +5 -29
  80. package/orchestrator/LocalQueueDriver.js +5 -256
  81. package/orchestrator/PreAggregations.js +4 -764
  82. package/orchestrator/QueryCache.js +5 -381
  83. package/orchestrator/QueryOrchestrator.js +5 -100
  84. package/orchestrator/QueryQueue.js +5 -378
  85. package/orchestrator/README.md +3 -0
  86. package/orchestrator/RedisCacheDriver.js +5 -45
  87. package/orchestrator/RedisFactory.js +6 -46
  88. package/orchestrator/RedisPool.js +5 -49
  89. package/orchestrator/RedisQueueDriver.js +5 -283
  90. package/orchestrator/TimeoutError.js +6 -1
  91. package/package.json +29 -11
  92. package/docker-compose.yml +0 -7
  93. package/test/integration/QueryQueueRedis.test.js +0 -5
  94. package/test/unit/PreAggregations.test.js +0 -337
  95. package/test/unit/QueryOrchestrator.test.js +0 -373
  96. package/test/unit/QueryQueue.test.js +0 -247
@@ -1,337 +0,0 @@
1
- /* eslint-disable global-require,no-unused-vars */
2
- /* globals describe, jest, beforeEach, test, expect */
3
- const R = require('ramda');
4
-
5
- class MockDriver {
6
- constructor() {
7
- this.tables = [];
8
- this.executedQueries = [];
9
- this.cancelledQueries = [];
10
- }
11
-
12
- query(query) {
13
- this.executedQueries.push(query);
14
- let promise = Promise.resolve([query]);
15
- if (query.match('orders_too_big')) {
16
- promise = promise.then((res) => new Promise(resolve => setTimeout(() => resolve(res), 3000)));
17
- }
18
- promise.cancel = async () => {
19
- this.cancelledQueries.push(query);
20
- };
21
- return promise;
22
- }
23
-
24
- async getTablesQuery(schema) {
25
- return this.tables.map(t => ({ table_name: t.replace(`${schema}.`, '') }));
26
- }
27
-
28
- async createSchemaIfNotExists(schema) {
29
- this.schema = schema;
30
- return null;
31
- }
32
-
33
- loadPreAggregationIntoTable(preAggregationTableName, loadSql) {
34
- this.tables.push(preAggregationTableName.substring(0, 100));
35
- return this.query(loadSql);
36
- }
37
-
38
- async dropTable(tableName) {
39
- this.tables = this.tables.filter(t => t !== tableName);
40
- return this.query(`DROP TABLE ${tableName}`);
41
- }
42
-
43
- async downloadTable(table) {
44
- return { rows: await this.query(`SELECT * FROM ${table}`) };
45
- }
46
-
47
- async tableColumnTypes(table) {
48
- return [];
49
- }
50
-
51
- async uploadTable(table, columns, tableData) {
52
- await this.createTable(table, columns);
53
- }
54
-
55
- createTable(quotedTableName, columns) {
56
- this.tables.push(quotedTableName);
57
- }
58
-
59
- readOnly() {
60
- return false;
61
- }
62
- }
63
-
64
- describe('PreAggregations', () => {
65
- let mockDriver = null;
66
- let mockExternalDriver = null;
67
- let mockDriverFactory = null;
68
- let mockDriverReadOnlyFactory = null;
69
- let mockExternalDriverFactory = null;
70
- let queryCache = null;
71
- const basicQuery = {
72
- query: 'SELECT "orders__created_at_week" "orders__created_at_week", sum("orders__count") "orders__count" FROM (SELECT * FROM stb_pre_aggregations.orders_number_and_count20191101) as partition_union WHERE ("orders__created_at_week" >= ($1::timestamptz::timestamptz AT TIME ZONE \'UTC\') AND "orders__created_at_week" <= ($2::timestamptz::timestamptz AT TIME ZONE \'UTC\')) GROUP BY 1 ORDER BY 1 ASC LIMIT 10000',
73
- values: ['2019-11-01T00:00:00Z', '2019-11-30T23:59:59Z'],
74
- cacheKeyQueries: {
75
- renewalThreshold: 21600,
76
- queries: [['SELECT date_trunc(\'hour\', (NOW()::timestamptz AT TIME ZONE \'UTC\')) as current_hour', []]]
77
- },
78
- preAggregations: [{
79
- preAggregationsSchema: 'stb_pre_aggregations',
80
- tableName: 'stb_pre_aggregations.orders_number_and_count20191101',
81
- loadSql: ['CREATE TABLE stb_pre_aggregations.orders_number_and_count20191101 AS SELECT\n date_trunc(\'week\', ("orders".created_at::timestamptz AT TIME ZONE \'UTC\')) "orders__created_at_week", count("orders".id) "orders__count", sum("orders".number) "orders__number"\n FROM\n public.orders AS "orders"\n WHERE ("orders".created_at >= $1::timestamptz AND "orders".created_at <= $2::timestamptz) GROUP BY 1', ['2019-11-01T00:00:00Z', '2019-11-30T23:59:59Z']],
82
- invalidateKeyQueries: [['SELECT date_trunc(\'hour\', (NOW()::timestamptz AT TIME ZONE \'UTC\')) as current_hour', []]]
83
- }],
84
- requestId: 'basic'
85
- };
86
- const basicQueryExternal = R.clone(basicQuery);
87
- basicQueryExternal.preAggregations[0].external = true;
88
- const basicQueryWithRenew = R.clone(basicQuery);
89
- basicQueryWithRenew.renewQuery = true;
90
- const basicQueryExternalWithRenew = R.clone(basicQueryExternal);
91
- basicQueryExternalWithRenew.renewQuery = true;
92
-
93
- beforeEach(() => {
94
- mockDriver = new MockDriver();
95
- mockExternalDriver = new MockDriver();
96
- mockDriverFactory = async () => mockDriver;
97
- mockDriverReadOnlyFactory = async () => {
98
- const driver = mockDriver;
99
- jest.spyOn(driver, 'readOnly').mockImplementation(() => true);
100
- return driver;
101
- };
102
- mockExternalDriverFactory = async () => {
103
- const driver = mockExternalDriver;
104
- driver.createTable('stb_pre_aggregations.orders_number_and_count20191101_kjypcoio_5yftl5il_1593709044209');
105
- return driver;
106
- };
107
-
108
- jest.resetModules();
109
- const QueryCache = require('../../orchestrator/QueryCache');
110
- queryCache = new QueryCache(
111
- 'TEST',
112
- mockDriverFactory,
113
- (msg, params) => {},
114
- {
115
- queueOptions: {
116
- executionTimeout: 1
117
- },
118
- },
119
- );
120
- });
121
-
122
- describe('loadAllPreAggregationsIfNeeded', () => {
123
- let preAggregations = null;
124
-
125
- beforeEach(async () => {
126
- const PreAggregations = require('../../orchestrator/PreAggregations');
127
- preAggregations = new PreAggregations(
128
- 'TEST',
129
- mockDriverFactory,
130
- (msg, params) => {},
131
- queryCache,
132
- {
133
- queueOptions: {
134
- executionTimeout: 1
135
- },
136
- },
137
- );
138
- });
139
-
140
- test('syncronously create rollup from scratch', async () => {
141
- const result = await preAggregations.loadAllPreAggregationsIfNeeded(basicQueryWithRenew);
142
- expect(result[0][1].targetTableName).toMatch(/stb_pre_aggregations.orders_number_and_count20191101_kjypcoio_5yftl5il/);
143
- });
144
- });
145
-
146
- describe('loadAllPreAggregationsIfNeeded with external rollup and writable source', () => {
147
- let preAggregations = null;
148
-
149
- beforeEach(async () => {
150
- const PreAggregations = require('../../orchestrator/PreAggregations');
151
- preAggregations = new PreAggregations(
152
- 'TEST',
153
- mockDriverFactory,
154
- (msg, params) => {},
155
- queryCache,
156
- {
157
- queueOptions: {
158
- executionTimeout: 1
159
- },
160
- externalDriverFactory: mockExternalDriverFactory,
161
- },
162
- );
163
- });
164
-
165
- test('refresh external preaggregation with a writable source (refreshImplTempTableExternalStrategy)', async () => {
166
- const result = await preAggregations.loadAllPreAggregationsIfNeeded(basicQueryExternal);
167
- expect(result[0][1].targetTableName).toMatch(/stb_pre_aggregations.orders_number_and_count20191101_kjypcoio_5yftl5il/);
168
- });
169
- });
170
-
171
- describe('loadAllPreAggregationsIfNeeded with external rollup and readonly source', () => {
172
- let preAggregations = null;
173
-
174
- beforeEach(async () => {
175
- const PreAggregations = require('../../orchestrator/PreAggregations');
176
- preAggregations = new PreAggregations(
177
- 'TEST',
178
- mockDriverReadOnlyFactory,
179
- (msg, params) => {},
180
- queryCache,
181
- {
182
- queueOptions: {
183
- executionTimeout: 1
184
- },
185
- externalDriverFactory: mockExternalDriverFactory,
186
- },
187
- );
188
- });
189
-
190
- test('refresh external preaggregation with a writable source (refreshImplStreamExternalStrategy)', async () => {
191
- const result = await preAggregations.loadAllPreAggregationsIfNeeded(basicQueryExternal);
192
- expect(result[0][1].targetTableName).toMatch(/stb_pre_aggregations.orders_number_and_count20191101_kjypcoio_5yftl5il/);
193
- });
194
- });
195
-
196
- describe('loadAllPreAggregationsIfNeeded with externalRefresh true', () => {
197
- let preAggregations = null;
198
-
199
- beforeEach(async () => {
200
- const PreAggregations = require('../../orchestrator/PreAggregations');
201
- preAggregations = new PreAggregations(
202
- 'TEST',
203
- mockDriverFactory,
204
- (msg, params) => {},
205
- queryCache,
206
- {
207
- queueOptions: {
208
- executionTimeout: 1
209
- },
210
- externalRefresh: true,
211
- },
212
- );
213
- });
214
-
215
- test('fail if waitForRenew is also specified', async () => {
216
- await expect(preAggregations.loadAllPreAggregationsIfNeeded(basicQueryWithRenew))
217
- .rejects.toThrowError(/Invalid configuration/);
218
- });
219
-
220
- test('fail if rollup doesn\'t already exist', async () => {
221
- await expect(preAggregations.loadAllPreAggregationsIfNeeded(basicQuery))
222
- .rejects.toThrowError(/One or more pre-aggregation tables could not be found to satisfy that query/);
223
- });
224
- });
225
-
226
- describe('loadAllPreAggregationsIfNeeded with external rollup and externalRefresh true', () => {
227
- let preAggregations = null;
228
-
229
- beforeEach(async () => {
230
- const PreAggregations = require('../../orchestrator/PreAggregations');
231
- preAggregations = new PreAggregations(
232
- 'TEST',
233
- () => { throw new Error('The source database factory should never be called when externalRefresh is true, as it will trigger testConnection'); },
234
- (msg, params) => {},
235
- queryCache,
236
- {
237
- queueOptions: {
238
- executionTimeout: 1
239
- },
240
- externalDriverFactory: mockExternalDriverFactory,
241
- externalRefresh: true,
242
- },
243
- );
244
- });
245
-
246
- test('fail if waitForRenew is also specified', async () => {
247
- await expect(preAggregations.loadAllPreAggregationsIfNeeded(basicQueryExternalWithRenew))
248
- .rejects.toThrowError(/Invalid configuration/);
249
- });
250
-
251
- test('load external preaggregation without communicating to the source database', async () => {
252
- const result = await preAggregations.loadAllPreAggregationsIfNeeded(basicQueryExternal);
253
- expect(result[0][1].targetTableName).toMatch(/stb_pre_aggregations.orders_number_and_count20191101_kjypcoio_5yftl5il/);
254
- });
255
- });
256
-
257
- describe('naming_version tests', () => {
258
- let preAggregations = null;
259
- let PreAggregations = null;
260
-
261
- beforeEach(async () => {
262
- PreAggregations = require('../../orchestrator/PreAggregations');
263
- preAggregations = new PreAggregations(
264
- 'TEST',
265
- mockDriverFactory,
266
- (msg, params) => {},
267
- queryCache,
268
- {
269
- queueOptions: {
270
- executionTimeout: 1
271
- },
272
- externalDriverFactory: async () => {
273
- const driver = mockExternalDriver;
274
- driver.createTable('stb_pre_aggregations.orders_number_and_count20191101_kjypcoio_5yftl5il_1593709044209');
275
- driver.createTable('stb_pre_aggregations.orders_number_and_count20191101_kjypcoio_5yftl5il_1fm6652');
276
- return driver;
277
- },
278
- },
279
- );
280
- });
281
-
282
- test('test for function targetTableName', () => {
283
- let result = PreAggregations.targetTableName({
284
- table_name: 'orders_number_and_count20191101',
285
- content_version: 'kjypcoio',
286
- structure_version: '5yftl5il',
287
- last_updated_at: 1600329890789,
288
- });
289
- expect(result).toEqual('orders_number_and_count20191101_kjypcoio_5yftl5il_1600329890789');
290
-
291
- result = PreAggregations.targetTableName({
292
- table_name: 'orders_number_and_count20191101',
293
- content_version: 'kjypcoio',
294
- structure_version: '5yftl5il',
295
- last_updated_at: 1600329890789,
296
- naming_version: 2
297
- });
298
- expect(result).toEqual('orders_number_and_count20191101_kjypcoio_5yftl5il_1fm6652');
299
- });
300
-
301
- test('naming_version and sort by last_updated_at', async () => {
302
- const result = await preAggregations.loadAllPreAggregationsIfNeeded(basicQueryExternal);
303
- expect(result[0][1].targetTableName).toMatch(/stb_pre_aggregations.orders_number_and_count20191101_kjypcoio_5yftl5il_1fm6652/);
304
- });
305
- });
306
-
307
- describe('naming_version sort tests', () => {
308
- let preAggregations = null;
309
- let PreAggregations = null;
310
-
311
- beforeEach(async () => {
312
- PreAggregations = require('../../orchestrator/PreAggregations');
313
- preAggregations = new PreAggregations(
314
- 'TEST',
315
- mockDriverFactory,
316
- (msg, params) => {},
317
- queryCache,
318
- {
319
- queueOptions: {
320
- executionTimeout: 1
321
- },
322
- externalDriverFactory: async () => {
323
- const driver = mockExternalDriver;
324
- driver.createTable('stb_pre_aggregations.orders_number_and_count20191101_kjypcoio_5yftl5il_1893709044209');
325
- driver.createTable('stb_pre_aggregations.orders_number_and_count20191101_kjypcoio_5yftl5il_1fm6652');
326
- return driver;
327
- },
328
- },
329
- );
330
- });
331
-
332
- test('naming_version and sort by last_updated_at', async () => {
333
- const result = await preAggregations.loadAllPreAggregationsIfNeeded(basicQueryExternal);
334
- expect(result[0][1].targetTableName).toMatch(/stb_pre_aggregations.orders_number_and_count20191101_kjypcoio_5yftl5il_1893709044209/);
335
- });
336
- });
337
- });