@@ -25,6 +25,7 @@ internal class Writer<TValue> : IWriter<TValue>
2525 private readonly ConcurrentQueue < MessageSending > _toSendBuffer = new ( ) ;
2626 private readonly ConcurrentQueue < MessageSending > _inFlightMessages = new ( ) ;
2727 private readonly CancellationTokenSource _disposeCts = new ( ) ;
28+ private readonly SemaphoreSlim _clearInFlightMessagesSemaphoreSlim = new ( 1 ) ;
2829
2930 private volatile TaskCompletionSource _tcsWakeUp = new ( ) ;
3031 private volatile TaskCompletionSource _tcsBufferAvailableEvent = new ( ) ;
@@ -161,7 +162,18 @@ private async void StartWriteWorker()
161162 continue ;
162163 }
163164
164- await _session . Write ( _toSendBuffer ) ;
165+ await _clearInFlightMessagesSemaphoreSlim . WaitAsync ( _disposeCts . Token ) ;
166+ try
167+ {
168+ if ( _session . IsActive )
169+ {
170+ await _session . Write ( _toSendBuffer ) ;
171+ }
172+ }
173+ finally
174+ {
175+ _clearInFlightMessagesSemaphoreSlim . Release ( ) ;
176+ }
165177 }
166178 }
167179 catch ( OperationCanceledException )
@@ -255,54 +267,66 @@ private async Task Initialize()
255267 return ;
256268 }
257269
258- var copyInFlightMessages = new ConcurrentQueue < MessageSending > ( ) ;
259- var lastSeqNo = initResponse . LastSeqNo ;
260- while ( _inFlightMessages . TryDequeue ( out var sendData ) )
270+ await _clearInFlightMessagesSemaphoreSlim . WaitAsync ( _disposeCts . Token ) ;
271+ try
261272 {
262- if ( lastSeqNo >= sendData . MessageData . SeqNo )
273+ var copyInFlightMessages = new ConcurrentQueue < MessageSending > ( ) ;
274+ var lastSeqNo = initResponse . LastSeqNo ;
275+ while ( _inFlightMessages . TryDequeue ( out var sendData ) )
263276 {
264- _logger . LogWarning (
265- "Message[SeqNo={SeqNo}] has been skipped because its sequence number " +
266- "is less than or equal to the last processed server's SeqNo[{LastSeqNo}]" ,
267- sendData . MessageData . SeqNo , lastSeqNo ) ;
277+ if ( lastSeqNo >= sendData . MessageData . SeqNo )
278+ {
279+ _logger . LogWarning (
280+ "Message[SeqNo={SeqNo}] has been skipped because its sequence number " +
281+ "is less than or equal to the last processed server's SeqNo[{LastSeqNo}]" ,
282+ sendData . MessageData . SeqNo , lastSeqNo ) ;
268283
269- sendData . Tcs . TrySetResult ( WriteResult . Skipped ) ;
284+ sendData . Tcs . TrySetResult ( WriteResult . Skipped ) ;
270285
271- continue ;
272- }
286+ continue ;
287+ }
273288
274289
275- // Calculate the next sequence number from the calculated previous messages.
276- lastSeqNo = Math . Max ( lastSeqNo , sendData . MessageData . SeqNo ) ;
290+ // Calculate the next sequence number from the calculated previous messages.
291+ lastSeqNo = Math . Max ( lastSeqNo , sendData . MessageData . SeqNo ) ;
277292
278- copyInFlightMessages . Enqueue ( sendData ) ;
279- }
293+ copyInFlightMessages . Enqueue ( sendData ) ;
294+ }
295+
296+ var newSession = new WriterSession (
297+ config : _config ,
298+ stream : stream ,
299+ lastSeqNo : lastSeqNo ,
300+ sessionId : initResponse . SessionId ,
301+ initialize : Initialize ,
302+ logger : _logger ,
303+ inFlightMessages : _inFlightMessages
304+ ) ;
305+
306+ if ( ! copyInFlightMessages . IsEmpty )
307+ {
308+ await newSession . Write ( copyInFlightMessages ) ; // retry prev in flight messages
309+ }
280310
281- var newSession = new WriterSession (
282- config : _config ,
283- stream : stream ,
284- lastSeqNo : lastSeqNo ,
285- sessionId : initResponse . SessionId ,
286- initialize : Initialize ,
287- logger : _logger ,
288- inFlightMessages : _inFlightMessages
289- ) ;
290-
291- if ( ! copyInFlightMessages . IsEmpty )
311+ _session = newSession ;
312+ newSession . RunProcessingWriteAck ( ) ;
313+ WakeUpWorker ( ) ; // attempt send buffer
314+ }
315+ finally
292316 {
293- await newSession . Write ( copyInFlightMessages ) ; // retry prev in flight messages
317+ _clearInFlightMessagesSemaphoreSlim . Release ( ) ;
294318 }
295-
296- _session = newSession ;
297- newSession . RunProcessingWriteAck ( ) ;
298- WakeUpWorker ( ) ; // attempt send buffer
299319 }
300320 catch ( Driver . TransportException e )
301321 {
302322 _logger . LogError ( e , "Transport error on creating WriterSession" ) ;
303323
304324 _ = Task . Run ( Initialize , _disposeCts . Token ) ;
305325 }
326+ catch ( OperationCanceledException )
327+ {
328+ _logger . LogWarning ( "Initialize writer is canceled because it has been disposed" ) ;
329+ }
306330 }
307331
308332 public void Dispose ( )
@@ -318,6 +342,8 @@ internal record MessageSending(MessageData MessageData, TaskCompletionSource<Wri
318342internal interface IWriteSession
319343{
320344 Task Write ( ConcurrentQueue < MessageSending > toSendBuffer ) ;
345+
346+ bool IsActive { get ; }
321347}
322348
323349internal class NotStartedWriterSession : IWriteSession
@@ -343,6 +369,8 @@ public Task Write(ConcurrentQueue<MessageSending> toSendBuffer)
343369
344370 return Task . CompletedTask ;
345371 }
372+
373+ public bool IsActive => true ;
346374}
347375
348376internal class DummyWriterSession : IWriteSession
@@ -357,6 +385,8 @@ public Task Write(ConcurrentQueue<MessageSending> toSendBuffer)
357385 {
358386 return Task . CompletedTask ;
359387 }
388+
389+ public bool IsActive => false ;
360390}
361391
362392internal class WriterSession : TopicSession < MessageFromClient , MessageFromServer > , IWriteSession
0 commit comments