@@ -19,13 +19,13 @@ const RelayProfiler = require('../util/RelayProfiler');
19
19
const RelayReader = require ( './RelayReader' ) ;
20
20
const RelayReferenceMarker = require ( './RelayReferenceMarker' ) ;
21
21
const RelayStoreReactFlightUtils = require ( './RelayStoreReactFlightUtils' ) ;
22
+ const RelayStoreSubscriptions = require ( './RelayStoreSubscriptions' ) ;
22
23
const RelayStoreUtils = require ( './RelayStoreUtils' ) ;
23
24
24
25
const deepFreeze = require ( '../util/deepFreeze' ) ;
25
26
const defaultGetDataID = require ( './defaultGetDataID' ) ;
26
27
const hasOverlappingIDs = require ( './hasOverlappingIDs' ) ;
27
28
const invariant = require ( 'invariant' ) ;
28
- const isEmptyObject = require ( '../util/isEmptyObject' ) ;
29
29
const recycleNodesInto = require ( '../util/recycleNodesInto' ) ;
30
30
const resolveImmediate = require ( '../util/resolveImmediate' ) ;
31
31
@@ -55,13 +55,6 @@ export opaque type InvalidationState = {|
55
55
invalidations : Map < DataID , ?number> ,
56
56
| } ;
57
57
58
- type Subscription = { |
59
- callback : ( snapshot : Snapshot ) => void ,
60
- snapshot : Snapshot ,
61
- stale : boolean ,
62
- backup : ?Snapshot ,
63
- | } ;
64
-
65
58
type InvalidationSubscription = { |
66
59
callback : ( ) => void ,
67
60
invalidationState : InvalidationState ,
@@ -107,7 +100,7 @@ class RelayModernStore implements Store {
107
100
| } ,
108
101
> ;
109
102
_shouldScheduleGC: boolean ;
110
- _subscriptions: Set < Subscription > ;
103
+ _storeSubscriptions: RelayStoreSubscriptions ;
111
104
_updatedRecordIDs: UpdatedRecords ;
112
105
113
106
constructor (
@@ -150,7 +143,7 @@ class RelayModernStore implements Store {
150
143
this . _releaseBuffer = [ ] ;
151
144
this . _roots = new Map ( ) ;
152
145
this . _shouldScheduleGC = false ;
153
- this . _subscriptions = new Set ( ) ;
146
+ this . _storeSubscriptions = new RelayStoreSubscriptions ( ) ;
154
147
this . _updatedRecordIDs = { } ;
155
148
156
149
initializeRecordSource ( this . _recordSource ) ;
@@ -303,17 +296,11 @@ class RelayModernStore implements Store {
303
296
304
297
const source = this . getSource ( ) ;
305
298
const updatedOwners = [ ] ;
306
- const hasUpdatedRecords = ! isEmptyObject ( this . _updatedRecordIDs ) ;
307
- this . _subscriptions . forEach ( subscription => {
308
- const owner = this . _updateSubscription (
309
- source ,
310
- subscription ,
311
- hasUpdatedRecords ,
312
- ) ;
313
- if ( owner != null ) {
314
- updatedOwners . push ( owner ) ;
315
- }
316
- } ) ;
299
+ this . _storeSubscriptions . updateSubscriptions (
300
+ source ,
301
+ this . _updatedRecordIDs ,
302
+ updatedOwners ,
303
+ ) ;
317
304
this . _invalidationSubscriptions . forEach ( subscription => {
318
305
this . _updateInvalidationSubscription (
319
306
subscription ,
@@ -395,12 +382,7 @@ class RelayModernStore implements Store {
395
382
snapshot : Snapshot ,
396
383
callback : ( snapshot : Snapshot ) = > void ,
397
384
) : Disposable {
398
- const subscription = { backup : null , callback, snapshot, stale : false } ;
399
- const dispose = ( ) => {
400
- this . _subscriptions . delete ( subscription ) ;
401
- } ;
402
- this . _subscriptions . add ( subscription ) ;
403
- return { dispose } ;
385
+ return this . _storeSubscriptions . subscribe ( snapshot , callback ) ;
404
386
}
405
387
406
388
holdGC ( ) : Disposable {
@@ -430,43 +412,6 @@ class RelayModernStore implements Store {
430
412
return this . _updatedRecordIDs ;
431
413
}
432
414
433
- // Returns the owner (RequestDescriptor) if the subscription was affected by the
434
- // latest update, or null if it was not affected.
435
- _updateSubscription (
436
- source : RecordSource ,
437
- subscription : Subscription ,
438
- hasUpdatedRecords : boolean ,
439
- ) : ?RequestDescriptor {
440
- const { backup, callback, snapshot, stale} = subscription ;
441
- const hasOverlappingUpdates =
442
- hasUpdatedRecords &&
443
- hasOverlappingIDs ( snapshot . seenRecords , this . _updatedRecordIDs ) ;
444
- if ( ! stale && ! hasOverlappingUpdates ) {
445
- return;
446
- }
447
- let nextSnapshot : Snapshot =
448
- hasOverlappingUpdates || ! backup
449
- ? RelayReader . read ( source , snapshot . selector )
450
- : backup ;
451
- const nextData = recycleNodesInto ( snapshot . data , nextSnapshot . data ) ;
452
- nextSnapshot = ( {
453
- data : nextData ,
454
- isMissingData : nextSnapshot . isMissingData ,
455
- seenRecords : nextSnapshot . seenRecords ,
456
- selector : nextSnapshot . selector ,
457
- missingRequiredFields : nextSnapshot . missingRequiredFields ,
458
- } : Snapshot ) ;
459
- if ( __DEV__ ) {
460
- deepFreeze ( nextSnapshot ) ;
461
- }
462
- subscription . snapshot = nextSnapshot ;
463
- subscription . stale = false ;
464
- if ( nextSnapshot . data !== snapshot . data ) {
465
- callback ( nextSnapshot ) ;
466
- return snapshot . selector . owner ;
467
- }
468
- }
469
-
470
415
lookupInvalidationState ( dataIDs : $ReadOnlyArray < DataID > ) : InvalidationState {
471
416
const invalidations = new Map ( ) ;
472
417
dataIDs . forEach ( dataID => {
@@ -546,29 +491,7 @@ class RelayModernStore implements Store {
546
491
name : 'store.snapshot' ,
547
492
} ) ;
548
493
}
549
- this . _subscriptions . forEach ( subscription => {
550
- // Backup occurs after writing a new "final" payload(s) and before (re)applying
551
- // optimistic changes. Each subscription's `snapshot` represents what was *last
552
- // published to the subscriber*, which notably may include previous optimistic
553
- // updates. Therefore a subscription can be in any of the following states:
554
- // - stale=true: This subscription was restored to a different value than
555
- // `snapshot`. That means this subscription has changes relative to its base,
556
- // but its base has changed (we just applied a final payload): recompute
557
- // a backup so that we can later restore to the state the subscription
558
- // should be in.
559
- // - stale=false: This subscription was restored to the same value than
560
- // `snapshot`. That means this subscription does *not* have changes relative
561
- // to its base, so the current `snapshot` is valid to use as a backup.
562
- if ( ! subscription . stale ) {
563
- subscription . backup = subscription . snapshot ;
564
- return ;
565
- }
566
- const snapshot = subscription . snapshot ;
567
- const backup = RelayReader . read ( this . getSource ( ) , snapshot . selector ) ;
568
- const nextData = recycleNodesInto ( snapshot . data , backup . data ) ;
569
- ( backup : $FlowFixMe ) . data = nextData ; // backup owns the snapshot and can safely mutate
570
- subscription . backup = backup ;
571
- } ) ;
494
+ this . _storeSubscriptions . snapshotSubscriptions ( this . getSource ( ) ) ;
572
495
if ( this . _gcRun ) {
573
496
this . _gcRun = null ;
574
497
this . _shouldScheduleGC = true ;
@@ -594,24 +517,7 @@ class RelayModernStore implements Store {
594
517
if ( this . _shouldScheduleGC ) {
595
518
this . scheduleGC ( ) ;
596
519
}
597
- this . _subscriptions . forEach ( subscription => {
598
- const backup = subscription . backup ;
599
- subscription . backup = null ;
600
- if ( backup ) {
601
- if ( backup . data !== subscription . snapshot . data ) {
602
- subscription . stale = true ;
603
- }
604
- subscription . snapshot = {
605
- data : subscription . snapshot . data ,
606
- isMissingData : backup . isMissingData ,
607
- seenRecords : backup . seenRecords ,
608
- selector : backup . selector ,
609
- missingRequiredFields : backup . missingRequiredFields ,
610
- } ;
611
- } else {
612
- subscription . stale = true ;
613
- }
614
- } ) ;
520
+ this . _storeSubscriptions . restoreSubscriptions ( ) ;
615
521
}
616
522
617
523
scheduleGC ( ) {
0 commit comments