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