public void ItCompletesTheTaskWhenSignalIsCalledSampleTimes() { var asyncACE = new AsyncCountdownEvent(SampleTimes); var task = asyncACE.WaitAsync(); for (int i = 0; i < SampleTimes; i++) { asyncACE.Signal(); } task.Wait(TimeSpan.FromSeconds(1)); Assert.IsTrue(task.IsCompleted); }
public async Task Do() { var messages = new ConcurrentQueue<TransportMessage>(); messages.Enqueue(new TransportMessage()); messages.Enqueue(new TransportMessage()); messages.Enqueue(new TransportMessage()); var countdown = new AsyncCountdownEvent(3); var chainFactory = new ChainFactory(); chainFactory.Register(() => new DelayElement()); chainFactory.Register(() => new LogElement()); chainFactory.Register(() => new DecrementElement(countdown)); var pushMessages = new PushMessages(messages, maxConcurrency: 1); await pushMessages.StartAsync(tm => Connector(chainFactory, tm)); await countdown.WaitAsync(); await pushMessages.StopAsync(); }
protected async Task CanHaveMultipleQueueInstancesWithLockingImplAsync(CacheLockProvider distributedLock) { var queue = GetQueue(retries: 0, retryDelay: TimeSpan.Zero); if (queue == null) { return; } try { await queue.DeleteQueueAsync(); await AssertEmptyQueueAsync(queue); const int workItemCount = 16; const int workerCount = 4; var countdown = new AsyncCountdownEvent(workItemCount); var info = new WorkInfo(); var workers = new List <IQueue <SimpleWorkItem> > { queue }; try { for (int i = 0; i < workerCount; i++) { var q = GetQueue(retries: 0, retryDelay: TimeSpan.Zero); int instanceCount = i; await q.StartWorkingAsync(async w => { _logger.Info("[{0}] Acquiring distributed lock in work item: {1}", instanceCount, w.Id); var l = await distributedLock.AcquireAsync("test"); Assert.NotNull(l); _logger.Info("[{0}] Acquired distributed lock: {1}", instanceCount, w.Id); SystemClock.Sleep(TimeSpan.FromMilliseconds(50)); await l.ReleaseAsync(); _logger.Info("[{0}] Released distributed lock: {1}", instanceCount, w.Id); await w.CompleteAsync(); info.IncrementCompletedCount(); countdown.Signal(); _logger.Info("[{0}] Signaled countdown: {1}", instanceCount, w.Id); }); workers.Add(q); } await Run.InParallelAsync(workItemCount, async i => { string id = await queue.EnqueueAsync(new SimpleWorkItem { Data = "Hello", Id = i }); _logger.Trace("Enqueued Index: {0} Id: {1}", i, id); }); await countdown.WaitAsync(TimeSpan.FromSeconds(5).ToCancellationToken()); await SystemClock.SleepAsync(50); _logger.Trace("Completed: {0} Abandoned: {1} Error: {2}", info.CompletedCount, info.AbandonCount, info.ErrorCount); _logger.Info("Work Info Stats: Completed: {completed} Abandoned: {abandoned} Error: {errors}", info.CompletedCount, info.AbandonCount, info.ErrorCount); Assert.Equal(workItemCount, info.CompletedCount + info.AbandonCount + info.ErrorCount); // In memory queue doesn't share state. if (queue.GetType() == typeof(InMemoryQueue <SimpleWorkItem>)) { var stats = await queue.GetQueueStatsAsync(); Assert.Equal(info.CompletedCount, stats.Completed); } else { var workerStats = new List <QueueStats>(); for (int i = 0; i < workers.Count; i++) { var stats = await workers[i].GetQueueStatsAsync(); _logger.Info("Worker#{i} Working: {working} Completed: {completed} Abandoned: {abandoned} Error: {errors} Deadletter: {deadletter}", i, stats.Working, stats.Completed, stats.Abandoned, stats.Errors, stats.Deadletter); workerStats.Add(stats); } Assert.Equal(info.CompletedCount, workerStats.Sum(s => s.Completed)); } } finally { foreach (var q in workers) { await CleanupQueueAsync(q); } } } finally { await CleanupQueueAsync(queue); } }
public async Task CanIncrementUsageAsync() { var messageBus = GetService <IMessageBus>(); var countdown = new AsyncCountdownEvent(2); await messageBus.SubscribeAsync <PlanOverage>(po => { _logger.LogInformation("Plan Overage for {organization} (Hourly: {IsHourly})", po.OrganizationId, po.IsHourly); countdown.Signal(); }); var organization = await _organizationRepository.AddAsync(new Organization { Name = "Test", MaxEventsPerMonth = 750, PlanId = _plans.SmallPlan.Id }, o => o.ImmediateConsistency()); var project = await _projectRepository.AddAsync(new Project { Name = "Test", OrganizationId = organization.Id, NextSummaryEndOfDayTicks = SystemClock.UtcNow.Ticks }, o => o.ImmediateConsistency()); Assert.InRange(organization.GetHourlyEventLimit(_plans), 1, 750); int totalToIncrement = organization.GetHourlyEventLimit(_plans) - 1; Assert.False(await _usageService.IncrementUsageAsync(organization, project, totalToIncrement)); organization = await _organizationRepository.GetByIdAsync(organization.Id); await countdown.WaitAsync(TimeSpan.FromMilliseconds(150)); Assert.Equal(2, countdown.CurrentCount); var organizationUsage = await _usageService.GetUsageAsync(organization); var projectUsage = await _usageService.GetUsageAsync(organization, project); Assert.Equal(totalToIncrement, organizationUsage.HourlyTotal); Assert.Equal(totalToIncrement, projectUsage.HourlyTotal); Assert.Equal(totalToIncrement, organizationUsage.MonthlyTotal); Assert.Equal(totalToIncrement, projectUsage.MonthlyTotal); Assert.Equal(0, organizationUsage.HourlyBlocked); Assert.Equal(0, projectUsage.HourlyBlocked); Assert.Equal(0, organizationUsage.MonthlyBlocked); Assert.Equal(0, projectUsage.MonthlyBlocked); Assert.True(await _usageService.IncrementUsageAsync(organization, project, 2)); await countdown.WaitAsync(TimeSpan.FromMilliseconds(150)); Assert.Equal(1, countdown.CurrentCount); organizationUsage = await _usageService.GetUsageAsync(organization); projectUsage = await _usageService.GetUsageAsync(organization, project); Assert.Equal(totalToIncrement + 2, organizationUsage.HourlyTotal); Assert.Equal(totalToIncrement + 2, projectUsage.HourlyTotal); Assert.Equal(totalToIncrement + 2, organizationUsage.MonthlyTotal); Assert.Equal(totalToIncrement + 2, projectUsage.MonthlyTotal); Assert.Equal(1, organizationUsage.HourlyBlocked); Assert.Equal(1, projectUsage.HourlyBlocked); Assert.Equal(1, organizationUsage.MonthlyBlocked); Assert.Equal(1, projectUsage.MonthlyBlocked); organization = await _organizationRepository.AddAsync(new Organization { Name = "Test", MaxEventsPerMonth = 750, PlanId = _plans.SmallPlan.Id }, o => o.ImmediateConsistency()); project = await _projectRepository.AddAsync(new Project { Name = "Test", OrganizationId = organization.Id, NextSummaryEndOfDayTicks = SystemClock.UtcNow.Ticks }, o => o.ImmediateConsistency()); await _cache.RemoveAllAsync(); totalToIncrement = organization.GetHourlyEventLimit(_plans) + 20; Assert.True(await _usageService.IncrementUsageAsync(organization, project, totalToIncrement)); await countdown.WaitAsync(TimeSpan.FromMilliseconds(150)); Assert.Equal(0, countdown.CurrentCount); organizationUsage = await _usageService.GetUsageAsync(organization); projectUsage = await _usageService.GetUsageAsync(organization, project); Assert.Equal(totalToIncrement, organizationUsage.HourlyTotal); Assert.Equal(totalToIncrement, projectUsage.HourlyTotal); Assert.Equal(totalToIncrement, organizationUsage.MonthlyTotal); Assert.Equal(totalToIncrement, projectUsage.MonthlyTotal); Assert.Equal(20, organizationUsage.HourlyBlocked); Assert.Equal(20, projectUsage.HourlyBlocked); Assert.Equal(20, organizationUsage.MonthlyBlocked); Assert.Equal(20, projectUsage.MonthlyBlocked); }
public async Task ProcessCrawlingQueueAsync(CrawlingQueue crawlingQueue) { _crawlingParameters.CancellationTokenSource.Token.Register(() => crawlingQueue.QueueCancellationTokenSource.Cancel() ); var tasksLock = new System.Threading.ReaderWriterLockSlim(); var tasks = new HashSet <Task>(); var queueItemsProcessingSemaphore = new SemaphoreSlim(crawlingQueue.CrawlingConfiguration.MaxSimmultaneousQueueItemsProcessed / 2, crawlingQueue.CrawlingConfiguration.MaxSimmultaneousQueueItemsProcessed); while (await queueItemsProcessingSemaphore.WaitAsync(crawlingQueue.CrawlingConfiguration.MaxTimeToProcessOneQueueItem)) { if (crawlingQueue.QueueCancellationTokenSource.IsCancellationRequested) { await Task.WhenAll(tasks.ToArray()); // TODO: Move remaining items from local queue to the distributed queue // TODO: Figure out how to filter out duplicates from the queue? Or should we? // We will probably have to resort to known urls-based duplicates check // Because otherwise we will drown in failing sql queries on multiplie machines Trace.TraceWarning("ProcessCrawlingQueueAsync: Queue cancellation requested. Preventing dequeing of new elements. Processing will be shut down after currently executing items are complete."); break; } var queueItem = await crawlingQueue.DequeueAsync(); if (queueItem == null) // Both Local and Proxy queues are depleted { // NOTE: If Queue is depleted, we must wait until all running tasks are executed, because they might add new items to queue await Task.WhenAll(tasks.ToArray()); // wait for all queue proxies to complete fetching items // TODO: consider locking (multithreading scenario) var queueProxiesPending = crawlingQueue.QueueProxies.Where(queueProxy => queueProxy.IsPending()).ToArray(); if (queueProxiesPending.Length > 0) { continue; } if (crawlingQueue.LocalQueue.Count > 0) { continue; } break; } if (!await _crawlingEventInterceptorManager.OnAfterDequeueAsync(queueItem)) { // If interceptor returns false, means it's an instruction to ignore this item; continue; } tasksLock.EnterWriteLock(); queueItem.ChangeStatus(CrawlingQueueItem.CrawlingStatuses.Downloading); tasks.Add(System.Threading.Tasks.TaskExtensions.Unwrap( CrawlAsync(queueItem.ResourceLink) .ContinueWith(async task => { tasksLock.EnterWriteLock(); tasks.Remove(task); // to avoid infinite bloating of the collection tasksLock.ExitWriteLock(); try { queueItem.ChangeStatus(CrawlingQueueItem.CrawlingStatuses.Downloaded); if (task.Status == TaskStatus.RanToCompletion) { var resourceContentUnits = task.Result; var httpResultUnit = resourceContentUnits.OfType <HttpResultUnit>().Single(); queueItem.ChangeStatus(CrawlingQueueItem.CrawlingStatuses.Processing); var resourceContentUnitsProcessingCountdown = new AsyncCountdownEvent(resourceContentUnits.Count); // Process resource content units extracted from Response foreach (var resourceContentUnit in resourceContentUnits) { switch (resourceContentUnit) { case ExtractedLinksUnit extractedLinksUnit: if (extractedLinksUnit.ExtractedLinks.Count > 0) { var linksProcessingCountdown = new AsyncCountdownEvent(extractedLinksUnit.ExtractedLinks.Count); foreach (var extractedLink in extractedLinksUnit.ExtractedLinks) { var crawlingQueueItem = new CrawlingQueueItem(extractedLink); // Do not enqueue item if prevented by any interceptor if (!await _crawlingEventInterceptorManager.OnBeforeEnqueueAsync(crawlingQueueItem)) { continue; } crawlingQueueItem.ProcessingCompleted += () => linksProcessingCountdown.AddCount(1) ; crawlingQueue.Enqueue(crawlingQueueItem); } // Wait while all links are processed before releasing the content units semaphore and set Status = Processed for parent linksProcessingCountdown.WaitAsync() .ContinueWith(linksProcessingTask => resourceContentUnitsProcessingCountdown.AddCount(1) ); } else { resourceContentUnitsProcessingCountdown.AddCount(1); } // Set Processed status when all extracted links are processed break; case ExtractedDataUnit extractedDataUnit: if (!await _crawlingEventInterceptorManager.OnDataDocumentDownloadedAsync( queueItem.ResourceLink, // May be a DocumentLink, or a FrameLink. Not quite intuitive and probably requires redesign. extractedDataUnit, httpResultUnit )) { // If any of interceptors failed to process the download result, // AND failed to store download result for later processing // we must re-enqueue the item, in order to ensure the results are not lost for good // We ignore the item and log the error. Chances are we couldn't process the item for a reason. And repeating would just make it stuck infinitely (re-downloading and re-processing) // (WAS) we must re-enqueue the item, in order to ensure the results are not lost for good //crawlingQueue.EnqueueAsync(queueItem); } resourceContentUnitsProcessingCountdown.Signal(); break; case DownloadedFilesUnit downloadedFileUnit: // If download file is a result of redirection, // we must either explicitly declare that we're expecting a file, or throw a processing exception var fileLink = queueItem.ResourceLink as FileLink; if (fileLink == null) { Trace.TraceError($"ProcessCrawlingQueueAsync: Downloaded file unit. Resource link is of type {queueItem.ResourceLink.GetType().Name}, expecting FileLink. Preventing processing."); break; } if (!await _crawlingEventInterceptorManager.OnFileDownloadedAsync( fileLink, downloadedFileUnit, httpResultUnit )) { // If any of interceptors failed to process the download result, // AND failed to store download result for later processing.... // We ignore the item and log the error. Chances are we couldn't process the item for a reason. And repeating would just make it stuck infinitely (re-downloading and re-processing) // (WAS) we must re-enqueue the item, in order to ensure the results are not lost for good //crawlingQueue.EnqueueAsync(queueItem); } resourceContentUnitsProcessingCountdown.Signal(); break; case HttpResultUnit httpResultUnitStub: // TODO: Determine what we should do if HTTP download failed. Either re-enqueue or ignore, or alert/do something else switch (httpResultUnitStub.HttpStatus) { //case HttpStatusCode.InternalServerError: // it's likely to repeat within the same run case HttpStatusCode.GatewayTimeout: case HttpStatusCode.RequestTimeout: queueItem.ChangeStatus(CrawlingQueueItem.CrawlingStatuses.NotLinked); crawlingQueue.Enqueue(queueItem); // Trying to recrawl item if it failed for some intermitent reason break; default: // We need to invoke ProcessingCompleted only after Data and Links extracted are really processed. //queueItem.ChangeStatus(CrawlingQueueItem.CrawlingStatuses.ProcessingCompleted); break; } resourceContentUnitsProcessingCountdown.Signal(); break; default: throw new NotSupportedException(); } } // Do not actually wait for related resources processing completion. // Those might be extracted links or files. No need to hold queue resources while linked units are downloaded // Set Processed status after all content units were registered and interceptors triggered await resourceContentUnitsProcessingCountdown.WaitAsync() .ContinueWith(resourceContentUnitsProcessingTask => queueItem.ChangeStatus(CrawlingQueueItem.CrawlingStatuses.Processed) ); } else { Trace.TraceError("CrawlAsync: Failed for queue item {0} with exception [{1}]", queueItem.ResourceLink, task.Exception); } } finally { queueItemsProcessingSemaphore.Release(); } }) ) ); tasksLock.ExitWriteLock(); } await Task.WhenAll(tasks.ToArray()); }
public async Task CanIncrementUsageAsync() { var cache = IoC.GetInstance <ICacheClient>() as InMemoryCacheClient; Assert.NotNull(cache); await cache.RemoveAllAsync(); var countdown = new AsyncCountdownEvent(2); var messagePublisher = IoC.GetInstance <IMessagePublisher>() as InMemoryMessageBus; Assert.NotNull(messagePublisher); messagePublisher.Subscribe <PlanOverage>(po => { _logger.Info($"Plan Overage for {po.OrganizationId} (Hourly: {po.IsHourly})"); countdown.Signal(); }); var o = await _repository.AddAsync(new Organization { Name = "Test", MaxEventsPerMonth = 750, PlanId = BillingManager.FreePlan.Id }); await _client.RefreshAsync(); Assert.InRange(o.GetHourlyEventLimit(), 1, 750); int totalToIncrement = o.GetHourlyEventLimit() - 1; Assert.False(await _repository.IncrementUsageAsync(o.Id, false, totalToIncrement)); await _client.RefreshAsync(); o = await _repository.GetByIdAsync(o.Id); await countdown.WaitAsync(TimeSpan.FromMilliseconds(150)); Assert.Equal(2, countdown.CurrentCount); Assert.Equal(totalToIncrement, await cache.GetAsync <long>(GetHourlyTotalCacheKey(o.Id), 0)); Assert.Equal(totalToIncrement, await cache.GetAsync <long>(GetMonthlyTotalCacheKey(o.Id), 0)); Assert.Equal(0, await cache.GetAsync <long>(GetHourlyBlockedCacheKey(o.Id), 0)); Assert.Equal(0, await cache.GetAsync <long>(GetMonthlyBlockedCacheKey(o.Id), 0)); Assert.True(await _repository.IncrementUsageAsync(o.Id, false, 2)); await _client.RefreshAsync(); o = await _repository.GetByIdAsync(o.Id); await countdown.WaitAsync(TimeSpan.FromMilliseconds(150)); Assert.Equal(1, countdown.CurrentCount); Assert.Equal(totalToIncrement + 2, await cache.GetAsync <long>(GetHourlyTotalCacheKey(o.Id), 0)); Assert.Equal(totalToIncrement + 2, await cache.GetAsync <long>(GetMonthlyTotalCacheKey(o.Id), 0)); Assert.Equal(1, await cache.GetAsync <long>(GetHourlyBlockedCacheKey(o.Id), 0)); Assert.Equal(1, await cache.GetAsync <long>(GetMonthlyBlockedCacheKey(o.Id), 0)); o = await _repository.AddAsync(new Organization { Name = "Test", MaxEventsPerMonth = 750, PlanId = BillingManager.FreePlan.Id }); await _client.RefreshAsync(); totalToIncrement = o.GetHourlyEventLimit() + 20; Assert.True(await _repository.IncrementUsageAsync(o.Id, false, totalToIncrement)); await countdown.WaitAsync(TimeSpan.FromMilliseconds(150)); Assert.Equal(0, countdown.CurrentCount); Assert.Equal(totalToIncrement, await cache.GetAsync <long>(GetHourlyTotalCacheKey(o.Id), 0)); Assert.Equal(totalToIncrement, await cache.GetAsync <long>(GetMonthlyTotalCacheKey(o.Id), 0)); Assert.Equal(20, await cache.GetAsync <long>(GetHourlyBlockedCacheKey(o.Id), 0)); Assert.Equal(20, await cache.GetAsync <long>(GetMonthlyBlockedCacheKey(o.Id), 0)); }
public async Task An_interval_can_be_specified_before_which_a_released_lease_will_be_granted_again() { var tally = new ConcurrentDictionary<string, int>(); var distributor = CreateDistributor(waitInterval: TimeSpan.FromMilliseconds(5000)).Trace(); var countdown = new AsyncCountdownEvent(10); distributor.OnReceive(async lease => { tally.AddOrUpdate(lease.LeasableResource.Name, addValueFactory: s => 1, updateValueFactory: (s, v) => v + 1); countdown.Signal(); }); await distributor.Start(); await countdown.WaitAsync().Timeout(); await distributor.Stop(); tally.Count.Should().Be(10); tally.Should().ContainKeys("1", "2", "3", "4", "5", "6", "7", "8", "9", "10"); tally.Should().ContainValues(1, 1, 1, 1, 1, 1, 1, 1, 1, 1); }
public virtual async Task CanHaveMultipleQueueInstances() { var queue = GetQueue(retries: 0, retryDelay: TimeSpan.Zero); if (queue == null) { return; } using (queue) { Logger.Trace().Message("Queue Id: {0}", queue.QueueId).Write(); await queue.DeleteQueueAsync(); const int workItemCount = 50; const int workerCount = 3; var countdown = new AsyncCountdownEvent(workItemCount); var info = new WorkInfo(); var workers = new List <IQueue <SimpleWorkItem> > { queue }; for (int i = 0; i < workerCount; i++) { var q = GetQueue(retries: 0, retryDelay: TimeSpan.Zero); Logger.Trace().Message("Queue Id: {0}, I: {1}", q.QueueId, i).Write(); q.StartWorking(async w => await DoWorkAsync(w, countdown, info)); workers.Add(q); } await Run.InParallel(workItemCount, async i => { var id = await queue.EnqueueAsync(new SimpleWorkItem { Data = "Hello", Id = i }); Logger.Trace().Message("Enqueued Index: {0} Id: {1}", i, id).Write(); }); await countdown.WaitAsync(); await Task.Delay(50); Logger.Trace().Message("Completed: {0} Abandoned: {1} Error: {2}", info.CompletedCount, info.AbandonCount, info.ErrorCount).Write(); Logger.Info().Message($"Work Info Stats: Completed: {info.CompletedCount} Abandoned: {info.AbandonCount} Error: {info.ErrorCount}").Write(); Assert.Equal(workItemCount, info.CompletedCount + info.AbandonCount + info.ErrorCount); // In memory queue doesn't share state. if (queue.GetType() == typeof(InMemoryQueue <SimpleWorkItem>)) { var stats = await queue.GetQueueStatsAsync(); Assert.Equal(0, stats.Working); Assert.Equal(0, stats.Timeouts); Assert.Equal(workItemCount, stats.Enqueued); Assert.Equal(workItemCount, stats.Dequeued); Assert.Equal(info.CompletedCount, stats.Completed); Assert.Equal(info.ErrorCount, stats.Errors); Assert.Equal(info.AbandonCount, stats.Abandoned - info.ErrorCount); Assert.Equal(info.AbandonCount + stats.Errors, stats.Deadletter); } else { var workerStats = new List <QueueStats>(); for (int i = 0; i < workers.Count; i++) { var stats = await workers[i].GetQueueStatsAsync(); Logger.Info().Message($"Worker#{i} Working: {stats.Working} Completed: {stats.Completed} Abandoned: {stats.Abandoned} Error: {stats.Errors} Deadletter: {stats.Deadletter}").Write(); workerStats.Add(stats); } Assert.Equal(info.CompletedCount, workerStats.Sum(s => s.Completed)); Assert.Equal(info.ErrorCount, workerStats.Sum(s => s.Errors)); Assert.Equal(info.AbandonCount, workerStats.Sum(s => s.Abandoned) - info.ErrorCount); Assert.Equal(info.AbandonCount + workerStats.Sum(s => s.Errors), (workerStats.LastOrDefault()?.Deadletter ?? 0)); } workers.ForEach(w => w.Dispose()); } }
public async void PodWatchDelete() { AsyncCountdownEvent requestHandled = new AsyncCountdownEvent(5); AsyncManualResetEvent serverShutdown = new AsyncManualResetEvent(); var podWatchData = await File.ReadAllTextAsync("podwatch.txt"); var addedAgent = BuildWatchEventStreamLine(podWatchData, WatchEventType.Added); var addedHub = BuildWatchEventStreamLine(podWatchData, WatchEventType.Added, 1); var addedSensor = BuildWatchEventStreamLine(podWatchData, WatchEventType.Added, 3); var v1PodList = JsonConvert.DeserializeObject <V1PodList>(podWatchData); V1Pod modHubPod = v1PodList.Items[1]; var modHub = BuildPodStreamLine(modHubPod, WatchEventType.Deleted); V1Pod tempSensorPod = v1PodList.Items[3]; var modTempSensor = BuildPodStreamLine(tempSensorPod, WatchEventType.Deleted); using (var server = new MockKubeApiServer( async httpContext => { await MockKubeApiServer.WriteStreamLine(httpContext, addedAgent); await MockKubeApiServer.WriteStreamLine(httpContext, addedHub); await MockKubeApiServer.WriteStreamLine(httpContext, addedSensor); await MockKubeApiServer.WriteStreamLine(httpContext, modTempSensor); await MockKubeApiServer.WriteStreamLine(httpContext, modHub); return(false); })) { var client = new Kubernetes( new KubernetesClientConfiguration { Host = server.Uri.ToString() }); var k8sRuntimeInfo = new KubernetesRuntimeInfoProvider(PodwatchNamespace, client); k8sRuntimeInfo.PropertyChanged += (sender, args) => { Assert.Equal("Modules", args.PropertyName); requestHandled.Signal(); }; k8sRuntimeInfo.Start(); await Task.WhenAny(requestHandled.WaitAsync(), Task.Delay(TestTimeout)); var runtimeModules = await k8sRuntimeInfo.GetModules(CancellationToken.None); var moduleRuntimeInfos = runtimeModules as ModuleRuntimeInfo[] ?? runtimeModules.ToArray(); Assert.Single(moduleRuntimeInfos); foreach (var i in moduleRuntimeInfos) { Assert.Equal("edgeAgent", i.Name); Assert.Equal(ModuleStatus.Running, i.ModuleStatus); Assert.Equal(new DateTime(2019, 6, 12), i.StartTime.GetOrElse(DateTime.MinValue).Date); Assert.Equal("docker", i.Type); if (i is ModuleRuntimeInfo <DockerReportedConfig> d) { Assert.NotEqual("unknown:unknown", d.Config.Image); } } } }
public void ItReturnsTaskWhenWaitAsyncIsCalled() { var asyncACE = new AsyncCountdownEvent(SampleTimes); Assert.IsInstanceOfType(asyncACE.WaitAsync(), typeof(Task)); }
/// <summary> /// Consume the tasks in parallel but with a rate limit. The results /// are returned as an observable. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="tasks"></param> /// <param name="rateLimit"></param> /// <returns></returns> public static IObservable <T> RateLimit <T>(IEnumerable <Func <Task <T> > > tasks, double rateLimit) { var s = System.Diagnostics.Stopwatch.StartNew(); var n = 0; var sem = new AsyncCountdownEvent(1); var errors = new ConcurrentBag <Exception>(); return(Observable.Create <T> (observer => { var ctx = new CancellationTokenSource(); Task.Run (async() => { foreach (var taskFn in tasks) { n++; ctx.Token.ThrowIfCancellationRequested(); var elapsedTotalSeconds = s.Elapsed.TotalSeconds; var delay = Delay(rateLimit, n, elapsedTotalSeconds); if (delay > 0) { await Task.Delay(TimeSpan.FromSeconds(delay), ctx.Token); } sem.AddCount(1); Task.Run (async() => { try { observer.OnNext(await taskFn()); } catch (Exception e) { errors.Add(e); } finally { sem.Signal(); } } , ctx.Token); } sem.Signal(); await sem.WaitAsync(ctx.Token); if (errors.Count > 0) { observer.OnError(new AggregateException(errors)); } else { observer.OnCompleted(); } } , ctx.Token); return Disposable.Create(() => ctx.Cancel()); })); }
public async Task DataflowBulkInsertBlockRetryTasksAsync(int seqNumber = 1, int frequency = 1000, int taskCount = 2, int count = 1, int orderCount = 100, int maxRetryCount = 2) { if (!_isInitialize) { throw new InvalidOperationException("not initialize"); } long totalOrderCount = taskCount * count * orderCount * maxRetryCount; var logger = _loggerFactory.CreateLogger($"DataflowBulkInser-{seqNumber}-OrderCount:{totalOrderCount}"); int currentRetryCount = 0; try { TimeSpan period = TimeSpan.FromMilliseconds(frequency); var transportTimeWatcher = Stopwatch.StartNew(); TimeSpan totalTransportTime = TimeSpan.Zero; var executionTimeWatcher = Stopwatch.StartNew(); logger.LogInformation($"----begin dataflow bulk insert {totalOrderCount} orders,now:{DateTime.Now.TimeOfDay}----"); while (true) { var signals = new AsyncCountdownEvent(taskCount); if (_cancellationTokenSource.Token.IsCancellationRequested) { _cancellationTokenSource.Token.ThrowIfCancellationRequested(); // _logger?.LogCritical($"message was cancelled"); break; } transportTimeWatcher.Restart(); var insertTasks = from tc in Enumerable.Range(0, taskCount) select Task.Run(() => { return DataflowBulkInsertBlockRetryTasksCoreAsync(signals, tc, count, orderCount); }, _cancellationTokenSource.Token); await Task.WhenAll(insertTasks); await signals.WaitAsync(); totalTransportTime += transportTimeWatcher.Elapsed; transportTimeWatcher.Reset(); await Task.Delay(period); currentRetryCount++; if (currentRetryCount >= maxRetryCount) { //_cancellationTokenSource.CancelAfter(TimeSpan.FromMilliseconds(200)); break; } } logger .LogInformation($"----dataflow bulk insert {totalOrderCount} orders,cost time:\"{executionTimeWatcher.Elapsed}\",transport time:{ totalTransportTime },count/time(sec):{Math.Ceiling(totalOrderCount / totalTransportTime.TotalSeconds)},now:\"{DateTime.Now.TimeOfDay}\"----"); } catch (Exception ex) { logger.LogError($"Error while dataflow bulk insert: {ex.Message}"); } }
/// <summary> /// Represents an replication operation to all destination servers of an item specified by ETag /// </summary> /// <param name="etag">ETag of an replicated item</param> /// <param name="timeout">Optional timeout</param> /// <param name="database">The database from which to check, if null, the default database for the document store connection string</param> /// <param name="replicas">The min number of replicas that must have the value before we can return (or the number of destinations, if higher)</param> /// <returns>Task which will have the number of nodes that the caught up to the specified etag</returns> public async Task <int> WaitAsync(Etag etag = null, TimeSpan?timeout = null, string database = null, int replicas = 2) { etag = etag ?? documentStore.LastEtagHolder.GetLastWrittenEtag(); if (etag == Etag.Empty) { return(replicas); // if the etag is empty, nothing to do } var asyncDatabaseCommands = documentStore.AsyncDatabaseCommands; if (database != null) { asyncDatabaseCommands = asyncDatabaseCommands.ForDatabase(database); } asyncDatabaseCommands.ForceReadFromMaster(); var doc = await asyncDatabaseCommands.GetAsync("Raven/Replication/Destinations"); if (doc == null) { return(-1); } var replicationDocument = doc.DataAsJson.JsonDeserialization <ReplicationDocument>(); if (replicationDocument == null) { return(-1); } var destinationsToCheck = replicationDocument.Destinations .Where( x => x.Disabled == false && x.IgnoredClient == false) .Select(x => x.ClientVisibleUrl ?? x.Url) .ToList(); if (destinationsToCheck.Count == 0) { return(0); } int toCheck = Math.Min(replicas, destinationsToCheck.Count); var countDown = new AsyncCountdownEvent(toCheck); var errors = new BlockingCollection <Exception>(); foreach (var url in destinationsToCheck) { WaitForReplicationFromServerAsync(url, countDown, etag, errors); } if (await countDown.WaitAsync().WaitWithTimeout(timeout) == false) { throw new TimeoutException( string.Format("Confirmed that the specified etag {0} was replicated to {1} of {2} servers, during {3}", etag, (toCheck - countDown.Count), toCheck, timeout)); } if (errors.Count > 0 && countDown.Count > 0) { throw new AggregateException(errors); } return(countDown.Count); }
public async Task SuriveBadLine() { AsyncCountdownEvent eventsReceived = new AsyncCountdownEvent(5); AsyncManualResetEvent serverShutdown = new AsyncManualResetEvent(); AsyncManualResetEvent connectionClosed = new AsyncManualResetEvent(); using (var server = new MockKubeApiServer( testOutput, async httpContext => { httpContext.Response.StatusCode = (int)HttpStatusCode.OK; httpContext.Response.ContentLength = null; await WriteStreamLine(httpContext, MockKubeApiServer.MockPodResponse); await WriteStreamLine(httpContext, MockBadStreamLine); await WriteStreamLine(httpContext, MockAddedEventStreamLine); await WriteStreamLine(httpContext, MockBadStreamLine); await WriteStreamLine(httpContext, MockModifiedStreamLine); // make server alive, cannot set to int.max as of it would block response await serverShutdown.WaitAsync(); return(false); })) { var client = new Kubernetes(new KubernetesClientConfiguration { Host = server.Uri.ToString() }); var listTask = await client.ListNamespacedPodWithHttpMessagesAsync("default", watch : true); var events = new HashSet <WatchEventType>(); var errors = 0; var watcher = listTask.Watch <V1Pod, V1PodList>( (type, item) => { testOutput.WriteLine($"Watcher received '{type}' event."); events.Add(type); eventsReceived.Signal(); }, error => { testOutput.WriteLine($"Watcher received '{error.GetType().FullName}' error."); errors += 1; eventsReceived.Signal(); }, onClosed: connectionClosed.Set ); // wait server yields all events await Task.WhenAny(eventsReceived.WaitAsync(), Task.Delay(TestTimeout)); Assert.True( eventsReceived.CurrentCount == 0, "Timed out waiting for all events / errors to be received." ); Assert.Contains(WatchEventType.Added, events); Assert.Contains(WatchEventType.Modified, events); Assert.Equal(3, errors); Assert.True(watcher.Watching); // Let the server know it can initiate a shut down. serverShutdown.Set(); await Task.WhenAny(connectionClosed.WaitAsync(), Task.Delay(TestTimeout)); Assert.True(connectionClosed.IsSet); } }
public async void PodWatchMods() { AsyncCountdownEvent requestHandled = new AsyncCountdownEvent(6); AsyncManualResetEvent serverShutdown = new AsyncManualResetEvent(); var podWatchData = await File.ReadAllTextAsync("podwatch.txt"); var addedAgent = BuildWatchEventStreamLine(podWatchData, WatchEventType.Added); var addedHub = BuildWatchEventStreamLine(podWatchData, WatchEventType.Added, 1); var addedSensor = BuildWatchEventStreamLine(podWatchData, WatchEventType.Added, 3); var v1PodList = JsonConvert.DeserializeObject <V1PodList>(podWatchData); V1Pod modAgentPod = v1PodList.Items[0]; modAgentPod.Status.ContainerStatuses[0].State.Running = null; modAgentPod.Status.ContainerStatuses[0].State.Terminated = new V1ContainerStateTerminated(139, finishedAt: DateTime.Parse("2019-06-12T16:13:07Z"), startedAt: DateTime.Parse("2019-06-12T16:11:22Z")); var modAgent = BuildPodStreamLine(modAgentPod, WatchEventType.Modified); V1Pod modHubPod = v1PodList.Items[1]; modHubPod.Status.ContainerStatuses[0].State.Running = null; modHubPod.Status.ContainerStatuses[1].State.Waiting = new V1ContainerStateWaiting("waiting", "reason"); var modHub = BuildPodStreamLine(modHubPod, WatchEventType.Modified); V1Pod tempSensorPod = v1PodList.Items[3]; // temp sensor has a "LastState" tempSensorPod.Status.ContainerStatuses[1].State.Running = null; var modTempSensor = BuildPodStreamLine(tempSensorPod, WatchEventType.Modified); using (var server = new MockKubeApiServer( async httpContext => { await MockKubeApiServer.WriteStreamLine(httpContext, addedAgent); await MockKubeApiServer.WriteStreamLine(httpContext, addedHub); await MockKubeApiServer.WriteStreamLine(httpContext, addedSensor); await MockKubeApiServer.WriteStreamLine(httpContext, modTempSensor); await MockKubeApiServer.WriteStreamLine(httpContext, modHub); await MockKubeApiServer.WriteStreamLine(httpContext, modAgent); return(false); })) { var client = new Kubernetes( new KubernetesClientConfiguration { Host = server.Uri.ToString() }); var k8sRuntimeInfo = new KubernetesRuntimeInfoProvider(PodwatchNamespace, client); k8sRuntimeInfo.PropertyChanged += (sender, args) => { Assert.Equal("Modules", args.PropertyName); requestHandled.Signal(); }; k8sRuntimeInfo.Start(); await Task.WhenAny(requestHandled.WaitAsync(), Task.Delay(TestTimeout)); var runtimeModules = await k8sRuntimeInfo.GetModules(CancellationToken.None); var moduleRuntimeInfos = runtimeModules as ModuleRuntimeInfo[] ?? runtimeModules.ToArray(); Assert.True(moduleRuntimeInfos.Count() == 3); foreach (var i in moduleRuntimeInfos) { if (!string.Equals("edgeAgent", i.Name)) { Assert.Equal(ModuleStatus.Unknown, i.ModuleStatus); } else { Assert.Equal(ModuleStatus.Failed, i.ModuleStatus); } if (string.Equals("edgeHub", i.Name)) { Assert.Equal(Option.None <DateTime>(), i.ExitTime); Assert.Equal(Option.None <DateTime>(), i.StartTime); } else { Assert.Equal(new DateTime(2019, 6, 12), i.StartTime.GetOrElse(DateTime.MinValue).Date); Assert.Equal(new DateTime(2019, 6, 12), i.ExitTime.GetOrElse(DateTime.MinValue).Date); } if (i is ModuleRuntimeInfo <DockerReportedConfig> d) { Assert.NotEqual("unknown:unknown", d.Config.Image); } } } }
public async Task DirectWatchEventsWithTimeout() { AsyncCountdownEvent eventsReceived = new AsyncCountdownEvent(4); AsyncManualResetEvent serverShutdown = new AsyncManualResetEvent(); using (var server = new MockKubeApiServer(testOutput, async httpContext => { await Task.Delay(TimeSpan.FromSeconds(120)); // The default timeout is 100 seconds await WriteStreamLine(httpContext, MockAddedEventStreamLine); await WriteStreamLine(httpContext, MockDeletedStreamLine); await WriteStreamLine(httpContext, MockModifiedStreamLine); await WriteStreamLine(httpContext, MockErrorStreamLine); // make server alive, cannot set to int.max as of it would block response await serverShutdown.WaitAsync(); return(false); })) { var client = new Kubernetes(new KubernetesClientConfiguration { Host = server.Uri.ToString() }); var events = new HashSet <WatchEventType>(); var errors = 0; var watcher = await client.WatchNamespacedPodAsync( name : "myPod", @namespace : "default", onEvent : (type, item) => { testOutput.WriteLine($"Watcher received '{type}' event."); events.Add(type); eventsReceived.Signal(); }, onError : error => { testOutput.WriteLine($"Watcher received '{error.GetType().FullName}' error."); errors += 1; eventsReceived.Signal(); } ); // wait server yields all events await Task.WhenAny(eventsReceived.WaitAsync(), Task.Delay(TestTimeout)); Assert.True( eventsReceived.CurrentCount == 0, "Timed out waiting for all events / errors to be received." ); Assert.Contains(WatchEventType.Added, events); Assert.Contains(WatchEventType.Deleted, events); Assert.Contains(WatchEventType.Modified, events); Assert.Contains(WatchEventType.Error, events); Assert.Equal(0, errors); Assert.True(watcher.Watching); serverShutdown.Set(); } }
public async Task ClientReady(string id, Guid queueId, string language) { var login = Context.User.GetLogin(); var client = Clients.Client(id); if (queueId == Guid.Empty) { _logger.LogWarning($"Client {login} | {id} has passed empty queueId."); return; } if (!_queue.Queue.TryRemove(queueId, out IEnumerable <WhoisDto> dtos)) { _logger.LogError($"Failed remove Ping Request {queueId} for client {id}."); await client.SendAsync("Exception", "Queue error."); return; } _logger.LogInformation($"User {login} has started Whois Request {queueId} with {dtos.Count()} host(s)."); var culture = await GetCultureAsync(id, language); _tasks.QueueTask(async token => { if (token.IsCancellationRequested) { return; } Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = culture; var taskFactory = new TaskFactory(TaskScheduler.Current); var cde = new AsyncCountdownEvent(dtos.Count()); var tasks = new List <Task>(); var whois = new YaWhoisClient(); whois.ResponseParsed += Whois_ResponseParsed; whois.ExceptionThrown += Whois_ExceptionThrown; foreach (var host in dtos.Select(a => a.Hostname)) { var data = new YaWhoisData() { Client = client, ClientId = id, Object = host }; tasks.Add(taskFactory.StartNew((d) => { whois.QueryAsync(host, token: token, value: d).Wait(); cde.Signal(); }, data, token)); } try { Task.WaitAll(tasks.ToArray()); } catch (Exception e) { var obj = e.Data["object"].ToString(); _logger.LogError(e, $"Whois {obj} failed (clientId: {id})."); } await cde.WaitAsync(); }); }
public async Task CanIncrementUsageAsync() { var messageBus = GetService <IMessageBus>(); var countdown = new AsyncCountdownEvent(2); await messageBus.SubscribeAsync <PlanOverage>(po => { _logger.Info($"Plan Overage for {po.OrganizationId} (Hourly: {po.IsHourly})"); countdown.Signal(); }); var o = await _organizationRepository.AddAsync(new Organization { Name = "Test", MaxEventsPerMonth = 750, PlanId = BillingManager.SmallPlan.Id }); var project = await _projectRepository.AddAsync(new Project { Name = "Test", OrganizationId = o.Id, NextSummaryEndOfDayTicks = SystemClock.UtcNow.Ticks }, opt => opt.Cache()); await _configuration.Client.RefreshAsync(Indices.All); Assert.InRange(o.GetHourlyEventLimit(), 1, 750); int totalToIncrement = o.GetHourlyEventLimit() - 1; Assert.False(await _usageService.IncrementUsageAsync(o.Id, project.Id, false, totalToIncrement)); await _configuration.Client.RefreshAsync(Indices.All); o = await _organizationRepository.GetByIdAsync(o.Id); await countdown.WaitAsync(TimeSpan.FromMilliseconds(150)); Assert.Equal(2, countdown.CurrentCount); Assert.Equal(totalToIncrement, await _cache.GetAsync <long>(GetHourlyTotalCacheKey(o.Id), 0)); Assert.Equal(totalToIncrement, await _cache.GetAsync <long>(GetHourlyTotalCacheKey(o.Id, project.Id), 0)); Assert.Equal(totalToIncrement, await _cache.GetAsync <long>(GetMonthlyTotalCacheKey(o.Id), 0)); Assert.Equal(totalToIncrement, await _cache.GetAsync <long>(GetMonthlyTotalCacheKey(o.Id, project.Id), 0)); Assert.Equal(0, await _cache.GetAsync <long>(GetHourlyBlockedCacheKey(o.Id), 0)); Assert.Equal(0, await _cache.GetAsync <long>(GetHourlyBlockedCacheKey(o.Id, project.Id), 0)); Assert.Equal(0, await _cache.GetAsync <long>(GetMonthlyBlockedCacheKey(o.Id), 0)); Assert.Equal(0, await _cache.GetAsync <long>(GetMonthlyBlockedCacheKey(o.Id, project.Id), 0)); Assert.True(await _usageService.IncrementUsageAsync(o.Id, project.Id, false, 2)); await _configuration.Client.RefreshAsync(Indices.All); o = await _organizationRepository.GetByIdAsync(o.Id); await countdown.WaitAsync(TimeSpan.FromMilliseconds(150)); Assert.Equal(1, countdown.CurrentCount); Assert.Equal(totalToIncrement + 2, await _cache.GetAsync <long>(GetHourlyTotalCacheKey(o.Id), 0)); Assert.Equal(totalToIncrement + 2, await _cache.GetAsync <long>(GetHourlyTotalCacheKey(o.Id, project.Id), 0)); Assert.Equal(totalToIncrement + 2, await _cache.GetAsync <long>(GetMonthlyTotalCacheKey(o.Id), 0)); Assert.Equal(totalToIncrement + 2, await _cache.GetAsync <long>(GetMonthlyTotalCacheKey(o.Id, project.Id), 0)); Assert.Equal(1, await _cache.GetAsync <long>(GetHourlyBlockedCacheKey(o.Id), 0)); Assert.Equal(1, await _cache.GetAsync <long>(GetHourlyBlockedCacheKey(o.Id, project.Id), 0)); Assert.Equal(1, await _cache.GetAsync <long>(GetMonthlyBlockedCacheKey(o.Id), 0)); Assert.Equal(1, await _cache.GetAsync <long>(GetMonthlyBlockedCacheKey(o.Id, project.Id), 0)); o = await _organizationRepository.AddAsync(new Organization { Name = "Test", MaxEventsPerMonth = 750, PlanId = BillingManager.SmallPlan.Id }); project = await _projectRepository.AddAsync(new Project { Name = "Test", OrganizationId = o.Id, NextSummaryEndOfDayTicks = SystemClock.UtcNow.Ticks }, opt => opt.Cache()); await _configuration.Client.RefreshAsync(Indices.All); await _cache.RemoveAllAsync(); totalToIncrement = o.GetHourlyEventLimit() + 20; Assert.True(await _usageService.IncrementUsageAsync(o.Id, project.Id, false, totalToIncrement)); await countdown.WaitAsync(TimeSpan.FromMilliseconds(150)); Assert.Equal(0, countdown.CurrentCount); Assert.Equal(totalToIncrement, await _cache.GetAsync <long>(GetHourlyTotalCacheKey(o.Id), 0)); Assert.Equal(totalToIncrement, await _cache.GetAsync <long>(GetHourlyTotalCacheKey(o.Id, project.Id), 0)); Assert.Equal(totalToIncrement, await _cache.GetAsync <long>(GetMonthlyTotalCacheKey(o.Id), 0)); Assert.Equal(totalToIncrement, await _cache.GetAsync <long>(GetMonthlyTotalCacheKey(o.Id, project.Id), 0)); Assert.Equal(20, await _cache.GetAsync <long>(GetHourlyBlockedCacheKey(o.Id), 0)); Assert.Equal(20, await _cache.GetAsync <long>(GetHourlyBlockedCacheKey(o.Id, project.Id), 0)); Assert.Equal(20, await _cache.GetAsync <long>(GetMonthlyBlockedCacheKey(o.Id), 0)); Assert.Equal(20, await _cache.GetAsync <long>(GetMonthlyBlockedCacheKey(o.Id, project.Id), 0)); }
public async Task InitialCountZero() { var evt = new AsyncCountdownEvent(0); await evt.WaitAsync(); }
public async Task When_receiver_throws_then_work_distribution_continues() { var received = 0; var distributor = CreateDistributor(waitInterval: TimeSpan.FromMilliseconds(100)).Trace(); var countdown = new AsyncCountdownEvent(20); distributor.OnReceive(async lease => { Interlocked.Increment(ref received); if (received < 10) { throw new Exception("dangit!"); } countdown.Signal(); }); await distributor.Start(); await countdown.WaitAsync().Timeout(); await distributor.Stop(); received.Should().BeGreaterOrEqualTo(20); }
public async Task CanReindexVersionedIndexWithUpdatedDocsAsync() { var version1Index = new VersionedEmployeeIndex(_configuration, 1); await version1Index.DeleteAsync(); var version2Index = new VersionedEmployeeIndex(_configuration, 2); await version2Index.DeleteAsync(); using (new DisposableAction(() => version1Index.DeleteAsync().GetAwaiter().GetResult())) { await version1Index.ConfigureAsync(); Assert.True(_client.IndexExists(version1Index.VersionedName).Exists); var repository = new EmployeeRepository(version1Index.Employee); var employee = await repository.AddAsync(EmployeeGenerator.Default, o => o.ImmediateConsistency()); Assert.NotNull(employee?.Id); using (new DisposableAction(() => version2Index.DeleteAsync().GetAwaiter().GetResult())) { await version2Index.ConfigureAsync(); Assert.True(_client.IndexExists(version2Index.VersionedName).Exists); Assert.Equal(1, await version2Index.GetCurrentVersionAsync()); // alias should still point to the old version until reindex var aliasResponse = await _client.GetAliasAsync(descriptor => descriptor.Name(version2Index.Name)); Assert.True(aliasResponse.IsValid); Assert.Equal(1, aliasResponse.Indices.Count); Assert.Equal(version1Index.VersionedName, aliasResponse.Indices.First().Key); var countdown = new AsyncCountdownEvent(1); var reindexTask = version2Index.ReindexAsync((progress, message) => { _logger.LogInformation($"Reindex Progress {progress}%: {message}"); if (progress == 91) { countdown.Signal(); SystemClock.Sleep(1000); } return(Task.CompletedTask); }); // Wait until the first reindex pass is done. await countdown.WaitAsync(); Assert.Equal(1, await version1Index.GetCurrentVersionAsync()); await repository.AddAsync(EmployeeGenerator.Generate(createdUtc: SystemClock.UtcNow)); employee.Name = "Updated"; await repository.SaveAsync(employee); // Resume after everythings been indexed. await reindexTask; aliasResponse = await _client.GetAliasAsync(descriptor => descriptor.Name(version2Index.Name)); Assert.True(aliasResponse.IsValid); Assert.Equal(1, aliasResponse.Indices.Count); Assert.Equal(version2Index.VersionedName, aliasResponse.Indices.First().Key); Assert.Equal(2, await version1Index.GetCurrentVersionAsync()); Assert.Equal(2, await version2Index.GetCurrentVersionAsync()); await _client.RefreshAsync(Indices.All); var countResponse = await _client.CountAsync <Employee>(d => d.Index(version2Index.VersionedName)); _logger.LogTrace(countResponse.GetRequest()); Assert.True(countResponse.IsValid); Assert.Equal(2, countResponse.Count); var result = await repository.GetByIdAsync(employee.Id); Assert.Equal(ToJson(employee), ToJson(result)); Assert.False((await _client.IndexExistsAsync(version1Index.VersionedName)).Exists); } } }
public async Task Any_given_lease_is_never_handed_out_to_more_than_one_handler_at_a_time() { var random = new Random(); var currentlyGranted = new HashSet<string>(); var everGranted = new HashSet<string>(); var leasedConcurrently = ""; var distributor = CreateDistributor(waitInterval: TimeSpan.FromSeconds(5)).Trace(); var countDown = new AsyncCountdownEvent(10); distributor.OnReceive(async lease => { lock (currentlyGranted) { if (currentlyGranted.Contains(lease.LeasableResource.Name)) { leasedConcurrently = lease.LeasableResource.Name; } currentlyGranted.Add(lease.LeasableResource.Name); everGranted.Add(lease.LeasableResource.Name); } await Task.Delay((int) (1000*random.NextDouble())); lock (currentlyGranted) { currentlyGranted.Remove(lease.LeasableResource.Name); } countDown.Signal(); }); Enumerable.Range(1, 10).ToList().ForEach(_ => { distributor.Distribute(1); }); await countDown.WaitAsync().Timeout(); leasedConcurrently.Should().BeEmpty(); everGranted.Count.Should().Be(10); }
public async Task DisposeWatch() { var connectionClosed = new AsyncManualResetEvent(); var eventsReceived = new AsyncCountdownEvent(1); bool serverRunning = true; using (var server = new MockKubeApiServer(testOutput, async httpContext => { await WriteStreamLine(httpContext, MockKubeApiServer.MockPodResponse); while (serverRunning) { await WriteStreamLine(httpContext, MockAddedEventStreamLine); } return(true); })) { var client = new Kubernetes(new KubernetesClientConfiguration { Host = server.Uri.ToString() }); var listTask = await client.ListNamespacedPodWithHttpMessagesAsync("default", watch : true); var events = new HashSet <WatchEventType>(); var watcher = listTask.Watch <V1Pod, V1PodList>( (type, item) => { events.Add(type); eventsReceived.Signal(); }, onClosed: connectionClosed.Set ); // wait at least an event await Task.WhenAny(eventsReceived.WaitAsync(), Task.Delay(TestTimeout)); Assert.True( eventsReceived.CurrentCount == 0, "Timed out waiting for events." ); Assert.NotEmpty(events); Assert.True(watcher.Watching); watcher.Dispose(); events.Clear(); // Let the server disconnect serverRunning = false; var timeout = Task.Delay(TestTimeout); while (!timeout.IsCompleted && watcher.Watching) { await Task.Yield(); } Assert.Empty(events); Assert.False(watcher.Watching); Assert.True(connectionClosed.IsSet); } }
public async Task CanReindexVersionedIndexWithDeletedDocsAsync() { var version1Index = new VersionedEmployeeIndex(_configuration, 1); await version1Index.DeleteAsync(); var version2Index = new VersionedEmployeeIndex(_configuration, 2); await version2Index.DeleteAsync(); using (new DisposableAction(() => version1Index.DeleteAsync().GetAwaiter().GetResult())) { await version1Index.ConfigureAsync(); Assert.True((await _client.Indices.ExistsAsync(version1Index.VersionedName)).Exists); IEmployeeRepository repository = new EmployeeRepository(_configuration); var employee = await repository.AddAsync(EmployeeGenerator.Default, o => o.ImmediateConsistency()); Assert.NotNull(employee?.Id); using (new DisposableAction(() => version2Index.DeleteAsync().GetAwaiter().GetResult())) { await version2Index.ConfigureAsync(); Assert.True((await _client.Indices.ExistsAsync(version2Index.VersionedName)).Exists); Assert.Equal(1, await version2Index.GetCurrentVersionAsync()); // alias should still point to the old version until reindex var aliasResponse = await _client.Indices.GetAliasAsync(version2Index.Name); _logger.LogRequest(aliasResponse); Assert.True(aliasResponse.IsValid); Assert.Equal(1, aliasResponse.Indices.Count); Assert.Equal(version1Index.VersionedName, aliasResponse.Indices.First().Key); var countdown = new AsyncCountdownEvent(1); var reindexTask = version2Index.ReindexAsync(async(progress, message) => { _logger.LogInformation($"Reindex Progress {progress}%: {message}"); if (progress == 91) { countdown.Signal(); await Task.Delay(1000); } }); // Wait until the first reindex pass is done. await countdown.WaitAsync(); Assert.Equal(1, await version1Index.GetCurrentVersionAsync()); await repository.RemoveAllAsync(o => o.ImmediateConsistency()); // Resume after everythings been indexed. await reindexTask; aliasResponse = await _client.Indices.GetAliasAsync(version2Index.Name); _logger.LogRequest(aliasResponse); Assert.True(aliasResponse.IsValid, aliasResponse.GetErrorMessage()); Assert.Equal(1, aliasResponse.Indices.Count); Assert.Equal(version2Index.VersionedName, aliasResponse.Indices.First().Key); Assert.Equal(2, await version1Index.GetCurrentVersionAsync()); Assert.Equal(2, await version2Index.GetCurrentVersionAsync()); var countResponse = await _client.CountAsync <Employee>(d => d.Index(version1Index.VersionedName)); _logger.LogRequest(countResponse); Assert.True(countResponse.ApiCall.HttpStatusCode == 404, countResponse.GetErrorMessage()); Assert.Equal(0, countResponse.Count); countResponse = await _client.CountAsync <Employee>(d => d.Index(version2Index.VersionedName)); _logger.LogRequest(countResponse); Assert.True(countResponse.IsValid, countResponse.GetErrorMessage()); Assert.Equal(1, countResponse.Count); Assert.Equal(employee, await repository.GetByIdAsync(employee.Id)); Assert.False((await _client.Indices.ExistsAsync(version1Index.VersionedName)).Exists); } } }
public static Task WaitAsync(this AsyncCountdownEvent countdownEvent, CancellationToken cancellationToken = default(CancellationToken)) { return(Task.WhenAny(countdownEvent.WaitAsync(), cancellationToken.AsTask())); }
public async Task CanIncrementSuspendedOrganizationUsageAsync() { var messageBus = GetService <IMessageBus>(); var countdown = new AsyncCountdownEvent(2); await messageBus.SubscribeAsync <PlanOverage>(po => { _logger.LogInformation("Plan Overage for {organization} (Hourly: {IsHourly})", po.OrganizationId, po.IsHourly); countdown.Signal(); }); var organization = await _organizationRepository.AddAsync(new Organization { Name = "Test", MaxEventsPerMonth = 750, PlanId = _plans.SmallPlan.Id }, o => o.ImmediateConsistency()); var project = await _projectRepository.AddAsync(new Project { Name = "Test", OrganizationId = organization.Id, NextSummaryEndOfDayTicks = SystemClock.UtcNow.Ticks }, o => o.ImmediateConsistency()); Assert.False(await _usageService.IncrementUsageAsync(organization, project, 5)); await countdown.WaitAsync(TimeSpan.FromMilliseconds(150)); Assert.Equal(2, countdown.CurrentCount); var organizationUsage = await _usageService.GetUsageAsync(organization); var projectUsage = await _usageService.GetUsageAsync(organization, project); Assert.Equal(5, organizationUsage.HourlyTotal); Assert.Equal(5, projectUsage.HourlyTotal); Assert.Equal(5, organizationUsage.MonthlyTotal); Assert.Equal(5, projectUsage.MonthlyTotal); Assert.Equal(0, organizationUsage.HourlyBlocked); Assert.Equal(0, projectUsage.HourlyBlocked); Assert.Equal(0, organizationUsage.MonthlyBlocked); Assert.Equal(0, projectUsage.MonthlyBlocked); organization.IsSuspended = true; organization.SuspendedByUserId = TestConstants.UserId; organization.SuspensionDate = SystemClock.UtcNow; organization.SuspensionCode = SuspensionCode.Billing; organization = await _organizationRepository.SaveAsync(organization, o => o.ImmediateConsistency()); Assert.True(await _usageService.IncrementUsageAsync(organization, project, 4995)); await countdown.WaitAsync(TimeSpan.FromMilliseconds(150)); Assert.Equal(1, countdown.CurrentCount); organizationUsage = await _usageService.GetUsageAsync(organization); projectUsage = await _usageService.GetUsageAsync(organization, project); Assert.Equal(5000, organizationUsage.HourlyTotal); Assert.Equal(5000, projectUsage.HourlyTotal); Assert.Equal(5000, organizationUsage.MonthlyTotal); Assert.Equal(5000, projectUsage.MonthlyTotal); Assert.Equal(4995, organizationUsage.HourlyBlocked); Assert.Equal(4995, projectUsage.HourlyBlocked); Assert.Equal(4995, organizationUsage.MonthlyBlocked); Assert.Equal(4995, projectUsage.MonthlyBlocked); organization.RemoveSuspension(); organization = await _organizationRepository.SaveAsync(organization, o => o.ImmediateConsistency()); Assert.False(await _usageService.IncrementUsageAsync(organization, project, 1)); await countdown.WaitAsync(TimeSpan.FromMilliseconds(150)); Assert.Equal(1, countdown.CurrentCount); organizationUsage = await _usageService.GetUsageAsync(organization); projectUsage = await _usageService.GetUsageAsync(organization, project); Assert.Equal(5001, organizationUsage.HourlyTotal); Assert.Equal(5001, projectUsage.HourlyTotal); Assert.Equal(5001, organizationUsage.MonthlyTotal); Assert.Equal(5001, projectUsage.MonthlyTotal); Assert.Equal(4995, organizationUsage.HourlyBlocked); Assert.Equal(4995, projectUsage.HourlyBlocked); Assert.Equal(4995, organizationUsage.MonthlyBlocked); Assert.Equal(4995, projectUsage.MonthlyBlocked); }
public static Task WaitAsync(this AsyncCountdownEvent countdownEvent, TimeSpan timeout) { return(countdownEvent.WaitAsync(timeout.ToCancellationToken())); }
public static Task WaitAsync(this AsyncCountdownEvent countdownEvent, TimeSpan timeout) { return Task.WhenAny(countdownEvent.WaitAsync(), SystemClock.SleepAsync(timeout)); }
async Task DoContexts(string url) { const int NumSurveyors = 1; const int NumResponders = 2; var readyToDial = new AsyncBarrier(NumSurveyors + NumResponders); var readyToSend = new AsyncBarrier(NumSurveyors + NumResponders); var ready = readyToSend.WaitAsync(); var numSurveyorReceive = new AsyncCountdownEvent(NumSurveyors); var numResponderReceive = new AsyncCountdownEvent(NumSurveyors); using (var surveySocket = Factory.SurveyorOpen().ThenListen(url).Unwrap()) using (var respondSocket = Factory.RespondentOpen().ThenDial(url).Unwrap()) { var duration = new nng_duration { TimeMs = DefaultTimeoutMs }; // Send() is not cancelable so need it to timeout surveySocket.SetOpt(nng.Native.Defines.NNG_OPT_SENDTIMEO, new nng_duration { TimeMs = 50 }); surveySocket.SetOpt(nng.Native.Defines.NNG_OPT_RECVTIMEO, nng_duration.Infinite); surveySocket.SetOpt(Native.Defines.NNG_OPT_SURVEYOR_SURVEYTIME, nng_duration.Infinite); respondSocket.SetOpt(nng.Native.Defines.NNG_OPT_SENDTIMEO, new nng_duration { TimeMs = 50 }); var cts = new CancellationTokenSource(); var tasks = new List <Task>(); for (var i = 0; i < NumSurveyors; ++i) { var id = i; var task = Task.Run(async() => { using (var ctx = surveySocket.CreateAsyncContext(Factory).Unwrap()) { ctx.Ctx.SetOpt(Native.Defines.NNG_OPT_RECVTIMEO, nng_duration.Infinite); ctx.Ctx.SetOpt(Native.Defines.NNG_OPT_SURVEYOR_SURVEYTIME, nng_duration.Infinite); await readyToDial.SignalAndWait(); await readyToSend.SignalAndWait(); // Send survey and receive responses var survey = Factory.CreateMessage(); var val = (uint)rng.Next(); survey.Append(val); //Assert.Equal(0, survey.Header.Append((uint)(0x8000000 | i))); // Protocol header contains "survey ID" (await ctx.Send(survey)).Unwrap(); while (!cts.IsCancellationRequested) { try { var response = (await ctx.Receive(cts.Token)).Unwrap(); response.Trim(out uint respVal); Assert.Equal(val, respVal); if (numSurveyorReceive.Signal() == 0) { break; } } catch (Exception ex) { Console.Error.WriteLine(ex.ToString()); throw ex; } } } }); tasks.Add(task); } for (var i = 0; i < NumResponders; ++i) { var id = i; var task = Task.Run(async() => { await readyToDial.SignalAndWait(); using (var ctx = respondSocket.CreateAsyncContext(Factory).Unwrap()) { // Receive survey and send response try { // Receive is async, give it a chance to start before signaling we are ready. // This to avoid race where surveyor sends before it actually starts receiving var recvFuture = ctx.Receive(cts.Token); await WaitShort(); await readyToSend.SignalAndWait(); var survey = (await recvFuture).Unwrap(); await Task.Delay(10); // Make sure surveyor has a chance to start receiving (await ctx.Send(survey)).Unwrap(); numResponderReceive.Signal(); await numSurveyorReceive.WaitAsync(); cts.Cancel(); // Cancel any responders still receiving } catch (Exception ex) { Console.WriteLine(ex.ToString()); throw ex; } } }); tasks.Add(task); } await Task.WhenAny(ready, Task.WhenAll(tasks)); await Util.CancelAfterAssertwait(tasks, cts); Assert.Equal(0, numSurveyorReceive.Count); Assert.Equal(0, numResponderReceive.Count); } }
public virtual async Task CanHaveMultipleQueueInstancesAsync() { var queue = GetQueue(retries: 0, retryDelay: TimeSpan.Zero); if (queue == null) { return; } try { await queue.DeleteQueueAsync(); await AssertEmptyQueueAsync(queue); const int workItemCount = 500; const int workerCount = 3; var countdown = new AsyncCountdownEvent(workItemCount); var info = new WorkInfo(); var workers = new List <IQueue <SimpleWorkItem> > { queue }; try { for (int i = 0; i < workerCount; i++) { var q = GetQueue(retries: 0, retryDelay: TimeSpan.Zero); _logger.Trace("Queue Id: {0}, I: {1}", q.QueueId, i); await q.StartWorkingAsync(w => DoWorkAsync(w, countdown, info)); workers.Add(q); } await Run.InParallelAsync(workItemCount, async i => { string id = await queue.EnqueueAsync(new SimpleWorkItem { Data = "Hello", Id = i }); _logger.Trace("Enqueued Index: {0} Id: {1}", i, id); }); await countdown.WaitAsync(); await SystemClock.SleepAsync(50); _logger.Trace("Completed: {0} Abandoned: {1} Error: {2}", info.CompletedCount, info.AbandonCount, info.ErrorCount); _logger.Info("Work Info Stats: Completed: {completed} Abandoned: {abandoned} Error: {errors}", info.CompletedCount, info.AbandonCount, info.ErrorCount); Assert.Equal(workItemCount, info.CompletedCount + info.AbandonCount + info.ErrorCount); // In memory queue doesn't share state. if (queue.GetType() == typeof(InMemoryQueue <SimpleWorkItem>)) { var stats = await queue.GetQueueStatsAsync(); Assert.Equal(0, stats.Working); Assert.Equal(0, stats.Timeouts); Assert.Equal(workItemCount, stats.Enqueued); Assert.Equal(workItemCount, stats.Dequeued); Assert.Equal(info.CompletedCount, stats.Completed); Assert.Equal(info.ErrorCount, stats.Errors); Assert.Equal(info.AbandonCount, stats.Abandoned - info.ErrorCount); Assert.Equal(info.AbandonCount + stats.Errors, stats.Deadletter); } else { var workerStats = new List <QueueStats>(); for (int i = 0; i < workers.Count; i++) { var stats = await workers[i].GetQueueStatsAsync(); _logger.Info("Worker#{i} Working: {working} Completed: {completed} Abandoned: {abandoned} Error: {errors} Deadletter: {deadletter}", i, stats.Working, stats.Completed, stats.Abandoned, stats.Errors, stats.Deadletter); workerStats.Add(stats); } Assert.Equal(info.CompletedCount, workerStats.Sum(s => s.Completed)); Assert.Equal(info.ErrorCount, workerStats.Sum(s => s.Errors)); Assert.Equal(info.AbandonCount, workerStats.Sum(s => s.Abandoned) - info.ErrorCount); Assert.Equal(info.AbandonCount + workerStats.Sum(s => s.Errors), (workerStats.LastOrDefault()?.Deadletter ?? 0)); } } finally { foreach (var q in workers) { await CleanupQueueAsync(q); } } } finally { await CleanupQueueAsync(queue); } }
private async Task <int> AnalyzeAffectedEntriesAsync(Stopwatch stopWatch) { IDependencyChainNode node; var remaining = 0; var ace = new AsyncCountdownEvent(0); while ((node = await _walker.GetNextAsync(_analyzerCancellationToken)) != null) { bool isCanceled; lock (_syncObj) { isCanceled = _isCanceled; } if (isCanceled) { switch (node) { case IDependencyChainLoopNode <PythonAnalyzerEntry> loop: // Loop analysis is not cancellable or else small // inner loops of a larger loop will not be analyzed // correctly as large loop may cancel inner loop pass. break; case IDependencyChainSingleNode <PythonAnalyzerEntry> single when !single.Value.NotAnalyzed: remaining++; node.MoveNext(); continue; } } var taskLimitReached = false; lock (_syncObj) { _runningTasks++; taskLimitReached = _runningTasks >= _maxTaskRunning || _walker.Remaining == 1; } if (taskLimitReached) { RunAnalysis(node, stopWatch); } else { ace.AddOne(); StartAnalysis(node, ace, stopWatch).DoNotWait(); } } await ace.WaitAsync(_analyzerCancellationToken); lock (_syncObj) { if (_walker.MissingKeys.Count == 0 || _walker.MissingKeys.All(k => k.IsTypeshed)) { Debug.Assert(_runningTasks == 0); } else if (!_isCanceled && _log != null && _log.LogLevel >= TraceEventType.Verbose) { _log?.Log(TraceEventType.Verbose, $"Missing keys: {string.Join(", ", _walker.MissingKeys)}"); } } return(remaining); }
public async Task WatchAllEvents() { AsyncCountdownEvent eventsReceived = new AsyncCountdownEvent(4 /* first line of response is eaten by WatcherDelegatingHandler */); AsyncManualResetEvent serverShutdown = new AsyncManualResetEvent(); var waitForClosed = new AsyncManualResetEvent(false); using (var server = new MockKubeApiServer(testOutput, async httpContext => { await WriteStreamLine(httpContext, MockAddedEventStreamLine); await WriteStreamLine(httpContext, MockDeletedStreamLine); await WriteStreamLine(httpContext, MockModifiedStreamLine); await WriteStreamLine(httpContext, MockErrorStreamLine); // make server alive, cannot set to int.max as of it would block response await serverShutdown.WaitAsync(); return(false); })) { var client = new Kubernetes(new KubernetesClientConfiguration { Host = server.Uri.ToString() }); var listTask = await client.ListNamespacedPodWithHttpMessagesAsync("default", watch : true); var events = new HashSet <WatchEventType>(); var errors = 0; var watcher = listTask.Watch <V1Pod, V1PodList>( (type, item) => { testOutput.WriteLine($"Watcher received '{type}' event."); events.Add(type); eventsReceived.Signal(); }, error => { testOutput.WriteLine($"Watcher received '{error.GetType().FullName}' error."); errors += 1; eventsReceived.Signal(); }, onClosed: waitForClosed.Set ); // wait server yields all events await Task.WhenAny(eventsReceived.WaitAsync(), Task.Delay(TestTimeout)); Assert.True( eventsReceived.CurrentCount == 0, "Timed out waiting for all events / errors to be received." ); Assert.Contains(WatchEventType.Added, events); Assert.Contains(WatchEventType.Deleted, events); Assert.Contains(WatchEventType.Modified, events); Assert.Contains(WatchEventType.Error, events); Assert.Equal(0, errors); Assert.True(watcher.Watching); serverShutdown.Set(); await Task.WhenAny(waitForClosed.WaitAsync(), Task.Delay(TestTimeout)); Assert.True(waitForClosed.IsSet); Assert.False(watcher.Watching); } }
public async Task CanIncrementSuspendedOrganizationUsageAsync() { var messageBus = GetService <IMessageBus>(); var countdown = new AsyncCountdownEvent(2); await messageBus.SubscribeAsync <PlanOverage>(po => { _logger.Info($"Plan Overage for {po.OrganizationId} (Hourly: {po.IsHourly}"); countdown.Signal(); }); var o = await _organizationRepository.AddAsync(new Organization { Name = "Test", MaxEventsPerMonth = 750, PlanId = BillingManager.SmallPlan.Id }, opt => opt.Cache()); var project = await _projectRepository.AddAsync(new Project { Name = "Test", OrganizationId = o.Id, NextSummaryEndOfDayTicks = SystemClock.UtcNow.Ticks }, opt => opt.Cache()); Assert.False(await _usageService.IncrementUsageAsync(o.Id, project.Id, false, 5)); await countdown.WaitAsync(TimeSpan.FromMilliseconds(150)); Assert.Equal(2, countdown.CurrentCount); Assert.Equal(5, await _cache.GetAsync <long>(GetHourlyTotalCacheKey(o.Id), 0)); Assert.Equal(5, await _cache.GetAsync <long>(GetHourlyTotalCacheKey(o.Id, project.Id), 0)); Assert.Equal(5, await _cache.GetAsync <long>(GetMonthlyTotalCacheKey(o.Id), 0)); Assert.Equal(5, await _cache.GetAsync <long>(GetMonthlyTotalCacheKey(o.Id, project.Id), 0)); Assert.Equal(0, await _cache.GetAsync <long>(GetHourlyBlockedCacheKey(o.Id), 0)); Assert.Equal(0, await _cache.GetAsync <long>(GetHourlyBlockedCacheKey(o.Id, project.Id), 0)); Assert.Equal(0, await _cache.GetAsync <long>(GetMonthlyBlockedCacheKey(o.Id), 0)); Assert.Equal(0, await _cache.GetAsync <long>(GetMonthlyBlockedCacheKey(o.Id, project.Id), 0)); o.IsSuspended = true; o.SuspendedByUserId = TestConstants.UserId; o.SuspensionDate = SystemClock.UtcNow; o.SuspensionCode = SuspensionCode.Billing; o = await _organizationRepository.SaveAsync(o, opt => opt.Cache()); Assert.True(await _usageService.IncrementUsageAsync(o.Id, project.Id, false, 4995)); await countdown.WaitAsync(TimeSpan.FromMilliseconds(150)); Assert.Equal(1, countdown.CurrentCount); Assert.Equal(5000, await _cache.GetAsync <long>(GetHourlyTotalCacheKey(o.Id), 0)); Assert.Equal(5000, await _cache.GetAsync <long>(GetHourlyTotalCacheKey(o.Id, project.Id), 0)); Assert.Equal(5000, await _cache.GetAsync <long>(GetMonthlyTotalCacheKey(o.Id), 0)); Assert.Equal(5000, await _cache.GetAsync <long>(GetMonthlyTotalCacheKey(o.Id, project.Id), 0)); Assert.Equal(4995, await _cache.GetAsync <long>(GetHourlyBlockedCacheKey(o.Id), 0)); Assert.Equal(4995, await _cache.GetAsync <long>(GetHourlyBlockedCacheKey(o.Id, project.Id), 0)); Assert.Equal(4995, await _cache.GetAsync <long>(GetMonthlyBlockedCacheKey(o.Id), 0)); Assert.Equal(4995, await _cache.GetAsync <long>(GetMonthlyBlockedCacheKey(o.Id, project.Id), 0)); o.RemoveSuspension(); o = await _organizationRepository.SaveAsync(o, opt => opt.Cache()); Assert.False(await _usageService.IncrementUsageAsync(o.Id, project.Id, false, 1)); await countdown.WaitAsync(TimeSpan.FromMilliseconds(150)); Assert.Equal(1, countdown.CurrentCount); Assert.Equal(5001, await _cache.GetAsync <long>(GetHourlyTotalCacheKey(o.Id), 0)); Assert.Equal(5001, await _cache.GetAsync <long>(GetHourlyTotalCacheKey(o.Id, project.Id), 0)); Assert.Equal(5001, await _cache.GetAsync <long>(GetMonthlyTotalCacheKey(o.Id), 0)); Assert.Equal(5001, await _cache.GetAsync <long>(GetMonthlyTotalCacheKey(o.Id, project.Id), 0)); Assert.Equal(4995, await _cache.GetAsync <long>(GetHourlyBlockedCacheKey(o.Id), 0)); Assert.Equal(4995, await _cache.GetAsync <long>(GetHourlyBlockedCacheKey(o.Id, project.Id), 0)); Assert.Equal(4995, await _cache.GetAsync <long>(GetMonthlyBlockedCacheKey(o.Id), 0)); Assert.Equal(4995, await _cache.GetAsync <long>(GetMonthlyBlockedCacheKey(o.Id, project.Id), 0)); }
public virtual async Task CanReceiveMessagesConcurrentlyAsync() { const int iterations = 100; var messageBus = GetMessageBus(); if (messageBus == null) { return; } var messageBuses = new List <IMessageBus>(10); try { var countdown = new AsyncCountdownEvent(iterations * 10); await Run.InParallelAsync(10, async i => { var bus = GetMessageBus(); await bus.SubscribeAsync <SimpleMessageA>(msg => { Assert.Equal("Hello", msg.Data); countdown.Signal(); }); messageBuses.Add(bus); }); var subscribe = Run.InParallelAsync(iterations, i => { #pragma warning disable AsyncFixer02 // Long running or blocking operations under an async method SystemClock.Sleep(RandomData.GetInt(0, 10)); #pragma warning restore AsyncFixer02 // Long running or blocking operations under an async method return(messageBuses.Random().SubscribeAsync <NeverPublishedMessage>(msg => Task.CompletedTask)); }); var publish = Run.InParallelAsync(iterations + 3, i => { switch (i) { case 1: return(messageBus.PublishAsync(new DerivedSimpleMessageA { Data = "Hello" })); case 2: return(messageBus.PublishAsync(new Derived2SimpleMessageA { Data = "Hello" })); case 3: return(messageBus.PublishAsync(new Derived3SimpleMessageA { Data = "Hello" })); case 4: return(messageBus.PublishAsync(new Derived4SimpleMessageA { Data = "Hello" })); case 5: return(messageBus.PublishAsync(new Derived5SimpleMessageA { Data = "Hello" })); case 6: return(messageBus.PublishAsync(new Derived6SimpleMessageA { Data = "Hello" })); case 7: return(messageBus.PublishAsync(new Derived7SimpleMessageA { Data = "Hello" })); case 8: return(messageBus.PublishAsync(new Derived8SimpleMessageA { Data = "Hello" })); case 9: return(messageBus.PublishAsync(new Derived9SimpleMessageA { Data = "Hello" })); case 10: return(messageBus.PublishAsync(new Derived10SimpleMessageA { Data = "Hello" })); case iterations + 1: return(messageBus.PublishAsync(new { Data = "Hello" })); case iterations + 2: return(messageBus.PublishAsync(new SimpleMessageC { Data = "Hello" })); case iterations + 3: return(messageBus.PublishAsync(new SimpleMessageB { Data = "Hello" })); default: return(messageBus.PublishAsync(new SimpleMessageA { Data = "Hello" })); } }); await Task.WhenAll(subscribe, publish); await countdown.WaitAsync(TimeSpan.FromSeconds(2)); Assert.Equal(0, countdown.CurrentCount); } finally { foreach (var mb in messageBuses) { await CleanupMessageBusAsync(mb); } await CleanupMessageBusAsync(messageBus); } }
public async Task CanPersistAndNotLoseMessages() { Log.MinimumLevel = LogLevel.Trace; var messageBus1 = new RabbitMQMessageBus(o => o .ConnectionString("amqp://localhost:5673") .LoggerFactory(Log) .SubscriptionQueueName($"{_topic}-offline") .IsSubscriptionQueueExclusive(false) .SubscriptionQueueAutoDelete(false) .AcknowledgementStrategy(AcknowledgementStrategy.Automatic)); var countdownEvent = new AsyncCountdownEvent(1); var cts = new CancellationTokenSource(); await messageBus1.SubscribeAsync <SimpleMessageA>(msg => { _logger.LogInformation("[Subscriber1] Got message: {Message}", msg.Data); countdownEvent.Signal(); }, cts.Token); await messageBus1.PublishAsync(new SimpleMessageA { Data = "Audit message 1" }); await countdownEvent.WaitAsync(TimeSpan.FromSeconds(5)); Assert.Equal(0, countdownEvent.CurrentCount); cts.Cancel(); await messageBus1.PublishAsync(new SimpleMessageA { Data = "Audit message 2" }); cts = new CancellationTokenSource(); countdownEvent.AddCount(1); await messageBus1.SubscribeAsync <SimpleMessageA>(msg => { _logger.LogInformation("[Subscriber2] Got message: {Message}", msg.Data); countdownEvent.Signal(); }, cts.Token); await countdownEvent.WaitAsync(TimeSpan.FromSeconds(5)); Assert.Equal(0, countdownEvent.CurrentCount); cts.Cancel(); await messageBus1.PublishAsync(new SimpleMessageA { Data = "Audit offline message 1" }); await messageBus1.PublishAsync(new SimpleMessageA { Data = "Audit offline message 2" }); await messageBus1.PublishAsync(new SimpleMessageA { Data = "Audit offline message 3" }); messageBus1.Dispose(); var messageBus2 = new RabbitMQMessageBus(o => o .ConnectionString("amqp://localhost:5673") .LoggerFactory(Log) .SubscriptionQueueName($"{_topic}-offline") .IsSubscriptionQueueExclusive(false) .SubscriptionQueueAutoDelete(false) .AcknowledgementStrategy(AcknowledgementStrategy.Automatic)); cts = new CancellationTokenSource(); countdownEvent.AddCount(4); await messageBus2.SubscribeAsync <SimpleMessageA>(msg => { _logger.LogInformation("[Subscriber3] Got message: {Message}", msg.Data); countdownEvent.Signal(); }, cts.Token); await messageBus2.PublishAsync(new SimpleMessageA { Data = "Another audit message 4" }); await countdownEvent.WaitAsync(TimeSpan.FromSeconds(5)); Assert.Equal(0, countdownEvent.CurrentCount); messageBus2.Dispose(); }