Example #1
0
        public async Task CanRunWorkItemJobUntilEmpty()
        {
            using (var queue = new InMemoryQueue <WorkItemData>(new InMemoryQueueOptions <WorkItemData> {
                LoggerFactory = Log
            })) {
                using (var messageBus = new InMemoryMessageBus(new InMemoryMessageBusOptions {
                    LoggerFactory = Log
                })) {
                    var handlerRegistry = new WorkItemHandlers();
                    var job             = new WorkItemJob(queue, messageBus, handlerRegistry, Log);

                    handlerRegistry.Register <MyWorkItem>(new MyWorkItemHandler(Log));

                    await queue.EnqueueAsync(new MyWorkItem {
                        SomeData = "Test"
                    }, true);

                    await queue.EnqueueAsync(new MyWorkItem {
                        SomeData = "Test"
                    }, true);

                    await job.RunUntilEmptyAsync();

                    var stats = await queue.GetQueueStatsAsync();

                    Assert.Equal(2, stats.Enqueued);
                    Assert.Equal(2, stats.Dequeued);
                    Assert.Equal(2, stats.Completed);
                }
            }
        }
Example #2
0
        public async Task TestAsyncEvents() {
            var q = new InMemoryQueue<SimpleWorkItem>();
            q.Enqueuing.AddHandler(async (sender, args) => {
                await Task.Delay(250);
                Logger.Info().Message("First Enqueuing.").Write();
            });
            q.Enqueuing.AddHandler(async(sender, args) => {
                await Task.Delay(250);
                Logger.Info().Message("Second Enqueuing.").Write();
            });
            var e1 = q.Enqueued.AddHandler(async (sender, args) => {
                await Task.Delay(250);
                Logger.Info().Message("First.").Write();
            });
            q.Enqueued.AddHandler(async(sender, args) => {
                await Task.Delay(250);
                Logger.Info().Message("Second.").Write();
            });
            var sw = Stopwatch.StartNew();
            await q.EnqueueAsync(new SimpleWorkItem());
            sw.Stop();
            _writer.WriteLine(sw.Elapsed.ToString());

            e1.Dispose();
            sw.Restart();
            await q.EnqueueAsync(new SimpleWorkItem());
            sw.Stop();
            _writer.WriteLine(sw.Elapsed.ToString());
        }
Example #3
0
        public async Task TestAsyncEvents()
        {
            var q = new InMemoryQueue <SimpleWorkItem>(loggerFactory: Log);

            q.Enqueuing.AddHandler(async(sender, args) => {
                await Task.Delay(250);
                _logger.Info("First Enqueuing.");
            });
            q.Enqueuing.AddHandler(async(sender, args) => {
                await Task.Delay(250);
                _logger.Info("Second Enqueuing.");
            });
            var e1 = q.Enqueued.AddHandler(async(sender, args) => {
                await Task.Delay(250);
                _logger.Info("First.");
            });

            q.Enqueued.AddHandler(async(sender, args) => {
                await Task.Delay(250);
                _logger.Info("Second.");
            });
            var sw = Stopwatch.StartNew();
            await q.EnqueueAsync(new SimpleWorkItem());

            sw.Stop();
            _logger.Trace(sw.Elapsed.ToString());

            e1.Dispose();
            sw.Restart();
            await q.EnqueueAsync(new SimpleWorkItem());

            sw.Stop();
            _logger.Trace(sw.Elapsed.ToString());
        }
Example #4
0
        public async Task TestAsyncEvents()
        {
            using (var q = new InMemoryQueue <SimpleWorkItem>(new InMemoryQueueOptions <SimpleWorkItem> {
                LoggerFactory = Log
            })) {
                var disposables = new List <IDisposable>(5);
                try {
                    disposables.Add(q.Enqueuing.AddHandler(async(sender, args) => {
                        await SystemClock.SleepAsync(250);
                        _logger.LogInformation("First Enqueuing.");
                    }));
                    disposables.Add(q.Enqueuing.AddHandler(async(sender, args) => {
                        await SystemClock.SleepAsync(250);
                        _logger.LogInformation("Second Enqueuing.");
                    }));
                    disposables.Add(q.Enqueued.AddHandler(async(sender, args) => {
                        await SystemClock.SleepAsync(250);
                        _logger.LogInformation("First.");
                    }));
                    disposables.Add(q.Enqueued.AddHandler(async(sender, args) => {
                        await SystemClock.SleepAsync(250);
                        _logger.LogInformation("Second.");
                    }));

                    var sw = Stopwatch.StartNew();
                    await q.EnqueueAsync(new SimpleWorkItem());

                    sw.Stop();
                    if (_logger.IsEnabled(LogLevel.Trace))
                    {
                        _logger.LogTrace("Time {Elapsed:g}", sw.Elapsed);
                    }

                    sw.Restart();
                    await q.EnqueueAsync(new SimpleWorkItem());

                    sw.Stop();
                    if (_logger.IsEnabled(LogLevel.Trace))
                    {
                        _logger.LogTrace("Time {Elapsed:g}", sw.Elapsed);
                    }
                } finally {
                    foreach (var disposable in disposables)
                    {
                        disposable.Dispose();
                    }
                }
            }
        }
Example #5
0
        public async Task CanRunWorkItemWithClassHandler()
        {
            ServiceProvider.SetServiceProvider(typeof(MyBootstrappedServiceProvider));
            var queue           = new InMemoryQueue <WorkItemData>();
            var messageBus      = new InMemoryMessageBus();
            var handlerRegistry = new WorkItemHandlers();
            var job             = new WorkItemJob(queue, messageBus, handlerRegistry, Log);

            handlerRegistry.Register <MyWorkItem, MyWorkItemHandler>();

            var jobId = await queue.EnqueueAsync(new MyWorkItem {
                SomeData = "Test"
            }, true);

            int statusCount = 0;

            messageBus.Subscribe <WorkItemStatus>(status => {
                _logger.Trace("Progress: {progress}", status.Progress);
                Assert.Equal(jobId, status.WorkItemId);
                statusCount++;
            });

            await job.RunUntilEmptyAsync();

            Assert.Equal(11, statusCount);
        }
Example #6
0
        public async Task CanRunWorkItemWithClassHandler()
        {
            using (var queue = new InMemoryQueue <WorkItemData>(new InMemoryQueueOptions <WorkItemData> {
                LoggerFactory = Log
            })) {
                using (var messageBus = new InMemoryMessageBus(new InMemoryMessageBusOptions {
                    LoggerFactory = Log
                })) {
                    var handlerRegistry = new WorkItemHandlers();
                    var job             = new WorkItemJob(queue, messageBus, handlerRegistry, Log);

                    handlerRegistry.Register <MyWorkItem>(new MyWorkItemHandler(Log));

                    string jobId = await queue.EnqueueAsync(new MyWorkItem {
                        SomeData = "Test"
                    }, true);

                    int statusCount = 0;
                    await messageBus.SubscribeAsync <WorkItemStatus>(status => {
                        _logger.Trace("Progress: {progress}", status.Progress);
                        Assert.Equal(jobId, status.WorkItemId);
                        statusCount++;
                    });

                    await job.RunUntilEmptyAsync();

                    Assert.Equal(11, statusCount);
                }
            }
        }
