public virtual async Task CanDequeueEfficientlyAsync() { const int iterations = 100; var queue = GetQueue(runQueueMaintenance: false); if (queue == null) { return; } try { await queue.DeleteQueueAsync(); await AssertEmptyQueueAsync(queue); await queue.EnqueueAsync(new SimpleWorkItem { Data = "Initialize queue to create more accurate metrics" }); Assert.NotNull(await queue.DequeueAsync(TimeSpan.FromSeconds(1))); using (var metrics = new InMemoryMetricsClient(new InMemoryMetricsClientOptions())) { queue.AttachBehavior(new MetricsQueueBehavior <SimpleWorkItem>(metrics, reportCountsInterval: TimeSpan.FromMilliseconds(100), loggerFactory: Log)); Task.Run(async() => { _logger.Trace("Starting enqueue loop."); for (int index = 0; index < iterations; index++) { await SystemClock.SleepAsync(RandomData.GetInt(10, 30)); await queue.EnqueueAsync(new SimpleWorkItem { Data = "Hello" }); } _logger.Trace("Finished enqueuing."); }); _logger.Trace("Starting dequeue loop."); for (int index = 0; index < iterations; index++) { var item = await queue.DequeueAsync(TimeSpan.FromSeconds(3)); Assert.NotNull(item); await item.CompleteAsync(); } _logger.Trace("Finished dequeuing."); await metrics.FlushAsync(); var timing = await metrics.GetTimerStatsAsync("simpleworkitem.queuetime"); _logger.Trace(() => $"AverageDuration: {timing.AverageDuration}"); Assert.InRange(timing.AverageDuration, 0, 75); } } finally { await CleanupQueueAsync(queue); } }
public virtual async Task CanRunMultipleQueueJobs() { const int jobCount = 5; const int workItemCount = 100; Log.SetLogLevel <SampleQueueJob>(LogLevel.Error); Log.SetLogLevel <InMemoryMetricsClient>(LogLevel.Trace); var metrics = new InMemoryMetricsClient(true, loggerFactory: Log); var queues = new List <IQueue <SampleQueueWorkItem> >(); for (int i = 0; i < jobCount; i++) { var q = GetSampleWorkItemQueue(retries: 3, retryDelay: TimeSpan.FromSeconds(1)); await q.DeleteQueueAsync(); q.AttachBehavior(new MetricsQueueBehavior <SampleQueueWorkItem>(metrics, "test", Log)); queues.Add(q); } var enqueueTask = Run.InParallel(workItemCount, async index => { var queue = queues[RandomData.GetInt(0, jobCount - 1)]; await queue.EnqueueAsync(new SampleQueueWorkItem { Created = DateTime.Now, Path = RandomData.GetString() }); }); var cancellationTokenSource = new CancellationTokenSource(); await Run.InParallel(jobCount, async index => { var queue = queues[index - 1]; var job = new SampleQueueJob(queue, metrics, Log); await job.RunUntilEmptyAsync(cancellationTokenSource.Token); cancellationTokenSource.Cancel(); }); await enqueueTask; var queueStats = new List <QueueStats>(); for (int i = 0; i < queues.Count; i++) { var stats = await queues[i].GetQueueStatsAsync(); _logger.Info("Queue#{i}: Working: {working} Completed: {completed} Abandoned: {abandoned} Error: {errors} Deadletter: {deadletter}", i, stats.Working, stats.Completed, stats.Abandoned, stats.Errors, stats.Deadletter); queueStats.Add(stats); } await metrics.FlushAsync(); var counter = await metrics.GetCounterStatsAsync("completed"); Assert.Equal(queueStats.Sum(s => s.Completed), counter.Count); Assert.InRange(queueStats.Sum(s => s.Completed), 0, workItemCount); }
public async Task JobLoopPerf() { const int iterations = 10000; var metrics = new InMemoryMetricsClient(new InMemoryMetricsClientOptions { LoggerFactory = Log }); var job = new SampleJob(metrics, Log); var sw = Stopwatch.StartNew(); await job.RunContinuousAsync(null, iterations); sw.Stop(); await metrics.FlushAsync(); _logger.Trace((await metrics.GetCounterStatsAsync("runs")).ToString()); _logger.Trace((await metrics.GetCounterStatsAsync("errors")).ToString()); _logger.Trace((await metrics.GetCounterStatsAsync("failed")).ToString()); _logger.Trace((await metrics.GetCounterStatsAsync("completed")).ToString()); }
public virtual async Task CanResumeDequeueEfficientlyAsync() { const int iterations = 10; var queue = GetQueue(runQueueMaintenance: false); if (queue == null) { return; } try { await queue.DeleteQueueAsync(); await AssertEmptyQueueAsync(queue); using (var metrics = new InMemoryMetricsClient(new InMemoryMetricsClientOptions())) { for (int index = 0; index < iterations; index++) { await queue.EnqueueAsync(new SimpleWorkItem { Data = "Hello" }); } using (var secondQueue = GetQueue(runQueueMaintenance: false)) { secondQueue.AttachBehavior(new MetricsQueueBehavior <SimpleWorkItem>(metrics, reportCountsInterval: TimeSpan.FromMilliseconds(100), loggerFactory: Log)); _logger.Trace("Starting dequeue loop."); for (int index = 0; index < iterations; index++) { _logger.Trace(() => $"[{index}] Calling Dequeue"); var item = await secondQueue.DequeueAsync(TimeSpan.FromSeconds(3)); Assert.NotNull(item); await item.CompleteAsync(); } await metrics.FlushAsync(); // This won't flush metrics queue behaviors var timing = await metrics.GetTimerStatsAsync("simpleworkitem.queuetime"); _logger.Trace(() => $"TotalDuration: {timing.TotalDuration} AverageDuration: {timing.AverageDuration}"); Assert.InRange(timing.AverageDuration, 0, 75); } } } finally { await CleanupQueueAsync(queue); } }
public virtual async Task CanRunWorkItemWithMetricsAsync() { int completedCount = 0; using (var metrics = new InMemoryMetricsClient(new InMemoryMetricsClientOptions { Buffered = false, LoggerFactory = Log })) { var behavior = new MetricsQueueBehavior <WorkItemData>(metrics, "metric", TimeSpan.FromMilliseconds(100), loggerFactory: Log); var options = new InMemoryQueueOptions <WorkItemData> { Behaviors = new[] { behavior }, LoggerFactory = Log }; using (var queue = new InMemoryQueue <WorkItemData>(options)) { Func <object, CompletedEventArgs <WorkItemData>, Task> handler = (sender, e) => { completedCount++; return(Task.CompletedTask); }; using (queue.Completed.AddHandler(handler)) { _logger.Trace("Before enqueue"); await queue.EnqueueAsync(new SimpleWorkItem { Id = 1, Data = "Testing" }); await queue.EnqueueAsync(new SimpleWorkItem { Id = 2, Data = "Testing" }); await queue.EnqueueAsync(new SimpleWorkItem { Id = 3, Data = "Testing" }); await SystemClock.SleepAsync(100); _logger.Trace("Before dequeue"); var item = await queue.DequeueAsync(); await item.CompleteAsync(); item = await queue.DequeueAsync(); await item.CompleteAsync(); item = await queue.DequeueAsync(); await item.AbandonAsync(); _logger.Trace("Before asserts"); Assert.Equal(2, completedCount); await SystemClock.SleepAsync(100); // flush metrics queue behaviors await metrics.FlushAsync(); Assert.InRange((await metrics.GetGaugeStatsAsync("metric.workitemdata.count")).Max, 1, 3); Assert.InRange((await metrics.GetGaugeStatsAsync("metric.workitemdata.working")).Max, 0, 1); Assert.Equal(3, await metrics.GetCounterCountAsync("metric.workitemdata.simple.enqueued")); Assert.Equal(3, await metrics.GetCounterCountAsync("metric.workitemdata.enqueued")); Assert.Equal(3, await metrics.GetCounterCountAsync("metric.workitemdata.simple.dequeued")); Assert.Equal(3, await metrics.GetCounterCountAsync("metric.workitemdata.dequeued")); Assert.Equal(2, await metrics.GetCounterCountAsync("metric.workitemdata.simple.completed")); Assert.Equal(2, await metrics.GetCounterCountAsync("metric.workitemdata.completed")); Assert.Equal(1, await metrics.GetCounterCountAsync("metric.workitemdata.simple.abandoned")); Assert.Equal(1, await metrics.GetCounterCountAsync("metric.workitemdata.abandoned")); var queueTiming = await metrics.GetTimerStatsAsync("metric.workitemdata.simple.queuetime"); Assert.Equal(3, queueTiming.Count); queueTiming = await metrics.GetTimerStatsAsync("metric.workitemdata.queuetime"); Assert.Equal(3, queueTiming.Count); var processTiming = await metrics.GetTimerStatsAsync("metric.workitemdata.simple.processtime"); Assert.Equal(3, processTiming.Count); processTiming = await metrics.GetTimerStatsAsync("metric.workitemdata.processtime"); Assert.Equal(3, processTiming.Count); var queueStats = await metrics.GetQueueStatsAsync("metric.workitemdata"); Assert.Equal(3, queueStats.Enqueued.Count); Assert.Equal(3, queueStats.Dequeued.Count); Assert.Equal(2, queueStats.Completed.Count); Assert.Equal(1, queueStats.Abandoned.Count); Assert.InRange(queueStats.Count.Max, 1, 3); Assert.InRange(queueStats.Working.Max, 0, 1); var subQueueStats = await metrics.GetQueueStatsAsync("metric.workitemdata", "simple"); Assert.Equal(3, subQueueStats.Enqueued.Count); Assert.Equal(3, subQueueStats.Dequeued.Count); Assert.Equal(2, subQueueStats.Completed.Count); Assert.Equal(1, subQueueStats.Abandoned.Count); } } } }
public virtual async Task CanRunMultipleQueueJobsAsync() { const int jobCount = 5; const int workItemCount = 100; Log.SetLogLevel <SampleQueueJob>(LogLevel.Information); Log.SetLogLevel <InMemoryMetricsClient>(LogLevel.None); using (var metrics = new InMemoryMetricsClient(new InMemoryMetricsClientOptions { LoggerFactory = Log, Buffered = true })) { var queues = new List <IQueue <SampleQueueWorkItem> >(); try { for (int i = 0; i < jobCount; i++) { var q = GetSampleWorkItemQueue(retries: 1, retryDelay: TimeSpan.Zero); await q.DeleteQueueAsync(); q.AttachBehavior(new MetricsQueueBehavior <SampleQueueWorkItem>(metrics, "test", loggerFactory: Log)); queues.Add(q); } _logger.LogInformation("Done setting up queues"); var enqueueTask = Run.InParallelAsync(workItemCount, index => { var queue = queues[RandomData.GetInt(0, jobCount - 1)]; return(queue.EnqueueAsync(new SampleQueueWorkItem { Created = SystemClock.UtcNow, Path = RandomData.GetString() })); }); _logger.LogInformation("Done enqueueing"); var cancellationTokenSource = new CancellationTokenSource(); await Run.InParallelAsync(jobCount, async index => { var queue = queues[index - 1]; var job = new SampleQueueJob(queue, metrics, Log); await job.RunUntilEmptyAsync(cancellationTokenSource.Token); cancellationTokenSource.Cancel(); }); _logger.LogInformation("Done running jobs until empty"); await enqueueTask; var queueStats = new List <QueueStats>(); for (int i = 0; i < queues.Count; i++) { var stats = await queues[i].GetQueueStatsAsync(); if (_logger.IsEnabled(LogLevel.Information)) { _logger.LogInformation("Queue#{Id}: Working: {Working} Completed: {Completed} Abandoned: {Abandoned} Error: {Errors} Deadletter: {Deadletter}", i, stats.Working, stats.Completed, stats.Abandoned, stats.Errors, stats.Deadletter); } queueStats.Add(stats); } _logger.LogInformation("Done getting queue stats"); await metrics.FlushAsync(); _logger.LogInformation("Done flushing metrics"); var queueSummary = await metrics.GetQueueStatsAsync("test.samplequeueworkitem"); Assert.Equal(queueStats.Sum(s => s.Completed), queueSummary.Completed.Count); Assert.InRange(queueStats.Sum(s => s.Completed), 0, workItemCount); } finally { foreach (var q in queues) { await q.DeleteQueueAsync(); q.Dispose(); } } } }