public async Task Can_recover_from_shutdown_with_twoway_replication() { var dataDirectory = "Data" + Guid.NewGuid(); ICounterStore storeA = null; RavenDbServer server = null; try { server = GetNewServer(port: 8091, runInMemory: false, dataDirectory: dataDirectory); storeA = NewRemoteCountersStore(DefaultCounterStorageName + "A", ravenServer: server); using (var storeB = NewRemoteCountersStore(DefaultCounterStorageName + "B")) { await SetupReplicationAsync(storeA, storeB); await SetupReplicationAsync(storeB, storeA); storeA.Dispose(); server.Dispose(); server = GetNewServer(port: 8091, runInMemory: false, dataDirectory: dataDirectory); storeA = NewRemoteCountersStore(DefaultCounterStorageName + "A", ravenServer: server); await storeA.ChangeAsync("group", "counter", 2); await storeB.ChangeAsync("group", "counter", 3); Assert.True(await WaitForReplicationBetween(storeA, storeB, "group", "counter")); } } finally { storeA?.Dispose(); server?.Dispose(); IOExtensions.DeleteDirectory(dataDirectory); } }
public IpThrottleMiddleware(RequestDelegate next, ThrottleOptions options, ICounterStore counterStore, ILogger <IdThrottleMiddleware> logger) : base(next, options, counterStore, logger) { var matcher = new IpAddressRuleMatcher(Options.ClientWhitelist, Options.ClientPolicies); Processor = new ThrottleProcessor(Options, counterStore, matcher); }
/// <summary> /// Initializes a new instance of the <see cref="ThrottleMiddleware"/> class. /// Makes this protected to prevent public call on an abstract class. /// </summary> /// <param name="next">The next middleware.</param> /// <param name="options">The throttle options.</param> /// <param name="counterStore">The store for throttle counters.</param> /// <param name="logger">The logger.</param> protected ThrottleMiddleware(RequestDelegate next, ThrottleOptions options, ICounterStore counterStore, ILogger logger) { Next = next; Options = options; CounterStore = counterStore; Logger = logger; }
private async Task ExportIncrementalData(ICounterStore counterStore, string exportFilename, JsonTextWriter jsonWriter) { var lastEtag = ReadLastEtagFromStateFile(exportFilename); var counterDeltas = (await GetCounterStatesSinceEtag(counterStore, lastEtag).WithCancellation(CancellationToken).ConfigureAwait(false)).ToList(); ShowProgress($"Incremental export -> starting from etag : {lastEtag}"); foreach (var delta in counterDeltas) { ShowProgress($"Exporting counter {delta.GroupName} - {delta.CounterName}"); jsonWriter.WriteStartObject(); jsonWriter.WritePropertyName("CounterName"); jsonWriter.WriteValue(delta.CounterName); jsonWriter.WritePropertyName("GroupName"); jsonWriter.WriteValue(delta.GroupName); jsonWriter.WritePropertyName("Sign"); jsonWriter.WriteValue(delta.Sign); jsonWriter.WritePropertyName("Value"); jsonWriter.WriteValue(delta.Value); jsonWriter.WriteEndObject(); } if (counterDeltas.Count > 0) { var etag = counterDeltas.Max(x => x.Etag); ShowProgress("Incremental export -> finished export, last exported etag : " + etag); WriteLastEtagToStateFile(exportFilename, etag); } }
private async Task ExportFullData(ICounterStore counterStore, JsonTextWriter jsonWriter) { ShowProgress("Starting full export..."); ShowProgress("Exporting from counter storage " + counterStore.Name); var counterStorageInfo = await counterStore.Admin.GetCountersByStorage(counterStore.Name, CancellationToken).WithCancellation(CancellationToken).ConfigureAwait(false); jsonWriter.WriteStartArray(); foreach (var counterInfo in counterStorageInfo) { ShowProgress($"Exporting counter {counterInfo.GroupName} - {counterInfo.CounterName}"); jsonWriter.WriteStartObject(); jsonWriter.WritePropertyName("Group"); jsonWriter.WriteValue(counterInfo.GroupName); jsonWriter.WritePropertyName("Name"); jsonWriter.WriteValue(counterInfo.CounterName); jsonWriter.WritePropertyName("Positive"); jsonWriter.WriteValue(counterInfo.Increments); jsonWriter.WritePropertyName("Negative"); jsonWriter.WriteValue(counterInfo.Decrements); jsonWriter.WriteEndObject(); } jsonWriter.WriteEndArray(); }
public CounterCollector(ICounterStore <T> store, ILogger log, int capacity = 2000, int batchSize = 200, int batchDelay = 1000) { this.store = store; inputQueue = Channel.CreateBounded <object>(new BoundedChannelOptions(capacity) { AllowSynchronousContinuations = true, SingleReader = true, SingleWriter = false }); writeQueue = Channel.CreateBounded <Job[]>(new BoundedChannelOptions(batchSize) { AllowSynchronousContinuations = true, SingleReader = true, SingleWriter = true }); inputQueue.Batch <Job, Job[]>(writeQueue, x => x.ToArray(), batchSize, batchDelay); task = Task.Run(Process); this.log = log; }
public CounterCollector(ICounterStore <T> store, int updateInterval, int maxSize = 20000) { this.store = store; this.maxSize = maxSize; timer = new CompletionTimer(updateInterval, StoreAsync, updateInterval); }
private async Task ImportIncrementalData(CounterConnectionStringOptions connectionString, Stream stream) { CountingStream sizeStream; JsonTextReader jsonReader; if (SmugglerHelper.TryGetJsonReaderForStream(stream, out jsonReader, out sizeStream) == false) { throw new InvalidOperationException("Failed to get reader for the data stream."); } if (jsonReader.TokenType != JsonToken.StartObject) { throw new InvalidDataException("StartObject was expected"); } ICounterStore store = null; try { if (jsonReader.Read() == false && jsonReader.TokenType != JsonToken.StartArray) { throw new InvalidDataException("StartArray was expected"); } store = new CounterStore { Url = connectionString.Url, Name = connectionString.CounterStoreId, Credentials = new OperationCredentials(connectionString.ApiKey, connectionString.Credentials) }; store.Initialize(true); ShowProgress($"Initialized connection to counter store (name = {store.Name})"); while (jsonReader.Read() && jsonReader.TokenType != JsonToken.EndArray) { if (jsonReader.TokenType != JsonToken.StartObject) { continue; } var counterDelta = RavenJToken.ReadFrom(jsonReader).ToObject <CounterState>(); ShowProgress($"Importing counter {counterDelta.GroupName} - {counterDelta.CounterName}"); if (counterDelta.Sign == ValueSign.Negative) { counterDelta.Value = -counterDelta.Value; } store.Batch.ScheduleChange(counterDelta.GroupName, counterDelta.CounterName, counterDelta.Value); } ShowProgress("Finished import of the current file."); await store.Batch.FlushAsync().WithCancellation(CancellationToken).ConfigureAwait(false); } finally { store?.Dispose(); } }
public ItemOutOfStockForOrderWorkflowActor( IKeyedListStore <ParkedOrderItem> parkedOrderItemStore, IKeyedListStore <OrderWaitingForProduct> orderWaitingForProductStore, ICounterStore counterStore) { _orderWaitingForProductStore = orderWaitingForProductStore; _parkedOrderItemStore = parkedOrderItemStore; _counterStore = counterStore; }
public ItemOutOfStockForOrderWorkflowActor( IKeyedListStore<ParkedOrderItem> parkedOrderItemStore, IKeyedListStore<OrderWaitingForProduct> orderWaitingForProductStore, ICounterStore counterStore) { _orderWaitingForProductStore = orderWaitingForProductStore; _parkedOrderItemStore = parkedOrderItemStore; _counterStore = counterStore; }
private CounterConnectionStringOptions ConnectionStringTo(ICounterStore counterStore, string overrideApiKey = null) { return(new CounterConnectionStringOptions { ApiKey = overrideApiKey ?? counterStore.Credentials.ApiKey, Credentials = counterStore.Credentials.Credentials, CounterStoreId = counterStore.Name, Url = counterStore.Url }); }
private static async Task SetupCounters(ICounterStore store, int groupCount, int countersInEachGroupCount) { const char initialSuffix = 'a'; for (int group = 0; group < groupCount; group++) { for (int counter = 0; counter < countersInEachGroupCount; counter++) { var groupName = "g" + (char)(initialSuffix + group); var counterName = "c" + (char)(initialSuffix + counter); await store.ChangeAsync(groupName, counterName, counter + 1); } } }
protected static async Task <object> SetupReplicationAsync(ICounterStore source, params ICounterStore[] destinations) { var replicationDocument = new CountersReplicationDocument(); foreach (var destStore in destinations) { replicationDocument.Destinations.Add(new CounterReplicationDestination { CounterStorageName = destStore.Name, ServerUrl = destStore.Url }); } await source.SaveReplicationsAsync(replicationDocument); return(null); }
private async Task <IEnumerable <CounterState> > GetCounterStatesSinceEtag(ICounterStore counterStore, long etag) { var deltas = new List <CounterState>(); do { var deltasFromRequest = await counterStore.Advanced.GetCounterStatesSinceEtag(etag, token : CancellationToken).ConfigureAwait(false); if (deltasFromRequest.Count == 0) { break; } etag = deltasFromRequest.Max(x => x.Etag); deltas.AddRange(deltasFromRequest); } while (true); return(deltas); }
protected async Task <bool> WaitForReplicationBetween(ICounterStore source, ICounterStore destination, string groupName, string counterName, int timeoutInSec = 3) { var waitStartingTime = DateTime.Now; var hasReplicated = false; if (Debugger.IsAttached) { timeoutInSec = 60 * 60; //1 hour timeout if debugging } while (true) { if ((DateTime.Now - waitStartingTime).TotalSeconds > timeoutInSec) { break; } try { var sourceValue = await source.GetOverallTotalAsync(groupName, counterName); var targetValue = await destination.GetOverallTotalAsync(groupName, counterName); if (sourceValue.IsExists && targetValue.IsExists && sourceValue.Total == targetValue.Total) { hasReplicated = true; break; } } catch (InvalidOperationException e) { var exception = e.InnerException as ErrorResponseException; if (exception != null && exception.StatusCode != HttpStatusCode.NotFound) { throw; } } Thread.Sleep(50); } return(hasReplicated); }
//assumes that the caller has responsibility to handle data stream disposal ("stream" parameter) private async Task ImportFullData(CounterConnectionStringOptions connectionString, Stream stream) { CountingStream sizeStream; JsonTextReader jsonReader; if (SmugglerHelper.TryGetJsonReaderForStream(stream, out jsonReader, out sizeStream) == false) { throw new InvalidOperationException("Failed to get reader for the data stream."); } if (jsonReader.TokenType != JsonToken.StartObject) { throw new InvalidDataException("StartObject was expected"); } ICounterStore store = null; try { if (jsonReader.Read() == false && jsonReader.TokenType != JsonToken.StartArray) { throw new InvalidDataException("StartArray was expected"); } store = new CounterStore { Url = connectionString.Url, Name = connectionString.CounterStoreId, Credentials = new OperationCredentials(connectionString.ApiKey, connectionString.Credentials) }; store.Initialize(true); ShowProgress($"Initialized connection to counter store (name = {store.Name})"); var existingCounterGroupsAndNames = await store.Admin.GetCounterStorageNameAndGroups(token : CancellationToken) .WithCancellation(CancellationToken) .ConfigureAwait(false); while (jsonReader.Read() && jsonReader.TokenType != JsonToken.EndArray) { if (jsonReader.TokenType != JsonToken.StartObject) { continue; } var counterInfo = (RavenJObject)RavenJToken.ReadFrom(jsonReader); var delta = Math.Abs(counterInfo.Value <long>("Positive")) - Math.Abs(counterInfo.Value <long>("Negative")); var groupName = counterInfo.Value <string>("Group"); var counterName = counterInfo.Value <string>("Name"); if (existingCounterGroupsAndNames.Any(x => x.Group == groupName && x.Name == counterName)) { ShowProgress($"Counter {groupName} - {counterName} is already there. Reset is performed"); await store.ResetAsync(groupName, counterName, CancellationToken).ConfigureAwait(false); //since it is a full import, the values are overwritten } ShowProgress($"Importing counter {groupName} - {counterName}"); store.Batch.ScheduleChange(groupName, counterName, delta); } ShowProgress("Finished import..."); await store.Batch.FlushAsync().WithCancellation(CancellationToken).ConfigureAwait(false); } finally { store?.Dispose(); } }
/// <summary> /// Initializes a new instance of the <see cref="ThrottleProcessor"/> class. /// </summary> /// <param name="options">The option object.</param> /// <param name="counterStore">The store for throttle data.</param> /// <param name="ruleMatcher">The matcher to get matching rules for specific client.</param> public ThrottleProcessor(BasicOptions options, ICounterStore counterStore, IClientRuleMatcher ruleMatcher) { Options = options ?? throw new ArgumentNullException(nameof(options)); _counterStore = counterStore ?? throw new ArgumentNullException(nameof(counterStore)); _ruleMatcher = ruleMatcher ?? throw new ArgumentNullException(nameof(ruleMatcher)); }
public ProductOutOfStockActor(ICounterStore stockLevelStore) { _stockLevelStore = stockLevelStore; }
public OrderItemInventoryActor(ICounterStore inventoryStore) { _inventoryStore = inventoryStore; }
public ThrottlerService(ICounterStore counterStore, ISystemClock systemClock) { _counterStore = counterStore; _systemClock = systemClock; }
public CounterService(ICounterStore <int> counterStore) { _counterStore = counterStore; }
public CountersController(ICounterStore <InMemoryCounterStore> inMemoryCounterStore, ICounterStore <RedisCounterStore> redisCounterStore) { _inMemoryCounterStore = inMemoryCounterStore; _redisCounterStore = redisCounterStore; }
public CounterRateLimter(ICounterStore store) { this._store = store; }