Example #7
0
        public async Task CanRunBadWorkItem()
        {
            using (var queue = new InMemoryQueue <WorkItemData>(new InMemoryQueueOptions <WorkItemData> {
                RetryDelay = TimeSpan.FromMilliseconds(500), LoggerFactory = Log
            })) {
                using (var messageBus = new InMemoryMessageBus(new InMemoryMessageBusOptions {
                    LoggerFactory = Log
                })) {
                    var handlerRegistry = new WorkItemHandlers();
                    var job             = new WorkItemJob(queue, messageBus, handlerRegistry, Log);

                    handlerRegistry.Register <MyWorkItem>(ctx => {
                        var jobData = ctx.GetData <MyWorkItem>();
                        Assert.Equal("Test", jobData.SomeData);
                        throw new Exception();
                    });

                    string jobId = await queue.EnqueueAsync(new MyWorkItem {
                        SomeData = "Test"
                    }, true);

                    int statusCount = 0;
                    await messageBus.SubscribeAsync <WorkItemStatus>(status => {
                        _logger.Trace("Progress: {progress}", status.Progress);
                        Assert.Equal(jobId, status.WorkItemId);
                        statusCount++;
                    });

                    await job.RunUntilEmptyAsync();

                    Assert.Equal(1, statusCount);
                }
            }
        }
        public void WorkItemsWillGetMovedToDeadletter() {
            var queue = new InMemoryQueue<SimpleWorkItem>(retries: 1, workItemTimeoutMilliseconds: 10);
            queue.EnqueueAsync(new SimpleWorkItem {
                Data = "Hello"
            });
            var workItem = queue.DequeueAsync(0).Result;
            Assert.Equal("Hello", workItem.Value.Data);
            Assert.Equal(1, queue.Dequeued);

            Assert.Equal(0, queue.Count);
            // wait for the task to be auto abandoned
            Task.Delay(100).Wait();
            Assert.Equal(1, queue.Count);
            Assert.Equal(1, queue.Abandoned);

            // work item should be retried 1 time.
            workItem = queue.DequeueAsync(0).Result;
            Assert.Equal("Hello", workItem.Value.Data);
            Assert.Equal(2, queue.Dequeued);

            Task.Delay(100).Wait();
            // work item should be moved to deadletter queue after retries.
            Assert.Equal(1, queue.DeadletterCount);
            Assert.Equal(2, queue.Abandoned);
        }
Example #9
0
        public void CanHaveMultipleWorkers()
        {
            const int workItemCount = 50;
            var       latch         = new CountDownLatch(workItemCount);
            int       errorCount    = 0;
            int       abandonCount  = 0;
            var       queue         = new InMemoryQueue <SimpleWorkItem>(retries: 1, workItemTimeoutMilliseconds: 50, retryDelayMilliseconds: 0);

            Parallel.For(0, workItemCount, i => queue.EnqueueAsync(new SimpleWorkItem {
                Data = "Hello",
                Id   = i
            }));

            Task.Factory.StartNew(() => queue.StartWorking(w => DoWork(w, latch, ref abandonCount, ref errorCount)));
            Task.Factory.StartNew(() => queue.StartWorking(w => DoWork(w, latch, ref abandonCount, ref errorCount)));
            Task.Factory.StartNew(() => queue.StartWorking(w => DoWork(w, latch, ref abandonCount, ref errorCount)));

            bool success = latch.Wait(2000);

            Assert.True(success, "Failed to receive all work items.");
            Task.Delay(50).Wait();
            Assert.Equal(workItemCount, queue.Completed + queue.DeadletterCount);
            Assert.Equal(errorCount, queue.WorkerErrors);
            Assert.Equal(abandonCount + errorCount, queue.Abandoned);
        }
Example #10
0
        public async Task CanRunBadWorkItem()
        {
            var queue           = new InMemoryQueue <WorkItemData>(retries: 2, retryDelay: TimeSpan.FromMilliseconds(500));
            var messageBus      = new InMemoryMessageBus();
            var handlerRegistry = new WorkItemHandlers();
            var job             = new WorkItemJob(queue, messageBus, handlerRegistry);

            handlerRegistry.Register <MyWorkItem>(ctx => {
                var jobData = ctx.GetData <MyWorkItem>();
                Assert.Equal("Test", jobData.SomeData);
                throw new ApplicationException();
            });

            var jobId = await queue.EnqueueAsync(new MyWorkItem {
                SomeData = "Test"
            }, true);

            int statusCount = 0;

            messageBus.Subscribe <WorkItemStatus>(status => {
                Logger.Trace().Message($"Progress: {status.Progress}").Write();
                Assert.Equal(jobId, status.WorkItemId);
                statusCount++;
            });

            await job.RunUntilEmptyAsync();

            Assert.Equal(1, statusCount);
        }
Example #11
0
        public void WorkItemsWillGetMovedToDeadletter()
        {
            var queue = new InMemoryQueue <SimpleWorkItem>(retries: 1, workItemTimeoutMilliseconds: 10, retryDelayMilliseconds: 10);

            queue.EnqueueAsync(new SimpleWorkItem {
                Data = "Hello"
            }).Wait();
            var workItem = queue.DequeueAsync(0).Result;

            Assert.Equal("Hello", workItem.Value.Data);
            Assert.Equal(1, queue.Dequeued);

            Assert.Equal(0, queue.Count);
            // wait for the task to be auto abandoned
            Task.Delay(100).Wait();
            Assert.Equal(1, queue.Count);
            Assert.Equal(1, queue.Abandoned);

            // work item should be retried 1 time.
            workItem = queue.DequeueAsync(0).Result;
            Assert.Equal("Hello", workItem.Value.Data);
            Assert.Equal(2, queue.Dequeued);

            Task.Delay(100).Wait();
            // work item should be moved to deadletter queue after retries.
            Assert.Equal(1, queue.DeadletterCount);
            Assert.Equal(2, queue.Abandoned);
        }
Example #12
0
        public async Task CanRunBadWorkItem()
        {
            using (var queue = new InMemoryQueue <WorkItemData>(o => o.RetryDelay(TimeSpan.FromMilliseconds(500)).LoggerFactory(Log))) {
                using (var messageBus = new InMemoryMessageBus(o => o.LoggerFactory(Log))) {
                    var handlerRegistry = new WorkItemHandlers();
                    var job             = new WorkItemJob(queue, messageBus, handlerRegistry, Log);

                    handlerRegistry.Register <MyWorkItem>(ctx => {
                        var jobData = ctx.GetData <MyWorkItem>();
                        Assert.Equal("Test", jobData.SomeData);
                        throw new Exception();
                    });

                    string jobId = await queue.EnqueueAsync(new MyWorkItem {
                        SomeData = "Test"
                    }, true);

                    var countdown = new AsyncCountdownEvent(1);
                    await messageBus.SubscribeAsync <WorkItemStatus>(status => {
                        if (_logger.IsEnabled(LogLevel.Trace))
                        {
                            _logger.LogTrace("Progress: {Progress}", status.Progress);
                        }
                        Assert.Equal(jobId, status.WorkItemId);
                        countdown.Signal();
                    });

                    await job.RunUntilEmptyAsync();

                    await countdown.WaitAsync(TimeSpan.FromSeconds(2));

                    Assert.Equal(0, countdown.CurrentCount);
                }
            }
        }
