@finos/legend-data-cube 0.1.1 → 0.1.3

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 (58) hide show
  1. package/lib/__lib__/DataCubeSetting.d.ts +1 -0
  2. package/lib/__lib__/DataCubeSetting.d.ts.map +1 -1
  3. package/lib/__lib__/DataCubeSetting.js +1 -0
  4. package/lib/__lib__/DataCubeSetting.js.map +1 -1
  5. package/lib/components/DataCubeStatusBar.d.ts.map +1 -1
  6. package/lib/components/DataCubeStatusBar.js +10 -3
  7. package/lib/components/DataCubeStatusBar.js.map +1 -1
  8. package/lib/components/DataCubeTitleBar.js +1 -1
  9. package/lib/components/DataCubeTitleBar.js.map +1 -1
  10. package/lib/components/core/DataCubeAlert.js +1 -1
  11. package/lib/components/core/DataCubeAlert.js.map +1 -1
  12. package/lib/components/view/grid/DataCubeGrid.d.ts.map +1 -1
  13. package/lib/components/view/grid/DataCubeGrid.js +10 -4
  14. package/lib/components/view/grid/DataCubeGrid.js.map +1 -1
  15. package/lib/index.css +1 -1
  16. package/lib/package.json +1 -1
  17. package/lib/stores/core/DataCubeEngine.d.ts +5 -1
  18. package/lib/stores/core/DataCubeEngine.d.ts.map +1 -1
  19. package/lib/stores/core/DataCubeEngine.js +1 -1
  20. package/lib/stores/core/DataCubeEngine.js.map +1 -1
  21. package/lib/stores/services/DataCubeSettingService.d.ts.map +1 -1
  22. package/lib/stores/services/DataCubeSettingService.js +8 -0
  23. package/lib/stores/services/DataCubeSettingService.js.map +1 -1
  24. package/lib/stores/services/DataCubeTaskService.d.ts +4 -4
  25. package/lib/stores/services/DataCubeTaskService.d.ts.map +1 -1
  26. package/lib/stores/services/DataCubeTaskService.js +7 -7
  27. package/lib/stores/services/DataCubeTaskService.js.map +1 -1
  28. package/lib/stores/view/DataCubeViewState.d.ts.map +1 -1
  29. package/lib/stores/view/DataCubeViewState.js +11 -4
  30. package/lib/stores/view/DataCubeViewState.js.map +1 -1
  31. package/lib/stores/view/editor/DataCubeEditorState.js +1 -1
  32. package/lib/stores/view/editor/DataCubeEditorState.js.map +1 -1
  33. package/lib/stores/view/extend/DataCubeExtendManagerState.js +2 -2
  34. package/lib/stores/view/extend/DataCubeExtendManagerState.js.map +1 -1
  35. package/lib/stores/view/grid/DataCubeGridClientEngine.d.ts.map +1 -1
  36. package/lib/stores/view/grid/DataCubeGridClientEngine.js +108 -114
  37. package/lib/stores/view/grid/DataCubeGridClientEngine.js.map +1 -1
  38. package/lib/stores/view/grid/DataCubeGridConfigurationBuilder.d.ts.map +1 -1
  39. package/lib/stores/view/grid/DataCubeGridConfigurationBuilder.js +3 -3
  40. package/lib/stores/view/grid/DataCubeGridConfigurationBuilder.js.map +1 -1
  41. package/lib/stores/view/grid/DataCubeGridState.d.ts.map +1 -1
  42. package/lib/stores/view/grid/DataCubeGridState.js +59 -14
  43. package/lib/stores/view/grid/DataCubeGridState.js.map +1 -1
  44. package/package.json +5 -5
  45. package/src/__lib__/DataCubeSetting.ts +1 -0
  46. package/src/components/DataCubeStatusBar.tsx +18 -3
  47. package/src/components/DataCubeTitleBar.tsx +3 -3
  48. package/src/components/core/DataCubeAlert.tsx +1 -1
  49. package/src/components/view/grid/DataCubeGrid.tsx +15 -2
  50. package/src/stores/core/DataCubeEngine.tsx +6 -0
  51. package/src/stores/services/DataCubeSettingService.tsx +8 -0
  52. package/src/stores/services/DataCubeTaskService.ts +7 -7
  53. package/src/stores/view/DataCubeViewState.ts +15 -4
  54. package/src/stores/view/editor/DataCubeEditorState.tsx +1 -1
  55. package/src/stores/view/extend/DataCubeExtendManagerState.tsx +2 -2
  56. package/src/stores/view/grid/DataCubeGridClientEngine.ts +154 -170
  57. package/src/stores/view/grid/DataCubeGridConfigurationBuilder.tsx +6 -7
  58. package/src/stores/view/grid/DataCubeGridState.ts +83 -18
