diff --git a/src/TogglTrack.cs b/src/TogglTrack.cs index 667a0ee..be1aeac 100644 --- a/src/TogglTrack.cs +++ b/src/TogglTrack.cs @@ -23,8 +23,12 @@ internal class TogglTrack SemaphoreSlim Token, SemaphoreSlim Me, SemaphoreSlim RunningTimeEntries, - SemaphoreSlim TimeEntries + SemaphoreSlim TimeEntries, + SemaphoreSlim SummaryReports, + SemaphoreSlim DetailedReports ) _semaphores = ( + new SemaphoreSlim(1, 1), + new SemaphoreSlim(1, 1), new SemaphoreSlim(1, 1), new SemaphoreSlim(1, 1), new SemaphoreSlim(1, 1), @@ -220,8 +224,18 @@ internal TogglTrack(PluginInitContext context, Settings settings) { string cacheKey = $"SummaryReport{workspaceId}{userId}{(int)reportGrouping}{start.ToString("yyyy-MM-dd")}{end?.ToString("yyyy-MM-dd")}"; - if (!force && this._cache.Contains(cacheKey)) + bool hasWaited = (this._semaphores.SummaryReports.CurrentCount == 0); + await this._semaphores.SummaryReports.WaitAsync(); + + if (token.IsCancellationRequested) + { + this._semaphores.SummaryReports.Release(); + token.ThrowIfCancellationRequested(); + } + + if ((!force || hasWaited) && this._cache.Contains(cacheKey)) { + this._semaphores.SummaryReports.Release(); return (SummaryReportResponse?)this._cache.Get(cacheKey); } @@ -240,8 +254,13 @@ internal TogglTrack(PluginInitContext context, Settings settings) this._cache.Set(cacheKey, summary, DateTimeOffset.Now.AddSeconds(60)); this._cacheKeys.Summary.Add(cacheKey); - token.ThrowIfCancellationRequested(); + if (token.IsCancellationRequested) + { + this._semaphores.SummaryReports.Release(); + token.ThrowIfCancellationRequested(); + } + this._semaphores.SummaryReports.Release(); return summary; } catch (Exception exception) @@ -249,6 +268,8 @@ internal TogglTrack(PluginInitContext context, Settings settings) token.ThrowIfCancellationRequested(); this._context.API.LogException("TogglTrack", "Failed to fetch summary reports", exception); + + this._semaphores.SummaryReports.Release(); return null; } } @@ -273,8 +294,18 @@ private void _ClearSummaryReportCache() { string cacheKey = $"DetailedReport{workspaceId}{userId}{string.Join(",", projectIds ?? new List())}{start.ToString("yyyy-MM-dd")}{end?.ToString("yyyy-MM-dd")}"; - if (!force && this._cache.Contains(cacheKey)) + bool hasWaited = (this._semaphores.DetailedReports.CurrentCount == 0); + await this._semaphores.DetailedReports.WaitAsync(); + + if (token.IsCancellationRequested) + { + this._semaphores.DetailedReports.Release(); + token.ThrowIfCancellationRequested(); + } + + if ((!force || hasWaited) && this._cache.Contains(cacheKey)) { + this._semaphores.DetailedReports.Release(); return (List?)this._cache.Get(cacheKey); } @@ -293,8 +324,13 @@ private void _ClearSummaryReportCache() this._cache.Set(cacheKey, report, DateTimeOffset.Now.AddSeconds(60)); this._cacheKeys.Detailed.Add(cacheKey); - token.ThrowIfCancellationRequested(); + if (token.IsCancellationRequested) + { + this._semaphores.DetailedReports.Release(); + token.ThrowIfCancellationRequested(); + } + this._semaphores.DetailedReports.Release(); return report; } catch (Exception exception) @@ -302,6 +338,8 @@ private void _ClearSummaryReportCache() token.ThrowIfCancellationRequested(); this._context.API.LogException("TogglTrack", "Failed to fetch detailed reports", exception); + + this._semaphores.DetailedReports.Release(); return null; } }