Browse Source

Enhance TelemetryActivityStorage with mutex-based file access control and update activity storage path for improved concurrency and organization.

pull/23059/head
Emre KARA 1 year ago
parent
commit
450cb3e55d
  1. 67
      framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/Activity/Storage/TelemetryActivityStorage.cs
  2. 2
      framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/Constants/TelemetryPaths.cs

67
framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/Activity/Storage/TelemetryActivityStorage.cs

@ -4,6 +4,7 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
@ -16,9 +17,11 @@ public class TelemetryActivityStorage : ITelemetryActivityStorage, ISingletonDep
{
private const int MaxFileRetries = 5;
private const int RetryDelayMs = 100;
private const int MutexTimeoutMs = 5000; // 5 seconds timeout
private readonly TelemetryActivityStorageOptions _options;
private TelemetryActivityStorageState? _cachedState;
private static readonly string MutexName = "Global\\TelemetryActivityStorage";
public TelemetryActivityStorage(IOptions<TelemetryActivityStorageOptions> options)
{
@ -156,18 +159,65 @@ public class TelemetryActivityStorage : ITelemetryActivityStorage, ISingletonDep
private async Task<TResult?> WithExclusiveFileLockAsync<TResult>(Func<FileStream, Task<TResult>> action)
{
using var mutex = new Mutex(false, MutexName);
for (int i = 0; i < MaxFileRetries; i++)
{
try
{
using var stream = new FileStream(
TelemetryPaths.ActivityStorage,
FileMode.OpenOrCreate,
FileAccess.ReadWrite,
FileShare.None
);
return await action(stream);
// Wait for mutex with timeout
if (!mutex.WaitOne(MutexTimeoutMs))
{
if (i == MaxFileRetries - 1)
{
return default;
}
await Task.Delay(RetryDelayMs);
continue;
}
try
{
using var stream = new FileStream(
TelemetryPaths.ActivityStorage,
FileMode.OpenOrCreate,
FileAccess.ReadWrite,
FileShare.Read // Allow read sharing since we have mutex protection
);
return await action(stream);
}
finally
{
mutex.ReleaseMutex();
}
}
catch (AbandonedMutexException)
{
// Previous process crashed, mutex is now owned by us
try
{
using var stream = new FileStream(
TelemetryPaths.ActivityStorage,
FileMode.OpenOrCreate,
FileAccess.ReadWrite,
FileShare.Read
);
return await action(stream);
}
catch
{
if (i == MaxFileRetries - 1)
{
return default;
}
await Task.Delay(RetryDelayMs);
}
finally
{
try { mutex.ReleaseMutex(); } catch { }
}
}
catch (IOException)
{
@ -175,7 +225,6 @@ public class TelemetryActivityStorage : ITelemetryActivityStorage, ISingletonDep
{
return default;
}
await Task.Delay(RetryDelayMs);
}
catch

2
framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/Constants/TelemetryPaths.cs

@ -7,7 +7,7 @@ public static class TelemetryPaths
{
public static string AccessToken => Path.Combine(AbpRootPath, "cli", "access-token.bin");
public static string ComputerId => Path.Combine(AbpRootPath, "cli", "computer-id.bin");
public static string ActivityStorage => Path.Combine(AbpRootPath, "activity-storage.json");
public static string ActivityStorage => Path.Combine(AbpRootPath , "telemetry", "activity-storage.json");
public static string Studio => Path.Combine(AbpRootPath, "studio");
private readonly static string AbpRootPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".abp");
}
Loading…
Cancel
Save