Example #13
0
        public async Task CanRunWorkItem() {
            using (var queue = new InMemoryQueue<WorkItemData>()) {
                using (var messageBus = new InMemoryMessageBus()) {
                    var handlerRegistry = new WorkItemHandlers();
                    var job = new WorkItemJob(queue, messageBus, handlerRegistry, Log);

                    handlerRegistry.Register<MyWorkItem>(async ctx => {
                        var jobData = ctx.GetData<MyWorkItem>();
                        Assert.Equal("Test", jobData.SomeData);

                        for (int i = 0; i < 10; i++) {
                            await SystemClock.SleepAsync(100);
                            await ctx.ReportProgressAsync(10 * i);
                        }
                    });

                    var jobId = await queue.EnqueueAsync(new MyWorkItem {
                        SomeData = "Test"
                    }, true);

                    int statusCount = 0;
                    messageBus.Subscribe<WorkItemStatus>(status => {
                        _logger.Trace("Progress: {progress}", status.Progress);
                        Assert.Equal(jobId, status.WorkItemId);
                        statusCount++;
                    });

                    await job.RunUntilEmptyAsync();
                    Assert.Equal(12, statusCount);
                }
            }
        }
Example #14
0
        public async Task CanRunWorkItem()
        {
            using (var queue = new InMemoryQueue <WorkItemData>()) {
                using (var messageBus = new InMemoryMessageBus()) {
                    var handlerRegistry = new WorkItemHandlers();
                    var job             = new WorkItemJob(queue, messageBus, handlerRegistry, Log);

                    handlerRegistry.Register <MyWorkItem>(async ctx => {
                        var jobData = ctx.GetData <MyWorkItem>();
                        Assert.Equal("Test", jobData.SomeData);

                        for (int i = 0; i < 10; i++)
                        {
                            await SystemClock.SleepAsync(100);
                            await ctx.ReportProgressAsync(10 * i);
                        }
                    });

                    var jobId = await queue.EnqueueAsync(new MyWorkItem {
                        SomeData = "Test"
                    }, true);

                    int statusCount = 0;
                    messageBus.Subscribe <WorkItemStatus>(status => {
                        _logger.Trace("Progress: {progress}", status.Progress);
                        Assert.Equal(jobId, status.WorkItemId);
                        statusCount++;
                    });

                    await job.RunUntilEmptyAsync();

                    Assert.Equal(12, statusCount);
                }
            }
        }
        public virtual async Task CanGetBufferedQueueMetrics() {
            using (var metrics = GetMetricsClient(true) as IBufferedMetricsClient) {
                var stats = metrics as IMetricsClientStats;
                if (stats == null)
                    return;

                using (var queue = new InMemoryQueue<SimpleWorkItem>(behaviors: new[] { new MetricsQueueBehavior<SimpleWorkItem>(metrics, loggerFactory: Log) }, loggerFactory: Log)) {
                    await queue.EnqueueAsync(new SimpleWorkItem { Id = 1, Data = "1" });
                    await SystemClock.SleepAsync(50);
                    var entry = await queue.DequeueAsync(TimeSpan.Zero);
                    await SystemClock.SleepAsync(30);
                    await entry.CompleteAsync();
                    await SystemClock.SleepAsync(500);  // give queue metrics time

                    await metrics.FlushAsync();

                    var queueStats = await stats.GetQueueStatsAsync("simpleworkitem");
                    Assert.Equal(1, queueStats.Count.Max);
                    Assert.Equal(0, queueStats.Count.Last);
                    Assert.Equal(1, queueStats.Enqueued.Count);
                    Assert.Equal(1, queueStats.Dequeued.Count);
                    Assert.Equal(1, queueStats.Completed.Count);
                    Assert.InRange(queueStats.QueueTime.AverageDuration, 50, 200);
                    Assert.InRange(queueStats.ProcessTime.AverageDuration, 30, 200);
                }
            }
        }
        public void WorkItemsWillTimeout() {
            var queue = new InMemoryQueue<SimpleWorkItem>(workItemTimeoutMilliseconds: 10);
            queue.EnqueueAsync(new SimpleWorkItem {
                Data = "Hello"
            });
            var workItem = queue.DequeueAsync(0).Result;
            Assert.Equal("Hello", workItem.Value.Data);

            Assert.Equal(0, queue.Count);
            // wait for the task to be auto abandoned
            Task.Delay(100).Wait();
            Assert.Equal(1, queue.Count);
            Assert.Equal(1, queue.Abandoned);
        }
Example #17
0
        public async Task TestAsyncEvents() {
            using (var q = new InMemoryQueue<SimpleWorkItem>(loggerFactory: Log)) {
                var disposables = new List<IDisposable>(5);
                try {
                    disposables.Add(q.Enqueuing.AddHandler(async (sender, args) => {
                        await SystemClock.SleepAsync(250);
                        _logger.Info("First Enqueuing.");
                    }));
                    disposables.Add(q.Enqueuing.AddHandler(async (sender, args) => {
                        await SystemClock.SleepAsync(250);
                        _logger.Info("Second Enqueuing.");
                    }));
                    disposables.Add(q.Enqueued.AddHandler(async (sender, args) => {
                        await SystemClock.SleepAsync(250);
                        _logger.Info("First.");
                    }));
                    disposables.Add(q.Enqueued.AddHandler(async (sender, args) => {
                        await SystemClock.SleepAsync(250);
                        _logger.Info("Second.");
                    }));

                    var sw = Stopwatch.StartNew();
                    await q.EnqueueAsync(new SimpleWorkItem());
                    sw.Stop();
                    _logger.Trace("Time {0}", sw.Elapsed);
                    
                    sw.Restart();
                    await q.EnqueueAsync(new SimpleWorkItem());
                    sw.Stop();
                    _logger.Trace("Time {0}", sw.Elapsed);
                } finally {
                    foreach (var disposable in disposables)
                        disposable.Dispose();
                }
            }
        }
        public void CanQueueAndDequeueWorkItem() {
            var queue = new InMemoryQueue<SimpleWorkItem>();
            queue.EnqueueAsync(new SimpleWorkItem {
                Data = "Hello"
            });
            Assert.Equal(1, queue.Count);

            var workItem = queue.DequeueAsync(0).Result;
            Assert.NotNull(workItem);
            Assert.Equal("Hello", workItem.Value.Data);
            Assert.Equal(0, queue.Count);
            Assert.Equal(1, queue.Dequeued);

            workItem.CompleteAsync().Wait();
            Assert.Equal(1, queue.Completed);
        }
Example #19
0
        public void WorkItemsWillTimeout()
        {
            var queue = new InMemoryQueue <SimpleWorkItem>(workItemTimeoutMilliseconds: 10, retryDelayMilliseconds: 0);

            queue.EnqueueAsync(new SimpleWorkItem {
                Data = "Hello"
            });
            var workItem = queue.DequeueAsync(0).Result;

            Assert.Equal("Hello", workItem.Value.Data);

            Assert.Equal(0, queue.Count);
            // wait for the task to be auto abandoned
            Task.Delay(100).Wait();
            Assert.Equal(1, queue.Count);
            Assert.Equal(1, queue.Abandoned);
        }