@@ -31,11 +31,7 @@ import {
31
31
  pruneObject,
32
32
  } from '@finos/legend-shared';
33
33
  import { buildExecutableQuery } from '../../core/DataCubeQueryBuilder.js';
34
- import {
35
- PureClientVersion,
36
- type TabularDataSet,
37
- V1_Lambda,
38
- } from '@finos/legend-graph';
34
+ import { PureClientVersion, type TabularDataSet } from '@finos/legend-graph';
39
35
  import { makeObservable, observable, runInAction } from 'mobx';
40
36
  import type {
41
37
  DataCubeConfiguration,
@@ -46,7 +42,6 @@ import { _findCol, _sortByColName } from '../../core/model/DataCubeColumn.js';
46
42
  import { isPivotResultColumnName } from '../../core/DataCubeQueryEngine.js';
47
43
  import { buildQuerySnapshot } from './DataCubeGridQuerySnapshotBuilder.js';
48
44
  import { AlertType } from '../../services/DataCubeAlertService.js';
49
- import { sum } from 'mathjs';
50
45
  import type { DataCubeViewState } from '../DataCubeViewState.js';
51
46
  import {
52
47
  _aggCountCol,
@@ -55,6 +50,8 @@ import {
55
50
  import { _colSpecArrayParam } from '../../core/DataCubeQuerySnapshotBuilderUtils.js';
56
51
  import { DataCubeSettingKey } from '../../../__lib__/DataCubeSetting.js';
57
52
  import { DEFAULT_ALERT_WINDOW_CONFIG } from '../../services/DataCubeLayoutService.js';
53
+ import type { DataCubeExecutionResult } from '../../core/DataCubeEngine.js';
54
+ import { _lambda } from '../../core/DataCubeQueryBuilderUtils.js';
58
55
 
59
56
  type DataCubeGridClientCellValue = string | number | boolean | null | undefined;
60
57
  type DataCubeGridClientRowData = {
@@ -231,19 +228,17 @@ function buildRowData(
231
228
  ? value
232
229
  : INTERNAL__GRID_CLIENT_MISSING_VALUE;
233
230
  if (snapshot.data.pivot && snapshot.data.groupBy) {
234
- row[INTERNAL__GRID_CLIENT_ROW_GROUPING_COUNT_AGG_COLUMN_ID] = Number(
235
- sum(
236
- result.columns
237
- .filter(
238
- (col) =>
239
- isPivotResultColumnName(col) &&
240
- col.endsWith(
241
- INTERNAL__GRID_CLIENT_ROW_GROUPING_COUNT_AGG_COLUMN_ID,
242
- ),
243
- )
244
- .map((col) => (row[col] as number | undefined) ?? 0),
245
- ).toString(),
246
- );
231
+ row[INTERNAL__GRID_CLIENT_ROW_GROUPING_COUNT_AGG_COLUMN_ID] =
232
+ result.columns
233
+ .filter(
234
+ (col) =>
235
+ isPivotResultColumnName(col) &&
236
+ col.endsWith(
237
+ INTERNAL__GRID_CLIENT_ROW_GROUPING_COUNT_AGG_COLUMN_ID,
238
+ ),
239
+ )
240
+ .map((col) => (row[col] as number | undefined) ?? 0)
241
+ .reduce((a, b) => a + b, 0);
247
242
  }
248
243
  });
249
244
  return row;
@@ -275,18 +270,20 @@ async function getCastColumns(
275
270
  },
276
271
  });
277
272
 
278
- const lambda = new V1_Lambda();
279
- lambda.body.push(query);
280
- const result = await view.engine.executeQuery(lambda, view.source, {
281
- debug: view.settingService.getBooleanValue(
282
- DataCubeSettingKey.DEBUGGER__ENABLE_DEBUG_MODE,
283
- ),
284
- clientVersion: view.settingService.getBooleanValue(
285
- DataCubeSettingKey.DEBUGGER__USE_DEV_CLIENT_PROTOCOL_VERSION,
286
- )
287
- ? PureClientVersion.VX_X_X
288
- : undefined,
289
- });
273
+ const result = await view.engine.executeQuery(
274
+ _lambda([], [query]),
275
+ view.source,
276
+ {
277
+ debug: view.settingService.getBooleanValue(
278
+ DataCubeSettingKey.DEBUGGER__ENABLE_DEBUG_MODE,
279
+ ),
280
+ clientVersion: view.settingService.getBooleanValue(
281
+ DataCubeSettingKey.DEBUGGER__USE_DEV_CLIENT_PROTOCOL_VERSION,
282
+ )
283
+ ? PureClientVersion.VX_X_X
284
+ : undefined,
285
+ },
286
+ );
290
287
 
291
288
  return result.result.builder.columns.map((column) => ({
292
289
  name: column.name,
@@ -324,7 +321,7 @@ export class DataCubeGridClientServerSideDataSource
324
321
  }
325
322
 
326
323
  async fetchRows(params: IServerSideGetRowsParams<unknown, unknown>) {
327
- const task = this._view.taskService.newTask('Fetching data');
324
+ const task = this._view.taskService.newTask('Fetching data...');
328
325
 
329
326
  // ------------------------------ SNAPSHOT ------------------------------
330
327
 
@@ -394,29 +391,18 @@ export class DataCubeGridClientServerSideDataSource
394
391
 
395
392
  // ------------------------------ DATA ------------------------------
396
393
 
394
+ const executableQuery = buildGridDataFetchExecutableQuery(
395
+ request,
396
+ newSnapshot,
397
+ this._view.source,
398
+ this._view.engine,
399
+ this._grid.isPaginationEnabled,
400
+ );
401
+ let result: DataCubeExecutionResult;
402
+
397
403
  try {
398
- const executableQuery = buildGridDataFetchExecutableQuery(
399
- request,
400
- newSnapshot,
401
- this._view.source,
402
- this._view.engine,
403
- this._grid.isPaginationEnabled,
404
- );
405
- const lambda = new V1_Lambda();
406
- lambda.body.push(executableQuery);
407
- if (
408
- this._view.settingService.getBooleanValue(
409
- DataCubeSettingKey.DEBUGGER__ENABLE_DEBUG_MODE,
410
- )
411
- ) {
412
- this._view.engine.debugProcess(
413
- `Execution Plan`,
414
- ['Query', lambda],
415
- ['Config', `pagination=${this._grid.isPaginationEnabled}`],
416
- );
417
- }
418
- const result = await this._view.engine.executeQuery(
419
- lambda,
404
+ result = await this._view.engine.executeQuery(
405
+ _lambda([], [executableQuery]),
420
406
  this._view.source,
421
407
  {
422
408
  debug: this._view.settingService.getBooleanValue(
@@ -429,136 +415,134 @@ export class DataCubeGridClientServerSideDataSource
429
415
  : undefined,
430
416
  },
431
417
  );
432
- const rowData = buildRowData(result.result.result, newSnapshot);
433
- if (
434
- this._view.settingService.getBooleanValue(
435
- DataCubeSettingKey.DEBUGGER__ENABLE_DEBUG_MODE,
436
- )
437
- ) {
438
- this._view.engine.debugProcess(
439
- `Execution`,
440
- ['Query', result.executedQuery],
441
- [
442
- 'Stats',
443
- `${rowData.length} rows, ${result.result.result.columns.length} columns`,
444
- ],
445
- ['SQL', result.executedSQL],
446
- ['SQL Execution Time', result.executionTime],
447
- );
448
- }
418
+ } catch (error) {
419
+ assertErrorThrown(error);
420
+ this._view.alertService.alertError(error, {
421
+ message: `Data Fetch Failure: ${error.message}`,
422
+ });
423
+ this._view.taskService.endTask(task);
424
+ params.fail();
425
+ return;
426
+ }
449
427
 
450
- if (this._grid.isPaginationEnabled) {
451
- params.success({ rowData });
452
- // only update row count when loading the top-level drilldown data
453
- if (isTopLevelRequest) {
454
- runInAction(() => {
455
- this.rowCount = (request.startRow ?? 0) + rowData.length;
456
- });
457
- }
428
+ const rowData = buildRowData(result.result.result, newSnapshot);
429
+ if (
430
+ this._view.settingService.getBooleanValue(
431
+ DataCubeSettingKey.DEBUGGER__ENABLE_DEBUG_MODE,
432
+ )
433
+ ) {
434
+ this._view.engine.debugProcess(
435
+ `Execution`,
436
+ ['Query', result.executedQuery],
437
+ [
438
+ 'Stats',
439
+ `${rowData.length} rows, ${result.result.result.columns.length} columns`,
440
+ ],
441
+ ['SQL', result.executedSQL],
442
+ ['SQL Execution Time', result.executionTime],
443
+ );
444
+ }
458
445
 
459
- // toggle no-rows overlay
446
+ if (this._grid.isPaginationEnabled) {
447
+ params.success({ rowData });
448
+ // only update row count when loading the top-level drilldown data
449
+ if (isTopLevelRequest) {
450
+ runInAction(() => {
451
+ this.rowCount = (request.startRow ?? 0) + rowData.length;
452
+ });
453
+ }
454
+
455
+ // toggle no-rows overlay
456
+ if (isTopLevelRequest && request.startRow === 0 && rowData.length === 0) {
457
+ this._grid.client.showNoRowsOverlay();
458
+ } else {
459
+ this._grid.client.hideOverlay();
460
+ }
461
+ } else {
462
+ // NOTE: When pagination is disabled and the user currently scrolls to somewhere in the grid, as data is fetched
463
+ // and the operation does not force a scroll top (for example, grouping will always force scrolling to the
464
+ // top, while sorting will leave scroll position as is), the grid ends up showing the wrong data because
465
+ // the data being displayed does not take into account the scroll position, but by the start and end row
466
+ // which stay constant as pagination is disabled.
467
+ //
468
+ // In order to handle this, when pagination is disabled, we tune the start and end row by setting the cache block size
469
+ // to a high-enough value (100k-1m). However, ag-grid use cache block size to pre-allocate memory for the rows,
470
+ // which means we must cap/tune this value reasonably to prevent the app from crashing.
471
+ //
472
+ // When there are just too many rows (exceeding the maximum cache block size), we will fallback to a slightly less ideal
473
+ // behavior by forcing a scroll top for every data fetch and also reset the cache block size to the default value to save memory
474
+ if (rowData.length > INTERNAL__GRID_CLIENT_MAX_CACHE_BLOCK_SIZE) {
460
475
  if (
461
- isTopLevelRequest &&
462
- request.startRow === 0 &&
463
- rowData.length === 0
476
+ !this._view.settingService.getBooleanValue(
477
+ DataCubeSettingKey.GRID_CLIENT__SUPPRESS_LARGE_DATASET_WARNING,
478
+ )
464
479
  ) {
465
- this._grid.client.showNoRowsOverlay();
466
- } else {
467
- this._grid.client.hideOverlay();
468
- }
469
- } else {
470
- // NOTE: When pagination is disabled and the user currently scrolls to somewhere in the grid, as data is fetched
471
- // and the operation does not force a scroll top (for example, grouping will always force scrolling to the
472
- // top, while sorting will leave scroll position as is), the grid ends up showing the wrong data because
473
- // the data being displayed does not take into account the scroll position, but by the start and end row
474
- // which stay constant as pagination is disabled.
475
- //
476
- // In order to handle this, when pagination is disabled, we tune the start and end row by setting the cache block size
477
- // to a high-enough value (100k-1m). However, ag-grid use cache block size to pre-allocate memory for the rows,
478
- // which means we must cap/tune this value reasonably to prevent the app from crashing.
479
- //
480
- // When there are just too many rows (exceeding the maximum cache block size), we will fallback to a slightly less ideal
481
- // behavior by forcing a scroll top for every data fetch and also reset the cache block size to the default value to save memory
482
- if (rowData.length > INTERNAL__GRID_CLIENT_MAX_CACHE_BLOCK_SIZE) {
483
- if (
484
- !this._view.settingService.getBooleanValue(
485
- DataCubeSettingKey.GRID_CLIENT__SUPPRESS_LARGE_DATASET_WARNING,
486
- )
487
- ) {
488
- this._view.alertService.alert({
489
- message: `Large dataset (>${INTERNAL__GRID_CLIENT_MAX_CACHE_BLOCK_SIZE} rows) detected!`,
490
- text: `Overall app performance can be impacted by large dataset due to longer query execution time and increased memory usage. At its limit, the engine can crash!\nTo boost performance, consider enabling pagination while working with large dataset.`,
491
- type: AlertType.WARNING,
492
- actions: [
493
- {
494
- label: 'Enable Pagination',
495
- handler: () => {
496
- this._grid.setPaginationEnabled(true);
497
- },
480
+ this._view.alertService.alert({
481
+ message: `Large dataset (>${INTERNAL__GRID_CLIENT_MAX_CACHE_BLOCK_SIZE} rows) detected!`,
482
+ text: `Overall app performance can be impacted by large dataset due to longer query execution time and increased memory usage. At its limit, the engine can crash!\nTo boost performance, consider enabling pagination while working with large dataset.`,
483
+ type: AlertType.WARNING,
484
+ actions: [
485
+ {
486
+ label: 'Enable Pagination',
487
+ handler: () => {
488
+ this._grid.setPaginationEnabled(true);
498
489
  },
499
- {
500
- label: 'Dismiss Warning',
501
- handler: () => {
502
- this._view.settingService.updateValue(
503
- this._view.dataCube.api,
504
- DataCubeSettingKey.GRID_CLIENT__SUPPRESS_LARGE_DATASET_WARNING,
505
- true,
506
- );
507
- },
490
+ },
491
+ {
492
+ label: 'Dismiss Warning',
493
+ handler: () => {
494
+ this._view.settingService.updateValue(
495
+ this._view.dataCube.api,
496
+ DataCubeSettingKey.GRID_CLIENT__SUPPRESS_LARGE_DATASET_WARNING,
497
+ true,
498
+ );
508
499
  },
509
- ],
510
- windowConfig: {
511
- ...DEFAULT_ALERT_WINDOW_CONFIG,
512
- width: 600,
513
- minWidth: 300,
514
- minHeight: 150,
515
500
  },
516
- });
517
- }
518
-
519
- // NOTE: when drilldown occurs, we will scroll top until the drilldown row is reached
520
- params.api.ensureIndexVisible(params.parentNode.rowIndex ?? 0, 'top');
521
- }
522
-
523
- params.success({
524
- rowData,
525
- // Setting row count to disable infinite-scrolling when pagination is disabled
526
- // See https://www.ag-grid.com/react-data-grid/infinite-scrolling/#setting-last-row-index
527
- rowCount: rowData.length,
528
- });
529
-
530
- // only update row count when loading the top-level drilldown data
531
- if (isTopLevelRequest) {
532
- runInAction(() => {
533
- this.rowCount = rowData.length;
501
+ ],
502
+ windowConfig: {
503
+ ...DEFAULT_ALERT_WINDOW_CONFIG,
504
+ width: 600,
505
+ minWidth: 300,
506
+ minHeight: 150,
507
+ },
534
508
  });
535
509
  }
536
510
 
537
- // toggle no-rows overlay
538
- if (isTopLevelRequest && rowData.length === 0) {
539
- this._grid.client.showNoRowsOverlay();
540
- } else {
541
- this._grid.client.hideOverlay();
542
- }
511
+ // NOTE: when drilldown occurs, we will scroll top until the drilldown row is reached
512
+ params.api.ensureIndexVisible(params.parentNode.rowIndex ?? 0, 'top');
543
513
  }
544
514
 
545
- // Resize columns to fit content on all actions (drilldown, changing queries, fetching new page, etc.)
546
- // NOTE: we might want to restrict this to only happen on certain actions
547
- //
548
- // `setTimeout()` is need to ensure this runs after the grid has been updated with the new data
549
- // since ag-grid does not provide an event hook for this action for server-side row model.
550
- setTimeout(() => {
551
- this._grid.client.autoSizeAllColumns();
552
- }, 0);
553
- } catch (error) {
554
- assertErrorThrown(error);
555
- this._view.alertService.alertError(error, {
556
- message: `Data Fetch Failure: ${error.message}`,
515
+ params.success({
516
+ rowData,
517
+ // Setting row count to disable infinite-scrolling when pagination is disabled
518
+ // See https://www.ag-grid.com/react-data-grid/infinite-scrolling/#setting-last-row-index
519
+ rowCount: rowData.length,
557
520
  });
558
- params.fail();
559
- } finally {
560
- this._view.taskService.endTask(task);
521
+
522
+ // only update row count when loading the top-level drilldown data
523
+ if (isTopLevelRequest) {
524
+ runInAction(() => {
525
+ this.rowCount = rowData.length;
526
+ });
527
+ }
528
+
529
+ // toggle no-rows overlay
530
+ if (isTopLevelRequest && rowData.length === 0) {
531
+ this._grid.client.showNoRowsOverlay();
532
+ } else {
533
+ this._grid.client.hideOverlay();
534
+ }
561
535
  }
536
+
537
+ // Resize columns to fit content on all actions (drilldown, changing queries, fetching new page, etc.)
538
+ // NOTE: we might want to restrict this to only happen on certain actions
539
+ //
540
+ // `setTimeout()` is need to ensure this runs after the grid has been updated with the new data
541
+ // since ag-grid does not provide an event hook for this action for server-side row model.
542
+ setTimeout(() => {
543
+ this._grid.client.autoSizeAllColumns();
544
+ }, 0);
545
+ this._view.taskService.endTask(task);
562
546
  }
563
547
 
564
548
  getRows(params: IServerSideGetRowsParams<unknown, unknown>) {
@@ -62,7 +62,6 @@ import {
62
62
  } from './DataCubeGridClientEngine.js';
63
63
  import {
64
64
  at,
65
- last,
66
65
  getQueryParameters,
67
66
  getQueryParameterValue,
68
67
  isNonNullable,
@@ -758,15 +757,15 @@ function generateDefinitionForPivotResultColumns(
758
757
 
759
758
  // sort the leaf level columns based on the order of selected/configuration columns
760
759
  (currentCollection as ColDef[]).sort((a, b) => {
761
- const colAName = last(
762
- a.colId?.split(PIVOT_COLUMN_NAME_VALUE_SEPARATOR) ?? [],
763
- );
760
+ const colAName = (
761
+ a.colId?.split(PIVOT_COLUMN_NAME_VALUE_SEPARATOR) ?? []
762
+ ).at(-1);
764
763
  const colAConf = colAName
765
764
  ? _findCol(configuration.columns, colAName)
766
765
  : undefined;
767
- const colBName = last(
768
- b.colId?.split(PIVOT_COLUMN_NAME_VALUE_SEPARATOR) ?? [],
769
- );
766
+ const colBName = (
767
+ b.colId?.split(PIVOT_COLUMN_NAME_VALUE_SEPARATOR) ?? []
768
+ ).at(-1);
770
769
  const colBConf = colBName
771
770
  ? _findCol(configuration.columns, colBName)
772
771
  : undefined;
@@ -38,6 +38,8 @@ import { DataCubeConfiguration } from '../../core/model/DataCubeConfiguration.js
38
38
  import { DataCubeGridControllerState } from './DataCubeGridControllerState.js';
39
39
  import { DataCubeGridClientExportEngine } from './DataCubeGridClientExportEngine.js';
40
40
  import { DataCubeSettingKey } from '../../../__lib__/DataCubeSetting.js';
41
+ import { DEFAULT_ALERT_WINDOW_CONFIG } from '../../services/DataCubeLayoutService.js';
42
+ import { AlertType } from '../../services/DataCubeAlertService.js';
41
43
 
42
44
  /**
43
45
  * This query editor state is responsible for syncing the internal state of ag-grid
@@ -125,32 +127,95 @@ export class DataCubeGridState extends DataCubeQuerySnapshotController {
125
127
  }
126
128
 
127
129
  async setCachingEnabled(val: boolean) {
128
- const currentVal = this.isCachingEnabled;
129
- if (val === currentVal) {
130
+ if (val === this.isCachingEnabled) {
130
131
  return;
131
132
  }
132
133
 
133
- runInAction(() => {
134
- this.isCachingEnabled = val;
135
- });
134
+ // disable caching
135
+ if (val === false) {
136
+ await this._view.disposeCache();
137
+
138
+ runInAction(() => {
139
+ this.isCachingEnabled = val;
136
140
 
137
- if (val) {
141
+ // hard reset the grid, this will force the grid to fetch data again
142
+ this.clientDataSource = new DataCubeGridClientServerSideDataSource(
143
+ this,
144
+ this._view,
145
+ );
146
+ });
147
+
148
+ return;
149
+ }
150
+
151
+ // enable caching
152
+ const run = async () => {
138
153
  await this._view.initializeCache();
139
- if (this._view.processCacheState.hasFailed) {
140
- this.isCachingEnabled = currentVal;
141
- return;
154
+
155
+ // only update value if cache processing succeeds
156
+ if (this._view.processCacheState.hasSucceeded) {
157
+ runInAction(() => {
158
+ this.isCachingEnabled = val;
159
+
160
+ // hard reset the grid, this will force the grid to fetch data again
161
+ this.clientDataSource = new DataCubeGridClientServerSideDataSource(
162
+ this,
163
+ this._view,
164
+ );
165
+ });
142
166
  }
167
+ };
168
+
169
+ // TODO?: we might want to do a quick check here for the amount of data the cache
170
+ // will handle, so maybe fire a COUNT query to check for the number of records
171
+ // and check that against a threshold, we will need to alter the prompt below accordingly.
172
+ if (
173
+ this._settingService.getBooleanValue(
174
+ DataCubeSettingKey.GRID_CLIENT__SHOW_CACHE_PERFORMANCE_WARNING,
175
+ )
176
+ ) {
177
+ this._view.alertService.alert({
178
+ message: `Confirm you want to proceed with caching`,
179
+ text: `When enabled, the source dataset will be cached locally in order to boost query performance. But depending on computational resource available to your environment, sometimes, caching can negatively impact the overall performance, and can even lead to crashes.\nDo you still want to proceed?`,
180
+ type: AlertType.WARNING,
181
+ actions: [
182
+ {
183
+ label: 'Abort',
184
+ handler: () => {},
185
+ },
186
+ {
187
+ label: 'Proceed',
188
+ handler: () => {
189
+ run().catch((error) =>
190
+ this._view.alertService.alertUnhandledError(error),
191
+ );
192
+ },
193
+ },
194
+ {
195
+ label: 'Dismiss Warning and Proceed',
196
+ handler: () => {
197
+ this._view.settingService.updateValue(
198
+ this._view.dataCube.api,
199
+ DataCubeSettingKey.GRID_CLIENT__SHOW_CACHE_PERFORMANCE_WARNING,
200
+ false,
201
+ );
202
+ run().catch((error) =>
203
+ this._view.alertService.alertUnhandledError(error),
204
+ );
205
+ },
206
+ },
207
+ ],
208
+ windowConfig: {
209
+ ...DEFAULT_ALERT_WINDOW_CONFIG,
210
+ width: 600,
211
+ height: 210,
212
+ minWidth: 300,
213
+ minHeight: 150,
214
+ },
215
+ });
143
216
  } else {
144
- await this._view.disposeCache();
217
+ await run();
145
218
  }
146
-
147
- runInAction(() => {
148
- // hard reset the grid, this will force the grid to fetch data again
149
- this.clientDataSource = new DataCubeGridClientServerSideDataSource(
150
- this,
151
- this._view,
152
- );
153
- });
154
219
  }
155
220
 
156
221
  setScrollHintText(val: string | undefined) {