@salesforce/lds-runtime-mobile 1.266.0-dev25 → 1.266.0-dev26

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/dist/main.js CHANGED
@@ -36,6 +36,8 @@ import eagerEvalValidAt from '@salesforce/gate/lds.eagerEvalValidAt';
36
36
  import eagerEvalStaleWhileRevalidate from '@salesforce/gate/lds.eagerEvalStaleWhileRevalidate';
37
37
  import eagerEvalDefaultCachePolicy from '@salesforce/gate/lds.eagerEvalDefaultCachePolicy';
38
38
  import ldsPrimingGraphqlBatch from '@salesforce/gate/lds.primingGraphqlBatch';
39
+ import aggressiveTrimGate from '@salesforce/gate/lds.aggressiveTrim';
40
+ import aggressiveTrimLowLimitGate from '@salesforce/gate/lds.aggressiveTrimLowLimit';
39
41
  import ldsMetadataRefreshEnabled from '@salesforce/gate/lds.metadataRefreshEnabled';
40
42
 
41
43
  /**
@@ -48,7 +50,7 @@ import ldsMetadataRefreshEnabled from '@salesforce/gate/lds.metadataRefreshEnabl
48
50
  const { parse: parse$6, stringify: stringify$6 } = JSON;
49
51
  const { join: join$2, push: push$2, unshift } = Array.prototype;
50
52
  const { isArray: isArray$5 } = Array;
51
- const { entries: entries$4, keys: keys$8 } = Object;
53
+ const { entries: entries$5, keys: keys$8 } = Object;
52
54
 
53
55
  const UI_API_BASE_URI = '/services/data/v60.0/ui-api';
54
56
 
@@ -360,7 +362,7 @@ function getFulfillingRequest(inflightRequests, resourceRequest) {
360
362
  if (fulfill === undefined) {
361
363
  return null;
362
364
  }
363
- const handlersMap = entries$4(inflightRequests);
365
+ const handlersMap = entries$5(inflightRequests);
364
366
  for (let i = 0, len = handlersMap.length; i < len; i += 1) {
365
367
  const [transactionKey, handlers] = handlersMap[i];
366
368
  // check fulfillment against only the first handler ([0]) because it's equal or
@@ -1181,7 +1183,7 @@ function makeDurable(environment, { durableStore, instrumentation, useRevivingSt
1181
1183
  // because we do not want some other code attempting to use the
1182
1184
  // in-memory values before the durable store onChanged handler
1183
1185
  // calls back and revives the values to in-memory
1184
- environment.storeEvict(key);
1186
+ environment.storeDealloc(key);
1185
1187
  };
1186
1188
  const publishStoreMetadata = function (recordId, storeMetadata) {
1187
1189
  validateNotDisposed();
@@ -7165,7 +7167,7 @@ function isArrayLike(x) {
7165
7167
  (x.length === 0 || (x.length > 0 && Object.prototype.hasOwnProperty.call(x, x.length - 1))));
7166
7168
  }
7167
7169
 
7168
- const { create: create$4, keys: keys$4, values: values$2, entries: entries$3, assign: assign$4 } = Object;
7170
+ const { create: create$4, keys: keys$4, values: values$2, entries: entries$4, assign: assign$4 } = Object;
7169
7171
  const { stringify: stringify$4, parse: parse$4 } = JSON;
7170
7172
  const { isArray: isArray$2, from: from$2 } = Array;
7171
7173
 
@@ -7897,7 +7899,7 @@ function filterToPredicates(where, recordType, alias, objectInfoMap, joins, draf
7897
7899
  }
7898
7900
  else {
7899
7901
  //`field` match the filedInfo's apiName
7900
- for (const [op, value] of entries$3(where[field])) {
7902
+ for (const [op, value] of entries$4(where[field])) {
7901
7903
  const operator = operatorToSql(op);
7902
7904
  /**
7903
7905
  Two types ID processing might be needed. Draft ID swapping is optional, which depends on DraftFunctions existence.
@@ -11734,7 +11736,7 @@ function referenceIdFieldForRelationship(relationshipName) {
11734
11736
  */
11735
11737
 
11736
11738
 
11737
- const { keys: keys$3, values: values$1, create: create$3, assign: assign$3, freeze } = Object;
11739
+ const { keys: keys$3, values: values$1, create: create$3, assign: assign$3, freeze, entries: entries$3 } = Object;
11738
11740
  const { stringify: stringify$3, parse: parse$3 } = JSON;
11739
11741
  const { shift } = Array.prototype;
11740
11742
  const { isArray: isArray$1, from: from$1 } = Array;
@@ -13063,7 +13065,7 @@ function getDenormalizedKey(originalKey, recordId, luvio) {
13063
13065
  }
13064
13066
  return keyBuilderRecord(luvio, { recordId });
13065
13067
  }
13066
- function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecords, getStoreMetadata, getStore) {
13068
+ function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecords, getStoreMetadata, getStore, sqlStore) {
13067
13069
  const getEntries = function (entries, segment) {
13068
13070
  // this HOF only inspects records in the default segment
13069
13071
  if (segment !== DefaultDurableSegment) {
@@ -13125,7 +13127,10 @@ function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecord
13125
13127
  });
13126
13128
  };