Example #20
0
        public void CanQueueAndDequeueWorkItem()
        {
            var queue = new InMemoryQueue <SimpleWorkItem>();

            queue.EnqueueAsync(new SimpleWorkItem {
                Data = "Hello"
            });
            Assert.Equal(1, queue.Count);

            var workItem = queue.DequeueAsync(0).Result;

            Assert.NotNull(workItem);
            Assert.Equal("Hello", workItem.Value.Data);
            Assert.Equal(0, queue.Count);
            Assert.Equal(1, queue.Dequeued);

            workItem.CompleteAsync().Wait();
            Assert.Equal(1, queue.Completed);
        }
        public void CanUseQueueWorker() {
            var resetEvent = new AutoResetEvent(false);
            var queue = new InMemoryQueue<SimpleWorkItem>();
            queue.StartWorking(w => {
                Assert.Equal("Hello", w.Value.Data);
                w.CompleteAsync().Wait();
                resetEvent.Set();
            });
            queue.EnqueueAsync(new SimpleWorkItem {
                Data = "Hello"
            });

            Assert.Equal(1, queue.Count);
            bool success = resetEvent.WaitOne(250);
            Assert.Equal(0, queue.Count);
            Assert.Equal(1, queue.Completed);
            Assert.True(success, "Failed to receive message.");
            Assert.Equal(0, queue.WorkerErrors);
        }
        public async Task CanRunWorkItemWithDelegateHandler()
        {
            using (var queue = new InMemoryQueue <WorkItemData>(new InMemoryQueueOptions <WorkItemData> {
                LoggerFactory = Log
            })) {
                using (var messageBus = new InMemoryMessageBus(new InMemoryMessageBusOptions {
                    LoggerFactory = Log
                })) {
                    var handlerRegistry = new WorkItemHandlers();
                    var job             = new WorkItemJob(queue, messageBus, handlerRegistry, Log);

                    handlerRegistry.Register <MyWorkItem>(async ctx => {
                        var jobData = ctx.GetData <MyWorkItem>();
                        Assert.Equal("Test", jobData.SomeData);

                        for (int i = 1; i < 10; i++)
                        {
                            await SystemClock.SleepAsync(100);
                            await ctx.ReportProgressAsync(10 * i);
                        }
                    }, Log.CreateLogger("MyWorkItem"));

                    string jobId = await queue.EnqueueAsync(new MyWorkItem {
                        SomeData = "Test"
                    }, true);

                    int statusCount = 0;
                    await messageBus.SubscribeAsync <WorkItemStatus>(status => {
                        if (_logger.IsEnabled(LogLevel.Trace))
                        {
                            _logger.LogTrace("Progress: {Progress}", status.Progress);
                        }
                        Assert.Equal(jobId, status.WorkItemId);
                        Interlocked.Increment(ref statusCount);
                    });

                    await job.RunUntilEmptyAsync();

                    Assert.Equal(11, statusCount);
                }
            }
        }
        public virtual async Task CanGetBufferedQueueMetricsAsync()
        {
            using (var metrics = GetMetricsClient(true) as IBufferedMetricsClient) {
                var stats = metrics as IMetricsClientStats;
                if (stats == null)
                {
                    return;
                }

                using (var behavior = new MetricsQueueBehavior <SimpleWorkItem>(metrics, reportCountsInterval: TimeSpan.FromMilliseconds(25), loggerFactory: Log)) {
                    using (var queue = new InMemoryQueue <SimpleWorkItem>(new InMemoryQueueOptions <SimpleWorkItem> {
                        Behaviors = new [] { behavior }, LoggerFactory = Log
                    })) {
                        await queue.EnqueueAsync(new SimpleWorkItem { Id = 1, Data = "1" });

                        await SystemClock.SleepAsync(50);

                        var entry = await queue.DequeueAsync(TimeSpan.Zero);

                        await SystemClock.SleepAsync(15);

                        await entry.CompleteAsync();

                        await SystemClock.SleepAsync(100); // give queue metrics time

                        await metrics.FlushAsync();

                        var queueStats = await stats.GetQueueStatsAsync("simpleworkitem");

                        Assert.Equal(1, queueStats.Count.Max);
                        Assert.Equal(0, queueStats.Count.Last);
                        Assert.Equal(1, queueStats.Enqueued.Count);
                        Assert.Equal(1, queueStats.Dequeued.Count);
                        Assert.Equal(1, queueStats.Completed.Count);
                        Assert.InRange(queueStats.QueueTime.AverageDuration, 45, 250);
                        Assert.InRange(queueStats.ProcessTime.AverageDuration, 10, 250);
                    }
                }
            }
        }
Example #24
0
        public async Task CanRunWorkItemWithDelegateHandler()
        {
            using (var queue = new InMemoryQueue <WorkItemData>(o => o.LoggerFactory(Log))) {
                using (var messageBus = new InMemoryMessageBus(o => o.LoggerFactory(Log))) {
                    var handlerRegistry = new WorkItemHandlers();
                    var job             = new WorkItemJob(queue, messageBus, handlerRegistry, Log);

                    handlerRegistry.Register <MyWorkItem>(async ctx => {
                        var jobData = ctx.GetData <MyWorkItem>();
                        Assert.Equal("Test", jobData.SomeData);

                        for (int i = 1; i < 10; i++)
                        {
                            await SystemClock.SleepAsync(100);
                            await ctx.ReportProgressAsync(10 * i);
                        }
                    }, Log.CreateLogger("MyWorkItem"));

                    string jobId = await queue.EnqueueAsync(new MyWorkItem {
                        SomeData = "Test"
                    }, true);

                    var countdown = new AsyncCountdownEvent(11);
                    await messageBus.SubscribeAsync <WorkItemStatus>(status => {
                        if (_logger.IsEnabled(LogLevel.Trace))
                        {
                            _logger.LogTrace("Progress: {Progress}", status.Progress);
                        }
                        Assert.Equal(jobId, status.WorkItemId);
                        countdown.Signal();
                    });

                    await job.RunUntilEmptyAsync();

                    await countdown.WaitAsync(TimeSpan.FromSeconds(2));

                    Assert.Equal(0, countdown.CurrentCount);
                }
            }
        }
        public void CanAutoCompleteWorker()
        {
            var resetEvent = new AutoResetEvent(false);
            var queue      = new InMemoryQueue <SimpleWorkItem>(workItemTimeoutMilliseconds: 100);

            queue.StartWorking(w => {
                Assert.Equal("Hello", w.Value.Data);
                resetEvent.Set();
            }, true);
            queue.EnqueueAsync(new SimpleWorkItem {
                Data = "Hello"
            });

            Assert.Equal(1, queue.Count);
            bool success = resetEvent.WaitOne(100);

            Assert.True(success, "Failed to recieve message.");
            Task.Delay(25).Wait();
            Assert.Equal(0, queue.Count);
            Assert.Equal(1, queue.Completed);
            Assert.Equal(0, queue.WorkerErrors);
        }
