diff --git a/Shared.EventStore.Tests/SubscriptionWorkerHelperTests.cs b/Shared.EventStore.Tests/SubscriptionWorkerHelperTests.cs index 524a062..50fc690 100644 --- a/Shared.EventStore.Tests/SubscriptionWorkerHelperTests.cs +++ b/Shared.EventStore.Tests/SubscriptionWorkerHelperTests.cs @@ -15,7 +15,7 @@ public class SubscriptionWorkerHelperTests { #region Fields - private Mock domainEventHandlerResolver; + private readonly Mock domainEventHandlerResolver; #endregion diff --git a/Shared.EventStore/SubscriptionWorker/SubscriptionRepository.cs b/Shared.EventStore/SubscriptionWorker/SubscriptionRepository.cs index 5d249c8..e941d6c 100644 --- a/Shared.EventStore/SubscriptionWorker/SubscriptionRepository.cs +++ b/Shared.EventStore/SubscriptionWorker/SubscriptionRepository.cs @@ -1,165 +1,121 @@ namespace Shared.EventStore.SubscriptionWorker; - -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; -using global::EventStore.Client; -using Newtonsoft.Json; - -[ExcludeFromCodeCoverage] -public class SubscriptionRepository : ISubscriptionRepository -{ - #region Fields - - private Int32 CacheHits; - - private Int32 FullRefreshHits; - - private Func>> GetAllSubscriptions; - - private readonly Func RefreshRequired; - - private Int32 running; - - private PersistentSubscriptions Subscriptions; - - #endregion - - #region Constructors - - private SubscriptionRepository(Int32 cacheDuration = 120) - { - this.Subscriptions = new PersistentSubscriptions(); - - this.RefreshRequired = (force, s) => force || s.InitialState || SubscriptionRepository.RefreshNeeded(s.LastTimeRefreshed, cacheDuration); - } - - #endregion - - #region Events - - public EventHandler Trace; - - #endregion - - #region Methods - - public static SubscriptionRepository Create(String eventStoreConnectionString,Int32 cacheDuration = 120) - { - EventStoreClientSettings settings = EventStoreClientSettings.Create(eventStoreConnectionString); - HttpClient httpClient = SubscriptionWorkerHelper.CreateHttpClient(settings); - - return new SubscriptionRepository(cacheDuration) - { - GetAllSubscriptions = cancellationToken => SubscriptionRepository.GetSubscriptions(httpClient, cancellationToken) - }; - } - - public static SubscriptionRepository Create(Task> func,Int32 cacheDuration = 120) - { - return new(cacheDuration) - { - GetAllSubscriptions = _ => func - }; - } - - public static SubscriptionRepository Create(Func>> func,Int32 cacheDuration = 120) - { - return new(cacheDuration) - { - GetAllSubscriptions = func - }; - } - - public static async Task> GetSubscriptions(HttpClient httpClient, CancellationToken cancellationToken) - { - try - { - HttpResponseMessage responseMessage = await httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Get, "subscriptions"), cancellationToken); - String responseBody = await responseMessage.Content.ReadAsStringAsync(cancellationToken); - - if (responseMessage.IsSuccessStatusCode) - { - List list = JsonConvert.DeserializeObject>(responseBody); - - return list; - } - - throw new Exception($"Response was [{responseBody}] and status code was [{responseMessage.StatusCode}]"); - } - catch (Exception ex) - { - throw new Exception($"Unable to get persistent subscription list. [{ex}]"); - } - } - - public async Task GetSubscriptions(Boolean forceRefresh, CancellationToken cancellationToken) - { - if (Interlocked.CompareExchange(ref this.running, 1, 0) != 0) - { - return this.GetSubscriptionsFromCache("no lock"); - } - - try - { - if (!this.RefreshRequired(forceRefresh, this.Subscriptions)) - { - return this.GetSubscriptionsFromCache("refresh not required"); - } - - this.WriteTrace("Full refresh on repository"); - - List list = await this.GetAllSubscriptions(cancellationToken); - - this.FullRefreshHits++; - - this.Subscriptions = this.Subscriptions.Update(list); - - this.WriteTrace($"Full refresh on repository completed {this.FullRefreshHits}"); - - return this.Subscriptions; - } - catch (Exception ex) - { - throw new Exception($"Unable to get persistent subscription list. [{ex}]"); - } - finally - { - Interlocked.Exchange(ref this.running, 0); - } - } - - public async Task PreWarm(CancellationToken cancellationToken) => await this.GetSubscriptions(true, cancellationToken); - - public void WriteTrace(String message) - { - if (this.Trace != null) - { - this.Trace(this, message); - } - } - - private PersistentSubscriptions GetSubscriptionsFromCache(String reason) - { - this.CacheHits++; - this.WriteTrace($"Cache hit {this.CacheHits} - {reason}"); - return this.Subscriptions; - } - - private static Boolean RefreshNeeded(DateTime lastRefreshed, Int32 cacheDuration) - { - TimeSpan elapsed = DateTime.Now - lastRefreshed; - - if (elapsed.TotalSeconds < cacheDuration) - { - return false; - } - - return true; - } - - #endregion -} \ No newline at end of file + using System; + using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; + using System.Net.Http; + using System.Threading; + using System.Threading.Tasks; + using global::EventStore.Client; + using Newtonsoft.Json; + + [ExcludeFromCodeCoverage] + public class SubscriptionRepository : ISubscriptionRepository { + private Int32 CacheHits; + private Int32 FullRefreshHits; + private Func>> GetAllSubscriptions; + private readonly Func RefreshRequired; + private Int32 running; + private PersistentSubscriptions Subscriptions; + + private SubscriptionRepository(Int32 cacheDuration = 120) { + this.Subscriptions = new PersistentSubscriptions(); + this.RefreshRequired = (force, + s) => force || s.InitialState || SubscriptionRepository.RefreshNeeded(s.LastTimeRefreshed, cacheDuration); + } + + public EventHandler Trace; + + public static SubscriptionRepository Create(String eventStoreConnectionString, + Int32 cacheDuration = 120) { + EventStoreClientSettings settings = EventStoreClientSettings.Create(eventStoreConnectionString); + HttpClient httpClient = SubscriptionWorkerHelper.CreateHttpClient(settings); + return new SubscriptionRepository(cacheDuration) { GetAllSubscriptions = cancellationToken => SubscriptionRepository.GetSubscriptions(httpClient, cancellationToken) }; + } + + public static SubscriptionRepository Create(Task> func, + Int32 cacheDuration = 120) { + + return new(cacheDuration) { GetAllSubscriptions = _ => func }; + + } + + public static SubscriptionRepository Create(Func>> func, + Int32 cacheDuration = 120) { + return new(cacheDuration) { GetAllSubscriptions = func }; + } + + public static async Task> GetSubscriptions(HttpClient httpClient, + CancellationToken cancellationToken) { + try { + HttpResponseMessage responseMessage = await httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Get, "subscriptions"), cancellationToken); + String responseBody = await responseMessage.Content.ReadAsStringAsync(cancellationToken); + + if (responseMessage.IsSuccessStatusCode) { + List list = JsonConvert.DeserializeObject>(responseBody); + + return list; + } + + throw new Exception($"Response was [{responseBody}] and status code was [{responseMessage.StatusCode}]"); + } + catch (Exception ex) { + throw new Exception($"Unable to get persistent subscription list. [{ex}]"); + } + } + + public async Task GetSubscriptions(Boolean forceRefresh, + CancellationToken cancellationToken) { + if (Interlocked.CompareExchange(ref this.running, 1, 0) != 0) { + return this.GetSubscriptionsFromCache("no lock"); + } + + try { + if (!this.RefreshRequired(forceRefresh, this.Subscriptions)) { + return this.GetSubscriptionsFromCache("refresh not required"); + } + + this.WriteTrace("Full refresh on repository"); + + List list = await this.GetAllSubscriptions(cancellationToken); + + this.FullRefreshHits++; + + this.Subscriptions = this.Subscriptions.Update(list); + + this.WriteTrace($"Full refresh on repository completed {this.FullRefreshHits}"); + + return this.Subscriptions; + } + catch (Exception ex) { + throw new Exception($"Unable to get persistent subscription list. [{ex}]"); + } + finally { + Interlocked.Exchange(ref this.running, 0); + } + } + + public async Task PreWarm(CancellationToken cancellationToken) => await this.GetSubscriptions(true, cancellationToken); + + public void WriteTrace(String message) { + if (this.Trace != null) { + this.Trace(this, message); + } + } + + private PersistentSubscriptions GetSubscriptionsFromCache(String reason) { + this.CacheHits++; + this.WriteTrace($"Cache hit {this.CacheHits} - {reason}"); + return this.Subscriptions; + } + + private static Boolean RefreshNeeded(DateTime lastRefreshed, + Int32 cacheDuration) { + TimeSpan elapsed = DateTime.Now - lastRefreshed; + + if (elapsed.TotalSeconds < cacheDuration) { + return false; + } + + return true; + } + } \ No newline at end of file diff --git a/Shared/Web/QueryStringBuilder.cs b/Shared/Web/QueryStringBuilder.cs index d14dce5..f561508 100644 --- a/Shared/Web/QueryStringBuilder.cs +++ b/Shared/Web/QueryStringBuilder.cs @@ -8,7 +8,7 @@ namespace Shared.Web; public class QueryStringBuilder { - private Dictionary parameters = new Dictionary(); + private readonly Dictionary parameters = new Dictionary(); public QueryStringBuilder AddParameter(string key, object value) =>