@cubejs-backend/query-orchestrator 0.30.46 → 0.30.51
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 +30 -0
- package/dist/src/driver/driver.interface.d.ts +12 -2
- package/dist/src/driver/driver.interface.d.ts.map +1 -1
- package/dist/src/orchestrator/PreAggregations.d.ts +29 -6
- package/dist/src/orchestrator/PreAggregations.d.ts.map +1 -1
- package/dist/src/orchestrator/PreAggregations.js +120 -51
- package/dist/src/orchestrator/PreAggregations.js.map +1 -1
- package/dist/src/orchestrator/QueryCache.d.ts +7 -2
- package/dist/src/orchestrator/QueryCache.d.ts.map +1 -1
- package/dist/src/orchestrator/QueryCache.js +48 -8
- package/dist/src/orchestrator/QueryCache.js.map +1 -1
- package/dist/src/orchestrator/QueryOrchestrator.d.ts.map +1 -1
- package/dist/src/orchestrator/QueryOrchestrator.js +5 -1
- package/dist/src/orchestrator/QueryOrchestrator.js.map +1 -1
- package/dist/src/orchestrator/QueryQueue.js +1 -1
- package/package.json +6 -4
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.PreAggregations = exports.PreAggregationPartitionRangeLoader = exports.PreAggregationLoader = exports.getLastUpdatedAtTimestamp = void 0;
|
|
6
|
+
exports.PreAggregations = exports.PreAggregationPartitionRangeLoader = exports.PreAggregationLoader = exports.getLastUpdatedAtTimestamp = exports.LAMBDA_TABLE_PREFIX = void 0;
|
|
7
7
|
const crypto_1 = __importDefault(require("crypto"));
|
|
8
8
|
const ramda_1 = __importDefault(require("ramda"));
|
|
9
9
|
const shared_1 = require("@cubejs-backend/shared");
|
|
@@ -13,6 +13,8 @@ const LocalCacheDriver_1 = require("./LocalCacheDriver");
|
|
|
13
13
|
const QueryCache_1 = require("./QueryCache");
|
|
14
14
|
const ContinueWaitError_1 = require("./ContinueWaitError");
|
|
15
15
|
const StreamObjectsCounter_1 = require("./StreamObjectsCounter");
|
|
16
|
+
/// Name of the inline table containing the lambda rows.
|
|
17
|
+
exports.LAMBDA_TABLE_PREFIX = 'lambda';
|
|
16
18
|
function encodeTimeStamp(time) {
|
|
17
19
|
return Math.floor(time / 1000).toString(32);
|
|
18
20
|
}
|
|
@@ -71,7 +73,7 @@ const tablesToVersionEntries = (schema, tables) => ramda_1.default.sortBy(table
|
|
|
71
73
|
const entity = {
|
|
72
74
|
table_name: `${schema}.${match[1]}`,
|
|
73
75
|
content_version: match[2],
|
|
74
|
-
structure_version: match[3]
|
|
76
|
+
structure_version: match[3],
|
|
75
77
|
};
|
|
76
78
|
if (match[4].length < 13) {
|
|
77
79
|
entity.last_updated_at = decodeTimeStamp(match[4]);
|
|
@@ -80,6 +82,9 @@ const tablesToVersionEntries = (schema, tables) => ramda_1.default.sortBy(table
|
|
|
80
82
|
else {
|
|
81
83
|
entity.last_updated_at = parseInt(match[4], 10);
|
|
82
84
|
}
|
|
85
|
+
if (table.build_range_end) {
|
|
86
|
+
entity.build_range_end = table.build_range_end;
|
|
87
|
+
}
|
|
83
88
|
return entity;
|
|
84
89
|
}).filter(ramda_1.default.identity));
|
|
85
90
|
class PreAggregationLoadCache {
|
|
@@ -129,9 +134,13 @@ class PreAggregationLoadCache {
|
|
|
129
134
|
async getTablesQuery(preAggregation) {
|
|
130
135
|
const redisKey = this.tablesRedisKey(preAggregation);
|
|
131
136
|
if (!this.tables[redisKey]) {
|
|
132
|
-
|
|
137
|
+
const tables = this.preAggregations.options.skipExternalCacheAndQueue && preAggregation.external ?
|
|
133
138
|
await this.fetchTablesNoCache(preAggregation) :
|
|
134
139
|
await this.tablesFromCache(preAggregation);
|
|
140
|
+
if (tables === undefined) {
|
|
141
|
+
throw new Error('Pre-aggregation tables are undefined.');
|
|
142
|
+
}
|
|
143
|
+
this.tables[redisKey] = tables;
|
|
135
144
|
}
|
|
136
145
|
return this.tables[redisKey];
|
|
137
146
|
}
|
|
@@ -300,7 +309,8 @@ class PreAggregationLoader {
|
|
|
300
309
|
return {
|
|
301
310
|
targetTableName: this.targetTableName(versionEntryByStructureVersion),
|
|
302
311
|
refreshKeyValues: [],
|
|
303
|
-
lastUpdatedAt: versionEntryByStructureVersion.last_updated_at
|
|
312
|
+
lastUpdatedAt: versionEntryByStructureVersion.last_updated_at,
|
|
313
|
+
buildRangeEnd: versionEntryByStructureVersion.build_range_end,
|
|
304
314
|
};
|
|
305
315
|
}
|
|
306
316
|
else {
|
|
@@ -329,7 +339,8 @@ class PreAggregationLoader {
|
|
|
329
339
|
return {
|
|
330
340
|
targetTableName: this.targetTableName(versionEntryByContentVersion),
|
|
331
341
|
refreshKeyValues: [],
|
|
332
|
-
lastUpdatedAt: versionEntryByContentVersion.last_updated_at
|
|
342
|
+
lastUpdatedAt: versionEntryByContentVersion.last_updated_at,
|
|
343
|
+
buildRangeEnd: versionEntryByContentVersion.build_range_end,
|
|
333
344
|
};
|
|
334
345
|
}
|
|
335
346
|
// TODO this check can be redundant due to structure version is already checked in loadPreAggregation()
|
|
@@ -341,7 +352,8 @@ class PreAggregationLoader {
|
|
|
341
352
|
return {
|
|
342
353
|
targetTableName: this.targetTableName(versionEntryByStructureVersion),
|
|
343
354
|
refreshKeyValues: [],
|
|
344
|
-
lastUpdatedAt: versionEntryByStructureVersion.last_updated_at
|
|
355
|
+
lastUpdatedAt: versionEntryByStructureVersion.last_updated_at,
|
|
356
|
+
buildRangeEnd: versionEntryByStructureVersion.build_range_end,
|
|
345
357
|
};
|
|
346
358
|
}
|
|
347
359
|
}
|
|
@@ -370,7 +382,8 @@ class PreAggregationLoader {
|
|
|
370
382
|
return {
|
|
371
383
|
targetTableName: this.targetTableName(lastVersion),
|
|
372
384
|
refreshKeyValues: [],
|
|
373
|
-
lastUpdatedAt: lastVersion.last_updated_at
|
|
385
|
+
lastUpdatedAt: lastVersion.last_updated_at,
|
|
386
|
+
buildRangeEnd: lastVersion.build_range_end,
|
|
374
387
|
};
|
|
375
388
|
};
|
|
376
389
|
if (this.forceBuild) {
|
|
@@ -424,7 +437,8 @@ class PreAggregationLoader {
|
|
|
424
437
|
return {
|
|
425
438
|
targetTableName: this.targetTableName(versionEntry),
|
|
426
439
|
refreshKeyValues: [],
|
|
427
|
-
lastUpdatedAt: versionEntry.last_updated_at
|
|
440
|
+
lastUpdatedAt: versionEntry.last_updated_at,
|
|
441
|
+
buildRangeEnd: versionEntry.build_range_end,
|
|
428
442
|
};
|
|
429
443
|
}
|
|
430
444
|
contentVersion(invalidationKeys) {
|
|
@@ -464,7 +478,7 @@ class PreAggregationLoader {
|
|
|
464
478
|
invalidationKeys,
|
|
465
479
|
forceBuild: this.forceBuild,
|
|
466
480
|
metadata: this.metadata,
|
|
467
|
-
orphanedTimeout: this.orphanedTimeout
|
|
481
|
+
orphanedTimeout: this.orphanedTimeout,
|
|
468
482
|
}, priority,
|
|
469
483
|
// eslint-disable-next-line no-use-before-define
|
|
470
484
|
{ stageQueryKey: PreAggregations.preAggregationQueryCacheKey(this.preAggregation), requestId: this.requestId });
|
|
@@ -478,18 +492,16 @@ class PreAggregationLoader {
|
|
|
478
492
|
// eslint-disable-next-line no-use-before-define
|
|
479
493
|
return PreAggregations.targetTableName(versionEntry);
|
|
480
494
|
}
|
|
481
|
-
refresh(
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
return utils_1.cancelCombinator(saveCancelFn => refreshStrategy.bind(this)(client, newVersionEntry, saveCancelFn, preAggregation, invalidationKeys));
|
|
492
|
-
};
|
|
495
|
+
refresh(newVersionEntry, invalidationKeys, client) {
|
|
496
|
+
let refreshStrategy = this.refreshImplStoreInSourceStrategy;
|
|
497
|
+
if (this.preAggregation.external) {
|
|
498
|
+
const readOnly = this.preAggregation.readOnly ||
|
|
499
|
+
client.config && client.config.readOnly ||
|
|
500
|
+
client.readOnly && (typeof client.readOnly === 'boolean' ? client.readOnly : client.readOnly());
|
|
501
|
+
refreshStrategy = readOnly ?
|
|
502
|
+
this.refreshImplStreamExternalStrategy : this.refreshImplTempTableExternalStrategy;
|
|
503
|
+
}
|
|
504
|
+
return utils_1.cancelCombinator(saveCancelFn => refreshStrategy.bind(this)(client, newVersionEntry, saveCancelFn, invalidationKeys));
|
|
493
505
|
}
|
|
494
506
|
logExecutingSql(payload) {
|
|
495
507
|
this.logger('Executing Load Pre Aggregation SQL', payload);
|
|
@@ -502,9 +514,10 @@ class PreAggregationLoader {
|
|
|
502
514
|
targetTableName,
|
|
503
515
|
requestId: this.requestId,
|
|
504
516
|
newVersionEntry,
|
|
517
|
+
buildRangeEnd: this.preAggregation.buildRangeEnd,
|
|
505
518
|
};
|
|
506
519
|
}
|
|
507
|
-
async refreshImplStoreInSourceStrategy(client, newVersionEntry, saveCancelFn,
|
|
520
|
+
async refreshImplStoreInSourceStrategy(client, newVersionEntry, saveCancelFn, invalidationKeys) {
|
|
508
521
|
const [loadSql, params] = Array.isArray(this.preAggregation.loadSql) ? this.preAggregation.loadSql : [this.preAggregation.loadSql, []];
|
|
509
522
|
const targetTableName = this.targetTableName(newVersionEntry);
|
|
510
523
|
const query = QueryCache_1.QueryCache.replacePreAggregationTableNames(loadSql, this.preAggregationsTablesToTempTables)
|
|
@@ -526,7 +539,7 @@ class PreAggregationLoader {
|
|
|
526
539
|
/**
|
|
527
540
|
* Strategy to copy pre-aggregation from source db (with write permissions) to external data
|
|
528
541
|
*/
|
|
529
|
-
async refreshImplTempTableExternalStrategy(client, newVersionEntry, saveCancelFn,
|
|
542
|
+
async refreshImplTempTableExternalStrategy(client, newVersionEntry, saveCancelFn, invalidationKeys) {
|
|
530
543
|
const [loadSql, params] = Array.isArray(this.preAggregation.loadSql) ? this.preAggregation.loadSql : [this.preAggregation.loadSql, []];
|
|
531
544
|
await client.createSchemaIfNotExists(this.preAggregation.preAggregationsSchema);
|
|
532
545
|
const targetTableName = this.targetTableName(newVersionEntry);
|
|
@@ -536,7 +549,7 @@ class PreAggregationLoader {
|
|
|
536
549
|
this.logExecutingSql(queryOptions);
|
|
537
550
|
await saveCancelFn(client.loadPreAggregationIntoTable(targetTableName, query, params, queryOptions));
|
|
538
551
|
try {
|
|
539
|
-
const tableData = await this.downloadTempExternalPreAggregation(client, newVersionEntry,
|
|
552
|
+
const tableData = await this.downloadTempExternalPreAggregation(client, newVersionEntry, saveCancelFn, queryOptions);
|
|
540
553
|
try {
|
|
541
554
|
await this.uploadExternalPreAggregation(tableData, newVersionEntry, saveCancelFn, queryOptions);
|
|
542
555
|
}
|
|
@@ -555,7 +568,7 @@ class PreAggregationLoader {
|
|
|
555
568
|
/**
|
|
556
569
|
* Strategy to copy pre-aggregation from source db (for read-only permissions) to external data
|
|
557
570
|
*/
|
|
558
|
-
async refreshImplStreamExternalStrategy(client, newVersionEntry, saveCancelFn,
|
|
571
|
+
async refreshImplStreamExternalStrategy(client, newVersionEntry, saveCancelFn, invalidationKeys) {
|
|
559
572
|
const [sql, params] = Array.isArray(this.preAggregation.sql) ? this.preAggregation.sql : [this.preAggregation.sql, []];
|
|
560
573
|
// @todo Deprecated, BaseDriver already implements it, before remove we need to add check for factoryDriver
|
|
561
574
|
if (!client.downloadQueryResults) {
|
|
@@ -600,7 +613,7 @@ class PreAggregationLoader {
|
|
|
600
613
|
/**
|
|
601
614
|
* Create table (for db with write permissions) and extract data via memory/stream/unload
|
|
602
615
|
*/
|
|
603
|
-
async downloadTempExternalPreAggregation(client, newVersionEntry,
|
|
616
|
+
async downloadTempExternalPreAggregation(client, newVersionEntry, saveCancelFn, queryOptions) {
|
|
604
617
|
// @todo Deprecated, BaseDriver already implements it, before remove we need to add check for factoryDriver
|
|
605
618
|
if (!client.downloadTable) {
|
|
606
619
|
throw new Error('Can\'t load external pre-aggregation: source driver doesn\'t support downloadTable()');
|
|
@@ -617,7 +630,7 @@ class PreAggregationLoader {
|
|
|
617
630
|
else if (capabilities.streamImport && client.stream) {
|
|
618
631
|
tableData = await saveCancelFn(client.stream(`SELECT * FROM ${table}`, [], this.getStreamingOptions()));
|
|
619
632
|
if (client.unload) {
|
|
620
|
-
const stream = new StreamObjectsCounter_1.LargeStreamWarning(preAggregation.preAggregationId, (msg) => {
|
|
633
|
+
const stream = new StreamObjectsCounter_1.LargeStreamWarning(this.preAggregation.preAggregationId, (msg) => {
|
|
621
634
|
this.logger('Downloading external pre-aggregation warning', {
|
|
622
635
|
...queryOptions,
|
|
623
636
|
error: msg
|
|
@@ -713,6 +726,7 @@ class PreAggregationPartitionRangeLoader {
|
|
|
713
726
|
// eslint-disable-next-line no-use-before-define
|
|
714
727
|
preAggregations, preAggregation, preAggregationsTablesToTempTables, loadCache, options = {
|
|
715
728
|
maxPartitions: 10000,
|
|
729
|
+
maxSourceRowLimit: 10000,
|
|
716
730
|
}) {
|
|
717
731
|
this.redisPrefix = redisPrefix;
|
|
718
732
|
this.driverFactory = driverFactory;
|
|
@@ -725,6 +739,7 @@ class PreAggregationPartitionRangeLoader {
|
|
|
725
739
|
this.options = options;
|
|
726
740
|
this.waitForRenew = options.waitForRenew;
|
|
727
741
|
this.requestId = options.requestId;
|
|
742
|
+
this.lambdaQuery = options.lambdaQuery;
|
|
728
743
|
this.dataSource = preAggregation.dataSource;
|
|
729
744
|
}
|
|
730
745
|
async loadRangeQuery(rangeQuery, partitionRange) {
|
|
@@ -742,7 +757,7 @@ class PreAggregationPartitionRangeLoader {
|
|
|
742
757
|
dataSource: this.dataSource,
|
|
743
758
|
useInMemory: true,
|
|
744
759
|
external: queryOptions === null || queryOptions === void 0 ? void 0 : queryOptions.external,
|
|
745
|
-
renewalKey: partitionRange ? await this.getInvalidationKeyValues(partitionRange) : null
|
|
760
|
+
renewalKey: partitionRange ? await this.getInvalidationKeyValues(partitionRange) : null,
|
|
746
761
|
});
|
|
747
762
|
}
|
|
748
763
|
getInvalidationKeyValues(range) {
|
|
@@ -785,32 +800,38 @@ class PreAggregationPartitionRangeLoader {
|
|
|
785
800
|
}), {
|
|
786
801
|
...options,
|
|
787
802
|
renewalThreshold: (options === null || options === void 0 ? void 0 : options.incremental) && updateWindowToBoundary < new Date() ?
|
|
788
|
-
// if updateWindowToBoundary passed just moments ago we want to renew it earlier in case
|
|
789
|
-
// and db clock don't match
|
|
803
|
+
// if updateWindowToBoundary passed just moments ago we want to renew it earlier in case
|
|
804
|
+
// of server and db clock don't match
|
|
790
805
|
Math.min(Math.round((new Date().getTime() - updateWindowToBoundary.getTime()) / 1000), options === null || options === void 0 ? void 0 : options.renewalThresholdOutsideUpdateWindow) : options === null || options === void 0 ? void 0 : options.renewalThreshold
|
|
791
806
|
}];
|
|
792
807
|
}
|
|
793
|
-
partitionPreAggregationDescription(range) {
|
|
808
|
+
partitionPreAggregationDescription(range, buildRange) {
|
|
794
809
|
const partitionTableName = PreAggregationPartitionRangeLoader.partitionTableName(this.preAggregation.tableName, this.preAggregation.partitionGranularity, range);
|
|
810
|
+
const [_, buildRangeEnd] = buildRange;
|
|
811
|
+
const loadRange = [...range];
|
|
812
|
+
if (this.preAggregation.unionWithSourceData && buildRangeEnd < range[1]) {
|
|
813
|
+
loadRange[1] = buildRangeEnd;
|
|
814
|
+
}
|
|
795
815
|
return {
|
|
796
816
|
...this.preAggregation,
|
|
797
817
|
tableName: partitionTableName,
|
|
798
818
|
loadSql: this.preAggregation.loadSql &&
|
|
799
|
-
this.replacePartitionSqlAndParams(this.preAggregation.loadSql,
|
|
819
|
+
this.replacePartitionSqlAndParams(this.preAggregation.loadSql, loadRange, partitionTableName),
|
|
800
820
|
sql: this.preAggregation.sql &&
|
|
801
|
-
this.replacePartitionSqlAndParams(this.preAggregation.sql,
|
|
821
|
+
this.replacePartitionSqlAndParams(this.preAggregation.sql, loadRange, partitionTableName),
|
|
802
822
|
invalidateKeyQueries: (this.preAggregation.invalidateKeyQueries || [])
|
|
803
823
|
.map(q => this.replacePartitionSqlAndParams(q, range, partitionTableName)),
|
|
804
824
|
indexesSql: (this.preAggregation.indexesSql || [])
|
|
805
825
|
.map(q => ({ ...q, sql: this.replacePartitionSqlAndParams(q.sql, range, partitionTableName) })),
|
|
806
826
|
previewSql: this.preAggregation.previewSql &&
|
|
807
|
-
this.replacePartitionSqlAndParams(this.preAggregation.previewSql, range, partitionTableName)
|
|
827
|
+
this.replacePartitionSqlAndParams(this.preAggregation.previewSql, range, partitionTableName),
|
|
828
|
+
buildRangeEnd,
|
|
808
829
|
};
|
|
809
830
|
}
|
|
810
831
|
async loadPreAggregations() {
|
|
811
832
|
if (this.preAggregation.partitionGranularity && !this.preAggregation.expandedPartition) {
|
|
812
|
-
const partitionRanges = await this.partitionRanges();
|
|
813
|
-
const partitionLoaders = partitionRanges.map(range => new PreAggregationLoader(this.redisPrefix, this.driverFactory, this.logger, this.queryCache, this.preAggregations, this.partitionPreAggregationDescription(range), this.preAggregationsTablesToTempTables, this.loadCache, this.options));
|
|
833
|
+
const { buildRange, partitionRanges } = await this.partitionRanges();
|
|
834
|
+
const partitionLoaders = partitionRanges.map(range => new PreAggregationLoader(this.redisPrefix, this.driverFactory, this.logger, this.queryCache, this.preAggregations, this.partitionPreAggregationDescription(range, buildRange), this.preAggregationsTablesToTempTables, this.loadCache, this.options));
|
|
814
835
|
const resolveResults = await Promise.all(partitionLoaders.map(l => l.loadPreAggregation(false)));
|
|
815
836
|
const loadResults = resolveResults.filter(res => res !== null);
|
|
816
837
|
if (this.options.externalRefresh && loadResults.length === 0) {
|
|
@@ -819,25 +840,65 @@ class PreAggregationPartitionRangeLoader {
|
|
|
819
840
|
'built yet. Please make sure your refresh worker is configured ' +
|
|
820
841
|
'correctly and running.');
|
|
821
842
|
}
|
|
822
|
-
const allTableTargetNames = loadResults
|
|
823
|
-
|
|
843
|
+
const allTableTargetNames = loadResults.map(targetTableName => targetTableName.targetTableName);
|
|
844
|
+
let lastUpdatedAt = getLastUpdatedAtTimestamp(loadResults.map(r => r.lastUpdatedAt));
|
|
845
|
+
let lambdaTable;
|
|
846
|
+
if (this.lambdaQuery && loadResults.length > 0) {
|
|
847
|
+
const { buildRangeEnd } = loadResults[loadResults.length - 1];
|
|
848
|
+
lambdaTable = await this.downloadLambdaTable(buildRangeEnd);
|
|
849
|
+
allTableTargetNames.push(lambdaTable.name);
|
|
850
|
+
lastUpdatedAt = Date.now();
|
|
851
|
+
}
|
|
824
852
|
const unionTargetTableName = allTableTargetNames
|
|
825
853
|
.map(targetTableName => `SELECT * FROM ${targetTableName}`)
|
|
826
854
|
.join(' UNION ALL ');
|
|
827
855
|
return {
|
|
828
856
|
targetTableName: allTableTargetNames.length === 1 ? allTableTargetNames[0] : `(${unionTargetTableName})`,
|
|
829
857
|
refreshKeyValues: loadResults.map(t => t.refreshKeyValues),
|
|
830
|
-
lastUpdatedAt
|
|
858
|
+
lastUpdatedAt,
|
|
859
|
+
buildRangeEnd: undefined,
|
|
860
|
+
lambdaTable,
|
|
831
861
|
};
|
|
832
862
|
}
|
|
833
863
|
else {
|
|
834
864
|
return new PreAggregationLoader(this.redisPrefix, this.driverFactory, this.logger, this.queryCache, this.preAggregations, this.preAggregation, this.preAggregationsTablesToTempTables, this.loadCache, this.options).loadPreAggregation(true);
|
|
835
865
|
}
|
|
836
866
|
}
|
|
867
|
+
/**
|
|
868
|
+
* Downloads the lambda table from the source DB.
|
|
869
|
+
*/
|
|
870
|
+
async downloadLambdaTable(fromDate) {
|
|
871
|
+
const { sqlAndParams, cacheKeyQueries } = this.lambdaQuery;
|
|
872
|
+
const [query, params] = sqlAndParams;
|
|
873
|
+
const values = params.map((p) => {
|
|
874
|
+
if (p === shared_1.FROM_PARTITION_RANGE) {
|
|
875
|
+
return fromDate;
|
|
876
|
+
}
|
|
877
|
+
if (p === shared_1.MAX_SOURCE_ROW_LIMIT) {
|
|
878
|
+
return this.options.maxSourceRowLimit;
|
|
879
|
+
}
|
|
880
|
+
return p;
|
|
881
|
+
});
|
|
882
|
+
const { data } = await this.queryCache.renewQuery(query, values, cacheKeyQueries, 60 * 60, [query, values], undefined, {
|
|
883
|
+
requestId: this.requestId,
|
|
884
|
+
skipRefreshKeyWaitForRenew: false,
|
|
885
|
+
dataSource: this.dataSource,
|
|
886
|
+
external: false,
|
|
887
|
+
useCsvQuery: true,
|
|
888
|
+
});
|
|
889
|
+
if (data.rowCount === this.options.maxSourceRowLimit) {
|
|
890
|
+
throw new Error(`The maximum number of source rows ${this.options.maxSourceRowLimit} was reached for ${this.preAggregation.preAggregationId}`);
|
|
891
|
+
}
|
|
892
|
+
return {
|
|
893
|
+
name: `${exports.LAMBDA_TABLE_PREFIX}_${this.preAggregation.tableName.replace('.', '_')}`,
|
|
894
|
+
columns: data.types,
|
|
895
|
+
csvRows: data.csvRows,
|
|
896
|
+
};
|
|
897
|
+
}
|
|
837
898
|
async partitionPreAggregations() {
|
|
838
899
|
if (this.preAggregation.partitionGranularity && !this.preAggregation.expandedPartition) {
|
|
839
|
-
const partitionRanges = await this.partitionRanges();
|
|
840
|
-
return partitionRanges.map(range => this.partitionPreAggregationDescription(range));
|
|
900
|
+
const { buildRange, partitionRanges } = await this.partitionRanges();
|
|
901
|
+
return partitionRanges.map(range => this.partitionPreAggregationDescription(range, buildRange));
|
|
841
902
|
}
|
|
842
903
|
else {
|
|
843
904
|
return [this.preAggregation];
|
|
@@ -846,7 +907,7 @@ class PreAggregationPartitionRangeLoader {
|
|
|
846
907
|
async partitionRanges() {
|
|
847
908
|
const buildRange = await this.loadBuildRange();
|
|
848
909
|
if (!buildRange[0] || !buildRange[1]) {
|
|
849
|
-
return [];
|
|
910
|
+
return { buildRange, partitionRanges: [] };
|
|
850
911
|
}
|
|
851
912
|
let dateRange = PreAggregationPartitionRangeLoader.intersectDateRanges(buildRange, this.preAggregation.matchedTimeDimensionDateRange);
|
|
852
913
|
if (!dateRange) {
|
|
@@ -854,11 +915,11 @@ class PreAggregationPartitionRangeLoader {
|
|
|
854
915
|
// use last partition so outer query can receive expected table structure.
|
|
855
916
|
dateRange = [buildRange[1], buildRange[1]];
|
|
856
917
|
}
|
|
857
|
-
const
|
|
858
|
-
if (
|
|
918
|
+
const partitionRanges = PreAggregationPartitionRangeLoader.timeSeries(this.preAggregation.partitionGranularity, dateRange);
|
|
919
|
+
if (partitionRanges.length > this.options.maxPartitions) {
|
|
859
920
|
throw new Error(`The maximum number of partitions (${this.options.maxPartitions}) was reached for the pre-aggregation`);
|
|
860
921
|
}
|
|
861
|
-
return
|
|
922
|
+
return { buildRange: dateRange, partitionRanges };
|
|
862
923
|
}
|
|
863
924
|
async loadBuildRange() {
|
|
864
925
|
const { preAggregationStartEndQueries } = this.preAggregation;
|
|
@@ -870,9 +931,12 @@ class PreAggregationPartitionRangeLoader {
|
|
|
870
931
|
const [rangeStart, rangeEnd] = await Promise.all(preAggregationStartEndQueries.map(async (rangeQuery, i) => PreAggregationPartitionRangeLoader.extractDate(await this.loadRangeQuery(rangeQuery, i === 0 ? wholeSeriesRanges[0] : wholeSeriesRanges[wholeSeriesRanges.length - 1]))));
|
|
871
932
|
return this.orNowIfEmpty([rangeStart, rangeEnd]);
|
|
872
933
|
}
|
|
934
|
+
now() {
|
|
935
|
+
return shared_1.utcToLocalTimeZone(this.preAggregation.timezone, 'YYYY-MM-DDTHH:mm:ss.SSS', new Date().toJSON().substring(0, 23));
|
|
936
|
+
}
|
|
873
937
|
orNowIfEmpty(dateRange) {
|
|
874
938
|
if (!dateRange[0] && !dateRange[1]) {
|
|
875
|
-
const now =
|
|
939
|
+
const now = this.now();
|
|
876
940
|
return [now, now];
|
|
877
941
|
}
|
|
878
942
|
if (!dateRange[0]) {
|
|
@@ -983,17 +1047,21 @@ class PreAggregations {
|
|
|
983
1047
|
};
|
|
984
1048
|
let queryParamsReplacement = null;
|
|
985
1049
|
const preAggregationsTablesToTempTablesPromise = preAggregations.map((p, i) => (preAggregationsTablesToTempTables) => {
|
|
1050
|
+
var _a;
|
|
986
1051
|
const loader = new PreAggregationPartitionRangeLoader(this.redisPrefix, () => this.driverFactory(p.dataSource || 'default'), this.logger, this.queryCache, this, p, preAggregationsTablesToTempTables, getLoadCacheByDataSource(p.dataSource, p.preAggregationsSchema), {
|
|
987
1052
|
maxPartitions: this.options.maxPartitions,
|
|
1053
|
+
maxSourceRowLimit: this.options.maxSourceRowLimit,
|
|
988
1054
|
waitForRenew: queryBody.renewQuery,
|
|
989
1055
|
// TODO workaround to avoid continuous waiting on building pre-aggregation dependencies
|
|
990
1056
|
forceBuild: i === preAggregations.length - 1 ? queryBody.forceBuildPreAggregations : false,
|
|
991
1057
|
requestId: queryBody.requestId,
|
|
992
1058
|
metadata: queryBody.metadata,
|
|
993
1059
|
orphanedTimeout: queryBody.orphanedTimeout,
|
|
1060
|
+
lambdaQuery: ((_a = queryBody.lambdaQueries) !== null && _a !== void 0 ? _a : {})[p.preAggregationId],
|
|
994
1061
|
externalRefresh: this.externalRefresh
|
|
995
1062
|
});
|
|
996
|
-
const preAggregationPromise =
|
|
1063
|
+
const preAggregationPromise = async () => {
|
|
1064
|
+
const loadResult = await loader.loadPreAggregations();
|
|
997
1065
|
const usedPreAggregation = {
|
|
998
1066
|
...loadResult,
|
|
999
1067
|
type: p.type,
|
|
@@ -1003,7 +1071,7 @@ class PreAggregations {
|
|
|
1003
1071
|
queryParamsReplacement = await loader.replaceQueryBuildRangeParams(queryBody.values);
|
|
1004
1072
|
}
|
|
1005
1073
|
return [p.tableName, usedPreAggregation];
|
|
1006
|
-
}
|
|
1074
|
+
};
|
|
1007
1075
|
return preAggregationPromise().then(res => preAggregationsTablesToTempTables.concat([res]));
|
|
1008
1076
|
}).reduce((promise, fn) => promise.then(fn), Promise.resolve([]));
|
|
1009
1077
|
return preAggregationsTablesToTempTablesPromise.then(preAggregationsTablesToTempTables => ({
|
|
@@ -1039,6 +1107,7 @@ class PreAggregations {
|
|
|
1039
1107
|
const expandedPreAggregations = await Promise.all(preAggregations.map(p => {
|
|
1040
1108
|
const loader = new PreAggregationPartitionRangeLoader(this.redisPrefix, () => this.driverFactory(p.dataSource || 'default'), this.logger, this.queryCache, this, p, [], getLoadCacheByDataSource(p.dataSource, p.preAggregationsSchema), {
|
|
1041
1109
|
maxPartitions: this.options.maxPartitions,
|
|
1110
|
+
maxSourceRowLimit: this.options.maxSourceRowLimit,
|
|
1042
1111
|
waitForRenew: queryBody.renewQuery,
|
|
1043
1112
|
requestId: queryBody.requestId,
|
|
1044
1113
|
externalRefresh: this.externalRefresh,
|
|
@@ -1057,9 +1126,9 @@ class PreAggregations {
|
|
|
1057
1126
|
async getQueue(dataSource = 'default') {
|
|
1058
1127
|
if (!this.queue[dataSource]) {
|
|
1059
1128
|
this.queue[dataSource] = QueryCache_1.QueryCache.createQueue(`SQL_PRE_AGGREGATIONS_${this.redisPrefix}_${dataSource}`, () => this.driverFactory(dataSource), (client, q) => {
|
|
1060
|
-
const { preAggregation, preAggregationsTablesToTempTables, newVersionEntry, requestId, invalidationKeys } = q;
|
|
1061
|
-
const loader = new PreAggregationLoader(this.redisPrefix, () => this.driverFactory(dataSource), this.logger, this.queryCache, this, preAggregation, preAggregationsTablesToTempTables, new PreAggregationLoadCache(this.redisPrefix, () => this.driverFactory(dataSource), this.queryCache, this, { requestId, dataSource }), { requestId, externalRefresh: this.externalRefresh });
|
|
1062
|
-
return loader.refresh(
|
|
1129
|
+
const { preAggregation, preAggregationsTablesToTempTables, newVersionEntry, requestId, invalidationKeys, buildRangeEnd } = q;
|
|
1130
|
+
const loader = new PreAggregationLoader(this.redisPrefix, () => this.driverFactory(dataSource), this.logger, this.queryCache, this, preAggregation, preAggregationsTablesToTempTables, new PreAggregationLoadCache(this.redisPrefix, () => this.driverFactory(dataSource), this.queryCache, this, { requestId, dataSource }), { requestId, externalRefresh: this.externalRefresh, buildRangeEnd });
|
|
1131
|
+
return loader.refresh(newVersionEntry, invalidationKeys, client);
|
|
1063
1132
|
}, {
|
|
1064
1133
|
concurrency: 1,
|
|
1065
1134
|
logger: this.logger,
|