Example #26
0
        public void CanUseQueueWorker()
        {
            var resetEvent = new AutoResetEvent(false);
            var queue      = new InMemoryQueue <SimpleWorkItem>();

            queue.EnqueueAsync(new SimpleWorkItem {
                Data = "Hello"
            });

            queue.StartWorking(w => {
                Assert.Equal("Hello", w.Value.Data);
                w.CompleteAsync().Wait();
                resetEvent.Set();
            });

            bool success = resetEvent.WaitOne(250);

            Assert.Equal(0, queue.Count);
            Assert.Equal(1, queue.Completed);
            Assert.True(success, "Failed to receive message.");
            Assert.Equal(0, queue.WorkerErrors);
        }
        public virtual async Task CanRunWorkItemWithMetrics()
        {
            var eventRaised = new ManualResetEvent(false);

            var metricsClient = new InMemoryMetricsClient();
            var behavior      = new MetricsQueueBehavior <WorkItemData>(metricsClient, "metric");
            var queue         = new InMemoryQueue <WorkItemData>(behaviors: new[] { behavior });

            queue.Completed.AddHandler((sender, e) => {
                eventRaised.Set();
                return(TaskHelper.Completed());
            });

            var work = new SimpleWorkItem {
                Id = 1, Data = "Testing"
            };

            await queue.EnqueueAsync(work);

            var item = await queue.DequeueAsync();

            await item.CompleteAsync();

            metricsClient.DisplayStats(_writer);

            Assert.True(eventRaised.WaitOne(TimeSpan.FromMinutes(1)));

            Assert.Equal(6, metricsClient.Counters.Count);
            Assert.Equal(4, metricsClient.Timings.Count);

            Assert.Equal(1, metricsClient.Counters["metric.workitemdata.simple.enqueued"]?.RecentValue);
            Assert.Equal(1, metricsClient.Counters["metric.workitemdata.simple.dequeued"]?.RecentValue);
            Assert.Equal(1, metricsClient.Counters["metric.workitemdata.simple.completed"]?.RecentValue);

            Assert.True(0 < metricsClient.Timings["metric.workitemdata.simple.queuetime"]?.Count);
            Assert.True(0 < metricsClient.Timings["metric.workitemdata.simple.processtime"]?.Count);
        }
Example #28
0
        public virtual async Task CanGetBufferedQueueMetrics()
        {
            using (var metrics = GetMetricsClient(true) as IBufferedMetricsClient) {
                var stats = metrics as IMetricsClientStats;
                if (stats == null)
                {
                    return;
                }

                using (var queue = new InMemoryQueue <SimpleWorkItem>(behaviors: new[] { new MetricsQueueBehavior <SimpleWorkItem>(metrics, loggerFactory: Log) }, loggerFactory: Log)) {
                    await queue.EnqueueAsync(new SimpleWorkItem { Id = 1, Data = "1" });

                    await SystemClock.SleepAsync(50);

                    var entry = await queue.DequeueAsync(TimeSpan.Zero);

                    await SystemClock.SleepAsync(30);

                    await entry.CompleteAsync();

                    await SystemClock.SleepAsync(500);  // give queue metrics time

                    await metrics.FlushAsync();

                    var queueStats = await stats.GetQueueStatsAsync("simpleworkitem");

                    Assert.Equal(1, queueStats.Count.Max);
                    Assert.Equal(0, queueStats.Count.Last);
                    Assert.Equal(1, queueStats.Enqueued.Count);
                    Assert.Equal(1, queueStats.Dequeued.Count);
                    Assert.Equal(1, queueStats.Completed.Count);
                    Assert.InRange(queueStats.QueueTime.AverageDuration, 50, 200);
                    Assert.InRange(queueStats.ProcessTime.AverageDuration, 30, 200);
                }
            }
        }
Example #29
0
        public virtual async Task CanRunWorkItemWithMetrics() {
            int completedCount = 0;
            //Log.MinimumLevel = LogLevel.Trace;
            //Log.SetLogLevel<ScheduledTimer>(LogLevel.Information);
            //Log.SetLogLevel<InMemoryCacheClient>(LogLevel.Information);

            using (var metricsClient = new InMemoryMetricsClient(false, loggerFactory: Log)) {
                var behavior = new MetricsQueueBehavior<WorkItemData>(metricsClient, "metric", loggerFactory: Log, reportCountsInterval: TimeSpan.Zero);
                using (var queue = new InMemoryQueue<WorkItemData>(behaviors: new[] { behavior }, loggerFactory: Log)) {
                    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);

                        Assert.InRange((await metricsClient.GetGaugeStatsAsync("metric.workitemdata.count")).Max, 1, 3);
                        Assert.InRange((await metricsClient.GetGaugeStatsAsync("metric.workitemdata.working")).Max, 0, 1);

                        Assert.Equal(3, await metricsClient.GetCounterCountAsync("metric.workitemdata.simple.enqueued"));
                        Assert.Equal(3, await metricsClient.GetCounterCountAsync("metric.workitemdata.enqueued"));

                        Assert.Equal(3, await metricsClient.GetCounterCountAsync("metric.workitemdata.simple.dequeued"));
                        Assert.Equal(3, await metricsClient.GetCounterCountAsync("metric.workitemdata.dequeued"));

                        Assert.Equal(2, await metricsClient.GetCounterCountAsync("metric.workitemdata.simple.completed"));
                        Assert.Equal(2, await metricsClient.GetCounterCountAsync("metric.workitemdata.completed"));

                        Assert.Equal(1, await metricsClient.GetCounterCountAsync("metric.workitemdata.simple.abandoned"));
                        Assert.Equal(1, await metricsClient.GetCounterCountAsync("metric.workitemdata.abandoned"));

                        var queueTiming = await metricsClient.GetTimerStatsAsync("metric.workitemdata.simple.queuetime");
                        Assert.Equal(3, queueTiming.Count);
                        queueTiming = await metricsClient.GetTimerStatsAsync("metric.workitemdata.queuetime");
                        Assert.Equal(3, queueTiming.Count);

                        var processTiming = await metricsClient.GetTimerStatsAsync("metric.workitemdata.simple.processtime");
                        Assert.Equal(3, processTiming.Count);
                        processTiming = await metricsClient.GetTimerStatsAsync("metric.workitemdata.processtime");
                        Assert.Equal(3, processTiming.Count);

                        var queueStats = await metricsClient.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 metricsClient.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);
                    }
                }
            }
        }
Example #30
0
        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 void CanHaveMultipleWorkers() {
            const int workItemCount = 50;
            var latch = new CountDownLatch(workItemCount);
            int errorCount = 0;
            int abandonCount = 0;
            var queue = new InMemoryQueue<SimpleWorkItem>(retries: 1, workItemTimeoutMilliseconds: 50);
            Task.Factory.StartNew(() => queue.StartWorking(w => DoWork(w, latch, ref abandonCount, ref errorCount)));
            Task.Factory.StartNew(() => queue.StartWorking(w => DoWork(w, latch, ref abandonCount, ref errorCount)));
            Task.Factory.StartNew(() => queue.StartWorking(w => DoWork(w, latch, ref abandonCount, ref errorCount)));

            Parallel.For(0, workItemCount, i => queue.EnqueueAsync(new SimpleWorkItem {
                Data = "Hello",
                Id = i
            }));

            bool success = latch.Wait(1000);
            Assert.True(success, "Failed to receive all work items.");
            Task.Delay(50).Wait();
            Assert.Equal(workItemCount, queue.Completed + queue.DeadletterCount);
            Assert.Equal(errorCount, queue.WorkerErrors);
            Assert.Equal(abandonCount + errorCount, queue.Abandoned);
        }
