@gooddata/sdk-backend-base 9.6.0-alpha.6 → 9.6.0-alpha.8

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 (61) hide show
  1. package/esm/cachingBackend/index.js +269 -260
  2. package/esm/cachingBackend/index.js.map +1 -1
  3. package/esm/customBackend/execution.js +107 -94
  4. package/esm/customBackend/execution.js.map +1 -1
  5. package/esm/customBackend/index.js +102 -95
  6. package/esm/customBackend/index.js.map +1 -1
  7. package/esm/customBackend/workspace.js +3 -0
  8. package/esm/customBackend/workspace.js.map +1 -1
  9. package/esm/decoratedBackend/analyticalWorkspace.js +3 -0
  10. package/esm/decoratedBackend/analyticalWorkspace.js.map +1 -1
  11. package/esm/decoratedBackend/attributes.js +1 -0
  12. package/esm/decoratedBackend/attributes.js.map +1 -1
  13. package/esm/decoratedBackend/catalog.js +5 -0
  14. package/esm/decoratedBackend/catalog.js.map +1 -1
  15. package/esm/decoratedBackend/dashboards.js +2 -0
  16. package/esm/decoratedBackend/dashboards.js.map +1 -1
  17. package/esm/decoratedBackend/elements.js +32 -6
  18. package/esm/decoratedBackend/elements.js.map +1 -1
  19. package/esm/decoratedBackend/execution.js +32 -13
  20. package/esm/decoratedBackend/execution.js.map +1 -1
  21. package/esm/decoratedBackend/index.js +4 -0
  22. package/esm/decoratedBackend/index.js.map +1 -1
  23. package/esm/decoratedBackend/organization.js +3 -0
  24. package/esm/decoratedBackend/organization.js.map +1 -1
  25. package/esm/decoratedBackend/organizations.js +2 -0
  26. package/esm/decoratedBackend/organizations.js.map +1 -1
  27. package/esm/decoratedBackend/securitySettings.js +2 -0
  28. package/esm/decoratedBackend/securitySettings.js.map +1 -1
  29. package/esm/decoratedBackend/workspaceSettings.js +1 -0
  30. package/esm/decoratedBackend/workspaceSettings.js.map +1 -1
  31. package/esm/dummyBackend/index.js +34 -10
  32. package/esm/dummyBackend/index.js.map +1 -1
  33. package/esm/eventingBackend/index.js +47 -44
  34. package/esm/eventingBackend/index.js.map +1 -1
  35. package/esm/ldmFactories/builder.js +2 -0
  36. package/esm/ldmFactories/builder.js.map +1 -1
  37. package/esm/ldmFactories/catalog/attributeFactory.js +1 -1
  38. package/esm/ldmFactories/catalog/attributeFactory.js.map +1 -1
  39. package/esm/ldmFactories/catalog/measureFactory.js +1 -1
  40. package/esm/ldmFactories/catalog/measureFactory.js.map +1 -1
  41. package/esm/ldmFactories/dashboard/insightWidgetFactory.js +5 -3
  42. package/esm/ldmFactories/dashboard/insightWidgetFactory.js.map +1 -1
  43. package/esm/ldmFactories/dashboard/kpiWidgetFactory.js +17 -9
  44. package/esm/ldmFactories/dashboard/kpiWidgetFactory.js.map +1 -1
  45. package/esm/ldmFactories/dashboard/widgetFactory.js +18 -18
  46. package/esm/ldmFactories/dashboard/widgetFactory.js.map +1 -1
  47. package/esm/normalizingBackend/index.js +79 -58
  48. package/esm/normalizingBackend/index.js.map +1 -1
  49. package/esm/normalizingBackend/normalizer.js +317 -297
  50. package/esm/normalizingBackend/normalizer.js.map +1 -1
  51. package/esm/toolkit/auth.js +33 -32
  52. package/esm/toolkit/auth.js.map +1 -1
  53. package/esm/toolkit/execution.js +2 -0
  54. package/esm/toolkit/execution.js.map +1 -1
  55. package/esm/toolkit/paging.js +48 -38
  56. package/esm/toolkit/paging.js.map +1 -1
  57. package/esm/toolkit/pluginUrlValidation.js +1 -2
  58. package/esm/toolkit/pluginUrlValidation.js.map +1 -1
  59. package/esm/workspaceSettingsBackend/index.js +11 -2
  60. package/esm/workspaceSettingsBackend/index.js.map +1 -1
  61. package/package.json +8 -10
