diff --git a/backend/src/Squidex.Infrastructure/Log/BackgroundRequestLogStore.cs b/backend/src/Squidex.Infrastructure/Log/BackgroundRequestLogStore.cs index 70d770210..d15a4666b 100644 --- a/backend/src/Squidex.Infrastructure/Log/BackgroundRequestLogStore.cs +++ b/backend/src/Squidex.Infrastructure/Log/BackgroundRequestLogStore.cs @@ -19,8 +19,9 @@ public sealed class BackgroundRequestLogStore : DisposableObjectBase, IRequestLo private readonly CompletionTimer logTimer; private readonly RequestLogStoreOptions options; private readonly ConcurrentQueue jobs = new ConcurrentQueue(); + private bool isUpdating; - public int PendingJobs => jobs.Count; + public bool HasPendingJobs => !jobs.IsEmpty || isUpdating; public bool IsEnabled => options.StoreEnabled; @@ -63,6 +64,7 @@ public sealed class BackgroundRequestLogStore : DisposableObjectBase, IRequestLo return; } + isUpdating = true; try { var batch = new List(options.BatchSize); @@ -87,6 +89,10 @@ public sealed class BackgroundRequestLogStore : DisposableObjectBase, IRequestLo { log.LogError(ex, "Failed to track usage in background."); } + finally + { + isUpdating = false; + } } public Task DeleteAsync(string key, diff --git a/backend/src/Squidex.Infrastructure/UsageTracking/BackgroundUsageTracker.cs b/backend/src/Squidex.Infrastructure/UsageTracking/BackgroundUsageTracker.cs index e91dd7bf6..407c7ec3b 100644 --- a/backend/src/Squidex.Infrastructure/UsageTracking/BackgroundUsageTracker.cs +++ b/backend/src/Squidex.Infrastructure/UsageTracking/BackgroundUsageTracker.cs @@ -18,8 +18,9 @@ public sealed class BackgroundUsageTracker : DisposableObjectBase, IUsageTracker private readonly ILogger log; private readonly CompletionTimer usageTimer; private ConcurrentDictionary<(string Key, string Category, DateTime Date), Counters> jobs = new ConcurrentDictionary<(string Key, string Category, DateTime Date), Counters>(); + private bool isUpdating; - public int PendingJobs => jobs.Count; + public bool HasPendingJobs => !jobs.IsEmpty || isUpdating; public string FallbackCategory => "*"; @@ -52,35 +53,41 @@ public sealed class BackgroundUsageTracker : DisposableObjectBase, IUsageTracker { try { + isUpdating = true; + var localUsages = Interlocked.Exchange(ref jobs, new ConcurrentDictionary<(string Key, string Category, DateTime Date), Counters>()); if (!localUsages.IsEmpty) { - var updates = new UsageUpdate[localUsages.Count]; + var updateBatch = new UsageUpdate[localUsages.Count]; var updateIndex = 0; foreach (var (key, value) in localUsages) { - if (updateIndex >= updates.Length) + if (updateIndex >= updateBatch.Length) { break; } - updates[updateIndex].Key = key.Key; - updates[updateIndex].Category = key.Category; - updates[updateIndex].Counters = value; - updates[updateIndex].Date = key.Date; + updateBatch[updateIndex].Key = key.Key; + updateBatch[updateIndex].Category = key.Category; + updateBatch[updateIndex].Counters = value; + updateBatch[updateIndex].Date = key.Date; updateIndex++; } - await usageRepository.TrackUsagesAsync(updates, ct); + await usageRepository.TrackUsagesAsync(updateBatch, ct); } } catch (Exception ex) { log.LogError(ex, "Failed to track usage in background."); } + finally + { + isUpdating = false; + } } public Task DeleteAsync(string key, diff --git a/backend/tests/Squidex.Infrastructure.Tests/Log/BackgroundRequestLogStoreTests.cs b/backend/tests/Squidex.Infrastructure.Tests/Log/BackgroundRequestLogStoreTests.cs index 20d9a8537..1e1858214 100644 --- a/backend/tests/Squidex.Infrastructure.Tests/Log/BackgroundRequestLogStoreTests.cs +++ b/backend/tests/Squidex.Infrastructure.Tests/Log/BackgroundRequestLogStoreTests.cs @@ -121,12 +121,14 @@ public class BackgroundRequestLogStoreTests using var tcs = new CancellationTokenSource(TimeSpan.FromSeconds(5000)); - while (sut.PendingJobs > 0) + while (sut.HasPendingJobs) { tcs.Token.ThrowIfCancellationRequested(); await Task.Delay(20, tcs.Token); } + + sut.Dispose(); } private static IEnumerable Batch(string from, string to) diff --git a/backend/tests/Squidex.Infrastructure.Tests/UsageTracking/BackgroundUsageTrackerTests.cs b/backend/tests/Squidex.Infrastructure.Tests/UsageTracking/BackgroundUsageTrackerTests.cs index 81b5bdf9e..b3df53210 100644 --- a/backend/tests/Squidex.Infrastructure.Tests/UsageTracking/BackgroundUsageTrackerTests.cs +++ b/backend/tests/Squidex.Infrastructure.Tests/UsageTracking/BackgroundUsageTrackerTests.cs @@ -249,12 +249,14 @@ public class BackgroundUsageTrackerTests using var tcs = new CancellationTokenSource(TimeSpan.FromSeconds(5)); - while (sut.PendingJobs > 0) + while (sut.HasPendingJobs) { tcs.Token.ThrowIfCancellationRequested(); await Task.Delay(20, tcs.Token); } + + sut.Dispose(); } private static Counters Counters(double? a = null, double? b = null)