Example #32
0
        public virtual async Task CanRunWorkItemWithMetrics() {
            var eventRaised = new ManualResetEvent(false);

            var metricsClient = new InMemoryMetricsClient();
            var behavior = new MetricsQueueBehavior<WorkItemData>(metricsClient, "metric");
            var queue = new InMemoryQueue<WorkItemData>(behaviors: new[] { behavior });
            queue.Completed.AddHandler((sender, e) => {
                eventRaised.Set();
                return TaskHelper.Completed();
            });

            var work = new SimpleWorkItem { Id = 1, Data = "Testing" };

            await queue.EnqueueAsync(work);
            var item = await queue.DequeueAsync();
            await item.CompleteAsync();

            metricsClient.DisplayStats(_writer);

            Assert.True(eventRaised.WaitOne(TimeSpan.FromMinutes(1)));

            Assert.Equal(6, metricsClient.Counters.Count);
            Assert.Equal(4, metricsClient.Timings.Count);

            Assert.Equal(1, metricsClient.Counters["metric.workitemdata.simple.enqueued"]?.RecentValue);
            Assert.Equal(1, metricsClient.Counters["metric.workitemdata.simple.dequeued"]?.RecentValue);
            Assert.Equal(1, metricsClient.Counters["metric.workitemdata.simple.completed"]?.RecentValue);

            Assert.True(0 < metricsClient.Timings["metric.workitemdata.simple.queuetime"]?.Count);
            Assert.True(0 < metricsClient.Timings["metric.workitemdata.simple.processtime"]?.Count);
        }
Example #33
0
        public async Task CanHandleMultipleWorkItemInstances() {
            const int workItemCount = 1000;

            using (var metrics = new InMemoryMetricsClient(loggerFactory: Log)) {
                using (var queue = new InMemoryQueue<WorkItemData>(retries: 0, retryDelay: TimeSpan.Zero, loggerFactory: Log)) {
                    queue.AttachBehavior(new MetricsQueueBehavior<WorkItemData>(metrics, loggerFactory: Log));
                    using (var messageBus = new InMemoryMessageBus(Log)) {
                        var handlerRegistry = new WorkItemHandlers();
                        var j1 = new WorkItemJob(queue, messageBus, handlerRegistry, Log);
                        var j2 = new WorkItemJob(queue, messageBus, handlerRegistry, Log);
                        var j3 = new WorkItemJob(queue, messageBus, handlerRegistry, Log);
                        int errors = 0;

                        var jobIds = new ConcurrentDictionary<string, int>();

                        handlerRegistry.Register<MyWorkItem>(async ctx => {
                            var jobData = ctx.GetData<MyWorkItem>();
                            Assert.Equal("Test", jobData.SomeData);

                            var jobWorkTotal = jobIds.AddOrUpdate(ctx.JobId, 1, (key, value) => value + 1);
                            if (jobData.Index % 100 == 0)
                                _logger.Trace("Job {jobId} processing work item #: {jobWorkTotal}", ctx.JobId, jobWorkTotal);

                            for (int i = 0; i < 10; i++)
                                await ctx.ReportProgressAsync(10 * i);

                            if (RandomData.GetBool(1)) {
                                Interlocked.Increment(ref errors);
                                throw new Exception("Boom!");
                            }
                        });

                        for (int i = 0; i < workItemCount; i++)
                            await queue.EnqueueAsync(new MyWorkItem {
                                SomeData = "Test",
                                Index = i
                            }, true);

                        var completedItems = new List<string>();
                        object completedItemsLock = new object();
                        messageBus.Subscribe<WorkItemStatus>(status => {
                            if (status.Progress == 100)
                                _logger.Trace("Progress: {progress}", status.Progress);

                            if (status.Progress < 100)
                                return;

                            lock (completedItemsLock)
                                completedItems.Add(status.WorkItemId);
                        });
            
                        var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(10));
                        var tasks = new List<Task> {
                            Task.Run(async () => {
                                await j1.RunUntilEmptyAsync(cancellationTokenSource.Token);
                                cancellationTokenSource.Cancel();
                            }, cancellationTokenSource.Token),
                            Task.Run(async () => {
                                await j2.RunUntilEmptyAsync(cancellationTokenSource.Token);
                                cancellationTokenSource.Cancel();
                            }, cancellationTokenSource.Token),
                            Task.Run(async () => {
                                await j3.RunUntilEmptyAsync(cancellationTokenSource.Token);
                                cancellationTokenSource.Cancel();
                            }, cancellationTokenSource.Token)
                        };

                        try {
                            await Task.WhenAll(tasks);
                            await SystemClock.SleepAsync(100);
                        } catch (TaskCanceledException) {}

                        _logger.Info("Completed: {completedItems} Errors: {errors}", completedItems.Count, errors);
            
                        Assert.Equal(workItemCount, completedItems.Count + errors);
                        Assert.Equal(3, jobIds.Count);
                        Assert.Equal(workItemCount, jobIds.Sum(kvp => kvp.Value));
                    }
                }
            }
        }
Example #34
0
        public virtual async Task CanRunWorkItemWithMetrics()
        {
            int completedCount = 0;

            Log.MinimumLevel = LogLevel.Trace;

            var metricsClient = new InMemoryMetricsClient(false, loggerFactory: Log);
            var behavior      = new MetricsQueueBehavior <WorkItemData>(metricsClient, "metric", loggerFactory: Log, reportCountsInterval: TimeSpan.Zero);
            var queue         = new InMemoryQueue <WorkItemData>(behaviors: new[] { behavior }, loggerFactory: Log);

            queue.Completed.AddHandler((sender, e) => {
                completedCount++;
                return(TaskHelper.Completed);
            });

            _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 Task.Delay(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);

            Assert.InRange((await metricsClient.GetGaugeStatsAsync("metric.workitemdata.count")).Max, 2, 3);
            Assert.InRange((await metricsClient.GetGaugeStatsAsync("metric.workitemdata.working")).Max, 0, 1);

            Assert.Equal(3, await metricsClient.GetCounterCountAsync("metric.workitemdata.simple.enqueued"));
            Assert.Equal(3, await metricsClient.GetCounterCountAsync("metric.workitemdata.enqueued"));

            Assert.Equal(3, await metricsClient.GetCounterCountAsync("metric.workitemdata.simple.dequeued"));
            Assert.Equal(3, await metricsClient.GetCounterCountAsync("metric.workitemdata.dequeued"));

            Assert.Equal(2, await metricsClient.GetCounterCountAsync("metric.workitemdata.simple.completed"));
            Assert.Equal(2, await metricsClient.GetCounterCountAsync("metric.workitemdata.completed"));

            Assert.Equal(1, await metricsClient.GetCounterCountAsync("metric.workitemdata.simple.abandoned"));
            Assert.Equal(1, await metricsClient.GetCounterCountAsync("metric.workitemdata.abandoned"));

            var queueTiming = await metricsClient.GetTimerStatsAsync("metric.workitemdata.simple.queuetime");

            Assert.Equal(3, queueTiming.Count);
            queueTiming = await metricsClient.GetTimerStatsAsync("metric.workitemdata.queuetime");

            Assert.Equal(3, queueTiming.Count);

            var processTiming = await metricsClient.GetTimerStatsAsync("metric.workitemdata.simple.processtime");

            Assert.Equal(3, processTiming.Count);
            processTiming = await metricsClient.GetTimerStatsAsync("metric.workitemdata.processtime");

            Assert.Equal(3, processTiming.Count);

            var queueStats = await metricsClient.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.Equal(3, queueStats.Count.Max);
            Assert.InRange(queueStats.Working.Max, 0, 1);

            var subQueueStats = await metricsClient.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);
        }
