Skip to content

Commit aa64b58

Browse files
Leonel Fernandez Mirfacebook-github-bot
authored andcommitted
Unsubscribing from resolvers before removing the record while runing the garbage collector
Reviewed By: captbaritone Differential Revision: D50540816 fbshipit-source-id: 2ddcb625b1e194bebdf3a1308b8c07944f41442e
1 parent 4422735 commit aa64b58

File tree

4 files changed

+32
-10
lines changed

4 files changed

+32
-10
lines changed

packages/react-relay/__tests__/LiveResolvers-test.js

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ const RelayRecordSource = require('relay-runtime/store/RelayRecordSource');
4343
const {
4444
disallowConsoleErrors,
4545
disallowWarnings,
46-
expectToWarn,
4746
} = require('relay-test-utils-internal');
4847

4948
disallowWarnings();
@@ -1539,24 +1538,28 @@ describe.each([
15391538
),
15401539
);
15411540

1541+
const subscriptionsCountBeforeGCRun = GLOBAL_STORE.getSubscriptionsCount();
1542+
15421543
// Go-go-go! Clean the store!
15431544
store.scheduleGC();
15441545
jest.runAllImmediates();
1545-
// This will clean the store, but won't unsubscribe from the external states
1546+
// This will clean the store, and unsubscribe from the external states
1547+
1548+
const subscriptionsCountAfterGCRun = GLOBAL_STORE.getSubscriptionsCount();
1549+
1550+
// this will verify that we unsubscribed from the external store
1551+
expect(subscriptionsCountAfterGCRun).toEqual(
1552+
subscriptionsCountBeforeGCRun - 1,
1553+
);
15461554

15471555
// Re-reading resolvers will create new records for them (but) the
15481556
// `live_counter_with_possible_missing_fragment_data` will have missing required data at this
15491557
// point so we won't be able to create a fully-valid live-resolver record for it (and subscribe/read)
15501558
// from the external state.
15511559
environment.lookup(operation.fragment);
15521560

1553-
// this will dispatch an action from the extenrnal store and the callback that was created before GC
1554-
expectToWarn(
1555-
'Unexpected callback for a incomplete live resolver record',
1556-
() => {
1557-
GLOBAL_STORE.dispatch({type: 'INCREMENT'});
1558-
},
1559-
);
1561+
// this will dispatch an action from the external store and the callback that was created before GC
1562+
GLOBAL_STORE.dispatch({type: 'INCREMENT'});
15601563

15611564
// The data for the live resolver is missing (it has missing dependecies)
15621565
snapshot = environment.lookup(operation.fragment);

packages/relay-runtime/store/__tests__/resolvers/ExampleExternalStateStore.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ class Store {
4444
this._state = 0;
4545
this._subscriptions = [];
4646
}
47+
getSubscriptionsCount(): number {
48+
return this._subscriptions.length;
49+
}
4750
}
4851

4952
const Selectors = {

packages/relay-runtime/store/experimental-live-resolvers/LiveResolverCache.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -895,4 +895,5 @@ function getConcreteTypename(
895895
module.exports = {
896896
LiveResolverCache,
897897
getUpdatedDataIDs,
898+
RELAY_RESOLVER_LIVE_STATE_SUBSCRIPTION_KEY,
898899
};

packages/relay-runtime/store/experimental-live-resolvers/LiveResolverStore.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,11 @@ const RelayReferenceMarker = require('../RelayReferenceMarker');
4848
const RelayStoreSubscriptions = require('../RelayStoreSubscriptions');
4949
const RelayStoreUtils = require('../RelayStoreUtils');
5050
const {ROOT_ID, ROOT_TYPE} = require('../RelayStoreUtils');
51-
const {LiveResolverCache, getUpdatedDataIDs} = require('./LiveResolverCache');
51+
const {
52+
LiveResolverCache,
53+
RELAY_RESOLVER_LIVE_STATE_SUBSCRIPTION_KEY,
54+
getUpdatedDataIDs,
55+
} = require('./LiveResolverCache');
5256
const invariant = require('invariant');
5357

5458
export type LiveState<+T> = {
@@ -706,6 +710,17 @@ class LiveResolverStore implements Store {
706710
for (let ii = 0; ii < storeIDs.length; ii++) {
707711
const dataID = storeIDs[ii];
708712
if (!references.has(dataID)) {
713+
const record = this._recordSource.get(dataID);
714+
if (record != null) {
715+
const maybeResolverSubscription = RelayModernRecord.getValue(
716+
record,
717+
RELAY_RESOLVER_LIVE_STATE_SUBSCRIPTION_KEY,
718+
);
719+
if (maybeResolverSubscription != null) {
720+
// $FlowFixMe - this value if it is not null, it is a function
721+
maybeResolverSubscription();
722+
}
723+
}
709724
this._recordSource.remove(dataID);
710725
}
711726
}

0 commit comments

Comments
 (0)