@@ -2,8 +2,15 @@ namespace PrompterOne.Shared.Services;
22
33internal sealed partial class GoLiveSessionService
44{
5+ private static readonly TimeSpan [ ] StateRequestCatchUpDelays =
6+ [
7+ TimeSpan . FromMilliseconds ( 250 ) ,
8+ TimeSpan . FromMilliseconds ( 750 )
9+ ] ;
10+
511 private readonly SemaphoreSlim _crossTabStartGate = new ( 1 , 1 ) ;
612
13+ private CancellationTokenSource ? _stateRequestCatchUpCancellationTokenSource ;
714 private bool _crossTabReady ;
815 private bool _disposed ;
916 private bool _stateRequestPublished ;
@@ -22,6 +29,21 @@ public async Task StartCrossTabSyncAsync(CancellationToken cancellationToken = d
2229 }
2330
2431 public async Task RequestCrossTabStateAsync ( CancellationToken cancellationToken = default )
32+ {
33+ await PublishCrossTabStateRequestAsync ( cancellationToken ) ;
34+ ScheduleCrossTabStateCatchUpRequests ( ) ;
35+ }
36+
37+ public async Task RequestCrossTabStateCatchUpAsync ( CancellationToken cancellationToken = default )
38+ {
39+ foreach ( var delay in StateRequestCatchUpDelays )
40+ {
41+ await Task . Delay ( delay , cancellationToken ) ;
42+ await PublishCrossTabStateRequestAsync ( cancellationToken ) ;
43+ }
44+ }
45+
46+ private async Task PublishCrossTabStateRequestAsync ( CancellationToken cancellationToken = default )
2547 {
2648 await EnsureCrossTabReadyAsync ( cancellationToken ) ;
2749 await _crossTabMessageBus . PublishAsync (
@@ -38,10 +60,38 @@ public void Dispose()
3860 }
3961
4062 _disposed = true ;
63+ _stateRequestCatchUpCancellationTokenSource ? . Cancel ( ) ;
64+ _stateRequestCatchUpCancellationTokenSource ? . Dispose ( ) ;
65+ _stateRequestCatchUpCancellationTokenSource = null ;
4166 _crossTabMessageBus . MessageReceived -= HandleCrossTabMessageAsync ;
4267 _crossTabStartGate . Dispose ( ) ;
4368 }
4469
70+ private void ScheduleCrossTabStateCatchUpRequests ( )
71+ {
72+ if ( _disposed )
73+ {
74+ return ;
75+ }
76+
77+ _stateRequestCatchUpCancellationTokenSource ? . Cancel ( ) ;
78+ _stateRequestCatchUpCancellationTokenSource ? . Dispose ( ) ;
79+ _stateRequestCatchUpCancellationTokenSource = new CancellationTokenSource ( ) ;
80+
81+ _ = RequestCrossTabStateCatchUpInBackgroundAsync ( _stateRequestCatchUpCancellationTokenSource . Token ) ;
82+ }
83+
84+ private async Task RequestCrossTabStateCatchUpInBackgroundAsync ( CancellationToken cancellationToken )
85+ {
86+ try
87+ {
88+ await RequestCrossTabStateCatchUpAsync ( cancellationToken ) ;
89+ }
90+ catch ( OperationCanceledException ) when ( cancellationToken . IsCancellationRequested )
91+ {
92+ }
93+ }
94+
4595 private async Task EnsureCrossTabReadyAsync ( CancellationToken cancellationToken )
4696 {
4797 if ( _crossTabReady )
0 commit comments