@salesforce/lds-runtime-mobile 1.352.0 → 1.353.0
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
|
@@ -53,7 +53,7 @@ const { entries: entries$3, keys: keys$5 } = Object;
|
|
|
53
53
|
|
|
54
54
|
const UI_API_BASE_URI = '/services/data/v64.0/ui-api';
|
|
55
55
|
|
|
56
|
-
let instrumentation$
|
|
56
|
+
let instrumentation$2 = {
|
|
57
57
|
aggregateUiChunkCount: (_cb) => { },
|
|
58
58
|
aggregateUiConnectError: () => { },
|
|
59
59
|
duplicateRequest: (_cb) => { },
|
|
@@ -65,7 +65,7 @@ let instrumentation$1 = {
|
|
|
65
65
|
networkRateLimitExceeded: () => { },
|
|
66
66
|
};
|
|
67
67
|
function instrument(newInstrumentation) {
|
|
68
|
-
instrumentation$
|
|
68
|
+
instrumentation$2 = Object.assign(instrumentation$2, newInstrumentation);
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
const LDS_RECORDS_AGGREGATE_UI = 'LDS_Records_AggregateUi';
|
|
@@ -135,7 +135,7 @@ function mergeRecordFields$2(first, second) {
|
|
|
135
135
|
* would otherwise cause a query length exception.
|
|
136
136
|
*/
|
|
137
137
|
function dispatchSplitRecordAggregateUiAction(recordId, networkAdapter, resourceRequest, resourceRequestContext) {
|
|
138
|
-
instrumentation$
|
|
138
|
+
instrumentation$2.getRecordAggregateInvoke();
|
|
139
139
|
return networkAdapter(resourceRequest, resourceRequestContext).then((resp) => {
|
|
140
140
|
const { body } = resp;
|
|
141
141
|
// This response body could be an executeAggregateUi, which we don't natively support.
|
|
@@ -151,7 +151,7 @@ function dispatchSplitRecordAggregateUiAction(recordId, networkAdapter, resource
|
|
|
151
151
|
}
|
|
152
152
|
const merged = body.compositeResponse.reduce((seed, response) => {
|
|
153
153
|
if (response.httpStatusCode !== HttpStatusCode.Ok) {
|
|
154
|
-
instrumentation$
|
|
154
|
+
instrumentation$2.getRecordAggregateReject(() => recordId);
|
|
155
155
|
throw createErrorResponse(HttpStatusCode.ServerError, {
|
|
156
156
|
error: response.message,
|
|
157
157
|
});
|
|
@@ -161,7 +161,7 @@ function dispatchSplitRecordAggregateUiAction(recordId, networkAdapter, resource
|
|
|
161
161
|
}
|
|
162
162
|
return mergeRecordFields$2(seed, response.body);
|
|
163
163
|
}, null);
|
|
164
|
-
instrumentation$
|
|
164
|
+
instrumentation$2.getRecordAggregateResolve(() => {
|
|
165
165
|
return {
|
|
166
166
|
recordId,
|
|
167
167
|
apiName: merged.apiName,
|
|
@@ -169,7 +169,7 @@ function dispatchSplitRecordAggregateUiAction(recordId, networkAdapter, resource
|
|
|
169
169
|
});
|
|
170
170
|
return createOkResponse$1(merged);
|
|
171
171
|
}, (err) => {
|
|
172
|
-
instrumentation$
|
|
172
|
+
instrumentation$2.getRecordAggregateReject(() => recordId);
|
|
173
173
|
// rethrow error
|
|
174
174
|
throw err;
|
|
175
175
|
});
|
|
@@ -247,7 +247,7 @@ function buildAndDispatchGetRecordAggregateUi(recordId, req, params) {
|
|
|
247
247
|
const { networkAdapter, resourceRequest, resourceRequestContext } = req;
|
|
248
248
|
const compositeRequest = buildGetRecordByFieldsCompositeRequest(resourceRequest, params);
|
|
249
249
|
// W-12245125: Emit chunk size metrics
|
|
250
|
-
instrumentation$
|
|
250
|
+
instrumentation$2.aggregateUiChunkCount(() => compositeRequest.length);
|
|
251
251
|
const aggregateUiParams = {
|
|
252
252
|
compositeRequest,
|
|
253
253
|
};
|
|
@@ -491,7 +491,7 @@ function platformNetworkAdapter(baseNetworkAdapter) {
|
|
|
491
491
|
return (resourceRequest, resourceRequestContext) => {
|
|
492
492
|
if (!tokenBucket.take(1)) {
|
|
493
493
|
// We are hitting rate limiting, add some metrics
|
|
494
|
-
instrumentation$
|
|
494
|
+
instrumentation$2.networkRateLimitExceeded();
|
|
495
495
|
}
|
|
496
496
|
const salesforceRequest = {
|
|
497
497
|
networkAdapter: baseNetworkAdapter,
|
|
@@ -52402,6 +52402,8 @@ const NimbusBinaryStore = {
|
|
|
52402
52402
|
},
|
|
52403
52403
|
};
|
|
52404
52404
|
|
|
52405
|
+
const priming_session_batch={namespace:"sf.lds",name:"PrimingSessionBatch",pbjsSchema:{"nested":{"sf":{"nested":{"lds":{"nested":{"PrimingSessionBatch":{"fields":{"container":{"id":8,"type":"string"},"idCount":{"id":1,"type":"uint32"},"missingCount":{"id":3,"type":"uint32"},"wasFromPagination":{"id":5,"type":"bool"},"successCount":{"id":2,"type":"uint32"},"paginationCount":{"id":6,"type":"uint32"},"conflictedCount":{"id":4,"type":"uint32"},"ingestDuration":{"id":7,"type":"double"}}}}}}}}}};
|
|
52406
|
+
|
|
52405
52407
|
class EventEmitter {
|
|
52406
52408
|
constructor() {
|
|
52407
52409
|
// @ts-ignore typescript doesn't like us setting this to an empty object for some reason
|
|
@@ -52515,6 +52517,12 @@ function buildFieldUnionArray(existingRecord, incomingRecord, objectInfo) {
|
|
|
52515
52517
|
fieldUnion.push(`${fieldName}.Id`);
|
|
52516
52518
|
includesSpanningFields = true;
|
|
52517
52519
|
}
|
|
52520
|
+
else {
|
|
52521
|
+
// Field exists on record but not in object info.
|
|
52522
|
+
// Fall back to getRecords resolver in this case.
|
|
52523
|
+
fieldUnion.push(fieldName);
|
|
52524
|
+
includesSpanningFields = true;
|
|
52525
|
+
}
|
|
52518
52526
|
}
|
|
52519
52527
|
else {
|
|
52520
52528
|
fieldUnion.push(fieldName);
|
|
@@ -52740,8 +52748,17 @@ class ConflictPool {
|
|
|
52740
52748
|
}
|
|
52741
52749
|
}
|
|
52742
52750
|
|
|
52751
|
+
const instrumentation$1 = getInstrumentation(O11Y_NAMESPACE_LDS_MOBILE);
|
|
52743
52752
|
const DEFAULT_BATCH_SIZE = 500;
|
|
52744
52753
|
const DEFAULT_CONCURRENCY = 6;
|
|
52754
|
+
const MAX_RETRY_COUNT = 2;
|
|
52755
|
+
const SESSION_BATCH_SIZE = 'priming-session-batch-size';
|
|
52756
|
+
const SESSION_CONCURRENCY_LIMIT = 'priming-session-concurrency-limit';
|
|
52757
|
+
const SESSION_ENQUEUE_RECORD_COUNT = 'priming-session-enqueue-record-count';
|
|
52758
|
+
const SESSION_INGEST_WRITTEN = 'priming-session-ingest-written-count';
|
|
52759
|
+
const SESSION_INGEST_CONFLICTED = 'priming-session-ingest-conflicted-count';
|
|
52760
|
+
const SESSION_INGEST_ERRORS = 'priming-session-ingest-error-count';
|
|
52761
|
+
const SESSION_INGEST_DURATION = 'priming-session-ingest-duration';
|
|
52745
52762
|
class PrimingSession extends EventEmitter {
|
|
52746
52763
|
constructor(config) {
|
|
52747
52764
|
super();
|
|
@@ -52753,6 +52770,9 @@ class PrimingSession extends EventEmitter {
|
|
|
52753
52770
|
this.ldsRecordRefresher = config.ldsRecordRefresher;
|
|
52754
52771
|
this.networkWorkerPool = new AsyncWorkerPool(this.concurrency);
|
|
52755
52772
|
this.conflictPool = new ConflictPool(config.store, this.objectInfoLoader);
|
|
52773
|
+
this.retryTracker = new Map();
|
|
52774
|
+
instrumentation$1.trackValue(SESSION_BATCH_SIZE, config.batchSize ? config.batchSize : 0);
|
|
52775
|
+
instrumentation$1.trackValue(SESSION_CONCURRENCY_LIMIT, config.concurrency ? config.concurrency : 0);
|
|
52756
52776
|
}
|
|
52757
52777
|
// function that enqueues priming work
|
|
52758
52778
|
async enqueue(work) {
|
|
@@ -52771,6 +52791,9 @@ class PrimingSession extends EventEmitter {
|
|
|
52771
52791
|
unavailableTypes,
|
|
52772
52792
|
});
|
|
52773
52793
|
if (unavailableIds.length > 0) {
|
|
52794
|
+
for (const id of unavailableIds) {
|
|
52795
|
+
this.retryTracker.delete(id);
|
|
52796
|
+
}
|
|
52774
52797
|
this.emit('error', {
|
|
52775
52798
|
ids: unavailableIds,
|
|
52776
52799
|
code: 'precondition-error',
|
|
@@ -52784,8 +52807,40 @@ class PrimingSession extends EventEmitter {
|
|
|
52784
52807
|
cancel() {
|
|
52785
52808
|
this.networkWorkerPool.cancel();
|
|
52786
52809
|
}
|
|
52787
|
-
|
|
52810
|
+
handleInstrumentation(activity, stats, errors) {
|
|
52811
|
+
const schema = priming_session_batch;
|
|
52812
|
+
const userData = {
|
|
52813
|
+
...stats,
|
|
52814
|
+
};
|
|
52815
|
+
if (errors.length) {
|
|
52816
|
+
for (const error in errors) {
|
|
52817
|
+
activity.error(error, schema, userData);
|
|
52818
|
+
}
|
|
52819
|
+
}
|
|
52820
|
+
else {
|
|
52821
|
+
activity.stop(schema, userData);
|
|
52822
|
+
}
|
|
52823
|
+
}
|
|
52824
|
+
enqueueBatches(batches, paginationCount = 0) {
|
|
52788
52825
|
for (const batch of batches) {
|
|
52826
|
+
instrumentation$1.trackValue(SESSION_ENQUEUE_RECORD_COUNT, batch.ids.length);
|
|
52827
|
+
const o11yActivity = instrumentation$1.startActivity('primingSessionBatch');
|
|
52828
|
+
let stats = {
|
|
52829
|
+
idCount: 0,
|
|
52830
|
+
successCount: 0,
|
|
52831
|
+
missingCount: 0,
|
|
52832
|
+
conflictedCount: 0,
|
|
52833
|
+
wasFromPagination: false,
|
|
52834
|
+
paginationCount: 0,
|
|
52835
|
+
ingestDuration: 0,
|
|
52836
|
+
container: '',
|
|
52837
|
+
};
|
|
52838
|
+
let errors = [];
|
|
52839
|
+
if (paginationCount > 0) {
|
|
52840
|
+
stats.wasFromPagination = true;
|
|
52841
|
+
stats.paginationCount = paginationCount;
|
|
52842
|
+
}
|
|
52843
|
+
stats.idCount = batch.ids.length;
|
|
52789
52844
|
const queuedTime = Date.now();
|
|
52790
52845
|
this.networkWorkerPool.push({
|
|
52791
52846
|
workFn: (abortController) => {
|
|
@@ -52795,6 +52850,9 @@ class PrimingSession extends EventEmitter {
|
|
|
52795
52850
|
.fetchRecordData(batch, abortController)
|
|
52796
52851
|
.then(async (results) => {
|
|
52797
52852
|
if (abortController.aborted) {
|
|
52853
|
+
for (const id of batch.ids) {
|
|
52854
|
+
this.retryTracker.delete(id);
|
|
52855
|
+
}
|
|
52798
52856
|
return;
|
|
52799
52857
|
}
|
|
52800
52858
|
this.emit('batch-fetched', {
|
|
@@ -52802,12 +52860,20 @@ class PrimingSession extends EventEmitter {
|
|
|
52802
52860
|
duration: Date.now() - workTime,
|
|
52803
52861
|
});
|
|
52804
52862
|
for (const result of results) {
|
|
52805
|
-
this.processFetchedRecords(result, abortController);
|
|
52863
|
+
const returnedError = this.processFetchedRecords(result, abortController, stats);
|
|
52864
|
+
if (returnedError) {
|
|
52865
|
+
errors.push(returnedError);
|
|
52866
|
+
}
|
|
52806
52867
|
}
|
|
52807
|
-
this.handlePaginations(results, batch);
|
|
52868
|
+
this.handlePaginations(results, batch, paginationCount);
|
|
52869
|
+
})
|
|
52870
|
+
.finally(() => {
|
|
52871
|
+
this.handleInstrumentation(o11yActivity, stats, errors);
|
|
52808
52872
|
});
|
|
52809
52873
|
},
|
|
52810
52874
|
cancelFn: () => {
|
|
52875
|
+
errors.push('cancelled');
|
|
52876
|
+
this.handleInstrumentation(o11yActivity, stats, errors);
|
|
52811
52877
|
this.emit('error', {
|
|
52812
52878
|
ids: batch.ids,
|
|
52813
52879
|
code: 'canceled',
|
|
@@ -52817,7 +52883,7 @@ class PrimingSession extends EventEmitter {
|
|
|
52817
52883
|
});
|
|
52818
52884
|
}
|
|
52819
52885
|
}
|
|
52820
|
-
handlePaginations(results, batch) {
|
|
52886
|
+
handlePaginations(results, batch, paginationCount) {
|
|
52821
52887
|
const ids = this.recordLoader.getMissingIdsWithPagination(results);
|
|
52822
52888
|
if (ids.size > 0) {
|
|
52823
52889
|
const batches = chunk(Array.from(ids), this.batchSize).map((chunkOfIds) => ({
|
|
@@ -52826,10 +52892,10 @@ class PrimingSession extends EventEmitter {
|
|
|
52826
52892
|
fields: batch.fields,
|
|
52827
52893
|
objectInfo: batch.objectInfo,
|
|
52828
52894
|
}));
|
|
52829
|
-
this.enqueueBatches(batches);
|
|
52895
|
+
this.enqueueBatches(batches, paginationCount + 1);
|
|
52830
52896
|
}
|
|
52831
52897
|
}
|
|
52832
|
-
processFetchedRecords(result, abortController) {
|
|
52898
|
+
processFetchedRecords(result, abortController, stats) {
|
|
52833
52899
|
if (result.ok === false) {
|
|
52834
52900
|
const { error } = result;
|
|
52835
52901
|
let primingError = 'unknown';
|
|
@@ -52844,10 +52910,14 @@ class PrimingSession extends EventEmitter {
|
|
|
52844
52910
|
code: primingError,
|
|
52845
52911
|
message: `${result.messages.join(',')}`,
|
|
52846
52912
|
});
|
|
52847
|
-
|
|
52913
|
+
for (const id of result.missingIds) {
|
|
52914
|
+
this.retryTracker.delete(id);
|
|
52915
|
+
}
|
|
52916
|
+
return error;
|
|
52848
52917
|
}
|
|
52849
52918
|
const { missingIds } = result;
|
|
52850
52919
|
if (missingIds.length > 0 && !this.recordLoader.isResultWithPagination(result)) {
|
|
52920
|
+
stats.missingCount = missingIds.length;
|
|
52851
52921
|
this.emit('error', {
|
|
52852
52922
|
ids: missingIds,
|
|
52853
52923
|
code: 'not-found',
|
|
@@ -52855,11 +52925,17 @@ class PrimingSession extends EventEmitter {
|
|
|
52855
52925
|
});
|
|
52856
52926
|
}
|
|
52857
52927
|
const { records } = result;
|
|
52928
|
+
stats.successCount = records.length;
|
|
52858
52929
|
const beforeWrite = Date.now();
|
|
52859
52930
|
// dispatch the write but DO NOT wait on it to unblock the network pool
|
|
52860
52931
|
this.recordIngestor
|
|
52861
52932
|
.insertRecords(records, false)
|
|
52862
52933
|
.then(({ written, conflicted, errors }) => {
|
|
52934
|
+
instrumentation$1.trackValue(SESSION_INGEST_WRITTEN, written.length);
|
|
52935
|
+
instrumentation$1.trackValue(SESSION_INGEST_CONFLICTED, conflicted.length);
|
|
52936
|
+
instrumentation$1.trackValue(SESSION_INGEST_ERRORS, errors.length);
|
|
52937
|
+
instrumentation$1.trackValue(SESSION_INGEST_DURATION, Date.now() - beforeWrite);
|
|
52938
|
+
stats.conflictedCount = conflicted.length;
|
|
52863
52939
|
this.emit('batch-written', {
|
|
52864
52940
|
written,
|
|
52865
52941
|
conflicted,
|
|
@@ -52867,6 +52943,17 @@ class PrimingSession extends EventEmitter {
|
|
|
52867
52943
|
duration: Date.now() - beforeWrite,
|
|
52868
52944
|
});
|
|
52869
52945
|
if (abortController.aborted) {
|
|
52946
|
+
for (const id of written) {
|
|
52947
|
+
this.retryTracker.delete(id);
|
|
52948
|
+
}
|
|
52949
|
+
for (const id of conflicted) {
|
|
52950
|
+
this.retryTracker.delete(id);
|
|
52951
|
+
}
|
|
52952
|
+
for (const error of errors) {
|
|
52953
|
+
for (const id of error.ids) {
|
|
52954
|
+
this.retryTracker.delete(id);
|
|
52955
|
+
}
|
|
52956
|
+
}
|
|
52870
52957
|
return;
|
|
52871
52958
|
}
|
|
52872
52959
|
if (errors.length > 0) {
|
|
@@ -52876,11 +52963,17 @@ class PrimingSession extends EventEmitter {
|
|
|
52876
52963
|
code: 'unknown',
|
|
52877
52964
|
message: message,
|
|
52878
52965
|
});
|
|
52966
|
+
for (const id of ids) {
|
|
52967
|
+
this.retryTracker.delete(id);
|
|
52968
|
+
}
|
|
52879
52969
|
});
|
|
52880
52970
|
}
|
|
52881
52971
|
// now that the records are persisted, emit the primed event
|
|
52882
52972
|
if (written.length > 0) {
|
|
52883
52973
|
this.emit('primed', Array.from(written));
|
|
52974
|
+
for (const id of written) {
|
|
52975
|
+
this.retryTracker.delete(id);
|
|
52976
|
+
}
|
|
52884
52977
|
}
|
|
52885
52978
|
// if any records could not be written to the store because there were conflicts, handle the conflicts
|
|
52886
52979
|
if (conflicted.length > 0) {
|
|
@@ -52891,14 +52984,39 @@ class PrimingSession extends EventEmitter {
|
|
|
52891
52984
|
async handleWriteConflicts(records, conflicted, abortController) {
|
|
52892
52985
|
const result = await this.conflictPool.enqueueConflictedRecords(records.filter((x) => conflicted.includes(x.id)), abortController);
|
|
52893
52986
|
if (abortController.aborted) {
|
|
52987
|
+
for (const id of conflicted) {
|
|
52988
|
+
this.retryTracker.delete(id);
|
|
52989
|
+
}
|
|
52894
52990
|
return;
|
|
52895
52991
|
}
|
|
52896
|
-
if (
|
|
52992
|
+
if (keys$2(result.additionalWork.records).length > 0) {
|
|
52897
52993
|
this.emit('conflict', {
|
|
52898
52994
|
ids: Object.values(result.additionalWork.records).flatMap((record) => record.ids),
|
|
52899
52995
|
resolution: 'priming-refresh',
|
|
52900
52996
|
});
|
|
52901
|
-
|
|
52997
|
+
// we're re-enqueuing here, so apply retry limits which may change the batches
|
|
52998
|
+
let limitedResult = this.applyRetryLimits(result.additionalWork);
|
|
52999
|
+
this.enqueue(limitedResult.additionalWork);
|
|
53000
|
+
if (limitedResult.recordsNeedingRefetch.size > 0) {
|
|
53001
|
+
for (const key in keys$2(limitedResult.recordsNeedingRefetch)) {
|
|
53002
|
+
const value = limitedResult.recordsNeedingRefetch.get(key);
|
|
53003
|
+
if (result.recordsNeedingRefetch.has(key)) {
|
|
53004
|
+
let existing = result.recordsNeedingRefetch.get(key);
|
|
53005
|
+
existing = {
|
|
53006
|
+
// merge the ids
|
|
53007
|
+
ids: [...existing.ids, ...value.ids],
|
|
53008
|
+
// This is safe because they derive from the same
|
|
53009
|
+
// input, no chance of getting a new field in the
|
|
53010
|
+
// limited result
|
|
53011
|
+
fields: existing.fields,
|
|
53012
|
+
};
|
|
53013
|
+
result.recordsNeedingRefetch.set(key, existing);
|
|
53014
|
+
}
|
|
53015
|
+
else {
|
|
53016
|
+
result.recordsNeedingRefetch.set(key, value);
|
|
53017
|
+
}
|
|
53018
|
+
}
|
|
53019
|
+
}
|
|
52902
53020
|
}
|
|
52903
53021
|
if (result.resolvedRecords.length > 0) {
|
|
52904
53022
|
this.emit('conflict', {
|
|
@@ -52906,8 +53024,14 @@ class PrimingSession extends EventEmitter {
|
|
|
52906
53024
|
resolution: 'priming-merge',
|
|
52907
53025
|
});
|
|
52908
53026
|
this.emit('primed', result.resolvedRecords);
|
|
53027
|
+
for (const id of result.resolvedRecords) {
|
|
53028
|
+
this.retryTracker.delete(id);
|
|
53029
|
+
}
|
|
52909
53030
|
}
|
|
52910
53031
|
if (result.recordsToWrite.length > 0) {
|
|
53032
|
+
for (const record of result.recordsToWrite) {
|
|
53033
|
+
this.retryTracker.delete(record.id);
|
|
53034
|
+
}
|
|
52911
53035
|
const { written, errors, conflicted } = await this.recordIngestor.insertRecords(result.recordsToWrite, true);
|
|
52912
53036
|
if (written.length > 0) {
|
|
52913
53037
|
const ids = Array.from(written);
|
|
@@ -52934,10 +53058,16 @@ class PrimingSession extends EventEmitter {
|
|
|
52934
53058
|
if (result.recordsNeedingRefetch.size > 0) {
|
|
52935
53059
|
const { loaded, errored } = await this.ldsRecordRefresher.loadRecords(result.recordsNeedingRefetch);
|
|
52936
53060
|
if (loaded.length > 0) {
|
|
53061
|
+
for (const id of loaded) {
|
|
53062
|
+
this.retryTracker.delete(id);
|
|
53063
|
+
}
|
|
52937
53064
|
this.emit('conflict', { resolution: 'lds-refresh', ids: loaded });
|
|
52938
53065
|
this.emit('primed', loaded);
|
|
52939
53066
|
}
|
|
52940
53067
|
if (errored.length > 0) {
|
|
53068
|
+
for (const id of errored) {
|
|
53069
|
+
this.retryTracker.delete(id);
|
|
53070
|
+
}
|
|
52941
53071
|
this.emit('error', {
|
|
52942
53072
|
ids: errored,
|
|
52943
53073
|
code: 'unknown',
|
|
@@ -52946,6 +53076,50 @@ class PrimingSession extends EventEmitter {
|
|
|
52946
53076
|
}
|
|
52947
53077
|
}
|
|
52948
53078
|
}
|
|
53079
|
+
applyRetryLimits(primingWork) {
|
|
53080
|
+
// retryable work goes back into priming session
|
|
53081
|
+
let retryableWork = {
|
|
53082
|
+
type: 'record-fields',
|
|
53083
|
+
records: {},
|
|
53084
|
+
};
|
|
53085
|
+
// refetchable work gets delegated to getRecords
|
|
53086
|
+
let refetchableWork = new Map();
|
|
53087
|
+
for (const key of keys$2(primingWork.records)) {
|
|
53088
|
+
let work = primingWork.records[key];
|
|
53089
|
+
let limitedIds = [];
|
|
53090
|
+
for (const id of work.ids) {
|
|
53091
|
+
let retryCount = this.retryTracker.get(id) || 0;
|
|
53092
|
+
retryCount += 1;
|
|
53093
|
+
if (retryCount > MAX_RETRY_COUNT) {
|
|
53094
|
+
limitedIds.push(id);
|
|
53095
|
+
this.retryTracker.delete(id);
|
|
53096
|
+
}
|
|
53097
|
+
else {
|
|
53098
|
+
this.retryTracker.set(id, retryCount);
|
|
53099
|
+
}
|
|
53100
|
+
}
|
|
53101
|
+
if (limitedIds.length < work.ids.length) {
|
|
53102
|
+
retryableWork.records[key] = {
|
|
53103
|
+
ids: work.ids.filter((id) => limitedIds.indexOf(id) === -1),
|
|
53104
|
+
fields: work.fields,
|
|
53105
|
+
};
|
|
53106
|
+
}
|
|
53107
|
+
if (limitedIds.length > 0) {
|
|
53108
|
+
this.emit('retry-limit-reached', { ids: limitedIds });
|
|
53109
|
+
refetchableWork.set(key, {
|
|
53110
|
+
ids: limitedIds,
|
|
53111
|
+
fields: work.fields,
|
|
53112
|
+
});
|
|
53113
|
+
}
|
|
53114
|
+
}
|
|
53115
|
+
return {
|
|
53116
|
+
additionalWork: retryableWork,
|
|
53117
|
+
recordsNeedingRefetch: refetchableWork,
|
|
53118
|
+
resolvedRecords: [],
|
|
53119
|
+
recordsToWrite: [],
|
|
53120
|
+
errors: [],
|
|
53121
|
+
};
|
|
53122
|
+
}
|
|
52949
53123
|
async fetchMetadata(batches) {
|
|
52950
53124
|
const apiNames = Array.from(batches.reduce((acc, x) => {
|
|
52951
53125
|
return acc.add(x.type);
|
|
@@ -52953,20 +53127,20 @@ class PrimingSession extends EventEmitter {
|
|
|
52953
53127
|
const objectInfoMap = await this.objectInfoLoader.getObjectInfos(apiNames);
|
|
52954
53128
|
const unavailableTypes = apiNames.filter((x) => !objectInfoMap[x]);
|
|
52955
53129
|
const availableTypes = apiNames.filter((x) => objectInfoMap[x]);
|
|
52956
|
-
const
|
|
53130
|
+
const unavailableBatches = batches.filter((x) => unavailableTypes.includes(x.type));
|
|
52957
53131
|
const availableBatches = batches
|
|
52958
53132
|
.filter((x) => !unavailableTypes.includes(x.type))
|
|
52959
53133
|
.map((x) => {
|
|
52960
53134
|
return { ...x, objectInfo: objectInfoMap[x.type] };
|
|
52961
53135
|
});
|
|
52962
|
-
const unavailableIds =
|
|
53136
|
+
const unavailableIds = unavailableBatches.reduce((acc, x) => {
|
|
52963
53137
|
acc.push(...x.ids);
|
|
52964
53138
|
return acc;
|
|
52965
53139
|
}, []);
|
|
52966
53140
|
return {
|
|
52967
53141
|
apiNames,
|
|
52968
53142
|
availableBatches,
|
|
52969
|
-
|
|
53143
|
+
unavailableBatches,
|
|
52970
53144
|
unavailableTypes,
|
|
52971
53145
|
availableTypes,
|
|
52972
53146
|
unavailableIds,
|
|
@@ -53196,7 +53370,9 @@ class RecordLoaderGraphQL extends NetworkRecordLoader {
|
|
|
53196
53370
|
return acc;
|
|
53197
53371
|
}, {});
|
|
53198
53372
|
fields['Id'] = { value: id, displayValue: null };
|
|
53199
|
-
fields['RecordTypeId']
|
|
53373
|
+
if (objectInfo.fields['RecordTypeId'] !== undefined) {
|
|
53374
|
+
fields['RecordTypeId'] = { value: recordTypeId, displayValue: null };
|
|
53375
|
+
}
|
|
53200
53376
|
let recordTypeInfo = null;
|
|
53201
53377
|
if (recordTypeId !== null &&
|
|
53202
53378
|
objectInfo.recordTypeInfos &&
|
|
@@ -55496,4 +55672,4 @@ register({
|
|
|
55496
55672
|
});
|
|
55497
55673
|
|
|
55498
55674
|
export { O11Y_NAMESPACE_LDS_MOBILE, getRuntime, ingest$1o as ingestDenormalizedRecordRepresentation, registerReportObserver, reportGraphqlQueryParseError };
|
|
55499
|
-
// version: 1.
|
|
55675
|
+
// version: 1.353.0-cc9b469dc4
|
|
@@ -4,7 +4,7 @@ import type { PrimingStore } from './PrimingStore';
|
|
|
4
4
|
import type { PrimingWork } from './types';
|
|
5
5
|
import type { ObjectInfoLoader } from './ObjectInfoLoader';
|
|
6
6
|
type ConflictResolutionError = 'object-info-missing';
|
|
7
|
-
interface ConflictResolutionResult {
|
|
7
|
+
export interface ConflictResolutionResult {
|
|
8
8
|
additionalWork: PrimingWork;
|
|
9
9
|
recordsToWrite: DurableRecordRepresentation[];
|
|
10
10
|
resolvedRecords: string[];
|
|
@@ -5,6 +5,7 @@ import type { ObjectInfoLoader } from './ObjectInfoLoader';
|
|
|
5
5
|
import type { PrimingStore } from './PrimingStore';
|
|
6
6
|
import type { LdsRecordRefresher } from './LdsRecordRefresher';
|
|
7
7
|
import { EventEmitter } from './Emitter';
|
|
8
|
+
export declare const instrumentation: import("o11y/dist/modules/o11y/client/interfaces").Instrumentation;
|
|
8
9
|
export interface PrimingSessionConfig {
|
|
9
10
|
store: PrimingStore;
|
|
10
11
|
recordLoader: RecordLoader;
|
|
@@ -36,6 +37,9 @@ export interface PrimingEvents {
|
|
|
36
37
|
errors: string[];
|
|
37
38
|
duration: number;
|
|
38
39
|
};
|
|
40
|
+
'retry-limit-reached': {
|
|
41
|
+
ids: string[];
|
|
42
|
+
};
|
|
39
43
|
}
|
|
40
44
|
interface EventErrorPayload {
|
|
41
45
|
ids: string[];
|
|
@@ -56,13 +60,16 @@ export declare class PrimingSession extends EventEmitter<PrimingEvents> {
|
|
|
56
60
|
private networkWorkerPool;
|
|
57
61
|
private conflictPool;
|
|
58
62
|
private ldsRecordRefresher;
|
|
63
|
+
private retryTracker;
|
|
59
64
|
constructor(config: PrimingSessionConfig);
|
|
60
65
|
enqueue(work: PrimingWork): Promise<void>;
|
|
61
66
|
cancel(): void;
|
|
67
|
+
private handleInstrumentation;
|
|
62
68
|
private enqueueBatches;
|
|
63
69
|
private handlePaginations;
|
|
64
70
|
private processFetchedRecords;
|
|
65
71
|
private handleWriteConflicts;
|
|
72
|
+
private applyRetryLimits;
|
|
66
73
|
private fetchMetadata;
|
|
67
74
|
}
|
|
68
75
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/lds-runtime-mobile",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.353.0",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
5
5
|
"description": "LDS runtime for mobile/hybrid environments.",
|
|
6
6
|
"main": "dist/main.js",
|
|
@@ -32,23 +32,24 @@
|
|
|
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.
|
|
36
|
-
"@salesforce/lds-bindings": "^1.
|
|
37
|
-
"@salesforce/lds-instrumentation": "^1.
|
|
35
|
+
"@salesforce/lds-adapters-uiapi": "^1.353.0",
|
|
36
|
+
"@salesforce/lds-bindings": "^1.353.0",
|
|
37
|
+
"@salesforce/lds-instrumentation": "^1.353.0",
|
|
38
38
|
"@salesforce/user": "0.0.21",
|
|
39
|
-
"o11y": "250.7.0"
|
|
39
|
+
"o11y": "250.7.0",
|
|
40
|
+
"o11y_schema": "256.126.0"
|
|
40
41
|
},
|
|
41
42
|
"devDependencies": {
|
|
42
|
-
"@salesforce/lds-adapters-graphql": "^1.
|
|
43
|
-
"@salesforce/lds-drafts": "^1.
|
|
44
|
-
"@salesforce/lds-durable-records": "^1.
|
|
45
|
-
"@salesforce/lds-network-adapter": "^1.
|
|
46
|
-
"@salesforce/lds-network-nimbus": "^1.
|
|
47
|
-
"@salesforce/lds-store-binary": "^1.
|
|
48
|
-
"@salesforce/lds-store-nimbus": "^1.
|
|
49
|
-
"@salesforce/lds-store-sql": "^1.
|
|
50
|
-
"@salesforce/lds-utils-adapters": "^1.
|
|
51
|
-
"@salesforce/nimbus-plugin-lds": "^1.
|
|
43
|
+
"@salesforce/lds-adapters-graphql": "^1.353.0",
|
|
44
|
+
"@salesforce/lds-drafts": "^1.353.0",
|
|
45
|
+
"@salesforce/lds-durable-records": "^1.353.0",
|
|
46
|
+
"@salesforce/lds-network-adapter": "^1.353.0",
|
|
47
|
+
"@salesforce/lds-network-nimbus": "^1.353.0",
|
|
48
|
+
"@salesforce/lds-store-binary": "^1.353.0",
|
|
49
|
+
"@salesforce/lds-store-nimbus": "^1.353.0",
|
|
50
|
+
"@salesforce/lds-store-sql": "^1.353.0",
|
|
51
|
+
"@salesforce/lds-utils-adapters": "^1.353.0",
|
|
52
|
+
"@salesforce/nimbus-plugin-lds": "^1.353.0",
|
|
52
53
|
"babel-plugin-dynamic-import-node": "^2.3.3",
|
|
53
54
|
"wait-for-expect": "^3.0.2"
|
|
54
55
|
},
|
package/sfdc/main.js
CHANGED
|
@@ -53,7 +53,7 @@ const { entries: entries$3, keys: keys$5 } = Object;
|
|
|
53
53
|
|
|
54
54
|
const UI_API_BASE_URI = '/services/data/v64.0/ui-api';
|
|
55
55
|
|
|
56
|
-
let instrumentation$
|
|
56
|
+
let instrumentation$2 = {
|
|
57
57
|
aggregateUiChunkCount: (_cb) => { },
|
|
58
58
|
aggregateUiConnectError: () => { },
|
|
59
59
|
duplicateRequest: (_cb) => { },
|
|
@@ -65,7 +65,7 @@ let instrumentation$1 = {
|
|
|
65
65
|
networkRateLimitExceeded: () => { },
|
|
66
66
|
};
|
|
67
67
|
function instrument(newInstrumentation) {
|
|
68
|
-
instrumentation$
|
|
68
|
+
instrumentation$2 = Object.assign(instrumentation$2, newInstrumentation);
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
const LDS_RECORDS_AGGREGATE_UI = 'LDS_Records_AggregateUi';
|
|
@@ -135,7 +135,7 @@ function mergeRecordFields$2(first, second) {
|
|
|
135
135
|
* would otherwise cause a query length exception.
|
|
136
136
|
*/
|
|
137
137
|
function dispatchSplitRecordAggregateUiAction(recordId, networkAdapter, resourceRequest, resourceRequestContext) {
|
|
138
|
-
instrumentation$
|
|
138
|
+
instrumentation$2.getRecordAggregateInvoke();
|
|
139
139
|
return networkAdapter(resourceRequest, resourceRequestContext).then((resp) => {
|
|
140
140
|
const { body } = resp;
|
|
141
141
|
// This response body could be an executeAggregateUi, which we don't natively support.
|
|
@@ -151,7 +151,7 @@ function dispatchSplitRecordAggregateUiAction(recordId, networkAdapter, resource
|
|
|
151
151
|
}
|
|
152
152
|
const merged = body.compositeResponse.reduce((seed, response) => {
|
|
153
153
|
if (response.httpStatusCode !== HttpStatusCode.Ok) {
|
|
154
|
-
instrumentation$
|
|
154
|
+
instrumentation$2.getRecordAggregateReject(() => recordId);
|
|
155
155
|
throw createErrorResponse(HttpStatusCode.ServerError, {
|
|
156
156
|
error: response.message,
|
|
157
157
|
});
|
|
@@ -161,7 +161,7 @@ function dispatchSplitRecordAggregateUiAction(recordId, networkAdapter, resource
|
|
|
161
161
|
}
|
|
162
162
|
return mergeRecordFields$2(seed, response.body);
|
|
163
163
|
}, null);
|
|
164
|
-
instrumentation$
|
|
164
|
+
instrumentation$2.getRecordAggregateResolve(() => {
|
|
165
165
|
return {
|
|
166
166
|
recordId,
|
|
167
167
|
apiName: merged.apiName,
|
|
@@ -169,7 +169,7 @@ function dispatchSplitRecordAggregateUiAction(recordId, networkAdapter, resource
|
|
|
169
169
|
});
|
|
170
170
|
return createOkResponse$1(merged);
|
|
171
171
|
}, (err) => {
|
|
172
|
-
instrumentation$
|
|
172
|
+
instrumentation$2.getRecordAggregateReject(() => recordId);
|
|
173
173
|
// rethrow error
|
|
174
174
|
throw err;
|
|
175
175
|
});
|
|
@@ -247,7 +247,7 @@ function buildAndDispatchGetRecordAggregateUi(recordId, req, params) {
|
|
|
247
247
|
const { networkAdapter, resourceRequest, resourceRequestContext } = req;
|
|
248
248
|
const compositeRequest = buildGetRecordByFieldsCompositeRequest(resourceRequest, params);
|
|
249
249
|
// W-12245125: Emit chunk size metrics
|
|
250
|
-
instrumentation$
|
|
250
|
+
instrumentation$2.aggregateUiChunkCount(() => compositeRequest.length);
|
|
251
251
|
const aggregateUiParams = {
|
|
252
252
|
compositeRequest,
|
|
253
253
|
};
|
|
@@ -491,7 +491,7 @@ function platformNetworkAdapter(baseNetworkAdapter) {
|
|
|
491
491
|
return (resourceRequest, resourceRequestContext) => {
|
|
492
492
|
if (!tokenBucket.take(1)) {
|
|
493
493
|
// We are hitting rate limiting, add some metrics
|
|
494
|
-
instrumentation$
|
|
494
|
+
instrumentation$2.networkRateLimitExceeded();
|
|
495
495
|
}
|
|
496
496
|
const salesforceRequest = {
|
|
497
497
|
networkAdapter: baseNetworkAdapter,
|
|
@@ -52402,6 +52402,8 @@ const NimbusBinaryStore = {
|
|
|
52402
52402
|
},
|
|
52403
52403
|
};
|
|
52404
52404
|
|
|
52405
|
+
const priming_session_batch={namespace:"sf.lds",name:"PrimingSessionBatch",pbjsSchema:{"nested":{"sf":{"nested":{"lds":{"nested":{"PrimingSessionBatch":{"fields":{"container":{"id":8,"type":"string"},"idCount":{"id":1,"type":"uint32"},"missingCount":{"id":3,"type":"uint32"},"wasFromPagination":{"id":5,"type":"bool"},"successCount":{"id":2,"type":"uint32"},"paginationCount":{"id":6,"type":"uint32"},"conflictedCount":{"id":4,"type":"uint32"},"ingestDuration":{"id":7,"type":"double"}}}}}}}}}};
|
|
52406
|
+
|
|
52405
52407
|
class EventEmitter {
|
|
52406
52408
|
constructor() {
|
|
52407
52409
|
// @ts-ignore typescript doesn't like us setting this to an empty object for some reason
|
|
@@ -52515,6 +52517,12 @@ function buildFieldUnionArray(existingRecord, incomingRecord, objectInfo) {
|
|
|
52515
52517
|
fieldUnion.push(`${fieldName}.Id`);
|
|
52516
52518
|
includesSpanningFields = true;
|
|
52517
52519
|
}
|
|
52520
|
+
else {
|
|
52521
|
+
// Field exists on record but not in object info.
|
|
52522
|
+
// Fall back to getRecords resolver in this case.
|
|
52523
|
+
fieldUnion.push(fieldName);
|
|
52524
|
+
includesSpanningFields = true;
|
|
52525
|
+
}
|
|
52518
52526
|
}
|
|
52519
52527
|
else {
|
|
52520
52528
|
fieldUnion.push(fieldName);
|
|
@@ -52740,8 +52748,17 @@ class ConflictPool {
|
|
|
52740
52748
|
}
|
|
52741
52749
|
}
|
|
52742
52750
|
|
|
52751
|
+
const instrumentation$1 = getInstrumentation(O11Y_NAMESPACE_LDS_MOBILE);
|
|
52743
52752
|
const DEFAULT_BATCH_SIZE = 500;
|
|
52744
52753
|
const DEFAULT_CONCURRENCY = 6;
|
|
52754
|
+
const MAX_RETRY_COUNT = 2;
|
|
52755
|
+
const SESSION_BATCH_SIZE = 'priming-session-batch-size';
|
|
52756
|
+
const SESSION_CONCURRENCY_LIMIT = 'priming-session-concurrency-limit';
|
|
52757
|
+
const SESSION_ENQUEUE_RECORD_COUNT = 'priming-session-enqueue-record-count';
|
|
52758
|
+
const SESSION_INGEST_WRITTEN = 'priming-session-ingest-written-count';
|
|
52759
|
+
const SESSION_INGEST_CONFLICTED = 'priming-session-ingest-conflicted-count';
|
|
52760
|
+
const SESSION_INGEST_ERRORS = 'priming-session-ingest-error-count';
|
|
52761
|
+
const SESSION_INGEST_DURATION = 'priming-session-ingest-duration';
|
|
52745
52762
|
class PrimingSession extends EventEmitter {
|
|
52746
52763
|
constructor(config) {
|
|
52747
52764
|
super();
|
|
@@ -52753,6 +52770,9 @@ class PrimingSession extends EventEmitter {
|
|
|
52753
52770
|
this.ldsRecordRefresher = config.ldsRecordRefresher;
|
|
52754
52771
|
this.networkWorkerPool = new AsyncWorkerPool(this.concurrency);
|
|
52755
52772
|
this.conflictPool = new ConflictPool(config.store, this.objectInfoLoader);
|
|
52773
|
+
this.retryTracker = new Map();
|
|
52774
|
+
instrumentation$1.trackValue(SESSION_BATCH_SIZE, config.batchSize ? config.batchSize : 0);
|
|
52775
|
+
instrumentation$1.trackValue(SESSION_CONCURRENCY_LIMIT, config.concurrency ? config.concurrency : 0);
|
|
52756
52776
|
}
|
|
52757
52777
|
// function that enqueues priming work
|
|
52758
52778
|
async enqueue(work) {
|
|
@@ -52771,6 +52791,9 @@ class PrimingSession extends EventEmitter {
|
|
|
52771
52791
|
unavailableTypes,
|
|
52772
52792
|
});
|
|
52773
52793
|
if (unavailableIds.length > 0) {
|
|
52794
|
+
for (const id of unavailableIds) {
|
|
52795
|
+
this.retryTracker.delete(id);
|
|
52796
|
+
}
|
|
52774
52797
|
this.emit('error', {
|
|
52775
52798
|
ids: unavailableIds,
|
|
52776
52799
|
code: 'precondition-error',
|
|
@@ -52784,8 +52807,40 @@ class PrimingSession extends EventEmitter {
|
|
|
52784
52807
|
cancel() {
|
|
52785
52808
|
this.networkWorkerPool.cancel();
|
|
52786
52809
|
}
|
|
52787
|
-
|
|
52810
|
+
handleInstrumentation(activity, stats, errors) {
|
|
52811
|
+
const schema = priming_session_batch;
|
|
52812
|
+
const userData = {
|
|
52813
|
+
...stats,
|
|
52814
|
+
};
|
|
52815
|
+
if (errors.length) {
|
|
52816
|
+
for (const error in errors) {
|
|
52817
|
+
activity.error(error, schema, userData);
|
|
52818
|
+
}
|
|
52819
|
+
}
|
|
52820
|
+
else {
|
|
52821
|
+
activity.stop(schema, userData);
|
|
52822
|
+
}
|
|
52823
|
+
}
|
|
52824
|
+
enqueueBatches(batches, paginationCount = 0) {
|
|
52788
52825
|
for (const batch of batches) {
|
|
52826
|
+
instrumentation$1.trackValue(SESSION_ENQUEUE_RECORD_COUNT, batch.ids.length);
|
|
52827
|
+
const o11yActivity = instrumentation$1.startActivity('primingSessionBatch');
|
|
52828
|
+
let stats = {
|
|
52829
|
+
idCount: 0,
|
|
52830
|
+
successCount: 0,
|
|
52831
|
+
missingCount: 0,
|
|
52832
|
+
conflictedCount: 0,
|
|
52833
|
+
wasFromPagination: false,
|
|
52834
|
+
paginationCount: 0,
|
|
52835
|
+
ingestDuration: 0,
|
|
52836
|
+
container: '',
|
|
52837
|
+
};
|
|
52838
|
+
let errors = [];
|
|
52839
|
+
if (paginationCount > 0) {
|
|
52840
|
+
stats.wasFromPagination = true;
|
|
52841
|
+
stats.paginationCount = paginationCount;
|
|
52842
|
+
}
|
|
52843
|
+
stats.idCount = batch.ids.length;
|
|
52789
52844
|
const queuedTime = Date.now();
|
|
52790
52845
|
this.networkWorkerPool.push({
|
|
52791
52846
|
workFn: (abortController) => {
|
|
@@ -52795,6 +52850,9 @@ class PrimingSession extends EventEmitter {
|
|
|
52795
52850
|
.fetchRecordData(batch, abortController)
|
|
52796
52851
|
.then(async (results) => {
|
|
52797
52852
|
if (abortController.aborted) {
|
|
52853
|
+
for (const id of batch.ids) {
|
|
52854
|
+
this.retryTracker.delete(id);
|
|
52855
|
+
}
|
|
52798
52856
|
return;
|
|
52799
52857
|
}
|
|
52800
52858
|
this.emit('batch-fetched', {
|
|
@@ -52802,12 +52860,20 @@ class PrimingSession extends EventEmitter {
|
|
|
52802
52860
|
duration: Date.now() - workTime,
|
|
52803
52861
|
});
|
|
52804
52862
|
for (const result of results) {
|
|
52805
|
-
this.processFetchedRecords(result, abortController);
|
|
52863
|
+
const returnedError = this.processFetchedRecords(result, abortController, stats);
|
|
52864
|
+
if (returnedError) {
|
|
52865
|
+
errors.push(returnedError);
|
|
52866
|
+
}
|
|
52806
52867
|
}
|
|
52807
|
-
this.handlePaginations(results, batch);
|
|
52868
|
+
this.handlePaginations(results, batch, paginationCount);
|
|
52869
|
+
})
|
|
52870
|
+
.finally(() => {
|
|
52871
|
+
this.handleInstrumentation(o11yActivity, stats, errors);
|
|
52808
52872
|
});
|
|
52809
52873
|
},
|
|
52810
52874
|
cancelFn: () => {
|
|
52875
|
+
errors.push('cancelled');
|
|
52876
|
+
this.handleInstrumentation(o11yActivity, stats, errors);
|
|
52811
52877
|
this.emit('error', {
|
|
52812
52878
|
ids: batch.ids,
|
|
52813
52879
|
code: 'canceled',
|
|
@@ -52817,7 +52883,7 @@ class PrimingSession extends EventEmitter {
|
|
|
52817
52883
|
});
|
|
52818
52884
|
}
|
|
52819
52885
|
}
|
|
52820
|
-
handlePaginations(results, batch) {
|
|
52886
|
+
handlePaginations(results, batch, paginationCount) {
|
|
52821
52887
|
const ids = this.recordLoader.getMissingIdsWithPagination(results);
|
|
52822
52888
|
if (ids.size > 0) {
|
|
52823
52889
|
const batches = chunk(Array.from(ids), this.batchSize).map((chunkOfIds) => ({
|
|
@@ -52826,10 +52892,10 @@ class PrimingSession extends EventEmitter {
|
|
|
52826
52892
|
fields: batch.fields,
|
|
52827
52893
|
objectInfo: batch.objectInfo,
|
|
52828
52894
|
}));
|
|
52829
|
-
this.enqueueBatches(batches);
|
|
52895
|
+
this.enqueueBatches(batches, paginationCount + 1);
|
|
52830
52896
|
}
|
|
52831
52897
|
}
|
|
52832
|
-
processFetchedRecords(result, abortController) {
|
|
52898
|
+
processFetchedRecords(result, abortController, stats) {
|
|
52833
52899
|
if (result.ok === false) {
|
|
52834
52900
|
const { error } = result;
|
|
52835
52901
|
let primingError = 'unknown';
|
|
@@ -52844,10 +52910,14 @@ class PrimingSession extends EventEmitter {
|
|
|
52844
52910
|
code: primingError,
|
|
52845
52911
|
message: `${result.messages.join(',')}`,
|
|
52846
52912
|
});
|
|
52847
|
-
|
|
52913
|
+
for (const id of result.missingIds) {
|
|
52914
|
+
this.retryTracker.delete(id);
|
|
52915
|
+
}
|
|
52916
|
+
return error;
|
|
52848
52917
|
}
|
|
52849
52918
|
const { missingIds } = result;
|
|
52850
52919
|
if (missingIds.length > 0 && !this.recordLoader.isResultWithPagination(result)) {
|
|
52920
|
+
stats.missingCount = missingIds.length;
|
|
52851
52921
|
this.emit('error', {
|
|
52852
52922
|
ids: missingIds,
|
|
52853
52923
|
code: 'not-found',
|
|
@@ -52855,11 +52925,17 @@ class PrimingSession extends EventEmitter {
|
|
|
52855
52925
|
});
|
|
52856
52926
|
}
|
|
52857
52927
|
const { records } = result;
|
|
52928
|
+
stats.successCount = records.length;
|
|
52858
52929
|
const beforeWrite = Date.now();
|
|
52859
52930
|
// dispatch the write but DO NOT wait on it to unblock the network pool
|
|
52860
52931
|
this.recordIngestor
|
|
52861
52932
|
.insertRecords(records, false)
|
|
52862
52933
|
.then(({ written, conflicted, errors }) => {
|
|
52934
|
+
instrumentation$1.trackValue(SESSION_INGEST_WRITTEN, written.length);
|
|
52935
|
+
instrumentation$1.trackValue(SESSION_INGEST_CONFLICTED, conflicted.length);
|
|
52936
|
+
instrumentation$1.trackValue(SESSION_INGEST_ERRORS, errors.length);
|
|
52937
|
+
instrumentation$1.trackValue(SESSION_INGEST_DURATION, Date.now() - beforeWrite);
|
|
52938
|
+
stats.conflictedCount = conflicted.length;
|
|
52863
52939
|
this.emit('batch-written', {
|
|
52864
52940
|
written,
|
|
52865
52941
|
conflicted,
|
|
@@ -52867,6 +52943,17 @@ class PrimingSession extends EventEmitter {
|
|
|
52867
52943
|
duration: Date.now() - beforeWrite,
|
|
52868
52944
|
});
|
|
52869
52945
|
if (abortController.aborted) {
|
|
52946
|
+
for (const id of written) {
|
|
52947
|
+
this.retryTracker.delete(id);
|
|
52948
|
+
}
|
|
52949
|
+
for (const id of conflicted) {
|
|
52950
|
+
this.retryTracker.delete(id);
|
|
52951
|
+
}
|
|
52952
|
+
for (const error of errors) {
|
|
52953
|
+
for (const id of error.ids) {
|
|
52954
|
+
this.retryTracker.delete(id);
|
|
52955
|
+
}
|
|
52956
|
+
}
|
|
52870
52957
|
return;
|
|
52871
52958
|
}
|
|
52872
52959
|
if (errors.length > 0) {
|
|
@@ -52876,11 +52963,17 @@ class PrimingSession extends EventEmitter {
|
|
|
52876
52963
|
code: 'unknown',
|
|
52877
52964
|
message: message,
|
|
52878
52965
|
});
|
|
52966
|
+
for (const id of ids) {
|
|
52967
|
+
this.retryTracker.delete(id);
|
|
52968
|
+
}
|
|
52879
52969
|
});
|
|
52880
52970
|
}
|
|
52881
52971
|
// now that the records are persisted, emit the primed event
|
|
52882
52972
|
if (written.length > 0) {
|
|
52883
52973
|
this.emit('primed', Array.from(written));
|
|
52974
|
+
for (const id of written) {
|
|
52975
|
+
this.retryTracker.delete(id);
|
|
52976
|
+
}
|
|
52884
52977
|
}
|
|
52885
52978
|
// if any records could not be written to the store because there were conflicts, handle the conflicts
|
|
52886
52979
|
if (conflicted.length > 0) {
|
|
@@ -52891,14 +52984,39 @@ class PrimingSession extends EventEmitter {
|
|
|
52891
52984
|
async handleWriteConflicts(records, conflicted, abortController) {
|
|
52892
52985
|
const result = await this.conflictPool.enqueueConflictedRecords(records.filter((x) => conflicted.includes(x.id)), abortController);
|
|
52893
52986
|
if (abortController.aborted) {
|
|
52987
|
+
for (const id of conflicted) {
|
|
52988
|
+
this.retryTracker.delete(id);
|
|
52989
|
+
}
|
|
52894
52990
|
return;
|
|
52895
52991
|
}
|
|
52896
|
-
if (
|
|
52992
|
+
if (keys$2(result.additionalWork.records).length > 0) {
|
|
52897
52993
|
this.emit('conflict', {
|
|
52898
52994
|
ids: Object.values(result.additionalWork.records).flatMap((record) => record.ids),
|
|
52899
52995
|
resolution: 'priming-refresh',
|
|
52900
52996
|
});
|
|
52901
|
-
|
|
52997
|
+
// we're re-enqueuing here, so apply retry limits which may change the batches
|
|
52998
|
+
let limitedResult = this.applyRetryLimits(result.additionalWork);
|
|
52999
|
+
this.enqueue(limitedResult.additionalWork);
|
|
53000
|
+
if (limitedResult.recordsNeedingRefetch.size > 0) {
|
|
53001
|
+
for (const key in keys$2(limitedResult.recordsNeedingRefetch)) {
|
|
53002
|
+
const value = limitedResult.recordsNeedingRefetch.get(key);
|
|
53003
|
+
if (result.recordsNeedingRefetch.has(key)) {
|
|
53004
|
+
let existing = result.recordsNeedingRefetch.get(key);
|
|
53005
|
+
existing = {
|
|
53006
|
+
// merge the ids
|
|
53007
|
+
ids: [...existing.ids, ...value.ids],
|
|
53008
|
+
// This is safe because they derive from the same
|
|
53009
|
+
// input, no chance of getting a new field in the
|
|
53010
|
+
// limited result
|
|
53011
|
+
fields: existing.fields,
|
|
53012
|
+
};
|
|
53013
|
+
result.recordsNeedingRefetch.set(key, existing);
|
|
53014
|
+
}
|
|
53015
|
+
else {
|
|
53016
|
+
result.recordsNeedingRefetch.set(key, value);
|
|
53017
|
+
}
|
|
53018
|
+
}
|
|
53019
|
+
}
|
|
52902
53020
|
}
|
|
52903
53021
|
if (result.resolvedRecords.length > 0) {
|
|
52904
53022
|
this.emit('conflict', {
|
|
@@ -52906,8 +53024,14 @@ class PrimingSession extends EventEmitter {
|
|
|
52906
53024
|
resolution: 'priming-merge',
|
|
52907
53025
|
});
|
|
52908
53026
|
this.emit('primed', result.resolvedRecords);
|
|
53027
|
+
for (const id of result.resolvedRecords) {
|
|
53028
|
+
this.retryTracker.delete(id);
|
|
53029
|
+
}
|
|
52909
53030
|
}
|
|
52910
53031
|
if (result.recordsToWrite.length > 0) {
|
|
53032
|
+
for (const record of result.recordsToWrite) {
|
|
53033
|
+
this.retryTracker.delete(record.id);
|
|
53034
|
+
}
|
|
52911
53035
|
const { written, errors, conflicted } = await this.recordIngestor.insertRecords(result.recordsToWrite, true);
|
|
52912
53036
|
if (written.length > 0) {
|
|
52913
53037
|
const ids = Array.from(written);
|
|
@@ -52934,10 +53058,16 @@ class PrimingSession extends EventEmitter {
|
|
|
52934
53058
|
if (result.recordsNeedingRefetch.size > 0) {
|
|
52935
53059
|
const { loaded, errored } = await this.ldsRecordRefresher.loadRecords(result.recordsNeedingRefetch);
|
|
52936
53060
|
if (loaded.length > 0) {
|
|
53061
|
+
for (const id of loaded) {
|
|
53062
|
+
this.retryTracker.delete(id);
|
|
53063
|
+
}
|
|
52937
53064
|
this.emit('conflict', { resolution: 'lds-refresh', ids: loaded });
|
|
52938
53065
|
this.emit('primed', loaded);
|
|
52939
53066
|
}
|
|
52940
53067
|
if (errored.length > 0) {
|
|
53068
|
+
for (const id of errored) {
|
|
53069
|
+
this.retryTracker.delete(id);
|
|
53070
|
+
}
|
|
52941
53071
|
this.emit('error', {
|
|
52942
53072
|
ids: errored,
|
|
52943
53073
|
code: 'unknown',
|
|
@@ -52946,6 +53076,50 @@ class PrimingSession extends EventEmitter {
|
|
|
52946
53076
|
}
|
|
52947
53077
|
}
|
|
52948
53078
|
}
|
|
53079
|
+
applyRetryLimits(primingWork) {
|
|
53080
|
+
// retryable work goes back into priming session
|
|
53081
|
+
let retryableWork = {
|
|
53082
|
+
type: 'record-fields',
|
|
53083
|
+
records: {},
|
|
53084
|
+
};
|
|
53085
|
+
// refetchable work gets delegated to getRecords
|
|
53086
|
+
let refetchableWork = new Map();
|
|
53087
|
+
for (const key of keys$2(primingWork.records)) {
|
|
53088
|
+
let work = primingWork.records[key];
|
|
53089
|
+
let limitedIds = [];
|
|
53090
|
+
for (const id of work.ids) {
|
|
53091
|
+
let retryCount = this.retryTracker.get(id) || 0;
|
|
53092
|
+
retryCount += 1;
|
|
53093
|
+
if (retryCount > MAX_RETRY_COUNT) {
|
|
53094
|
+
limitedIds.push(id);
|
|
53095
|
+
this.retryTracker.delete(id);
|
|
53096
|
+
}
|
|
53097
|
+
else {
|
|
53098
|
+
this.retryTracker.set(id, retryCount);
|
|
53099
|
+
}
|
|
53100
|
+
}
|
|
53101
|
+
if (limitedIds.length < work.ids.length) {
|
|
53102
|
+
retryableWork.records[key] = {
|
|
53103
|
+
ids: work.ids.filter((id) => limitedIds.indexOf(id) === -1),
|
|
53104
|
+
fields: work.fields,
|
|
53105
|
+
};
|
|
53106
|
+
}
|
|
53107
|
+
if (limitedIds.length > 0) {
|
|
53108
|
+
this.emit('retry-limit-reached', { ids: limitedIds });
|
|
53109
|
+
refetchableWork.set(key, {
|
|
53110
|
+
ids: limitedIds,
|
|
53111
|
+
fields: work.fields,
|
|
53112
|
+
});
|
|
53113
|
+
}
|
|
53114
|
+
}
|
|
53115
|
+
return {
|
|
53116
|
+
additionalWork: retryableWork,
|
|
53117
|
+
recordsNeedingRefetch: refetchableWork,
|
|
53118
|
+
resolvedRecords: [],
|
|
53119
|
+
recordsToWrite: [],
|
|
53120
|
+
errors: [],
|
|
53121
|
+
};
|
|
53122
|
+
}
|
|
52949
53123
|
async fetchMetadata(batches) {
|
|
52950
53124
|
const apiNames = Array.from(batches.reduce((acc, x) => {
|
|
52951
53125
|
return acc.add(x.type);
|
|
@@ -52953,20 +53127,20 @@ class PrimingSession extends EventEmitter {
|
|
|
52953
53127
|
const objectInfoMap = await this.objectInfoLoader.getObjectInfos(apiNames);
|
|
52954
53128
|
const unavailableTypes = apiNames.filter((x) => !objectInfoMap[x]);
|
|
52955
53129
|
const availableTypes = apiNames.filter((x) => objectInfoMap[x]);
|
|
52956
|
-
const
|
|
53130
|
+
const unavailableBatches = batches.filter((x) => unavailableTypes.includes(x.type));
|
|
52957
53131
|
const availableBatches = batches
|
|
52958
53132
|
.filter((x) => !unavailableTypes.includes(x.type))
|
|
52959
53133
|
.map((x) => {
|
|
52960
53134
|
return { ...x, objectInfo: objectInfoMap[x.type] };
|
|
52961
53135
|
});
|
|
52962
|
-
const unavailableIds =
|
|
53136
|
+
const unavailableIds = unavailableBatches.reduce((acc, x) => {
|
|
52963
53137
|
acc.push(...x.ids);
|
|
52964
53138
|
return acc;
|
|
52965
53139
|
}, []);
|
|
52966
53140
|
return {
|
|
52967
53141
|
apiNames,
|
|
52968
53142
|
availableBatches,
|
|
52969
|
-
|
|
53143
|
+
unavailableBatches,
|
|
52970
53144
|
unavailableTypes,
|
|
52971
53145
|
availableTypes,
|
|
52972
53146
|
unavailableIds,
|
|
@@ -53196,7 +53370,9 @@ class RecordLoaderGraphQL extends NetworkRecordLoader {
|
|
|
53196
53370
|
return acc;
|
|
53197
53371
|
}, {});
|
|
53198
53372
|
fields['Id'] = { value: id, displayValue: null };
|
|
53199
|
-
fields['RecordTypeId']
|
|
53373
|
+
if (objectInfo.fields['RecordTypeId'] !== undefined) {
|
|
53374
|
+
fields['RecordTypeId'] = { value: recordTypeId, displayValue: null };
|
|
53375
|
+
}
|
|
53200
53376
|
let recordTypeInfo = null;
|
|
53201
53377
|
if (recordTypeId !== null &&
|
|
53202
53378
|
objectInfo.recordTypeInfos &&
|
|
@@ -55496,4 +55672,4 @@ register({
|
|
|
55496
55672
|
});
|
|
55497
55673
|
|
|
55498
55674
|
export { O11Y_NAMESPACE_LDS_MOBILE, getRuntime, ingest$1o as ingestDenormalizedRecordRepresentation, registerReportObserver, reportGraphqlQueryParseError };
|
|
55499
|
-
// version: 1.
|
|
55675
|
+
// version: 1.353.0-cc9b469dc4
|
|
@@ -4,7 +4,7 @@ import type { PrimingStore } from './PrimingStore';
|
|
|
4
4
|
import type { PrimingWork } from './types';
|
|
5
5
|
import type { ObjectInfoLoader } from './ObjectInfoLoader';
|
|
6
6
|
type ConflictResolutionError = 'object-info-missing';
|
|
7
|
-
interface ConflictResolutionResult {
|
|
7
|
+
export interface ConflictResolutionResult {
|
|
8
8
|
additionalWork: PrimingWork;
|
|
9
9
|
recordsToWrite: DurableRecordRepresentation[];
|
|
10
10
|
resolvedRecords: string[];
|
|
@@ -5,6 +5,7 @@ import type { ObjectInfoLoader } from './ObjectInfoLoader';
|
|
|
5
5
|
import type { PrimingStore } from './PrimingStore';
|
|
6
6
|
import type { LdsRecordRefresher } from './LdsRecordRefresher';
|
|
7
7
|
import { EventEmitter } from './Emitter';
|
|
8
|
+
export declare const instrumentation: import("o11y/dist/modules/o11y/client/interfaces").Instrumentation;
|
|
8
9
|
export interface PrimingSessionConfig {
|
|
9
10
|
store: PrimingStore;
|
|
10
11
|
recordLoader: RecordLoader;
|
|
@@ -36,6 +37,9 @@ export interface PrimingEvents {
|
|
|
36
37
|
errors: string[];
|
|
37
38
|
duration: number;
|
|
38
39
|
};
|
|
40
|
+
'retry-limit-reached': {
|
|
41
|
+
ids: string[];
|
|
42
|
+
};
|
|
39
43
|
}
|
|
40
44
|
interface EventErrorPayload {
|
|
41
45
|
ids: string[];
|
|
@@ -56,13 +60,16 @@ export declare class PrimingSession extends EventEmitter<PrimingEvents> {
|
|
|
56
60
|
private networkWorkerPool;
|
|
57
61
|
private conflictPool;
|
|
58
62
|
private ldsRecordRefresher;
|
|
63
|
+
private retryTracker;
|
|
59
64
|
constructor(config: PrimingSessionConfig);
|
|
60
65
|
enqueue(work: PrimingWork): Promise<void>;
|
|
61
66
|
cancel(): void;
|
|
67
|
+
private handleInstrumentation;
|
|
62
68
|
private enqueueBatches;
|
|
63
69
|
private handlePaginations;
|
|
64
70
|
private processFetchedRecords;
|
|
65
71
|
private handleWriteConflicts;
|
|
72
|
+
private applyRetryLimits;
|
|
66
73
|
private fetchMetadata;
|
|
67
74
|
}
|
|
68
75
|
export {};
|