13127
13129
  const denormalizeEntries = function (entries) {
13130
+ let hasEntries = false;
13131
+ let hasMetadata = false;
13128
13132
  const putEntries = create$3(null);
13133
+ const putMetadata = create$3(null);
13129
13134
  const keys$1 = keys$3(entries);
13130
13135
  const putRecords = {};
13131
13136
  const putRecordViews = {};
@@ -13168,6 +13173,7 @@ function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecord
13168
13173
  putRecords[recordId] = true;
13169
13174
  }
13170
13175
  if (isStoreRecordError(record)) {
13176
+ hasEntries = true;
13171
13177
  putEntries[recordKey] = value;
13172
13178
  continue;
13173
13179
  }
@@ -13180,24 +13186,43 @@ function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecord
13180
13186
  }
13181
13187
  const denormalizedRecord = buildDurableRecordRepresentation(record, storeRecords, recordEntries, store);
13182
13188
  if (denormalizedRecord !== undefined) {
13189
+ hasEntries = true;
13183
13190
  putEntries[recordKey] = {
13184
13191
  data: denormalizedRecord,
13185
13192
  metadata,
13186
13193
  };
13194
+ // if undefined then it is pending
13195
+ // we should still update metadata on pending records
13196
+ }
13197
+ else {
13198
+ hasMetadata = true;
13199
+ metadata.expirationTimestamp = metadata.ingestionTimestamp;
13200
+ putMetadata[recordKey] = {
13201
+ metadata,
13202
+ };
13187
13203
  }
13188
13204
  }
13189
13205
  else {
13206
+ hasEntries = true;
13190
13207
  putEntries[key] = value;
13191
13208
  }
13192
13209
  }
13193
- return putEntries;
13210
+ return { putEntries, putMetadata, hasEntries, hasMetadata };
13194
13211
  };
13195
13212
  const setEntries = function (entries, segment) {
13196
13213
  if (segment !== DefaultDurableSegment) {
13197
13214
  return durableStore.setEntries(entries, segment);
13198
13215
  }
13199
- const putEntries = denormalizeEntries(entries);
13200
- return durableStore.setEntries(putEntries, segment);
13216
+ const { putEntries, putMetadata, hasEntries, hasMetadata } = denormalizeEntries(entries);
13217
+ const promises = [
13218
+ hasEntries ? durableStore.setEntries(putEntries, segment) : undefined,
13219
+ ];
13220
+ if (sqlStore !== undefined && sqlStore.isBatchUpdateSupported()) {
13221
+ promises.push(hasMetadata && sqlStore !== undefined
13222
+ ? durableStore.setMetadata(putMetadata, segment)
13223
+ : undefined);
13224
+ }
13225
+ return Promise.all(promises).then(() => { });
13201
13226
  };
13202
13227
  const batchOperations = function (operations) {
13203
13228
  const operationsWithDenormedRecords = [];
@@ -13214,10 +13239,20 @@ function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecord
13214
13239
  // this is determined by the plugin supporting update batch calls before it gets to this HOF.
13215
13240
  // so we only need to check one entry to confirm this for performance
13216
13241
  if (firstEntry.data !== undefined) {
13242
+ const { putEntries, putMetadata, hasMetadata } = denormalizeEntries(operation.entries);
13217
13243
  operationsWithDenormedRecords.push({
13218
13244
  ...operation,
13219
- entries: denormalizeEntries(operation.entries),
13245
+ entries: putEntries,
13220
13246
  });
13247
+ if (hasMetadata &&
13248
+ sqlStore !== undefined &&
13249
+ sqlStore.isBatchUpdateSupported() === true) {
13250
+ operationsWithDenormedRecords.push({
13251
+ ...operation,
13252
+ entries: putMetadata,
13253
+ type: 'setMetadata',
13254
+ });
13255
+ }
13221
13256
  }
13222
13257
  else {
13223
13258
  operationsWithDenormedRecords.push(operation);
@@ -13229,10 +13264,20 @@ function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecord
13229
13264
  operationsWithDenormedRecords.push(operation);
13230
13265
  continue;
13231
13266
  }
13267
+ const { putEntries, putMetadata, hasMetadata } = denormalizeEntries(operation.entries);
13232
13268
  operationsWithDenormedRecords.push({
13233
13269
  ...operation,
13234
- entries: denormalizeEntries(operation.entries),
13270
+ entries: putEntries,
13235
13271
  });
13272
+ if (hasMetadata &&
13273
+ sqlStore !== undefined &&
13274
+ sqlStore.isBatchUpdateSupported() === true) {
13275
+ operationsWithDenormedRecords.push({
13276
+ ...operation,
13277
+ entries: putMetadata,
13278
+ type: 'setMetadata',
13279
+ });
13280
+ }
13236
13281
  }
13237
13282
  return durableStore.batchOperations(operationsWithDenormedRecords);
13238
13283
  };