Example #35
0
        public async Task CanRunBadWorkItem() {
            using (var queue = new InMemoryQueue<WorkItemData>(retries: 2, retryDelay: TimeSpan.FromMilliseconds(500))) {
                using (var messageBus = new InMemoryMessageBus()) {
                    var handlerRegistry = new WorkItemHandlers();
                    var job = new WorkItemJob(queue, messageBus, handlerRegistry, Log);

                    handlerRegistry.Register<MyWorkItem>(ctx => {
                        var jobData = ctx.GetData<MyWorkItem>();
                        Assert.Equal("Test", jobData.SomeData);
                        throw new Exception();
                    });

                    var jobId = await queue.EnqueueAsync(new MyWorkItem {
                        SomeData = "Test"
                    }, true);

                    int statusCount = 0;
                    messageBus.Subscribe<WorkItemStatus>(status => {
                        _logger.Trace("Progress: {progress}", status.Progress);
                        Assert.Equal(jobId, status.WorkItemId);
                        statusCount++;
                    });

                    await job.RunUntilEmptyAsync();
                    Assert.Equal(1, statusCount);
                }
            }
        }
Example #36
0
        public async Task CanRunWorkItemWithClassHandler() {
            using (var queue = new InMemoryQueue<WorkItemData>()) {
                using (var messageBus = new InMemoryMessageBus()) {
                    var handlerRegistry = new WorkItemHandlers();
                    var job = new WorkItemJob(queue, messageBus, handlerRegistry, Log);

                    handlerRegistry.Register<MyWorkItem>(new MyWorkItemHandler(Log));

                    var jobId = await queue.EnqueueAsync(new MyWorkItem {
                        SomeData = "Test"
                    }, true);

                    int statusCount = 0;
                    messageBus.Subscribe<WorkItemStatus>(status => {
                        _logger.Trace("Progress: {progress}", status.Progress);
                        Assert.Equal(jobId, status.WorkItemId);
                        statusCount++;
                    });

                    await job.RunUntilEmptyAsync();

                    Assert.Equal(11, statusCount);
                }
            }
        }
Example #37
0
        public virtual async Task CanRunWorkItemWithMetrics()
        {
            int completedCount = 0;

            //Log.MinimumLevel = LogLevel.Trace;
            //Log.SetLogLevel<ScheduledTimer>(LogLevel.Information);
            //Log.SetLogLevel<InMemoryCacheClient>(LogLevel.Information);

            using (var metricsClient = new InMemoryMetricsClient(false, loggerFactory: Log)) {
                var behavior = new MetricsQueueBehavior <WorkItemData>(metricsClient, "metric", loggerFactory: Log, reportCountsInterval: TimeSpan.Zero);
                using (var queue = new InMemoryQueue <WorkItemData>(behaviors: new[] { behavior }, loggerFactory: Log)) {
                    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);

                        Assert.InRange((await metricsClient.GetGaugeStatsAsync("metric.workitemdata.count")).Max, 1, 3);
                        Assert.InRange((await metricsClient.GetGaugeStatsAsync("metric.workitemdata.working")).Max, 0, 1);

                        Assert.Equal(3, await metricsClient.GetCounterCountAsync("metric.workitemdata.simple.enqueued"));
                        Assert.Equal(3, await metricsClient.GetCounterCountAsync("metric.workitemdata.enqueued"));

                        Assert.Equal(3, await metricsClient.GetCounterCountAsync("metric.workitemdata.simple.dequeued"));
                        Assert.Equal(3, await metricsClient.GetCounterCountAsync("metric.workitemdata.dequeued"));

                        Assert.Equal(2, await metricsClient.GetCounterCountAsync("metric.workitemdata.simple.completed"));
                        Assert.Equal(2, await metricsClient.GetCounterCountAsync("metric.workitemdata.completed"));

                        Assert.Equal(1, await metricsClient.GetCounterCountAsync("metric.workitemdata.simple.abandoned"));
                        Assert.Equal(1, await metricsClient.GetCounterCountAsync("metric.workitemdata.abandoned"));

                        var queueTiming = await metricsClient.GetTimerStatsAsync("metric.workitemdata.simple.queuetime");

                        Assert.Equal(3, queueTiming.Count);
                        queueTiming = await metricsClient.GetTimerStatsAsync("metric.workitemdata.queuetime");

                        Assert.Equal(3, queueTiming.Count);

                        var processTiming = await metricsClient.GetTimerStatsAsync("metric.workitemdata.simple.processtime");

                        Assert.Equal(3, processTiming.Count);
                        processTiming = await metricsClient.GetTimerStatsAsync("metric.workitemdata.processtime");

                        Assert.Equal(3, processTiming.Count);

                        var queueStats = await metricsClient.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 metricsClient.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);
                    }
                }
            }
        }
