22using System . Collections . Generic ;
33using System . IO ;
44using System . Linq ;
5+ using System . Net . Http ;
6+ using System . Net . Sockets ;
57using System . Threading ;
68using System . Threading . Tasks ;
79using Sentry . Extensibility ;
@@ -76,6 +78,10 @@ public CachingTransport(ITransport innerTransport, SentryOptions options)
7678 await _workerSignal . WaitAsync ( _workerCts . Token ) . ConfigureAwait ( false ) ;
7779 await ProcessCacheAsync ( _workerCts . Token ) . ConfigureAwait ( false ) ;
7880 }
81+ catch ( OperationCanceledException )
82+ {
83+ throw ; // Avoid logging an error.
84+ }
7985 catch ( Exception ex )
8086 {
8187 _options . DiagnosticLogger ? . LogError (
@@ -91,6 +97,7 @@ public CachingTransport(ITransport innerTransport, SentryOptions options)
9197 catch ( OperationCanceledException )
9298 {
9399 // Worker has been shut down, it's okay
100+ _options . DiagnosticLogger ? . LogDebug ( "Background worker of CachingTransport has shutdown." ) ;
94101 }
95102 } ) ;
96103 }
@@ -174,17 +181,17 @@ private async ValueTask ProcessCacheAsync(CancellationToken cancellationToken =
174181 envelope . TryGetEventId ( )
175182 ) ;
176183 }
177- catch ( OperationCanceledException )
184+ catch ( Exception ex ) when ( IsRetryable ( ex ) )
178185 {
186+ // Let the worker catch, log, wait a bit and retry.
179187 throw ;
180188 }
181189 catch ( Exception ex )
182190 {
183191 _options . DiagnosticLogger ? . LogError (
184- "Failed to send cached envelope: {0}" ,
192+ "Failed to send cached envelope: {0}, discarding cached envelope. " ,
185193 ex ,
186- envelopeFilePath
187- ) ;
194+ envelopeFilePath ) ;
188195 }
189196
190197 // Envelope & file stream must be disposed prior to reaching this point
@@ -194,6 +201,15 @@ private async ValueTask ProcessCacheAsync(CancellationToken cancellationToken =
194201 }
195202 }
196203
204+ // Loading an Envelope only reads the headers. The payload is read lazily, so we do Disk -> Network I/O
205+ // via stream directly instead of loading the whole file in memory. For that reason capturing an envelope
206+ // from disk could raise an IOException related to Disk I/O.
207+ // For that reason, we're not retrying IOException, to avoid any disk related exception from retrying.
208+ private static bool IsRetryable ( Exception exception ) =>
209+ exception is OperationCanceledException // Timed-out or Shutdown triggered
210+ || exception is HttpRequestException // Myriad of HTTP related errors
211+ || exception is SocketException ; // Network related
212+
197213 // Gets the next cache file and moves it to "processing"
198214 private async ValueTask < string ? > TryPrepareNextCacheFileAsync (
199215 CancellationToken cancellationToken = default )
0 commit comments