@@ -16297,6 +16342,9 @@ class NimbusSqliteStore {
16297
16342
  isEvalSupported() {
16298
16343
  return true;
16299
16344
  }
16345
+ isBatchUpdateSupported() {
16346
+ return this.supportsBatchUpdates;
16347
+ }
16300
16348
  query(sql, params) {
16301
16349
  return new Promise((resolve, reject) => {
16302
16350
  this.plugin.query(sql, params, (result) => {
@@ -16339,6 +16387,7 @@ class NimbusSqliteStore {
16339
16387
  return this.batchOperationAsPromise([operation]);
16340
16388
  }
16341
16389
  batchOperations(operations) {
16390
+ let fallbackSetMetadata = [];
16342
16391
  const sqliteOperations = operations.reduce((acc, cur) => {
16343
16392
  if (cur.type === 'setEntries') {
16344
16393
  const table = this.getTable(cur.segment);
@@ -16362,7 +16411,14 @@ class NimbusSqliteStore {
16362
16411
  }
16363
16412
  return acc;
16364
16413
  }, []);
16365
- return this.batchOperationAsPromise(sqliteOperations);
16414
+ return this.batchOperationAsPromise(sqliteOperations).then(() => {
16415
+ if (fallbackSetMetadata.length > 0) {
16416
+ return Promise.all(fallbackSetMetadata.map((fallback) => {
16417
+ const { entries, segment } = fallback;
16418
+ return this.setMetadata(entries, segment);
16419
+ })).then(() => { });
16420
+ }
16421
+ });
16366
16422
  }
16367
16423
  evictEntries(entryIds, segment) {
16368
16424
  const sqliteOperation = this.idsToDeleteOperation(entryIds, segment);
@@ -17833,6 +17889,76 @@ function primingSessionFactory(config) {
17833
17889
  return instrumentPrimingSession(session);
17834
17890
  }
17835
17891
 
17892
+ const DEFAULT_MAX_RECORD_COUNT = aggressiveTrimLowLimitGate.isOpen({ fallback: false })
17893
+ ? 20000
17894
+ : 200000;
17895
+ const DEFAULT_MAX_BATCH_SIZE = 200;
17896
+ async function aggressiveTrim(data, deallocateFn, options = {}) {
17897
+ const maxStoreRecords = options.maxStoreRecords !== undefined ? options.maxStoreRecords : DEFAULT_MAX_RECORD_COUNT;
17898
+ const batchSize = options.batchSize !== undefined ? options.batchSize : DEFAULT_MAX_BATCH_SIZE;
17899
+ let deallocatedCount = 0;
17900
+ const { pendingTrimKeys, retainedIds, storeRecords } = data;
17901
+ const storeKeyLength = keys$1(storeRecords).length;
17902
+ if (storeKeyLength <= maxStoreRecords) {
17903
+ return { deallocatedCount, trimKeysSkipped: pendingTrimKeys };
17904
+ }
17905
+ const overFlowSize = storeKeyLength - maxStoreRecords;
17906
+ if (overFlowSize <= 0) {
17907
+ return { deallocatedCount, trimKeysSkipped: pendingTrimKeys };
17908
+ }
17909
+ const trimKeys = new Set();
17910
+ for (const key of pendingTrimKeys) {
17911
+ if (storeKeyLength - trimKeys.size <= maxStoreRecords) {
17912
+ break;
17913
+ }
17914
+ if ((retainedIds[key] === undefined && storeRecords[key] !== undefined) ||
17915
+ (retainedIds[key] !== undefined && retainedIds[key] <= 1)) {
17916
+ trimKeys.add(key);
17917
+ }
17918
+ }
17919
+ const batches = batchKeys(trimKeys, batchSize).map((batch) => {
17920
+ return () => batchToPromise(batch, deallocateFn);
17921
+ });
17922
+ for (const batch of batches) {
17923
+ // execute each batch between ticks
17924
+ const count = await batch();
17925
+ deallocatedCount = deallocatedCount + count;
17926
+ }
17927
+ const trimKeysSkipped = makeSetFilteredFromDifference(pendingTrimKeys, (key) => trimKeys.has(key) === false);
17928
+ return {
17929
+ deallocatedCount,
17930
+ trimKeysSkipped,
17931
+ };
17932
+ }
17933
+ function batchToPromise(batch, deallocateFn) {
17934
+ return new Promise((resolve) => {
17935
+ let count = 0;
17936
+ batch.forEach((key) => {
17937
+ deallocateFn(key);
17938
+ count++;
17939
+ });
17940
+ resolve(count);
17941
+ });
17942
+ }
17943
+ function batchKeys(keys, batchSize) {
17944
+ const keyArray = Array.from(keys);
17945
+ const batches = [];
17946
+ for (let i = 0, len = keyArray.length; i < len; i += batchSize) {
17947
+ const batch = keyArray.slice(i, i + batchSize);
17948
+ batches.push(batch);
17949
+ }
17950
+ return batches;
17951
+ }
17952
+ function makeSetFilteredFromDifference(setToFilter, diff) {
17953
+ let filteredSet = new Set();
17954
+ setToFilter.forEach((t) => {
17955
+ if (diff(t)) {
17956
+ filteredSet.add(t);
17957
+ }
17958
+ });
17959
+ return filteredSet;
17960
+ }
17961
+
17836
17962
  // so eslint doesn't complain about nimbus
17837
17963
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
17838
17964
  /* global __nimbus */
@@ -17861,7 +17987,11 @@ function getRuntime() {
17861
17987
  // user id centric record ID generator
17862
17988
  const { newRecordId, isGenerated } = recordIdGenerator(userId);
17863
17989
  // non-draft-aware base services
17864
- const store = new InMemoryStore();
17990
+ let storeOptions = {};
17991
+ if (aggressiveTrimGate.isOpen({ fallback: false })) {
17992
+ storeOptions.customTrimPolicy = aggressiveTrim;
17993
+ }
17994
+ const store = new InMemoryStore(storeOptions);
17865
17995
  lazyNetworkAdapter = platformNetworkAdapter(makeNetworkAdapterChunkRecordFields(NimbusNetworkAdapter, {
17866
17996
  reportChunkCandidateUrlLength: reportChunkCandidateUrlLength,
17867
17997
  }));
@@ -17888,7 +18018,7 @@ function getRuntime() {
17888
18018
  let getIngestRecords;
17889
18019
  let getIngestMetadata;
17890
18020
  let getIngestStore;
17891
- const recordDenormingStore = makeRecordDenormalizingDurableStore(lazyLuvio, lazyBaseDurableStore, () => (getIngestRecords !== undefined ? getIngestRecords() : {}), () => (getIngestMetadata !== undefined ? getIngestMetadata() : {}), () => (getIngestStore !== undefined ? getIngestStore() : undefined));
18021
+ const recordDenormingStore = makeRecordDenormalizingDurableStore(lazyLuvio, lazyBaseDurableStore, () => (getIngestRecords !== undefined ? getIngestRecords() : {}), () => (getIngestMetadata !== undefined ? getIngestMetadata() : {}), () => (getIngestStore !== undefined ? getIngestStore() : undefined), lazyBaseDurableStore);
17892
18022
  const baseEnv = new Environment(store, lazyNetworkAdapter);
17893
18023
  const gqlEnv = makeEnvironmentGraphqlAware(baseEnv);
17894
18024
  const durableEnv = makeDurable(gqlEnv, {
@@ -17999,4 +18129,4 @@ register({
17999
18129
  });
18000
18130
 
18001
18131
  export { O11Y_NAMESPACE_LDS_MOBILE, getRuntime, registerReportObserver, reportGraphqlQueryParseError };
18002
- // version: 1.266.0-dev25-c260f46ec
18132
+ // version: 1.266.0-dev26-c7c66cb1b
@@ -0,0 +1,7 @@
1
+ import type { TrimTaskData, DeallocationFunction, TrimResult } from '@luvio/engine';
2
+ type TrimOptions = {
3
+ batchSize?: number;
4
+ maxStoreRecords?: number;
5
+ };
6
+ export declare function aggressiveTrim(data: TrimTaskData, deallocateFn: DeallocationFunction, options?: TrimOptions): Promise<TrimResult>;
7
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/lds-runtime-mobile",
3
- "version": "1.266.0-dev25",
3
+ "version": "1.266.0-dev26",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
5
  "description": "LDS runtime for mobile/hybrid environments.",
6
6
  "main": "dist/main.js",
@@ -32,25 +32,25 @@
32
32
  "release:corejar": "yarn build && ../core-build/scripts/core.js --name=lds-runtime-mobile"
33
33
  },
34
34
  "dependencies": {
35
- "@salesforce/lds-adapters-uiapi": "^1.266.0-dev25",
36
- "@salesforce/lds-bindings": "^1.266.0-dev25",
37
- "@salesforce/lds-instrumentation": "^1.266.0-dev25",
38
- "@salesforce/lds-priming": "^1.266.0-dev25",
35
+ "@salesforce/lds-adapters-uiapi": "^1.266.0-dev26",
36
+ "@salesforce/lds-bindings": "^1.266.0-dev26",
37
+ "@salesforce/lds-instrumentation": "^1.266.0-dev26",
38
+ "@salesforce/lds-priming": "^1.266.0-dev26",
39
39
  "@salesforce/user": "0.0.21",
40
40
  "o11y": "244.0.0"
41
41
  },
42
42
  "devDependencies": {
43
- "@salesforce/lds-adapters-graphql": "^1.266.0-dev25",
44
- "@salesforce/lds-drafts": "^1.266.0-dev25",
45
- "@salesforce/lds-drafts-adapters-uiapi": "^1.266.0-dev25",
46
- "@salesforce/lds-graphql-eval": "^1.266.0-dev25",
47
- "@salesforce/lds-network-adapter": "^1.266.0-dev25",
48
- "@salesforce/lds-network-nimbus": "^1.266.0-dev25",
49
- "@salesforce/lds-store-binary": "^1.266.0-dev25",
50
- "@salesforce/lds-store-nimbus": "^1.266.0-dev25",
51
- "@salesforce/lds-store-sql": "^1.266.0-dev25",
52
- "@salesforce/lds-utils-adapters": "^1.266.0-dev25",
53
- "@salesforce/nimbus-plugin-lds": "^1.266.0-dev25",
43
+ "@salesforce/lds-adapters-graphql": "^1.266.0-dev26",
44
+ "@salesforce/lds-drafts": "^1.266.0-dev26",
45
+ "@salesforce/lds-drafts-adapters-uiapi": "^1.266.0-dev26",
46
+ "@salesforce/lds-graphql-eval": "^1.266.0-dev26",
47
+ "@salesforce/lds-network-adapter": "^1.266.0-dev26",
48
+ "@salesforce/lds-network-nimbus": "^1.266.0-dev26",
49
+ "@salesforce/lds-store-binary": "^1.266.0-dev26",
50
+ "@salesforce/lds-store-nimbus": "^1.266.0-dev26",
51
+ "@salesforce/lds-store-sql": "^1.266.0-dev26",
52
+ "@salesforce/lds-utils-adapters": "^1.266.0-dev26",
53
+ "@salesforce/nimbus-plugin-lds": "^1.266.0-dev26",
54
54
  "babel-plugin-dynamic-import-node": "^2.3.3",
55
55
  "wait-for-expect": "^3.0.2"
56
56
  },
@@ -59,7 +59,7 @@
59
59
  "path": "./dist/main.js",
60
60
  "maxSize": {
61
61
  "none": "800 kB",
62
- "min": "315 kB",
62
+ "min": "350 kB",
63
63
  "compressed": "150 kB"
64
64
  }
65
65
  },
@@ -67,7 +67,7 @@
67
67
  "path": "./sfdc/main.js",
68
68
  "maxSize": {
69
69
  "none": "800 kB",
70
- "min": "315 kB",
70
+ "min": "350 kB",
71
71
  "compressed": "150 kB"
72
72
  }
73
73
  }
package/sfdc/main.js CHANGED
@@ -36,6 +36,8 @@ import eagerEvalValidAt from '@salesforce/gate/lds.eagerEvalValidAt';
36
36
  import eagerEvalStaleWhileRevalidate from '@salesforce/gate/lds.eagerEvalStaleWhileRevalidate';
37
37
  import eagerEvalDefaultCachePolicy from '@salesforce/gate/lds.eagerEvalDefaultCachePolicy';
38
38
  import ldsPrimingGraphqlBatch from '@salesforce/gate/lds.primingGraphqlBatch';
39
+ import aggressiveTrimGate from '@salesforce/gate/lds.aggressiveTrim';
40
+ import aggressiveTrimLowLimitGate from '@salesforce/gate/lds.aggressiveTrimLowLimit';
39
41
  import ldsMetadataRefreshEnabled from '@salesforce/gate/lds.metadataRefreshEnabled';
40
42
 
41
43
  /**
@@ -48,7 +50,7 @@ import ldsMetadataRefreshEnabled from '@salesforce/gate/lds.metadataRefreshEnabl
48
50
  const { parse: parse$6, stringify: stringify$6 } = JSON;
49
51
  const { join: join$2, push: push$2, unshift } = Array.prototype;
50
52
  const { isArray: isArray$5 } = Array;
51
- const { entries: entries$4, keys: keys$8 } = Object;
53
+ const { entries: entries$5, keys: keys$8 } = Object;
52
54
 
53
55
  const UI_API_BASE_URI = '/services/data/v60.0/ui-api';
54
56
 
@@ -360,7 +362,7 @@ function getFulfillingRequest(inflightRequests, resourceRequest) {
360
362
  if (fulfill === undefined) {
361
363
  return null;
362
364
  }
363
- const handlersMap = entries$4(inflightRequests);
365
+ const handlersMap = entries$5(inflightRequests);
364
366
  for (let i = 0, len = handlersMap.length; i < len; i += 1) {
365
367
  const [transactionKey, handlers] = handlersMap[i];
366
368
  // check fulfillment against only the first handler ([0]) because it's equal or
@@ -1181,7 +1183,7 @@ function makeDurable(environment, { durableStore, instrumentation, useRevivingSt
1181
1183
  // because we do not want some other code attempting to use the
1182
1184
  // in-memory values before the durable store onChanged handler
1183
1185
  // calls back and revives the values to in-memory
1184
- environment.storeEvict(key);
1186
+ environment.storeDealloc(key);
1185
1187
  };
1186
1188
  const publishStoreMetadata = function (recordId, storeMetadata) {
1187
1189
  validateNotDisposed();
@@ -7165,7 +7167,7 @@ function isArrayLike(x) {
7165
7167
  (x.length === 0 || (x.length > 0 && Object.prototype.hasOwnProperty.call(x, x.length - 1))));
7166
7168
  }
7167
7169
 
7168
- const { create: create$4, keys: keys$4, values: values$2, entries: entries$3, assign: assign$4 } = Object;
7170
+ const { create: create$4, keys: keys$4, values: values$2, entries: entries$4, assign: assign$4 } = Object;
7169
7171
  const { stringify: stringify$4, parse: parse$4 } = JSON;
7170
7172
  const { isArray: isArray$2, from: from$2 } = Array;
7171
7173
 
@@ -7897,7 +7899,7 @@ function filterToPredicates(where, recordType, alias, objectInfoMap, joins, draf
7897
7899
  }
7898
7900
  else {
7899
7901
  //`field` match the filedInfo's apiName
7900
- for (const [op, value] of entries$3(where[field])) {
7902
+ for (const [op, value] of entries$4(where[field])) {
7901
7903
  const operator = operatorToSql(op);
7902
7904
  /**
7903
7905
  Two types ID processing might be needed. Draft ID swapping is optional, which depends on DraftFunctions existence.
@@ -11734,7 +11736,7 @@ function referenceIdFieldForRelationship(relationshipName) {
11734
11736
  */
11735
11737
 
11736
11738
 
11737
- const { keys: keys$3, values: values$1, create: create$3, assign: assign$3, freeze } = Object;
11739
+ const { keys: keys$3, values: values$1, create: create$3, assign: assign$3, freeze, entries: entries$3 } = Object;
11738
11740
  const { stringify: stringify$3, parse: parse$3 } = JSON;
11739
11741
  const { shift } = Array.prototype;
11740
11742
  const { isArray: isArray$1, from: from$1 } = Array;
@@ -13063,7 +13065,7 @@ function getDenormalizedKey(originalKey, recordId, luvio) {
13063
13065
  }
13064
13066
  return keyBuilderRecord(luvio, { recordId });
13065
13067
  }
13066
- function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecords, getStoreMetadata, getStore) {
13068
+ function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecords, getStoreMetadata, getStore, sqlStore) {
13067
13069
  const getEntries = function (entries, segment) {
13068
13070
  // this HOF only inspects records in the default segment
13069
13071
  if (segment !== DefaultDurableSegment) {
@@ -13125,7 +13127,10 @@ function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecord
13125
13127
  });
13126
13128
  };
13127
13129
  const denormalizeEntries = function (entries) {
13130
+ let hasEntries = false;
13131
+ let hasMetadata = false;
13128
13132
  const putEntries = create$3(null);
13133
+ const putMetadata = create$3(null);
13129
13134
  const keys$1 = keys$3(entries);
13130
13135
  const putRecords = {};
13131
13136
  const putRecordViews = {};
@@ -13168,6 +13173,7 @@ function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecord
13168
13173
  putRecords[recordId] = true;
13169
13174
  }
13170
13175
  if (isStoreRecordError(record)) {
13176
+ hasEntries = true;
13171
13177
  putEntries[recordKey] = value;
13172
13178
  continue;
13173
13179
  }
@@ -13180,24 +13186,43 @@ function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecord
13180
13186
  }
13181
13187
  const denormalizedRecord = buildDurableRecordRepresentation(record, storeRecords, recordEntries, store);
13182
13188
  if (denormalizedRecord !== undefined) {
13189
+ hasEntries = true;
13183
13190
  putEntries[recordKey] = {
13184
13191
  data: denormalizedRecord,
13185
13192
  metadata,
13186
13193
  };
13194
+ // if undefined then it is pending
13195
+ // we should still update metadata on pending records
13196
+ }
13197
+ else {
13198
+ hasMetadata = true;
13199
+ metadata.expirationTimestamp = metadata.ingestionTimestamp;
13200
+ putMetadata[recordKey] = {
13201
+ metadata,
13202
+ };
13187
13203
  }
13188
13204
  }
13189
13205
  else {
13206
+ hasEntries = true;
13190
13207
  putEntries[key] = value;
13191
13208
  }
13192
13209
  }
13193
- return putEntries;
13210
+ return { putEntries, putMetadata, hasEntries, hasMetadata };
13194
13211
  };
13195
13212
  const setEntries = function (entries, segment) {
13196
13213
  if (segment !== DefaultDurableSegment) {
13197
13214
  return durableStore.setEntries(entries, segment);
13198
13215
  }
13199
- const putEntries = denormalizeEntries(entries);
13200
- return durableStore.setEntries(putEntries, segment);
13216
+ const { putEntries, putMetadata, hasEntries, hasMetadata } = denormalizeEntries(entries);
13217
+ const promises = [
13218
+ hasEntries ? durableStore.setEntries(putEntries, segment) : undefined,
13219
+ ];
13220
+ if (sqlStore !== undefined && sqlStore.isBatchUpdateSupported()) {
13221
+ promises.push(hasMetadata && sqlStore !== undefined
13222
+ ? durableStore.setMetadata(putMetadata, segment)
13223
+ : undefined);
13224
+ }
13225
+ return Promise.all(promises).then(() => { });
13201
13226
  };
13202
13227
  const batchOperations = function (operations) {
13203
13228
  const operationsWithDenormedRecords = [];
@@ -13214,10 +13239,20 @@ function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecord
13214
13239
  // this is determined by the plugin supporting update batch calls before it gets to this HOF.
13215
13240
  // so we only need to check one entry to confirm this for performance
13216
13241
  if (firstEntry.data !== undefined) {
13242
+ const { putEntries, putMetadata, hasMetadata } = denormalizeEntries(operation.entries);
13217
13243
  operationsWithDenormedRecords.push({
13218
13244
  ...operation,
13219
- entries: denormalizeEntries(operation.entries),
13245
+ entries: putEntries,
13220
13246
  });
13247
+ if (hasMetadata &&
13248
+ sqlStore !== undefined &&
13249
+ sqlStore.isBatchUpdateSupported() === true) {
13250
+ operationsWithDenormedRecords.push({
13251
+ ...operation,
13252
+ entries: putMetadata,
13253
+ type: 'setMetadata',
13254
+ });
13255
+ }
13221
13256
  }
13222
13257
  else {
13223
13258
  operationsWithDenormedRecords.push(operation);
@@ -13229,10 +13264,20 @@ function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecord
13229
13264
  operationsWithDenormedRecords.push(operation);
13230
13265
  continue;
13231
13266
  }
13267
+ const { putEntries, putMetadata, hasMetadata } = denormalizeEntries(operation.entries);
13232
13268
  operationsWithDenormedRecords.push({
13233
13269
  ...operation,
13234
- entries: denormalizeEntries(operation.entries),
13270
+ entries: putEntries,
13235
13271
  });
13272
+ if (hasMetadata &&
13273
+ sqlStore !== undefined &&
13274
+ sqlStore.isBatchUpdateSupported() === true) {
13275
+ operationsWithDenormedRecords.push({
13276
+ ...operation,
13277
+ entries: putMetadata,
13278
+ type: 'setMetadata',
13279
+ });
13280
+ }
13236
13281
  }
13237
13282
  return durableStore.batchOperations(operationsWithDenormedRecords);
13238
13283
  };
@@ -16297,6 +16342,9 @@ class NimbusSqliteStore {
16297
16342
  isEvalSupported() {
16298
16343
  return true;
16299
16344
  }
16345
+ isBatchUpdateSupported() {
16346
+ return this.supportsBatchUpdates;
16347
+ }
16300
16348
  query(sql, params) {
16301
16349
  return new Promise((resolve, reject) => {
16302
16350
  this.plugin.query(sql, params, (result) => {
@@ -16339,6 +16387,7 @@ class NimbusSqliteStore {
16339
16387
  return this.batchOperationAsPromise([operation]);
16340
16388
  }
16341
16389
  batchOperations(operations) {
16390
+ let fallbackSetMetadata = [];
16342
16391
  const sqliteOperations = operations.reduce((acc, cur) => {
16343
16392
  if (cur.type === 'setEntries') {
16344
16393
  const table = this.getTable(cur.segment);
@@ -16362,7 +16411,14 @@ class NimbusSqliteStore {
16362
16411
  }
16363
16412
  return acc;
16364
16413
  }, []);
16365
- return this.batchOperationAsPromise(sqliteOperations);
16414
+ return this.batchOperationAsPromise(sqliteOperations).then(() => {
16415
+ if (fallbackSetMetadata.length > 0) {
16416
+ return Promise.all(fallbackSetMetadata.map((fallback) => {
16417
+ const { entries, segment } = fallback;
16418
+ return this.setMetadata(entries, segment);
16419
+ })).then(() => { });
16420
+ }
16421
+ });
16366
16422
  }
16367
16423
  evictEntries(entryIds, segment) {
16368
16424
  const sqliteOperation = this.idsToDeleteOperation(entryIds, segment);
@@ -17833,6 +17889,76 @@ function primingSessionFactory(config) {
17833
17889
  return instrumentPrimingSession(session);
17834
17890
  }
17835
17891
 
17892
+ const DEFAULT_MAX_RECORD_COUNT = aggressiveTrimLowLimitGate.isOpen({ fallback: false })
17893
+ ? 20000
17894
+ : 200000;
17895
+ const DEFAULT_MAX_BATCH_SIZE = 200;
17896
+ async function aggressiveTrim(data, deallocateFn, options = {}) {
17897
+ const maxStoreRecords = options.maxStoreRecords !== undefined ? options.maxStoreRecords : DEFAULT_MAX_RECORD_COUNT;
17898
+ const batchSize = options.batchSize !== undefined ? options.batchSize : DEFAULT_MAX_BATCH_SIZE;
17899
+ let deallocatedCount = 0;
17900
+ const { pendingTrimKeys, retainedIds, storeRecords } = data;
17901
+ const storeKeyLength = keys$1(storeRecords).length;
17902
+ if (storeKeyLength <= maxStoreRecords) {
17903
+ return { deallocatedCount, trimKeysSkipped: pendingTrimKeys };
17904
+ }
17905
+ const overFlowSize = storeKeyLength - maxStoreRecords;
17906
+ if (overFlowSize <= 0) {
17907
+ return { deallocatedCount, trimKeysSkipped: pendingTrimKeys };
17908
+ }
17909
+ const trimKeys = new Set();
17910
+ for (const key of pendingTrimKeys) {
17911
+ if (storeKeyLength - trimKeys.size <= maxStoreRecords) {
17912
+ break;
17913
+ }
17914
+ if ((retainedIds[key] === undefined && storeRecords[key] !== undefined) ||
17915
+ (retainedIds[key] !== undefined && retainedIds[key] <= 1)) {
17916
+ trimKeys.add(key);
17917
+ }
17918
+ }
17919
+ const batches = batchKeys(trimKeys, batchSize).map((batch) => {
17920
+ return () => batchToPromise(batch, deallocateFn);
17921
+ });
17922
+ for (const batch of batches) {
17923
+ // execute each batch between ticks
17924
+ const count = await batch();
17925
+ deallocatedCount = deallocatedCount + count;
17926
+ }
17927
+ const trimKeysSkipped = makeSetFilteredFromDifference(pendingTrimKeys, (key) => trimKeys.has(key) === false);
17928
+ return {
17929
+ deallocatedCount,
17930
+ trimKeysSkipped,
17931
+ };
17932
+ }
17933
+ function batchToPromise(batch, deallocateFn) {
17934
+ return new Promise((resolve) => {
17935
+ let count = 0;
17936
+ batch.forEach((key) => {
17937
+ deallocateFn(key);
17938
+ count++;
17939
+ });
17940
+ resolve(count);
17941
+ });
17942
+ }
17943
+ function batchKeys(keys, batchSize) {
17944
+ const keyArray = Array.from(keys);
17945
+ const batches = [];
17946
+ for (let i = 0, len = keyArray.length; i < len; i += batchSize) {
17947
+ const batch = keyArray.slice(i, i + batchSize);
17948
+ batches.push(batch);
17949
+ }
17950
+ return batches;
17951
+ }
17952
+ function makeSetFilteredFromDifference(setToFilter, diff) {
17953
+ let filteredSet = new Set();
17954
+ setToFilter.forEach((t) => {
17955
+ if (diff(t)) {
17956
+ filteredSet.add(t);
17957
+ }
17958
+ });
17959
+ return filteredSet;
17960
+ }
17961
+
17836
17962
  // so eslint doesn't complain about nimbus
17837
17963
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
17838
17964
  /* global __nimbus */
@@ -17861,7 +17987,11 @@ function getRuntime() {
17861
17987
  // user id centric record ID generator
17862
17988
  const { newRecordId, isGenerated } = recordIdGenerator(userId);
17863
17989
  // non-draft-aware base services
17864
- const store = new InMemoryStore();
17990
+ let storeOptions = {};
17991
+ if (aggressiveTrimGate.isOpen({ fallback: false })) {
17992
+ storeOptions.customTrimPolicy = aggressiveTrim;
17993
+ }
17994
+ const store = new InMemoryStore(storeOptions);
17865
17995
  lazyNetworkAdapter = platformNetworkAdapter(makeNetworkAdapterChunkRecordFields(NimbusNetworkAdapter, {
17866
17996
  reportChunkCandidateUrlLength: reportChunkCandidateUrlLength,
17867
17997
  }));
@@ -17888,7 +18018,7 @@ function getRuntime() {
17888
18018
  let getIngestRecords;
17889
18019
  let getIngestMetadata;
17890
18020
  let getIngestStore;
17891
- const recordDenormingStore = makeRecordDenormalizingDurableStore(lazyLuvio, lazyBaseDurableStore, () => (getIngestRecords !== undefined ? getIngestRecords() : {}), () => (getIngestMetadata !== undefined ? getIngestMetadata() : {}), () => (getIngestStore !== undefined ? getIngestStore() : undefined));
18021
+ const recordDenormingStore = makeRecordDenormalizingDurableStore(lazyLuvio, lazyBaseDurableStore, () => (getIngestRecords !== undefined ? getIngestRecords() : {}), () => (getIngestMetadata !== undefined ? getIngestMetadata() : {}), () => (getIngestStore !== undefined ? getIngestStore() : undefined), lazyBaseDurableStore);
17892
18022
  const baseEnv = new Environment(store, lazyNetworkAdapter);
17893
18023
  const gqlEnv = makeEnvironmentGraphqlAware(baseEnv);
17894
18024
  const durableEnv = makeDurable(gqlEnv, {
@@ -17999,4 +18129,4 @@ register({
17999
18129
  });
18000
18130
 
18001
18131
  export { O11Y_NAMESPACE_LDS_MOBILE, getRuntime, registerReportObserver, reportGraphqlQueryParseError };
18002
- // version: 1.266.0-dev25-c260f46ec
18132
+ // version: 1.266.0-dev26-c7c66cb1b
@@ -0,0 +1,7 @@
1
+ import type { TrimTaskData, DeallocationFunction, TrimResult } from '@luvio/engine';
2
+ type TrimOptions = {
3
+ batchSize?: number;
4
+ maxStoreRecords?: number;
5
+ };
6
+ export declare function aggressiveTrim(data: TrimTaskData, deallocateFn: DeallocationFunction, options?: TrimOptions): Promise<TrimResult>;
7
+ export {};