public void CanIncrementCounter() { var metrics = new InMemoryMetricsClient(); metrics.Counter("c1"); Assert.Equal(1, metrics.GetCount("c1")); metrics.Counter("c1", 5); Assert.Equal(6, metrics.GetCount("c1")); var counter = metrics.Counters["c1"]; Assert.True(counter.Rate > 400); metrics.Gauge("g1", 2.534); Assert.Equal(2.534, metrics.GetGaugeValue("g1")); metrics.Timer("t1", 50788); var stats = metrics.GetMetricStats(); Assert.Equal(1, stats.Timings.Count); metrics.DisplayStats(_writer); }
public virtual async Task CanRunWorkItemWithMetrics() { var eventRaised = new ManualResetEvent(false); var metricsClient = new InMemoryMetricsClient(false); 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(); Assert.True(eventRaised.WaitOne(TimeSpan.FromMinutes(1))); Assert.Equal(1, await metricsClient.GetCounterCountAsync("metric.workitemdata.simple.enqueued")); Assert.Equal(1, await metricsClient.GetCounterCountAsync("metric.workitemdata.simple.dequeued")); Assert.Equal(1, await metricsClient.GetCounterCountAsync("metric.workitemdata.simple.completed")); var queueTiming = await metricsClient.GetTimerStatsAsync("metric.workitemdata.simple.queuetime"); Assert.True(0 < queueTiming.Count); var processTiming = await metricsClient.GetTimerStatsAsync("metric.workitemdata.simple.processtime"); Assert.True(0 < processTiming.Count); }
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)); } } } }
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(); } } } }
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); } } } }
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); }
public void RegisterServices(Container container) { container.RegisterSingle <IDependencyResolver>(() => new SimpleInjectorCoreDependencyResolver(container)); var metricsClient = new InMemoryMetricsClient(); metricsClient.StartDisplayingStats(); container.RegisterSingle <IMetricsClient>(metricsClient); container.RegisterSingle <MongoDatabase>(() => { if (String.IsNullOrEmpty(Settings.Current.MongoConnectionString)) { throw new ConfigurationErrorsException("MongoConnectionString was not found in the Web.config."); } MongoDefaults.MaxConnectionIdleTime = TimeSpan.FromMinutes(1); MongoServer server = new MongoClient(new MongoUrl(Settings.Current.MongoConnectionString)).GetServer(); return(server.GetDatabase(Settings.Current.MongoDatabaseName)); }); container.RegisterSingle <IElasticClient>(() => ElasticSearchConfiguration.GetElasticClient(Settings.Current.ElasticSearchConnectionString.Split(',').Select(url => new Uri(url)))); container.RegisterSingle <ICacheClient, InMemoryCacheClient>(); container.RegisterSingle <IQueue <EventPost> >(() => new InMemoryQueue <EventPost>(statName: MetricNames.PostsQueueSize, metrics: container.GetInstance <IMetricsClient>())); container.RegisterSingle <IQueue <EventUserDescription> >(() => new InMemoryQueue <EventUserDescription>(statName: MetricNames.EventsUserDescriptionQueueSize, metrics: container.GetInstance <IMetricsClient>())); container.RegisterSingle <IQueue <EventNotificationWorkItem> >(() => new InMemoryQueue <EventNotificationWorkItem>(statName: MetricNames.EventNotificationQueueSize, metrics: container.GetInstance <IMetricsClient>())); container.RegisterSingle <IQueue <WebHookNotification> >(() => new InMemoryQueue <WebHookNotification>(statName: MetricNames.WebHookQueueSize, metrics: container.GetInstance <IMetricsClient>())); container.RegisterSingle <IQueue <MailMessage> >(() => new InMemoryQueue <MailMessage>(statName: MetricNames.EmailsQueueSize, metrics: container.GetInstance <IMetricsClient>())); container.RegisterSingle <IQueue <StatusMessage> >(() => new InMemoryQueue <StatusMessage>()); container.RegisterSingle <IMessageBus, InMemoryMessageBus>(); container.RegisterSingle <IMessagePublisher>(container.GetInstance <IMessageBus>); container.RegisterSingle <IMessageSubscriber>(container.GetInstance <IMessageBus>); if (!String.IsNullOrEmpty(Settings.Current.StorageFolder)) { container.RegisterSingle <IFileStorage>(new FolderFileStorage(Settings.Current.StorageFolder)); } else { container.RegisterSingle <IFileStorage>(new InMemoryFileStorage()); } container.RegisterSingle <IStackRepository, StackRepository>(); container.RegisterSingle <IEventRepository, EventRepository>(); container.RegisterSingle <IOrganizationRepository, OrganizationRepository>(); container.RegisterSingle <IProjectRepository, ProjectRepository>(); container.RegisterSingle <IUserRepository, UserRepository>(); container.RegisterSingle <IWebHookRepository, WebHookRepository>(); container.RegisterSingle <ITokenRepository, TokenRepository>(); container.RegisterSingle <IApplicationRepository, ApplicationRepository>(); container.RegisterSingle <IGeoIPResolver, MindMaxGeoIPResolver>(); container.RegisterSingle <IValidator <Application>, ApplicationValidator>(); container.RegisterSingle <IValidator <Organization>, OrganizationValidator>(); container.RegisterSingle <IValidator <PersistentEvent>, PersistentEventValidator>(); container.RegisterSingle <IValidator <Project>, ProjectValidator>(); container.RegisterSingle <IValidator <Stack>, StackValidator>(); container.RegisterSingle <IValidator <Models.Admin.Token>, TokenValidator>(); container.RegisterSingle <IValidator <UserDescription>, UserDescriptionValidator>(); container.RegisterSingle <IValidator <User>, UserValidator>(); container.RegisterSingle <IValidator <WebHook>, WebHookValidator>(); container.RegisterSingle <IEmailGenerator>(() => new RazorEmailGenerator(@"Mail\Templates")); container.RegisterSingle <IMailer, Mailer>(); if (Settings.Current.WebsiteMode != WebsiteMode.Dev) { container.RegisterSingle <IMailSender, SmtpMailSender>(); } else { container.RegisterSingle <IMailSender>(() => new InMemoryMailSender()); } container.Register <ILockProvider, CacheLockProvider>(); container.Register <StripeEventHandler>(); container.RegisterSingle <BillingManager>(); container.RegisterSingle <DataHelper>(); container.RegisterSingle <EventStats>(); container.RegisterSingle <EventPipeline>(); container.RegisterSingle <EventPluginManager>(); container.RegisterSingle <FormattingPluginManager>(); container.RegisterSingle <ICoreLastReferenceIdManager, NullCoreLastReferenceIdManager>(); }
public void RegisterServices(Container container) { container.RegisterSingle <IDependencyResolver>(() => new SimpleInjectorCoreDependencyResolver(container)); if (Settings.Current.EnableAppStats) { container.RegisterSingle <IMetricsClient>(() => new StatsDMetricsClient(Settings.Current.AppStatsServerName, Settings.Current.AppStatsServerPort)); } else { var metricsClient = new InMemoryMetricsClient(); metricsClient.StartDisplayingStats(); container.RegisterSingle <IMetricsClient>(metricsClient); } container.RegisterSingle <IDependencyResolver>(() => new SimpleInjectorCoreDependencyResolver(container)); container.RegisterSingle <MongoDatabase>(() => { if (String.IsNullOrEmpty(Settings.Current.MongoConnectionString)) { throw new ConfigurationErrorsException("MongoConnectionString was not found in the Web.config."); } MongoDefaults.MaxConnectionIdleTime = TimeSpan.FromMinutes(1); var url = new MongoUrl(Settings.Current.MongoConnectionString); string databaseName = url.DatabaseName; if (Settings.Current.AppendMachineNameToDatabase) { databaseName += String.Concat("-", Environment.MachineName.ToLower()); } MongoServer server = new MongoClient(url).GetServer(); return(server.GetDatabase(databaseName)); }); container.RegisterSingle <IElasticClient>(() => ElasticSearchConfiguration.GetElasticClient(Settings.Current.ElasticSearchConnectionString.Split(',').Select(url => new Uri(url)))); ExceptionlessClient.Default.Configuration.SetVersion(ThisAssembly.AssemblyInformationalVersion); //ExceptionlessClient.Default.Configuration.UseLogger(new Exceptionless.NLog.NLogExceptionlessLog()); ExceptionlessClient.Default.Configuration.UseInMemoryStorage(); container.RegisterSingle <ExceptionlessClient>(() => ExceptionlessClient.Default); if (Settings.Current.EnableRedis) { var muxer = ConnectionMultiplexer.Connect(Settings.Current.RedisConnectionString); container.RegisterSingle(muxer); container.RegisterSingle <ICacheClient, RedisHybridCacheClient>(); container.RegisterSingle <IQueue <EventPost> >(() => new RedisQueue <EventPost>(muxer, statName: MetricNames.PostsQueueSize, metrics: container.GetInstance <IMetricsClient>())); container.RegisterSingle <IQueue <EventUserDescription> >(() => new RedisQueue <EventUserDescription>(muxer, statName: MetricNames.EventsUserDescriptionQueueSize, metrics: container.GetInstance <IMetricsClient>())); container.RegisterSingle <IQueue <EventNotification> >(() => new RedisQueue <EventNotification>(muxer, statName: MetricNames.EventNotificationQueueSize, metrics: container.GetInstance <IMetricsClient>())); container.RegisterSingle <IQueue <WebHookNotification> >(() => new RedisQueue <WebHookNotification>(muxer, statName: MetricNames.WebHookQueueSize, metrics: container.GetInstance <IMetricsClient>())); container.RegisterSingle <IQueue <MailMessage> >(() => new RedisQueue <MailMessage>(muxer, statName: MetricNames.EmailsQueueSize, metrics: container.GetInstance <IMetricsClient>())); container.RegisterSingle <IMessageBus>(() => new RedisMessageBus(muxer.GetSubscriber())); } else { container.RegisterSingle <ICacheClient, InMemoryCacheClient>(); container.RegisterSingle <IQueue <EventPost> >(() => new InMemoryQueue <EventPost>(statName: MetricNames.PostsQueueSize, metrics: container.GetInstance <IMetricsClient>())); container.RegisterSingle <IQueue <EventUserDescription> >(() => new InMemoryQueue <EventUserDescription>(statName: MetricNames.EventsUserDescriptionQueueSize, metrics: container.GetInstance <IMetricsClient>())); container.RegisterSingle <IQueue <EventNotification> >(() => new InMemoryQueue <EventNotification>(statName: MetricNames.EventNotificationQueueSize, metrics: container.GetInstance <IMetricsClient>())); container.RegisterSingle <IQueue <WebHookNotification> >(() => new InMemoryQueue <WebHookNotification>(statName: MetricNames.WebHookQueueSize, metrics: container.GetInstance <IMetricsClient>())); container.RegisterSingle <IQueue <MailMessage> >(() => new InMemoryQueue <MailMessage>(statName: MetricNames.EmailsQueueSize, metrics: container.GetInstance <IMetricsClient>())); container.RegisterSingle <IMessageBus, InMemoryMessageBus>(); } container.RegisterSingle <IMessagePublisher>(container.GetInstance <IMessageBus>); container.RegisterSingle <IMessageSubscriber>(container.GetInstance <IMessageBus>); if (Settings.Current.EnableAzureStorage) { container.RegisterSingle <IFileStorage>(new AzureFileStorage(Settings.Current.AzureStorageConnectionString)); } else if (!String.IsNullOrEmpty(Settings.Current.StorageFolder)) { container.RegisterSingle <IFileStorage>(new FolderFileStorage(Settings.Current.StorageFolder)); } else { container.RegisterSingle <IFileStorage>(new InMemoryFileStorage()); } container.RegisterSingle <IStackRepository, StackRepository>(); container.RegisterSingle <IEventRepository, EventRepository>(); container.RegisterSingle <IOrganizationRepository, OrganizationRepository>(); container.RegisterSingle <IProjectRepository, ProjectRepository>(); container.RegisterSingle <IUserRepository, UserRepository>(); container.RegisterSingle <IWebHookRepository, WebHookRepository>(); container.RegisterSingle <ITokenRepository, TokenRepository>(); container.RegisterSingle <IApplicationRepository, ApplicationRepository>(); container.RegisterSingle <IGeoIPResolver, MindMaxGeoIPResolver>(); container.RegisterSingle <IValidator <Application>, ApplicationValidator>(); container.RegisterSingle <IValidator <Organization>, OrganizationValidator>(); container.RegisterSingle <IValidator <PersistentEvent>, PersistentEventValidator>(); container.RegisterSingle <IValidator <Project>, ProjectValidator>(); container.RegisterSingle <IValidator <Stack>, StackValidator>(); container.RegisterSingle <IValidator <Token>, TokenValidator>(); container.RegisterSingle <IValidator <UserDescription>, UserDescriptionValidator>(); container.RegisterSingle <IValidator <User>, UserValidator>(); container.RegisterSingle <IValidator <WebHook>, WebHookValidator>(); container.RegisterSingle <IEmailGenerator>(() => new RazorEmailGenerator(@"Mail\Templates")); container.RegisterSingle <IMailer, Mailer>(); if (Settings.Current.WebsiteMode != WebsiteMode.Dev) { container.RegisterSingle <IMailSender, SmtpMailSender>(); } else { container.RegisterSingle <IMailSender>(() => new InMemoryMailSender()); } container.Register <ILockProvider, CacheLockProvider>(); container.Register <StripeEventHandler>(); container.RegisterSingle <BillingManager>(); container.RegisterSingle <DataHelper>(); container.RegisterSingle <EventStats>(); container.RegisterSingle <EventPipeline>(); container.RegisterSingle <EventPluginManager>(); container.RegisterSingle <FormattingPluginManager>(); }
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)); }