Skip to content

Commit fe5b60b

Browse files
Update caching transport and tests (#1617)
1 parent ed90819 commit fe5b60b

File tree

6 files changed

+127
-147
lines changed

6 files changed

+127
-147
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
- Workaround `System.Text.Json` issue with Unity IL2CPP. ([#1583](https://github.com/getsentry/sentry-dotnet/pull/1583))
1212
- Demystify stack traces for exceptions that fire in a `BeforeSend` callback. ([#1587](https://github.com/getsentry/sentry-dotnet/pull/1587))
13+
- Fix a minor issue in the caching transport related to recovery of files from previous session. ([#1617](https://github.com/getsentry/sentry-dotnet/pull/1617))
1314

1415
## 3.16.0
1516

src/Sentry/Internal/Http/CachingTransport.cs

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ internal class CachingTransport : ITransport, IAsyncDisposable, IDisposable
4141
// Inner transport exposed internally primarily for testing
4242
internal ITransport InnerTransport => _innerTransport;
4343

44-
public static CachingTransport Create(ITransport innerTransport, SentryOptions options)
44+
public static CachingTransport Create(ITransport innerTransport, SentryOptions options, bool startWorker = true)
4545
{
4646
var transport = new CachingTransport(innerTransport, options);
47-
transport.Initialize();
47+
transport.Initialize(startWorker);
4848
return transport;
4949
}
5050

@@ -64,38 +64,21 @@ private CachingTransport(ITransport innerTransport, SentryOptions options)
6464
_processingDirectoryPath = Path.Combine(_isolatedCacheDirectoryPath, "__processing");
6565
}
6666

67-
private void Initialize()
67+
private void Initialize(bool startWorker)
6868
{
69+
// Restore any abandoned files from a previous session
70+
MoveUnprocessedFilesBackToCache();
71+
72+
// Ensure directories exist
6973
Directory.CreateDirectory(_isolatedCacheDirectoryPath);
7074
Directory.CreateDirectory(_processingDirectoryPath);
7175

72-
_worker = Task.Run(CachedTransportBackgroundTaskAsync);
76+
// Start a worker, if one is needed
77+
_worker = startWorker ? Task.Run(CachedTransportBackgroundTaskAsync) : Task.CompletedTask;
7378
}
7479

7580
private async Task CachedTransportBackgroundTaskAsync()
7681
{
77-
try
78-
{
79-
// Processing directory may already contain some files left from previous session
80-
// if the worker has been terminated unexpectedly.
81-
// Move everything from that directory back to cache directory.
82-
if (Directory.Exists(_processingDirectoryPath))
83-
{
84-
foreach (var filePath in Directory.EnumerateFiles(_processingDirectoryPath))
85-
{
86-
var destinationPath = Path.Combine(_isolatedCacheDirectoryPath, Path.GetFileName(filePath));
87-
_options.LogDebug("Moving unprocessed file back to cache: {0} to {1}.",
88-
filePath, destinationPath);
89-
90-
File.Move(filePath, destinationPath);
91-
}
92-
}
93-
}
94-
catch (Exception e)
95-
{
96-
_options.LogError("Failed to move unprocessed files back to cache.", e);
97-
}
98-
9982
while (!_workerCts.IsCancellationRequested)
10083
{
10184
try
@@ -130,6 +113,34 @@ private async Task CachedTransportBackgroundTaskAsync()
130113
_options.LogDebug("Background worker of CachingTransport has shutdown.");
131114
}
132115

116+
private void MoveUnprocessedFilesBackToCache()
117+
{
118+
// Processing directory may already contain some files left from previous session
119+
// if the cache was working when the process terminated unexpectedly.
120+
// Move everything from that directory back to cache directory.
121+
122+
if (!Directory.Exists(_processingDirectoryPath))
123+
{
124+
// nothing to do
125+
return;
126+
}
127+
128+
foreach (var filePath in Directory.EnumerateFiles(_processingDirectoryPath))
129+
{
130+
try
131+
{
132+
var destinationPath = Path.Combine(_isolatedCacheDirectoryPath, Path.GetFileName(filePath));
133+
_options.LogDebug("Moving unprocessed file back to cache: {0} to {1}.",
134+
filePath, destinationPath);
135+
File.Move(filePath, destinationPath);
136+
}
137+
catch (Exception e)
138+
{
139+
_options.LogError("Failed to move unprocessed file back to cache: {0}", e, filePath);
140+
}
141+
}
142+
}
143+
133144
private void EnsureFreeSpaceInCache()
134145
{
135146
// Trim files, leaving only (X - 1) of the newest ones.
@@ -206,6 +217,13 @@ private async Task InnerProcessCacheAsync(string file, CancellationToken cancell
206217
// Let the worker catch, log, wait a bit and retry.
207218
throw;
208219
}
220+
221+
if (ex.Source == "FakeFailingTransport")
222+
{
223+
// HACK: Deliberately sent from unit tests to avoid deleting the file from processing
224+
return;
225+
}
226+
209227
LogFailureWithDiscard(file, ex);
210228
}
211229
}

test/Sentry.Testing/FakeFailingTransport.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ public Task SendEnvelopeAsync(
66
Envelope envelope,
77
CancellationToken cancellationToken = default)
88
{
9-
throw new Exception("Expected transport failure has occured.");
9+
throw new Exception("Expected transport failure has occured.")
10+
{
11+
Source = nameof(FakeFailingTransport)
12+
};
1013
}
1114
}

test/Sentry.Testing/Waiter.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
namespace Sentry.Testing;
2+
3+
public sealed class Waiter<T> : IDisposable
4+
{
5+
private readonly TaskCompletionSource<object> _taskCompletionSource = new();
6+
private readonly CancellationTokenSource _cancellationTokenSource = new();
7+
8+
public Waiter(Action<EventHandler<T>> callback)
9+
{
10+
_cancellationTokenSource.Token.Register(() => _taskCompletionSource.SetCanceled());
11+
callback.Invoke((_, _) => _taskCompletionSource.SetResult(null));
12+
}
13+
14+
public async Task WaitAsync(TimeSpan timeout)
15+
{
16+
_cancellationTokenSource.CancelAfter(timeout);
17+
await _taskCompletionSource.Task;
18+
}
19+
20+
public void Dispose()
21+
{
22+
_cancellationTokenSource.Dispose();
23+
}
24+
}

0 commit comments

Comments
 (0)