Example #38
0
        public async Task CanHandleMultipleWorkItemInstances()
        {
            const int workItemCount = 1000;

            var metrics = new InMemoryMetricsClient();
            var queue   = new InMemoryQueue <WorkItemData>(retries: 0, retryDelay: TimeSpan.Zero);

            queue.AttachBehavior(new MetricsQueueBehavior <WorkItemData>(metrics));
            var messageBus      = new InMemoryMessageBus();
            var handlerRegistry = new WorkItemHandlers();
            var j1     = new WorkItemJob(queue, messageBus, handlerRegistry);
            var j2     = new WorkItemJob(queue, messageBus, handlerRegistry);
            var j3     = new WorkItemJob(queue, messageBus, handlerRegistry);
            int errors = 0;

            var jobIds = new ConcurrentDictionary <string, int>();

            handlerRegistry.Register <MyWorkItem>(async ctx => {
                var jobData = ctx.GetData <MyWorkItem>();
                Assert.Equal("Test", jobData.SomeData);

                var jobWorkTotal = jobIds.AddOrUpdate(ctx.JobId, 1, (key, value) => value + 1);
                Logger.Trace().Message($"Job {ctx.JobId} processing work item #: {jobWorkTotal}").Write();

                for (int i = 0; i < 10; i++)
                {
                    await ctx.ReportProgressAsync(10 * i);
                }

                if (RandomData.GetBool(1))
                {
                    Interlocked.Increment(ref errors);
                    throw new ApplicationException("Boom!");
                }
            });

            for (int i = 0; i < workItemCount; i++)
            {
                await queue.EnqueueAsync(new MyWorkItem {
                    SomeData = "Test",
                    Index    = i
                }, true);
            }

            var    completedItems     = new List <string>();
            object completedItemsLock = new object();

            messageBus.Subscribe <WorkItemStatus>(status => {
                Logger.Trace().Message($"Progress: {status.Progress}").Write();
                if (status.Progress < 100)
                {
                    return;
                }

                lock (completedItemsLock)
                    completedItems.Add(status.WorkItemId);
            });

            var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(10));
            var tasks = new List <Task> {
                Task.Run(async() => {
                    await j1.RunUntilEmptyAsync(cancellationTokenSource.Token);
                    cancellationTokenSource.Cancel();
                }, cancellationTokenSource.Token),
                Task.Run(async() => {
                    await j2.RunUntilEmptyAsync(cancellationTokenSource.Token);
                    cancellationTokenSource.Cancel();
                }, cancellationTokenSource.Token),
                Task.Run(async() => {
                    await j3.RunUntilEmptyAsync(cancellationTokenSource.Token);
                    cancellationTokenSource.Cancel();
                }, cancellationTokenSource.Token)
            };

            try {
                await Task.WhenAll(tasks);

                await Task.Delay(100);
            } catch (TaskCanceledException) {}

            Logger.Info().Message($"Completed: {completedItems.Count} Errors: {errors}").Write();
            metrics.DisplayStats(_writer);

            Assert.Equal(workItemCount, completedItems.Count + errors);
            Assert.Equal(3, jobIds.Count);
            Assert.Equal(workItemCount, jobIds.Sum(kvp => kvp.Value));
        }
        public void CanAutoCompleteWorker() {
            var resetEvent = new AutoResetEvent(false);
            var queue = new InMemoryQueue<SimpleWorkItem>(workItemTimeoutMilliseconds: 100);
            queue.StartWorking(w => {
                Assert.Equal("Hello", w.Value.Data);
                resetEvent.Set();
            }, true);
            queue.EnqueueAsync(new SimpleWorkItem {
                Data = "Hello"
            });

            Assert.Equal(1, queue.Count);
            bool success = resetEvent.WaitOne(100);
            Assert.True(success, "Failed to receive message.");
            Task.Delay(25).Wait();
            Assert.Equal(0, queue.Count);
            Assert.Equal(1, queue.Completed);
            Assert.Equal(0, queue.WorkerErrors);
        }
Example #40
0
        public async Task CanHandleMultipleWorkItemInstances()
        {
            const int workItemCount = 1000;

            using (var metrics = new InMemoryMetricsClient(new InMemoryMetricsClientOptions {
                LoggerFactory = Log
            })) {
                var options = new InMemoryQueueOptions <WorkItemData> {
                    Retries = 0, RetryDelay = TimeSpan.Zero, LoggerFactory = Log
                };
                using (var queue = new InMemoryQueue <WorkItemData>(options)) {
                    queue.AttachBehavior(new MetricsQueueBehavior <WorkItemData>(metrics, loggerFactory: Log));
                    using (var messageBus = new InMemoryMessageBus(new InMemoryMessageBusOptions {
                        LoggerFactory = Log
                    })) {
                        var handlerRegistry = new WorkItemHandlers();
                        var j1     = new WorkItemJob(queue, messageBus, handlerRegistry, Log);
                        var j2     = new WorkItemJob(queue, messageBus, handlerRegistry, Log);
                        var j3     = new WorkItemJob(queue, messageBus, handlerRegistry, Log);
                        int errors = 0;

                        var jobIds = new ConcurrentDictionary <string, int>();

                        handlerRegistry.Register <MyWorkItem>(async ctx => {
                            var jobData = ctx.GetData <MyWorkItem>();
                            Assert.Equal("Test", jobData.SomeData);

                            int jobWorkTotal = jobIds.AddOrUpdate(ctx.JobId, 1, (key, value) => value + 1);
                            if (jobData.Index % 100 == 0)
                            {
                                _logger.Trace("Job {jobId} processing work item #: {jobWorkTotal}", ctx.JobId, jobWorkTotal);
                            }

                            for (int i = 0; i < 10; i++)
                            {
                                await ctx.ReportProgressAsync(10 * i);
                            }

                            if (RandomData.GetBool(1))
                            {
                                Interlocked.Increment(ref errors);
                                throw new Exception("Boom!");
                            }
                        });

                        for (int i = 0; i < workItemCount; i++)
                        {
                            await queue.EnqueueAsync(new MyWorkItem {
                                SomeData = "Test",
                                Index    = i
                            }, true);
                        }

                        var    completedItems     = new List <string>();
                        object completedItemsLock = new object();
                        await messageBus.SubscribeAsync <WorkItemStatus>(status => {
                            if (status.Progress == 100)
                            {
                                _logger.Trace("Progress: {progress}", status.Progress);
                            }

                            if (status.Progress < 100)
                            {
                                return;
                            }

                            lock (completedItemsLock)
                                completedItems.Add(status.WorkItemId);
                        });

                        var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(10));
                        var tasks = new List <Task> {
                            Task.Run(async() => {
                                await j1.RunUntilEmptyAsync(cancellationTokenSource.Token);
                                cancellationTokenSource.Cancel();
                            }, cancellationTokenSource.Token),
                            Task.Run(async() => {
                                await j2.RunUntilEmptyAsync(cancellationTokenSource.Token);
                                cancellationTokenSource.Cancel();
                            }, cancellationTokenSource.Token),
                            Task.Run(async() => {
                                await j3.RunUntilEmptyAsync(cancellationTokenSource.Token);
                                cancellationTokenSource.Cancel();
                            }, cancellationTokenSource.Token)
                        };

                        try {
                            await Task.WhenAll(tasks);
                        } catch (OperationCanceledException ex) {
                            _logger.Error(ex, $"One or more tasks were cancelled: {ex.Message}");
                        }

                        await SystemClock.SleepAsync(100);

                        _logger.Info("Completed: {completedItems} Errors: {errors}", completedItems.Count, errors);
                        Assert.Equal(workItemCount, completedItems.Count + errors);
                        Assert.Equal(3, jobIds.Count);
                        Assert.Equal(workItemCount, jobIds.Sum(kvp => kvp.Value));
                    }
                }
            }
        }
Example #41
0
        public async Task CanRunWorkItemWithClassHandler() {
            ServiceProvider.SetServiceProvider(typeof(MyBootstrappedServiceProvider));
            var queue = new InMemoryQueue<WorkItemData>();
            var messageBus = new InMemoryMessageBus();
            var handlerRegistry = new WorkItemHandlers();
            var job = new WorkItemJob(queue, messageBus, handlerRegistry);

            handlerRegistry.Register<MyWorkItem, MyWorkItemHandler>();

            var jobId = await queue.EnqueueAsync(new MyWorkItem {
                SomeData = "Test"
            }, true);

            int statusCount = 0;
            messageBus.Subscribe<WorkItemStatus>(status => {
                Logger.Trace().Message($"Progress: {status.Progress}").Write();
                Assert.Equal(jobId, status.WorkItemId);
                statusCount++;
            });

            await job.RunUntilEmptyAsync();

            Assert.Equal(11, statusCount);
        }