Пример #1
0
        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);
            }
        }
Пример #2
0
        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;
 }
Пример #4
0
        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);
            }
        }
Пример #5
0
        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();
        }
Пример #6
0
        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;
        }
Пример #7
0
        public CounterCollector(ICounterStore <T> store, int updateInterval, int maxSize = 20000)
        {
            this.store = store;

            this.maxSize = maxSize;

            timer = new CompletionTimer(updateInterval, StoreAsync, updateInterval);
        }
Пример #8
0
        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();
            }
        }
Пример #9
0
 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;
 }
Пример #11
0
 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);
                }
            }
        }
Пример #13
0
        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);
        }
Пример #14
0
        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);
        }
Пример #15
0
        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);
        }
Пример #16
0
        //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();
            }
        }
Пример #17
0
 /// <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));
 }
Пример #18
0
 public ProductOutOfStockActor(ICounterStore stockLevelStore)
 {
     _stockLevelStore = stockLevelStore;
 }
Пример #19
0
 public OrderItemInventoryActor(ICounterStore inventoryStore)
 {
     _inventoryStore = inventoryStore;
 }
Пример #20
0
 public OrderItemInventoryActor(ICounterStore inventoryStore)
 {
     _inventoryStore = inventoryStore;
 }
Пример #21
0
 public ProductOutOfStockActor(ICounterStore stockLevelStore)
 {
     _stockLevelStore = stockLevelStore;
 }
Пример #22
0
 public ThrottlerService(ICounterStore counterStore, ISystemClock systemClock)
 {
     _counterStore = counterStore;
     _systemClock  = systemClock;
 }
Пример #23
0
 public CounterService(ICounterStore <int> counterStore)
 {
     _counterStore = counterStore;
 }
Пример #24
0
 public CountersController(ICounterStore <InMemoryCounterStore> inMemoryCounterStore, ICounterStore <RedisCounterStore> redisCounterStore)
 {
     _inMemoryCounterStore = inMemoryCounterStore;
     _redisCounterStore    = redisCounterStore;
 }
 public CounterRateLimter(ICounterStore store)
 {
     this._store = store;
 }