relay-runtime 18.2.0 → 20.0.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/experimental.js +1 -1
- package/experimental.js.flow +8 -6
- package/index.js +1 -1
- package/index.js.flow +3 -0
- package/lib/experimental.js +5 -2
- package/lib/index.js +3 -0
- package/lib/multi-actor-environment/ActorSpecificEnvironment.js +1 -1
- package/lib/mutations/RelayRecordSourceProxy.js +2 -1
- package/lib/mutations/createUpdatableProxy.js +1 -1
- package/lib/mutations/validateMutation.js +2 -2
- package/lib/network/RelayObservable.js +1 -3
- package/lib/network/wrapNetworkWithLogObserver.js +2 -2
- package/lib/query/fetchQuery.js +1 -1
- package/lib/store/DataChecker.js +12 -8
- package/lib/store/OperationExecutor.js +93 -43
- package/lib/store/RelayModernEnvironment.js +13 -4
- package/lib/store/RelayModernFragmentSpecResolver.js +4 -4
- package/lib/store/RelayModernStore.js +49 -24
- package/lib/store/RelayPublishQueue.js +11 -15
- package/lib/store/RelayReader.js +134 -151
- package/lib/store/RelayReferenceMarker.js +14 -7
- package/lib/store/RelayResponseNormalizer.js +57 -31
- package/lib/store/RelayStoreSubscriptions.js +2 -2
- package/lib/store/RelayStoreUtils.js +8 -0
- package/lib/store/ResolverFragments.js +2 -2
- package/lib/store/createRelayLoggingContext.js +17 -0
- package/lib/store/generateTypenamePrefixedDataID.js +9 -0
- package/lib/store/live-resolvers/LiveResolverCache.js +4 -2
- package/lib/store/live-resolvers/resolverDataInjector.js +4 -4
- package/lib/store/normalizeResponse.js +2 -2
- package/lib/store/observeFragmentExperimental.js +60 -13
- package/lib/store/observeQueryExperimental.js +21 -0
- package/lib/util/RelayFeatureFlags.js +7 -1
- package/lib/util/handlePotentialSnapshotErrors.js +11 -8
- package/multi-actor-environment/ActorSpecificEnvironment.js.flow +1 -0
- package/mutations/RelayRecordSourceProxy.js.flow +4 -0
- package/mutations/createUpdatableProxy.js.flow +1 -1
- package/mutations/validateMutation.js.flow +3 -3
- package/network/RelayNetworkTypes.js.flow +3 -0
- package/network/RelayObservable.js.flow +1 -5
- package/network/wrapNetworkWithLogObserver.js.flow +19 -1
- package/package.json +1 -1
- package/query/fetchQuery.js.flow +1 -1
- package/store/DataChecker.js.flow +16 -4
- package/store/OperationExecutor.js.flow +101 -15
- package/store/RelayExperimentalGraphResponseTransform.js.flow +4 -4
- package/store/RelayModernEnvironment.js.flow +22 -6
- package/store/RelayModernFragmentSpecResolver.js.flow +6 -6
- package/store/RelayModernSelector.js.flow +2 -0
- package/store/RelayModernStore.js.flow +86 -27
- package/store/RelayPublishQueue.js.flow +32 -21
- package/store/RelayReader.js.flow +168 -97
- package/store/RelayReferenceMarker.js.flow +15 -5
- package/store/RelayResponseNormalizer.js.flow +104 -69
- package/store/RelayStoreSubscriptions.js.flow +2 -2
- package/store/RelayStoreTypes.js.flow +34 -4
- package/store/RelayStoreUtils.js.flow +29 -0
- package/store/ResolverCache.js.flow +2 -2
- package/store/ResolverFragments.js.flow +5 -3
- package/store/StoreInspector.js.flow +5 -0
- package/store/createRelayContext.js.flow +3 -2
- package/store/createRelayLoggingContext.js.flow +46 -0
- package/store/generateTypenamePrefixedDataID.js.flow +25 -0
- package/store/live-resolvers/LiveResolverCache.js.flow +7 -2
- package/store/live-resolvers/resolverDataInjector.js.flow +10 -6
- package/store/normalizeResponse.js.flow +2 -0
- package/store/observeFragmentExperimental.js.flow +82 -28
- package/store/observeQueryExperimental.js.flow +61 -0
- package/store/waitForFragmentExperimental.js.flow +4 -3
- package/util/NormalizationNode.js.flow +2 -1
- package/util/RelayConcreteNode.js.flow +2 -0
- package/util/RelayError.js.flow +1 -0
- package/util/RelayFeatureFlags.js.flow +28 -0
- package/util/RelayRuntimeTypes.js.flow +6 -3
- package/util/getPaginationVariables.js.flow +2 -0
- package/util/handlePotentialSnapshotErrors.js.flow +23 -11
- package/util/registerEnvironmentWithDevTools.js.flow +4 -2
- package/util/withProvidedVariables.js.flow +1 -0
- package/util/withStartAndDuration.js.flow +3 -0
- package/relay-runtime-experimental.js +0 -4
- package/relay-runtime-experimental.min.js +0 -9
- package/relay-runtime.js +0 -4
- package/relay-runtime.min.js +0 -9
|
@@ -107,6 +107,7 @@ class RelayModernStore implements Store {
|
|
|
107
107
|
fetchTime: ?number,
|
|
108
108
|
},
|
|
109
109
|
>;
|
|
110
|
+
_shouldRetainWithinTTL_EXPERIMENTAL: boolean;
|
|
110
111
|
_shouldScheduleGC: boolean;
|
|
111
112
|
_storeSubscriptions: StoreSubscriptions;
|
|
112
113
|
_updatedRecordIDs: DataIDSet;
|
|
@@ -127,6 +128,9 @@ class RelayModernStore implements Store {
|
|
|
127
128
|
shouldProcessClientComponents?: ?boolean,
|
|
128
129
|
resolverContext?: ResolverContext,
|
|
129
130
|
|
|
131
|
+
// Experimental
|
|
132
|
+
shouldRetainWithinTTL_EXPERIMENTAL?: boolean,
|
|
133
|
+
|
|
130
134
|
// These additional config options are only used if the experimental
|
|
131
135
|
// @outputType resolver feature is used
|
|
132
136
|
treatMissingFieldsAsNull?: ?boolean,
|
|
@@ -147,6 +151,8 @@ class RelayModernStore implements Store {
|
|
|
147
151
|
this._gcHoldCounter = 0;
|
|
148
152
|
this._gcReleaseBufferSize =
|
|
149
153
|
options?.gcReleaseBufferSize ?? DEFAULT_RELEASE_BUFFER_SIZE;
|
|
154
|
+
this._shouldRetainWithinTTL_EXPERIMENTAL =
|
|
155
|
+
options?.shouldRetainWithinTTL_EXPERIMENTAL ?? false;
|
|
150
156
|
this._gcRun = null;
|
|
151
157
|
this._gcScheduler = options?.gcScheduler ?? resolveImmediate;
|
|
152
158
|
this._getDataID = options?.getDataID ?? defaultGetDataID;
|
|
@@ -165,14 +171,15 @@ class RelayModernStore implements Store {
|
|
|
165
171
|
() => this._getMutableRecordSource(),
|
|
166
172
|
this,
|
|
167
173
|
);
|
|
174
|
+
this._resolverContext = options?.resolverContext;
|
|
168
175
|
this._storeSubscriptions = new RelayStoreSubscriptions(
|
|
169
176
|
options?.log,
|
|
170
177
|
this._resolverCache,
|
|
178
|
+
this._resolverContext,
|
|
171
179
|
);
|
|
172
180
|
this._updatedRecordIDs = new Set();
|
|
173
181
|
this._shouldProcessClientComponents =
|
|
174
182
|
options?.shouldProcessClientComponents ?? false;
|
|
175
|
-
this._resolverContext = options?.resolverContext;
|
|
176
183
|
|
|
177
184
|
this._treatMissingFieldsAsNull = options?.treatMissingFieldsAsNull ?? false;
|
|
178
185
|
this._actorIdentifier = options?.actorIdentifier;
|
|
@@ -235,6 +242,11 @@ class RelayModernStore implements Store {
|
|
|
235
242
|
const selector = operation.root;
|
|
236
243
|
const source = this._getMutableRecordSource();
|
|
237
244
|
const globalInvalidationEpoch = this._globalInvalidationEpoch;
|
|
245
|
+
const useExecTimeResolvers =
|
|
246
|
+
operation.request.node.operation.use_exec_time_resolvers ??
|
|
247
|
+
operation.request.node.operation.exec_time_resolvers_enabled_provider?.get() ===
|
|
248
|
+
true ??
|
|
249
|
+
false;
|
|
238
250
|
|
|
239
251
|
const rootEntry = this._roots.get(operation.request.identifier);
|
|
240
252
|
const operationLastWrittenAt = rootEntry != null ? rootEntry.epoch : null;
|
|
@@ -279,6 +291,7 @@ class RelayModernStore implements Store {
|
|
|
279
291
|
this._getDataID,
|
|
280
292
|
this._shouldProcessClientComponents,
|
|
281
293
|
this.__log,
|
|
294
|
+
useExecTimeResolvers,
|
|
282
295
|
);
|
|
283
296
|
|
|
284
297
|
return getAvailabilityStatus(
|
|
@@ -315,7 +328,9 @@ class RelayModernStore implements Store {
|
|
|
315
328
|
rootEntry.fetchTime <= Date.now() - _queryCacheExpirationTime;
|
|
316
329
|
|
|
317
330
|
if (rootEntryIsStale) {
|
|
318
|
-
this.
|
|
331
|
+
if (!this._shouldRetainWithinTTL_EXPERIMENTAL) {
|
|
332
|
+
this._roots.delete(id);
|
|
333
|
+
}
|
|
319
334
|
this.scheduleGC();
|
|
320
335
|
} else {
|
|
321
336
|
this._releaseBuffer.push(id);
|
|
@@ -325,8 +340,10 @@ class RelayModernStore implements Store {
|
|
|
325
340
|
// buffer have a refCount of 0.
|
|
326
341
|
if (this._releaseBuffer.length > this._gcReleaseBufferSize) {
|
|
327
342
|
const _id = this._releaseBuffer.shift();
|
|
328
|
-
|
|
329
|
-
|
|
343
|
+
if (!this._shouldRetainWithinTTL_EXPERIMENTAL) {
|
|
344
|
+
// $FlowFixMe[incompatible-call]
|
|
345
|
+
this._roots.delete(_id);
|
|
346
|
+
}
|
|
330
347
|
this.scheduleGC();
|
|
331
348
|
}
|
|
332
349
|
}
|
|
@@ -688,6 +705,14 @@ class RelayModernStore implements Store {
|
|
|
688
705
|
};
|
|
689
706
|
|
|
690
707
|
*_collect(): Generator<void, void, void> {
|
|
708
|
+
if (
|
|
709
|
+
this._shouldRetainWithinTTL_EXPERIMENTAL &&
|
|
710
|
+
this._queryCacheExpirationTime == null
|
|
711
|
+
) {
|
|
712
|
+
// Null expiration time indicates infinite TTL, so we don't need to
|
|
713
|
+
// run GC.
|
|
714
|
+
return;
|
|
715
|
+
}
|
|
691
716
|
/* eslint-disable no-labels */
|
|
692
717
|
const log = this.__log;
|
|
693
718
|
top: while (true) {
|
|
@@ -699,15 +724,43 @@ class RelayModernStore implements Store {
|
|
|
699
724
|
const startEpoch = this._currentWriteEpoch;
|
|
700
725
|
const references = new Set<DataID>();
|
|
701
726
|
|
|
702
|
-
|
|
703
|
-
|
|
727
|
+
for (const [
|
|
728
|
+
dataID,
|
|
729
|
+
{operation, refCount, fetchTime},
|
|
730
|
+
] of this._roots.entries()) {
|
|
731
|
+
if (this._shouldRetainWithinTTL_EXPERIMENTAL) {
|
|
732
|
+
// Do not mark records that should be garbage collected
|
|
733
|
+
const {_queryCacheExpirationTime} = this;
|
|
734
|
+
invariant(
|
|
735
|
+
_queryCacheExpirationTime != null,
|
|
736
|
+
'Query cache expiration time should be non-null if executing GC',
|
|
737
|
+
);
|
|
738
|
+
const recordHasExpired =
|
|
739
|
+
fetchTime == null ||
|
|
740
|
+
fetchTime <= Date.now() - _queryCacheExpirationTime;
|
|
741
|
+
const recordShouldBeCollected =
|
|
742
|
+
recordHasExpired &&
|
|
743
|
+
refCount === 0 &&
|
|
744
|
+
!this._releaseBuffer.includes(dataID);
|
|
745
|
+
if (recordShouldBeCollected) {
|
|
746
|
+
continue;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
// Mark all records that are traversable from a root that is still valid
|
|
704
751
|
const selector = operation.root;
|
|
752
|
+
const useExecTimeResolvers =
|
|
753
|
+
operation.request.node.operation.use_exec_time_resolvers ??
|
|
754
|
+
operation.request.node.operation.exec_time_resolvers_enabled_provider?.get() ===
|
|
755
|
+
true ??
|
|
756
|
+
false;
|
|
705
757
|
RelayReferenceMarker.mark(
|
|
706
758
|
this._recordSource,
|
|
707
759
|
selector,
|
|
708
760
|
references,
|
|
709
761
|
this._operationLoader,
|
|
710
762
|
this._shouldProcessClientComponents,
|
|
763
|
+
useExecTimeResolvers,
|
|
711
764
|
);
|
|
712
765
|
// Yield for other work after each operation
|
|
713
766
|
yield;
|
|
@@ -723,31 +776,36 @@ class RelayModernStore implements Store {
|
|
|
723
776
|
}
|
|
724
777
|
}
|
|
725
778
|
|
|
726
|
-
//
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
}
|
|
779
|
+
// NOTE: It may be tempting to use `this._recordSource.clear()`
|
|
780
|
+
// when no references are found, but that would prevent calling
|
|
781
|
+
// maybeResolverSubscription() on any records that have an active
|
|
782
|
+
// resolver subscription. This would result in a memory leak.
|
|
783
|
+
|
|
784
|
+
// Evict any unreferenced nodes
|
|
785
|
+
const storeIDs = this._recordSource.getRecordIDs();
|
|
786
|
+
for (let ii = 0; ii < storeIDs.length; ii++) {
|
|
787
|
+
const dataID = storeIDs[ii];
|
|
788
|
+
if (!references.has(dataID)) {
|
|
789
|
+
const record = this._recordSource.get(dataID);
|
|
790
|
+
if (record != null) {
|
|
791
|
+
const maybeResolverSubscription = RelayModernRecord.getValue(
|
|
792
|
+
record,
|
|
793
|
+
RELAY_RESOLVER_LIVE_STATE_SUBSCRIPTION_KEY,
|
|
794
|
+
);
|
|
795
|
+
if (maybeResolverSubscription != null) {
|
|
796
|
+
// $FlowFixMe - this value if it is not null, it is a function
|
|
797
|
+
maybeResolverSubscription();
|
|
746
798
|
}
|
|
747
|
-
|
|
799
|
+
}
|
|
800
|
+
this._recordSource.remove(dataID);
|
|
801
|
+
if (this._shouldRetainWithinTTL_EXPERIMENTAL) {
|
|
802
|
+
// Note: A record that was never retained will not be in the roots map
|
|
803
|
+
// but the following line should not throw
|
|
804
|
+
this._roots.delete(dataID);
|
|
748
805
|
}
|
|
749
806
|
}
|
|
750
807
|
}
|
|
808
|
+
|
|
751
809
|
if (log != null) {
|
|
752
810
|
log({
|
|
753
811
|
name: 'store.gc.end',
|
|
@@ -765,6 +823,7 @@ class RelayModernStore implements Store {
|
|
|
765
823
|
return {
|
|
766
824
|
path,
|
|
767
825
|
getDataID: this._getDataID,
|
|
826
|
+
log: this.__log,
|
|
768
827
|
treatMissingFieldsAsNull: this._treatMissingFieldsAsNull,
|
|
769
828
|
shouldProcessClientComponents: this._shouldProcessClientComponents,
|
|
770
829
|
actorIdentifier: this._actorIdentifier,
|
|
@@ -15,6 +15,7 @@ import type {HandlerProvider} from '../handlers/RelayDefaultHandlerProvider';
|
|
|
15
15
|
import type {Disposable} from '../util/RelayRuntimeTypes';
|
|
16
16
|
import type {GetDataID} from './RelayResponseNormalizer';
|
|
17
17
|
import type {
|
|
18
|
+
LogFunction,
|
|
18
19
|
MissingFieldHandler,
|
|
19
20
|
MutationParameters,
|
|
20
21
|
OperationDescriptor,
|
|
@@ -33,6 +34,7 @@ import type {
|
|
|
33
34
|
const RelayRecordSourceMutator = require('../mutations/RelayRecordSourceMutator');
|
|
34
35
|
const RelayRecordSourceProxy = require('../mutations/RelayRecordSourceProxy');
|
|
35
36
|
const RelayRecordSourceSelectorProxy = require('../mutations/RelayRecordSourceSelectorProxy');
|
|
37
|
+
const RelayFeatureFlags = require('../util/RelayFeatureFlags');
|
|
36
38
|
const RelayReader = require('./RelayReader');
|
|
37
39
|
const RelayRecordSource = require('./RelayRecordSource');
|
|
38
40
|
const invariant = require('invariant');
|
|
@@ -60,8 +62,10 @@ type PendingUpdater = {
|
|
|
60
62
|
const _global: typeof global | $FlowFixMe =
|
|
61
63
|
typeof global !== 'undefined'
|
|
62
64
|
? global
|
|
63
|
-
:
|
|
64
|
-
|
|
65
|
+
: // $FlowFixMe[cannot-resolve-name]
|
|
66
|
+
typeof window !== 'undefined'
|
|
67
|
+
? // $FlowFixMe[cannot-resolve-name]
|
|
68
|
+
window
|
|
65
69
|
: undefined;
|
|
66
70
|
|
|
67
71
|
const applyWithGuard =
|
|
@@ -84,6 +88,7 @@ class RelayPublishQueue implements PublishQueue {
|
|
|
84
88
|
_handlerProvider: ?HandlerProvider;
|
|
85
89
|
_missingFieldHandlers: $ReadOnlyArray<MissingFieldHandler>;
|
|
86
90
|
_getDataID: GetDataID;
|
|
91
|
+
_log: ?LogFunction;
|
|
87
92
|
|
|
88
93
|
_hasStoreSnapshot: boolean;
|
|
89
94
|
// True if the next `run()` should apply the backup and rerun all optimistic
|
|
@@ -112,6 +117,7 @@ class RelayPublishQueue implements PublishQueue {
|
|
|
112
117
|
handlerProvider?: ?HandlerProvider,
|
|
113
118
|
getDataID: GetDataID,
|
|
114
119
|
missingFieldHandlers: $ReadOnlyArray<MissingFieldHandler>,
|
|
120
|
+
log: LogFunction,
|
|
115
121
|
) {
|
|
116
122
|
this._hasStoreSnapshot = false;
|
|
117
123
|
this._handlerProvider = handlerProvider || null;
|
|
@@ -123,6 +129,7 @@ class RelayPublishQueue implements PublishQueue {
|
|
|
123
129
|
this._gcHold = null;
|
|
124
130
|
this._getDataID = getDataID;
|
|
125
131
|
this._missingFieldHandlers = missingFieldHandlers;
|
|
132
|
+
this._log = log;
|
|
126
133
|
}
|
|
127
134
|
|
|
128
135
|
/**
|
|
@@ -219,24 +226,27 @@ class RelayPublishQueue implements PublishQueue {
|
|
|
219
226
|
this._pendingOptimisticUpdates.size === 0 &&
|
|
220
227
|
!runWillClearGcHold;
|
|
221
228
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
229
|
+
warning(
|
|
230
|
+
!runIsANoop,
|
|
231
|
+
'RelayPublishQueue.run was called, but the call would have been a noop.',
|
|
232
|
+
);
|
|
233
|
+
RelayFeatureFlags.DISALLOW_NESTED_UPDATES
|
|
234
|
+
? invariant(
|
|
235
|
+
this._isRunning !== true,
|
|
236
|
+
'A store update was detected within another store update. Please ' +
|
|
237
|
+
"make sure new store updates aren't being executed within an " +
|
|
238
|
+
'updater function for a different update.',
|
|
239
|
+
)
|
|
240
|
+
: warning(
|
|
241
|
+
this._isRunning !== true,
|
|
242
|
+
'A store update was detected within another store update. Please ' +
|
|
243
|
+
"make sure new store updates aren't being executed within an " +
|
|
244
|
+
'updater function for a different update.',
|
|
245
|
+
);
|
|
246
|
+
this._isRunning = true;
|
|
235
247
|
|
|
236
248
|
if (runIsANoop) {
|
|
237
|
-
|
|
238
|
-
this._isRunning = false;
|
|
239
|
-
}
|
|
249
|
+
this._isRunning = false;
|
|
240
250
|
return [];
|
|
241
251
|
}
|
|
242
252
|
|
|
@@ -268,9 +278,7 @@ class RelayPublishQueue implements PublishQueue {
|
|
|
268
278
|
this._gcHold = null;
|
|
269
279
|
}
|
|
270
280
|
}
|
|
271
|
-
|
|
272
|
-
this._isRunning = false;
|
|
273
|
-
}
|
|
281
|
+
this._isRunning = false;
|
|
274
282
|
return this._store.notify(sourceOperation, invalidatedStore);
|
|
275
283
|
}
|
|
276
284
|
|
|
@@ -292,6 +300,7 @@ class RelayPublishQueue implements PublishQueue {
|
|
|
292
300
|
this._getDataID,
|
|
293
301
|
this._handlerProvider,
|
|
294
302
|
this._missingFieldHandlers,
|
|
303
|
+
this._log,
|
|
295
304
|
);
|
|
296
305
|
if (fieldPayloads && fieldPayloads.length) {
|
|
297
306
|
fieldPayloads.forEach(fieldPayload => {
|
|
@@ -355,6 +364,7 @@ class RelayPublishQueue implements PublishQueue {
|
|
|
355
364
|
this._getDataID,
|
|
356
365
|
this._handlerProvider,
|
|
357
366
|
this._missingFieldHandlers,
|
|
367
|
+
this._log,
|
|
358
368
|
);
|
|
359
369
|
applyWithGuard(
|
|
360
370
|
updater,
|
|
@@ -388,6 +398,7 @@ class RelayPublishQueue implements PublishQueue {
|
|
|
388
398
|
this._getDataID,
|
|
389
399
|
this._handlerProvider,
|
|
390
400
|
this._missingFieldHandlers,
|
|
401
|
+
this._log,
|
|
391
402
|
);
|
|
392
403
|
|
|
393
404
|
// $FlowFixMe[unclear-type] see explanation above.
|