@@ -19,32 +19,33 @@ import { DecoratedWorkspaceSettingsService } from "../decoratedBackend/workspace
19
19
  // Execution caching
20
20
  //
21
21
  class WithExecutionCaching extends DecoratedPreparedExecution {
22
+ ctx;
22
23
  constructor(decorated, ctx) {
23
24
  super(decorated);
24
25
  this.ctx = ctx;
25
- this.execute = async () => {
26
- const cacheKey = this.fingerprint();
27
- const cache = this.ctx.caches.execution;
28
- let cacheEntry = cache.get(cacheKey);
29
- if (!cacheEntry) {
30
- const result = super
31
- .execute()
32
- .then((res) => {
33
- return new WithExecutionResultCaching(res, this.createNew, this.ctx);
34
- })
35
- .catch((e) => {
36
- cache.delete(cacheKey);
37
- throw e;
38
- });
39
- cacheEntry = { result };
40
- cache.set(cacheKey, cacheEntry);
41
- }
42
- return new DefinitionSanitizingExecutionResult(await cacheEntry.result, this.createNew, this.definition);
43
- };
44
- this.createNew = (decorated) => {
45
- return new WithExecutionCaching(decorated, this.ctx);
46
- };
47
26
  }
27
+ execute = async () => {
28
+ const cacheKey = this.fingerprint();
29
+ const cache = this.ctx.caches.execution;
30
+ let cacheEntry = cache.get(cacheKey);
31
+ if (!cacheEntry) {
32
+ const result = super
33
+ .execute()
34
+ .then((res) => {
35
+ return new WithExecutionResultCaching(res, this.createNew, this.ctx);
36
+ })
37
+ .catch((e) => {
38
+ cache.delete(cacheKey);
39
+ throw e;
40
+ });
41
+ cacheEntry = { result };
42
+ cache.set(cacheKey, cacheEntry);
43
+ }
44
+ return new DefinitionSanitizingExecutionResult(await cacheEntry.result, this.createNew, this.definition);
45
+ };
46
+ createNew = (decorated) => {
47
+ return new WithExecutionCaching(decorated, this.ctx);
48
+ };
48
49
  }
