@@ -145,7 +145,7 @@ class LiveResolverCache implements ResolverCache {
145
145
// Clean up any existing subscriptions before creating the new subscription
146
146
// to avoid being double subscribed, or having a dangling subscription in
147
147
// the event of an error during subscription.
148
- this . _maybeUnsubscribeFromLiveState ( linkedRecord ) ;
148
+ maybeUnsubscribeFromLiveState ( linkedRecord ) ;
149
149
}
150
150
linkedID = linkedID ?? generateClientID ( recordID , storageKey ) ;
151
151
linkedRecord = RelayModernRecord . create (
@@ -339,18 +339,6 @@ class LiveResolverCache implements ResolverCache {
339
339
} ) ;
340
340
}
341
341
342
- _maybeUnsubscribeFromLiveState ( linkedRecord : Record ) {
343
- // If there's an existing subscription, unsubscribe.
344
- // $FlowFixMe[incompatible-type] - casting mixed
345
- const previousUnsubscribe : ( ) => void = RelayModernRecord . getValue (
346
- linkedRecord ,
347
- RELAY_RESOLVER_LIVE_STATE_SUBSCRIPTION_KEY ,
348
- ) ;
349
- if ( previousUnsubscribe != null ) {
350
- previousUnsubscribe ( ) ;
351
- }
352
- }
353
-
354
342
// Register a new Live State object in the store, subscribing to future
355
343
// updates.
356
344
_setLiveStateValue (
@@ -674,7 +662,7 @@ class LiveResolverCache implements ResolverCache {
674
662
continue ;
675
663
}
676
664
for ( const anotherRecordID of recordSet ) {
677
- this . _markInvalidatedResolverRecord ( anotherRecordID , recordSource ) ;
665
+ markInvalidatedResolverRecord ( anotherRecordID , recordSource ) ;
678
666
if ( ! visited . has ( anotherRecordID ) ) {
679
667
recordsToVisit . push ( anotherRecordID ) ;
680
668
}
@@ -684,28 +672,6 @@ class LiveResolverCache implements ResolverCache {
684
672
}
685
673
}
686
674
687
- _markInvalidatedResolverRecord (
688
- dataID : DataID ,
689
- recordSource : MutableRecordSource , // Written to
690
- ) {
691
- const record = recordSource . get ( dataID ) ;
692
- if ( ! record ) {
693
- warning (
694
- false ,
695
- 'Expected a resolver record with ID %s, but it was missing.' ,
696
- dataID ,
697
- ) ;
698
- return ;
699
- }
700
- const nextRecord = RelayModernRecord . clone ( record ) ;
701
- RelayModernRecord . setValue (
702
- nextRecord ,
703
- RELAY_RESOLVER_INVALIDATION_KEY ,
704
- true ,
705
- ) ;
706
- recordSource . set ( dataID , nextRecord ) ;
707
- }
708
-
709
675
_isInvalid (
710
676
record : Record ,
711
677
getDataForResolverFragment : GetDataForResolverFragmentFn ,
@@ -752,19 +718,10 @@ class LiveResolverCache implements ResolverCache {
752
718
}
753
719
754
720
unsubscribeFromLiveResolverRecords ( invalidatedDataIDs : Set < DataID > ) : void {
755
- if ( invalidatedDataIDs . size === 0 ) {
756
- return ;
757
- }
758
-
759
- for ( const dataID of invalidatedDataIDs ) {
760
- const record = this . _getRecordSource ( ) . get ( dataID ) ;
761
- if (
762
- record != null &&
763
- RelayModernRecord . getType ( record ) === RELAY_RESOLVER_RECORD_TYPENAME
764
- ) {
765
- this . _maybeUnsubscribeFromLiveState ( record ) ;
766
- }
767
- }
721
+ return unsubscribeFromLiveResolverRecordsImpl (
722
+ this . _getRecordSource ( ) ,
723
+ invalidatedDataIDs ,
724
+ ) ;
768
725
}
769
726
770
727
// Given the set of possible invalidated DataID
@@ -778,10 +735,7 @@ class LiveResolverCache implements ResolverCache {
778
735
779
736
for ( const dataID of invalidatedDataIDs ) {
780
737
const record = this . _getRecordSource ( ) . get ( dataID ) ;
781
- if (
782
- record != null &&
783
- RelayModernRecord . getType ( record ) === RELAY_RESOLVER_RECORD_TYPENAME
784
- ) {
738
+ if ( record != null && isResolverRecord ( record ) ) {
785
739
this . _getRecordSource ( ) . delete ( dataID ) ;
786
740
}
787
741
}
@@ -856,7 +810,11 @@ function updateCurrentSource(
856
810
const updatedRecord = RelayModernRecord . update ( currentRecord , nextRecord ) ;
857
811
if ( updatedRecord !== currentRecord ) {
858
812
updatedDataIDs . add ( recordID ) ;
859
- currentSource . set ( recordID , nextRecord ) ;
813
+ currentSource . set ( recordID , updatedRecord ) ;
814
+ // We also need to mark all linked records from the current record as invalidated,
815
+ // so that the next time these records are accessed in RelayReader,
816
+ // they will be re-read and re-evaluated by the LiveResolverCache and re-subscribed.
817
+ markInvalidatedLinkedResolverRecords ( currentRecord , currentSource ) ;
860
818
}
861
819
} else {
862
820
currentSource . set ( recordID , nextRecord ) ;
@@ -866,6 +824,91 @@ function updateCurrentSource(
866
824
return updatedDataIDs ;
867
825
}
868
826
827
+ function getAllLinkedRecordIds ( record : Record ) : DataIDSet {
828
+ const linkedRecordIDs = new Set < DataID > ( ) ;
829
+ RelayModernRecord . getFields ( record ) . forEach ( field => {
830
+ if ( RelayModernRecord . hasLinkedRecordID ( record , field ) ) {
831
+ const linkedRecordID = RelayModernRecord . getLinkedRecordID ( record , field ) ;
832
+ if ( linkedRecordID != null ) {
833
+ linkedRecordIDs . add ( linkedRecordID ) ;
834
+ }
835
+ } else if ( RelayModernRecord . hasLinkedRecordIDs ( record , field ) ) {
836
+ RelayModernRecord . getLinkedRecordIDs ( record , field ) ?. forEach (
837
+ linkedRecordID => {
838
+ if ( linkedRecordID != null ) {
839
+ linkedRecordIDs . add ( linkedRecordID ) ;
840
+ }
841
+ } ,
842
+ ) ;
843
+ }
844
+ } ) ;
845
+
846
+ return linkedRecordIDs ;
847
+ }
848
+
849
+ function markInvalidatedResolverRecord (
850
+ dataID : DataID ,
851
+ recordSource : MutableRecordSource , // Written to
852
+ ) {
853
+ const record = recordSource . get ( dataID ) ;
854
+ if ( ! record ) {
855
+ warning (
856
+ false ,
857
+ 'Expected a resolver record with ID %s, but it was missing.' ,
858
+ dataID ,
859
+ ) ;
860
+ return ;
861
+ }
862
+ const nextRecord = RelayModernRecord . clone ( record ) ;
863
+ RelayModernRecord . setValue ( nextRecord , RELAY_RESOLVER_INVALIDATION_KEY , true ) ;
864
+ recordSource . set ( dataID , nextRecord ) ;
865
+ }
866
+
867
+ function markInvalidatedLinkedResolverRecords (
868
+ record : Record ,
869
+ recordSource : MutableRecordSource ,
870
+ ) : void {
871
+ const currentLinkedDataIDs = getAllLinkedRecordIds ( record ) ;
872
+ for ( const recordID of currentLinkedDataIDs ) {
873
+ const record = recordSource . get ( recordID ) ;
874
+ if ( record != null && isResolverRecord ( record ) ) {
875
+ markInvalidatedResolverRecord ( recordID , recordSource ) ;
876
+ }
877
+ }
878
+ }
879
+
880
+ function unsubscribeFromLiveResolverRecordsImpl (
881
+ recordSource : RecordSource ,
882
+ invalidatedDataIDs : $ReadOnlySet < DataID > ,
883
+ ) : void {
884
+ if ( invalidatedDataIDs . size === 0 ) {
885
+ return ;
886
+ }
887
+
888
+ for ( const dataID of invalidatedDataIDs ) {
889
+ const record = recordSource . get ( dataID ) ;
890
+ if ( record != null && isResolverRecord ( record ) ) {
891
+ maybeUnsubscribeFromLiveState ( record ) ;
892
+ }
893
+ }
894
+ }
895
+
896
+ function isResolverRecord ( record : Record ) : boolean {
897
+ return RelayModernRecord . getType ( record ) === RELAY_RESOLVER_RECORD_TYPENAME ;
898
+ }
899
+
900
+ function maybeUnsubscribeFromLiveState ( linkedRecord : Record ) : void {
901
+ // If there's an existing subscription, unsubscribe.
902
+ // $FlowFixMe[incompatible-type] - casting mixed
903
+ const previousUnsubscribe : ( ) = > void = RelayModernRecord . getValue (
904
+ linkedRecord ,
905
+ RELAY_RESOLVER_LIVE_STATE_SUBSCRIPTION_KEY ,
906
+ ) ;
907
+ if ( previousUnsubscribe != null ) {
908
+ previousUnsubscribe ( ) ;
909
+ }
910
+ }
911
+
869
912
function expectRecord ( source : RecordSource , recordID : DataID ) : Record {
870
913
const record = source . get ( recordID ) ;
871
914
invariant (
0 commit comments