49
50
  /**
50
51
  * This DataView decorator makes sure that definition used in it is the same as the definition in the result.
@@ -69,55 +70,58 @@ class DefinitionSanitizingDataView extends DecoratedDataView {
69
70
  class DefinitionSanitizingExecutionResult extends DecoratedExecutionResult {
70
71
  constructor(decorated, wrapper, definitionOverride) {
71
72
  super(decorated, wrapper);
72
- this.readAll = async () => {
73
- return this.withSanitizedDefinition(await super.readAll());
74
- };
75
- this.readWindow = async (offset, size) => {
76
- return this.withSanitizedDefinition(await super.readWindow(offset, size));
77
- };
78
- this.withSanitizedDefinition = (original) => {
79
- return new DefinitionSanitizingDataView(original, this);
80
- };
81
73
  this.definition = definitionOverride;
82
74
  }
75
+ readAll = async () => {
76
+ return this.withSanitizedDefinition(await super.readAll());
77
+ };
78
+ readWindow = async (offset, size) => {
79
+ return this.withSanitizedDefinition(await super.readWindow(offset, size));
80
+ };
81
+ withSanitizedDefinition = (original) => {
82
+ return new DefinitionSanitizingDataView(original, this);
83
+ };
83
84
  }
84
85
  function windowKey(offset, size) {
85
86
  return `o(${offset.join(",")})_s(${size.join(",")})`;
86
87
  }
87
88
  class WithExecutionResultCaching extends DecoratedExecutionResult {
89
+ ctx;
90
+ allData;
91
+ windows;
88
92
  constructor(decorated, wrapper, ctx) {
89
93
  super(decorated, wrapper);
90
94
  this.ctx = ctx;
91
- this.readAll = () => {
92
- if (!this.allData) {
93
- this.allData = super.readAll().catch((e) => {
94
- this.allData = undefined;
95
- throw e;
96
- });
97
- }
98
- return this.allData;
99
- };
100
- this.readWindow = (offset, size) => {
101
- if (!this.windows) {
102
- return super.readWindow(offset, size);
103
- }
104
- const cacheKey = windowKey(offset, size);
105
- let window = this.windows.get(cacheKey);
106
- if (!window) {
107
- window = super.readWindow(offset, size).catch((e) => {
108
- if (this.windows) {
109
- this.windows.delete(cacheKey);
110
- }
111
- throw e;
112
- });
113
- this.windows.set(cacheKey, window);
114
- }
115
- return window;
116
- };
117
95
  if (cachingEnabled(this.ctx.config.maxResultWindows)) {
118
96
  this.windows = new LRUCache({ max: this.ctx.config.maxResultWindows });
119
97
  }
120
98
  }
99
+ readAll = () => {
100
+ if (!this.allData) {
101
+ this.allData = super.readAll().catch((e) => {
102
+ this.allData = undefined;
103
+ throw e;
104
+ });
105
+ }
106
+ return this.allData;
107
+ };
108
+ readWindow = (offset, size) => {
109
+ if (!this.windows) {
110
+ return super.readWindow(offset, size);
111
+ }
112
+ const cacheKey = windowKey(offset, size);
113
+ let window = this.windows.get(cacheKey);
114
+ if (!window) {
115
+ window = super.readWindow(offset, size).catch((e) => {
116
+ if (this.windows) {
117
+ this.windows.delete(cacheKey);
118
+ }
119
+ throw e;
120
+ });
121
+ this.windows.set(cacheKey, window);
122
+ }
123
+ return window;
124
+ };
121
125
  }
122
126
  //
123
127
  // Catalog caching
@@ -126,39 +130,40 @@ function optionsKey(options) {
126
130
  return stringify(options);
127
131
  }
128
132
  class WithCatalogCaching extends DecoratedWorkspaceCatalogFactory {
133
+ ctx;
129
134
  constructor(decorated, ctx) {
130
135
  super(decorated);
131
136
  this.ctx = ctx;
132
- this.load = () => {
133
- const cache = this.getOrCreateWorkspaceEntry(this.workspace).catalogForOptions;
134
- const cacheKey = optionsKey(this.options);
135
- let catalog = cache.get(cacheKey);
136
- if (!catalog) {
137
- catalog = super.load().catch((e) => {
138
- cache.delete(cacheKey);
139
- throw e;
140
- });
141
- cache.set(cacheKey, catalog);
142
- }
143
- return catalog;
144
- };
145
- this.createNew = (decorated) => {
146
- return new WithCatalogCaching(decorated, this.ctx);
147
- };
148
- this.getOrCreateWorkspaceEntry = (workspace) => {
149
- const cache = this.ctx.caches.workspaceCatalogs;
150
- let cacheEntry = cache.get(workspace);
151
- if (!cacheEntry) {
152
- cacheEntry = {
153
- catalogForOptions: new LRUCache({
154
- max: this.ctx.config.maxCatalogOptions,
155
- }),
156
- };
157
- cache.set(workspace, cacheEntry);
158
- }
159
- return cacheEntry;
160
- };
161
137
  }
138
+ load = () => {
139
+ const cache = this.getOrCreateWorkspaceEntry(this.workspace).catalogForOptions;
140
+ const cacheKey = optionsKey(this.options);
141
+ let catalog = cache.get(cacheKey);
142
+ if (!catalog) {
143
+ catalog = super.load().catch((e) => {
144
+ cache.delete(cacheKey);
145
+ throw e;
146
+ });
147
+ cache.set(cacheKey, catalog);
148
+ }
149
+ return catalog;
150
+ };
151
+ createNew = (decorated) => {
152
+ return new WithCatalogCaching(decorated, this.ctx);
153
+ };
154
+ getOrCreateWorkspaceEntry = (workspace) => {
155
+ const cache = this.ctx.caches.workspaceCatalogs;
156
+ let cacheEntry = cache.get(workspace);
157
+ if (!cacheEntry) {
158
+ cacheEntry = {
159
+ catalogForOptions: new LRUCache({
160
+ max: this.ctx.config.maxCatalogOptions,
161
+ }),
162
+ };
163
+ cache.set(workspace, cacheEntry);
164
+ }
165
+ return cacheEntry;
166
+ };
162
167
  }
163
168
  //
164
169
  // Organization security settings caching
@@ -167,86 +172,73 @@ function validUrlInContextKey(url, context) {
167
172
  return `${context}_${stringify(url)}`;
168
173
  }
169
174
  class WithSecuritySettingsCaching extends DecoratedSecuritySettingsService {
175
+ ctx;
170
176
  constructor(decorated, ctx) {
171
177
  super(decorated);
172
178
  this.ctx = ctx;
173
- this.isUrlValid = (url, context) => {
174
- const cache = this.getOrCreateSecuritySettingsEntry(this.scope).valid;
175
- const cacheKey = validUrlInContextKey(url, context);
176
- let result = cache.get(cacheKey);
177
- if (!result) {
178
- result = super.isUrlValid(url, context).catch((e) => {
179
- cache.delete(cacheKey);
180
- throw e;
181
- });
182
- cache.set(cacheKey, result);
183
- }
184
- return result;
185
- };
186
- this.isDashboardPluginUrlValid = (url, workspace) => {
187
- const scope = `plugins_${workspace}`;
188
- const cache = this.getOrCreateSecuritySettingsEntry(scope).valid;
189
- let result = cache.get(url);
190
- if (!result) {
191
- result = super.isDashboardPluginUrlValid(url, workspace).catch((e) => {
192
- cache.delete(url);
193
- throw e;
194
- });
195
- cache.set(url, result);
196
- }
197
- return result;
198
- };
199
- this.getOrCreateSecuritySettingsEntry = (scope) => {
200
- const cache = this.ctx.caches.securitySettings;
201
- let cacheEntry = cache.get(scope);
202
- if (!cacheEntry) {
203
- cacheEntry = {
204
- valid: new LRUCache({
205
- max: this.ctx.config.maxSecuritySettingsOrgUrls,
206
- ttl: this.ctx.config.maxSecuritySettingsOrgUrlsAge,
207
- }),
208
- };
209
- cache.set(scope, cacheEntry);
210
- }
211
- return cacheEntry;
212
- };
213
179
  }
180
+ isUrlValid = (url, context) => {
181
+ const cache = this.getOrCreateSecuritySettingsEntry(this.scope).valid;
182
+ const cacheKey = validUrlInContextKey(url, context);
183
+ let result = cache.get(cacheKey);
184
+ if (!result) {
185
+ result = super.isUrlValid(url, context).catch((e) => {
186
+ cache.delete(cacheKey);
187
+ throw e;
188
+ });
189
+ cache.set(cacheKey, result);
190
+ }
191
+ return result;
192
+ };
193
+ isDashboardPluginUrlValid = (url, workspace) => {
194
+ const scope = `plugins_${workspace}`;
195
+ const cache = this.getOrCreateSecuritySettingsEntry(scope).valid;
196
+ let result = cache.get(url);
197
+ if (!result) {
198
+ result = super.isDashboardPluginUrlValid(url, workspace).catch((e) => {
199
+ cache.delete(url);
200
+ throw e;
201
+ });
202
+ cache.set(url, result);
203
+ }
204
+ return result;
205
+ };
206
+ getOrCreateSecuritySettingsEntry = (scope) => {
207
+ const cache = this.ctx.caches.securitySettings;
208
+ let cacheEntry = cache.get(scope);
209
+ if (!cacheEntry) {
210
+ cacheEntry = {
211
+ valid: new LRUCache({
212
+ max: this.ctx.config.maxSecuritySettingsOrgUrls,
213
+ ttl: this.ctx.config.maxSecuritySettingsOrgUrlsAge,
214
+ }),
215
+ };
216
+ cache.set(scope, cacheEntry);
217
+ }
218
+ return cacheEntry;
219
+ };
214
220
  }
215
221
  class WithWorkspaceSettingsCaching extends DecoratedWorkspaceSettingsService {
222
+ ctx;
223
+ workspace;
216
224
  constructor(decorated, ctx, workspace) {
217
225
  super(decorated);
218
226
  this.ctx = ctx;
219
227
  this.workspace = workspace;
220
- this.getSettings = () => {
221
- const cache = this.getOrCreateWorkspaceEntry(this.workspace).workspaceSettings;
222
- const cacheKey = this.workspace;
223
- let workspaceSettings = cache.get(cacheKey);
224
- if (!workspaceSettings) {
225
- workspaceSettings = super.getSettings().catch((e) => {
226
- cache.delete(cacheKey);
227
- throw e;
228
- });
229
- cache.set(cacheKey, workspaceSettings);
230
- }
231
- return workspaceSettings;
232
- };
233
- this.getOrCreateWorkspaceEntry = (workspace) => {
234
- const cache = this.ctx.caches.workspaceSettings;
235
- let cacheEntry = cache.get(workspace);
236
- if (!cacheEntry) {
237
- cacheEntry = {
238
- userWorkspaceSettings: new LRUCache({
239
- max: this.ctx.config.maxWorkspaceSettings,
240
- }),
241
- workspaceSettings: new LRUCache({
242
- max: this.ctx.config.maxWorkspaceSettings,
243
- }),
244
- };
245
- cache.set(workspace, cacheEntry);
246
- }
247
- return cacheEntry;
248
- };
249
228
  }
229
+ getSettings = () => {
230
+ const cache = this.getOrCreateWorkspaceEntry(this.workspace).workspaceSettings;
231
+ const cacheKey = this.workspace;
232
+ let workspaceSettings = cache.get(cacheKey);
233
+ if (!workspaceSettings) {
234
+ workspaceSettings = super.getSettings().catch((e) => {
235
+ cache.delete(cacheKey);
236
+ throw e;
237
+ });
238
+ cache.set(cacheKey, workspaceSettings);
239
+ }
240
+ return workspaceSettings;
241
+ };
250
242
  getSettingsForCurrentUser() {
251
243
  const cache = this.getOrCreateWorkspaceEntry(this.workspace).userWorkspaceSettings;
252
244
  const cacheKey = this.workspace; // we assume that the current user does not change over the life span of the backend instance
@@ -269,6 +261,22 @@ class WithWorkspaceSettingsCaching extends DecoratedWorkspaceSettingsService {
269
261
  async setTheme(themeId) {
270
262
  return super.setTheme(themeId);
271
263
  }
264
+ getOrCreateWorkspaceEntry = (workspace) => {
265
+ const cache = this.ctx.caches.workspaceSettings;
266
+ let cacheEntry = cache.get(workspace);
267
+ if (!cacheEntry) {
268
+ cacheEntry = {
269
+ userWorkspaceSettings: new LRUCache({
270
+ max: this.ctx.config.maxWorkspaceSettings,
271
+ }),
272
+ workspaceSettings: new LRUCache({
273
+ max: this.ctx.config.maxWorkspaceSettings,
274
+ }),
275
+ };
276
+ cache.set(workspace, cacheEntry);
277
+ }
278
+ return cacheEntry;
279
+ };
272
280
  }
273
281
  //
274
282
  // Attributes caching
@@ -304,36 +312,40 @@ function getOrCreateAttributeCache(ctx, workspace) {
304
312
  return cacheEntry;
305
313
  }
306
314
  class CachedElementsQuery extends DecoratedElementsQuery {
315
+ ctx;
316
+ workspace;
317
+ ref;
307
318
  constructor(decorated, ctx, workspace, ref, settings = {}) {
308
319
  super(decorated, settings);
309
320
  this.ctx = ctx;
310
321
  this.workspace = workspace;
311
322
  this.ref = ref;
312
- this.query = async () => {
313
- var _a;
314
- const canCache = !((_a = this.settings.options) === null || _a === void 0 ? void 0 : _a.filter);
315
- if (!canCache) {
316
- return super.query();
317
- }
318
- const cache = getOrCreateAttributeCache(this.ctx, this.workspace).attributeElementResults;
319
- invariant(cache, "inconsistent attribute element cache config");
320
- const cacheKey = elementsCacheKey(this.ref, this.settings);
321
- let result = cache.get(cacheKey);
322
- if (!result) {
323
- result = super.query().catch((e) => {
324
- cache.delete(cacheKey);
325
- throw e;
326
- });
327
- cache.set(cacheKey, result);
328
- }
329
- return result;
330
- };
331
323
  }
324
+ query = async () => {
325
+ const canCache = !this.settings.options?.filter;
326
+ if (!canCache) {
327
+ return super.query();
328
+ }
329
+ const cache = getOrCreateAttributeCache(this.ctx, this.workspace).attributeElementResults;
330
+ invariant(cache, "inconsistent attribute element cache config");
331
+ const cacheKey = elementsCacheKey(this.ref, this.settings);
332
+ let result = cache.get(cacheKey);
333
+ if (!result) {
334
+ result = super.query().catch((e) => {
335
+ cache.delete(cacheKey);
336
+ throw e;
337
+ });
338
+ cache.set(cacheKey, result);
339
+ }
340
+ return result;
341
+ };
332
342
  createNew(decorated, settings) {
333
343
  return new CachedElementsQuery(decorated, this.ctx, this.workspace, this.ref, settings);
334
344
  }
335
345
  }
336
346
  class CachedElementsQueryFactory extends DecoratedElementsQueryFactory {
347
+ ctx;
348
+ workspace;
337
349
  constructor(decorated, ctx, workspace) {
338
350
  super(decorated);
339
351
  this.ctx = ctx;
@@ -345,98 +357,100 @@ class CachedElementsQueryFactory extends DecoratedElementsQueryFactory {
345
357
  }
346
358
  }
347
359
  class WithAttributesCaching extends DecoratedWorkspaceAttributesService {
360
+ ctx;
361
+ workspace;
348
362
  constructor(decorated, ctx, workspace) {
349
363
  super(decorated);
350
364
  this.ctx = ctx;
351
365
  this.workspace = workspace;
352
- this.getAttributeDisplayForm = (ref) => {
353
- const cache = getOrCreateAttributeCache(this.ctx, this.workspace).displayForms;
354
- const idCacheKey = isIdentifierRef(ref) ? ref.identifier : undefined;
355
- const uriCacheKey = isUriRef(ref) ? ref.uri : undefined;
356
- let cacheItem = firstDefined([idCacheKey, uriCacheKey].map((key) => key && cache.get(key)));
357
- if (!cacheItem) {
358
- cacheItem = super.getAttributeDisplayForm(ref).catch((e) => {
359
- if (idCacheKey) {
360
- cache.delete(idCacheKey);
361
- }
362
- if (uriCacheKey) {
363
- cache.delete(uriCacheKey);
364
- }
365
- throw e;
366
- });
366
+ }
367
+ getAttributeDisplayForm = (ref) => {
368
+ const cache = getOrCreateAttributeCache(this.ctx, this.workspace).displayForms;
369
+ const idCacheKey = isIdentifierRef(ref) ? ref.identifier : undefined;
370
+ const uriCacheKey = isUriRef(ref) ? ref.uri : undefined;
371
+ let cacheItem = firstDefined([idCacheKey, uriCacheKey].map((key) => key && cache.get(key)));
372
+ if (!cacheItem) {
373
+ cacheItem = super.getAttributeDisplayForm(ref).catch((e) => {
367
374
  if (idCacheKey) {
368
- cache.set(idCacheKey, cacheItem);
375
+ cache.delete(idCacheKey);
369
376
  }
370
377
  if (uriCacheKey) {
371
- cache.set(uriCacheKey, cacheItem);
378
+ cache.delete(uriCacheKey);
372
379
  }
373
- }
374
- return cacheItem;
375
- };
376
- this.getAttributeDisplayForms = async (refs) => {
377
- const cache = getOrCreateAttributeCache(this.ctx, this.workspace).displayForms;
378
- // grab a reference to the cache results as soon as possible in case they would get evicted while loading the ones with missing data in cache
379
- // then would might not be able to call cache.get again and be guaranteed to get the data
380
- const refsWithCacheResults = refs.map((ref) => {
381
- const idCacheKey = isIdentifierRef(ref) ? ref.identifier : undefined;
382
- const uriCacheKey = isUriRef(ref) ? ref.uri : undefined;
383
- const cacheHit = firstDefined([idCacheKey, uriCacheKey].map((key) => key && cache.get(key)));
384
- return { ref, cacheHit };
385
- });
386
- const [withCacheHits, withoutCacheHits] = partition(refsWithCacheResults, ({ cacheHit }) => !!cacheHit);
387
- const refsToLoad = withoutCacheHits.map((item) => item.ref);
388
- const [alreadyInCache, loadedFromServer] = await Promise.all([
389
- // await the stuff from cache, we need the data available (we cannot just return the promises)
390
- Promise.all(withCacheHits.map((item) => item.cacheHit)),
391
- // load items not in cache using the bulk operation
392
- this.decorated.getAttributeDisplayForms(refsToLoad),
393
- ]);
394
- // save newly loaded to cache for future reference
395
- loadedFromServer.forEach((loaded) => {
396
- const promisifiedResult = Promise.resolve(loaded);
397
- // save the cache item for both types of refs
398
- cache.set(loaded.id, promisifiedResult);
399
- cache.set(loaded.uri, promisifiedResult);
400
- });
401
- const loadedRefs = loadedFromServer.map((item) => item.ref);
402
- const outputRefs = this.ctx.capabilities.allowsInconsistentRelations
403
- ? skipMissingReferences(refs, refsToLoad, loadedRefs)
404
- : refs;
405
- // reconstruct the original ordering
406
- const candidates = [...loadedFromServer, ...alreadyInCache];
407
- return outputRefs.map((ref) => {
408
- const match = candidates.find((item) => refMatchesMdObject(ref, item, "displayForm"));
409
- // if this bombs, some data got lost in the process
410
- invariant(match);
411
- return match;
380
+ throw e;
412
381
  });
413
- };
414
- this.getAttributeByDisplayForm = async (ref) => {
415
- const cache = getOrCreateAttributeCache(this.ctx, this.workspace).attributesByDisplayForms;
382
+ if (idCacheKey) {
383
+ cache.set(idCacheKey, cacheItem);
384
+ }
385
+ if (uriCacheKey) {
386
+ cache.set(uriCacheKey, cacheItem);
387
+ }
388
+ }
389
+ return cacheItem;
390
+ };
391
+ getAttributeDisplayForms = async (refs) => {
392
+ const cache = getOrCreateAttributeCache(this.ctx, this.workspace).displayForms;
393
+ // grab a reference to the cache results as soon as possible in case they would get evicted while loading the ones with missing data in cache
394
+ // then would might not be able to call cache.get again and be guaranteed to get the data
395
+ const refsWithCacheResults = refs.map((ref) => {
416
396
  const idCacheKey = isIdentifierRef(ref) ? ref.identifier : undefined;
417
397
  const uriCacheKey = isUriRef(ref) ? ref.uri : undefined;
418
- let cacheItem = firstDefined([idCacheKey, uriCacheKey].map((key) => key && cache.get(key)));
419
- if (!cacheItem) {
420
- // eslint-disable-next-line sonarjs/no-identical-functions
421
- cacheItem = super.getAttributeByDisplayForm(ref).catch((e) => {
422
- if (idCacheKey) {
423
- cache.delete(idCacheKey);
424
- }
425
- if (uriCacheKey) {
426
- cache.delete(uriCacheKey);
427
- }
428
- throw e;
429
- });
398
+ const cacheHit = firstDefined([idCacheKey, uriCacheKey].map((key) => key && cache.get(key)));
399
+ return { ref, cacheHit };
400
+ });
401
+ const [withCacheHits, withoutCacheHits] = partition(refsWithCacheResults, ({ cacheHit }) => !!cacheHit);
402
+ const refsToLoad = withoutCacheHits.map((item) => item.ref);
403
+ const [alreadyInCache, loadedFromServer] = await Promise.all([
404
+ // await the stuff from cache, we need the data available (we cannot just return the promises)
405
+ Promise.all(withCacheHits.map((item) => item.cacheHit)),
406
+ // load items not in cache using the bulk operation
407
+ this.decorated.getAttributeDisplayForms(refsToLoad),
408
+ ]);
409
+ // save newly loaded to cache for future reference
410
+ loadedFromServer.forEach((loaded) => {
411
+ const promisifiedResult = Promise.resolve(loaded);
412
+ // save the cache item for both types of refs
413
+ cache.set(loaded.id, promisifiedResult);
414
+ cache.set(loaded.uri, promisifiedResult);
415
+ });
416
+ const loadedRefs = loadedFromServer.map((item) => item.ref);
417
+ const outputRefs = this.ctx.capabilities.allowsInconsistentRelations
418
+ ? skipMissingReferences(refs, refsToLoad, loadedRefs)
419
+ : refs;
420
+ // reconstruct the original ordering
421
+ const candidates = [...loadedFromServer, ...alreadyInCache];
422
+ return outputRefs.map((ref) => {
423
+ const match = candidates.find((item) => refMatchesMdObject(ref, item, "displayForm"));
424
+ // if this bombs, some data got lost in the process
425
+ invariant(match);
426
+ return match;
427
+ });
428
+ };
429
+ getAttributeByDisplayForm = async (ref) => {
430
+ const cache = getOrCreateAttributeCache(this.ctx, this.workspace).attributesByDisplayForms;
431
+ const idCacheKey = isIdentifierRef(ref) ? ref.identifier : undefined;
432
+ const uriCacheKey = isUriRef(ref) ? ref.uri : undefined;
433
+ let cacheItem = firstDefined([idCacheKey, uriCacheKey].map((key) => key && cache.get(key)));
434
+ if (!cacheItem) {
435
+ // eslint-disable-next-line sonarjs/no-identical-functions
436
+ cacheItem = super.getAttributeByDisplayForm(ref).catch((e) => {
430
437
  if (idCacheKey) {
431
- cache.set(idCacheKey, cacheItem);
438
+ cache.delete(idCacheKey);
432
439
  }
433
440
  if (uriCacheKey) {
434
- cache.set(uriCacheKey, cacheItem);
441
+ cache.delete(uriCacheKey);
435
442
  }
443
+ throw e;
444
+ });
445
+ if (idCacheKey) {
446
+ cache.set(idCacheKey, cacheItem);
436
447
  }
437
- return cacheItem;
438
- };
439
- }
448
+ if (uriCacheKey) {
449
+ cache.set(uriCacheKey, cacheItem);
450
+ }
451
+ }
452
+ return cacheItem;
453
+ };
440
454
  elements() {
441
455
  const decorated = this.decorated.elements();
442
456
  return cachingEnabled(this.ctx.config.maxAttributeElementResultsPerWorkspace)
@@ -468,24 +482,19 @@ function cachingEnabled(desiredSize) {
468
482
  function cacheControl(ctx) {
469
483
  const control = {
470
484
  resetExecutions: () => {
471
- var _a;
472
- (_a = ctx.caches.execution) === null || _a === void 0 ? void 0 : _a.clear();
485
+ ctx.caches.execution?.clear();
473
486
  },
474
487
  resetCatalogs: () => {
475
- var _a;
476
- (_a = ctx.caches.workspaceCatalogs) === null || _a === void 0 ? void 0 : _a.clear();
488
+ ctx.caches.workspaceCatalogs?.clear();
477
489
  },
478
490
  resetSecuritySettings: () => {
479
- var _a;
480
- (_a = ctx.caches.securitySettings) === null || _a === void 0 ? void 0 : _a.clear();
491
+ ctx.caches.securitySettings?.clear();
481
492
  },
482
493
  resetAttributes: () => {
483
- var _a;
484
- (_a = ctx.caches.workspaceAttributes) === null || _a === void 0 ? void 0 : _a.clear();
494
+ ctx.caches.workspaceAttributes?.clear();
485
495
  },
486
496
  resetWorkspaceSettings: () => {
487
- var _a;
488
- (_a = ctx.caches.workspaceSettings) === null || _a === void 0 ? void 0 : _a.clear();
497
+ ctx.caches.workspaceSettings?.clear();
489
498
  },
490
499
  resetAll: () => {
491
500
  control.resetExecutions();