public async Task Add() { var identity1 = await _identityRepository.AddAsync(IdentityGenerator.Generate()); Assert.NotNull(identity1?.Id); var disposables = new List<IDisposable>(2); var countdownEvent = new AsyncCountdownEvent(2); try { var identity2 = IdentityGenerator.Default; disposables.Add(_identityRepository.DocumentsAdding.AddSyncHandler((o, args) => { Assert.Equal(identity2, args.Documents.First()); countdownEvent.Signal(); })); disposables.Add(_identityRepository.DocumentsAdded.AddSyncHandler((o, args) => { Assert.Equal(identity2, args.Documents.First()); countdownEvent.Signal(); })); var result = await _identityRepository.AddAsync(identity2); Assert.Equal(IdentityGenerator.Default.Id, result.Id); await countdownEvent.WaitAsync(new CancellationTokenSource(TimeSpan.FromMilliseconds(250)).Token); Assert.Equal(0, countdownEvent.CurrentCount); } finally { foreach (var disposable in disposables) disposable.Dispose(); disposables.Clear(); } }
public virtual async Task CanSendMessageToMultipleSubscribers() { var messageBus = GetMessageBus(); if (messageBus == null) return; using (messageBus) { var countdown = new AsyncCountdownEvent(3); messageBus.Subscribe<SimpleMessageA>(msg => { Assert.Equal("Hello", msg.Data); countdown.Signal(); }); messageBus.Subscribe<SimpleMessageA>(msg => { Assert.Equal("Hello", msg.Data); countdown.Signal(); }); messageBus.Subscribe<SimpleMessageA>(msg => { Assert.Equal("Hello", msg.Data); countdown.Signal(); }); await messageBus.PublishAsync(new SimpleMessageA { Data = "Hello" }); await countdown.WaitAsync(TimeSpan.FromSeconds(2)); } }
/// <summary> /// Completes the deferral. /// </summary> void IDisposable.Dispose() { if (_count == null) return; _count.Signal(); _count = null; }
public virtual async Task CanSendDelayedMessage() { const int numConcurrentMessages = 10000; var messageBus = GetMessageBus(); if (messageBus == null) return; using (messageBus) { var countdown = new AsyncCountdownEvent(numConcurrentMessages); messageBus.Subscribe<SimpleMessageA>(msg => { Logger.Trace().Message("Got message").Write(); Assert.Equal("Hello", msg.Data); countdown.Signal(); Logger.Trace().Message("Set event").Write(); }); var sw = Stopwatch.StartNew(); await Run.InParallel(numConcurrentMessages, async i => { await messageBus.PublishAsync(new SimpleMessageA { Data = "Hello" }, TimeSpan.FromMilliseconds(RandomData.GetInt(0, 300))); Logger.Trace().Message("Published one...").Write(); }); await countdown.WaitAsync(TimeSpan.FromSeconds(2)); sw.Stop(); Assert.True(sw.Elapsed > TimeSpan.FromMilliseconds(80)); } }
public async Task SearchByQuery() { var identity = IdentityGenerator.Default; var result = await _identityRepository.AddAsync(identity); Assert.Equal(identity, result); await _client.RefreshAsync(); var results = await _identityRepository.SearchAsync(null, "id:test"); Assert.Equal(0, results.Documents.Count); var disposables = new List<IDisposable>(1); var countdownEvent = new AsyncCountdownEvent(1); try { var filter = $"id:{identity.Id}"; disposables.Add(_identityRepository.BeforeQuery.AddSyncHandler((o, args) => { Assert.Equal(filter, ((ElasticQuery)args.Query).Filter); countdownEvent.Signal(); })); results = await _identityRepository.SearchAsync(null, filter); Assert.Equal(1, results.Documents.Count); await countdownEvent.WaitAsync(new CancellationTokenSource(TimeSpan.FromMilliseconds(250)).Token); Assert.Equal(0, countdownEvent.CurrentCount); } finally { foreach (var disposable in disposables) disposable.Dispose(); disposables.Clear(); } }
public void TryAddCount_AfterSet_ReturnsFalse() { var ce = new AsyncCountdownEvent(1); ce.Signal(); var result = ce.TryAddCount(); Assert.IsFalse(result); }
/// <summary> /// Gets a deferral. The deferral is complete when disposed. /// </summary> /// <returns>The deferral.</returns> public IDisposable GetDeferral() { if (_count == null) _count = new AsyncCountdownEvent(1); var ret = new Deferral(_count); _count.AddCount(); return ret; }
public void WaitAsync_Unset_IsNotCompleted() { AsyncContext.Run(async () => { var ce = new AsyncCountdownEvent(1); var task = ce.WaitAsync(); Assert.AreEqual(1, ce.CurrentCount); await AssertEx.NeverCompletesAsync(task); }); }
public void WaitAsync_AfterCountingDown_IsCompleted() { var ce = new AsyncCountdownEvent(2); Assert.AreEqual(2, ce.CurrentCount); ce.Signal(); var task = ce.WaitAsync(); Assert.AreEqual(1, ce.CurrentCount); Assert.IsFalse(task.IsCompleted); ce.Signal(); Assert.AreEqual(0, ce.CurrentCount); Assert.IsTrue(task.IsCompleted); }
private BackgroundTaskManager() { // Start the count at 1 and decrement it when ASP.NET notifies us we're shutting down. shutdown = new CancellationTokenSource(); count = new AsyncCountdownEvent(1); shutdown.Token.Register(() => count.Signal(), useSynchronizationContext: false); // Register the object and unregister it when the count reaches zero. HostingEnvironment.RegisterObject(this); done = count.WaitAsync() .ContinueWith(_ => HostingEnvironment.UnregisterObject(this), TaskContinuationOptions.ExecuteSynchronously); }
public async Task CanRun() { var countdown = new AsyncCountdownEvent(1); Func<Task<DateTime?>> callback = () => { countdown.Signal(); return null; }; using (var timer = new ScheduledTimer(callback, loggerFactory: Log)) { timer.ScheduleNext(); await countdown.WaitAsync(TimeSpan.FromMilliseconds(100)); Assert.Equal(0, countdown.CurrentCount); } }
public void AddCount_IncrementsCount() { var ce = new AsyncCountdownEvent(1); var task = ce.WaitAsync(); Assert.AreEqual(1, ce.CurrentCount); Assert.IsFalse(task.IsCompleted); ce.AddCount(); Assert.AreEqual(2, ce.CurrentCount); Assert.IsFalse(task.IsCompleted); ce.Signal(); Assert.AreEqual(1, ce.CurrentCount); Assert.IsFalse(task.IsCompleted); ce.Signal(); Assert.AreEqual(0, ce.CurrentCount); Assert.IsTrue(task.IsCompleted); }
public async Task CanRunWithMinimumInterval() { var countdown = new AsyncCountdownEvent(2); Func<Task<DateTime?>> callback = async () => { _logger.Info("Starting work."); countdown.Signal(); await SystemClock.SleepAsync(500); _logger.Info("Finished work."); return null; }; using (var timer = new ScheduledTimer(callback, minimumIntervalTime: TimeSpan.FromMilliseconds(100), loggerFactory: Log)) { for (int i = 0; i < 4; i++) { timer.ScheduleNext(); SystemClock.Sleep(1); } await countdown.WaitAsync(TimeSpan.FromMilliseconds(100)); Assert.Equal(1, countdown.CurrentCount); await countdown.WaitAsync(TimeSpan.FromSeconds(1.5)); Assert.Equal(0, countdown.CurrentCount); } }
public virtual async Task CanSubscribeToAllMessageTypes() { var messageBus = GetMessageBus(); if (messageBus == null) return; using (messageBus) { var countdown = new AsyncCountdownEvent(3); messageBus.Subscribe<object>(msg => { countdown.Signal(); }); await messageBus.PublishAsync(new SimpleMessageA { Data = "Hello" }); await messageBus.PublishAsync(new SimpleMessageB { Data = "Hello" }); await messageBus.PublishAsync(new SimpleMessageC { Data = "Hello" }); await countdown.WaitAsync(TimeSpan.FromSeconds(2)); Assert.Equal(0, countdown.CurrentCount); } }
public virtual async Task CanHaveMultipleQueueInstances() { var queue = GetQueue(retries: 0, retryDelay: TimeSpan.Zero); if (queue == null) return; using (queue) { Logger.Trace().Message("Queue Id: {0}", queue.QueueId).Write(); await queue.DeleteQueueAsync(); const int workItemCount = 50; const int workerCount = 3; var countdown = new AsyncCountdownEvent(workItemCount); var info = new WorkInfo(); var workers = new List<IQueue<SimpleWorkItem>> {queue}; for (int i = 0; i < workerCount; i++) { var q = GetQueue(retries: 0, retryDelay: TimeSpan.Zero); Logger.Trace().Message("Queue Id: {0}, I: {1}", q.QueueId, i).Write(); q.StartWorking(async w => await DoWorkAsync(w, countdown, info)); workers.Add(q); } await Run.InParallel(workItemCount, async i => { var id = await queue.EnqueueAsync(new SimpleWorkItem { Data = "Hello", Id = i }); Logger.Trace().Message("Enqueued Index: {0} Id: {1}", i, id).Write(); }); await countdown.WaitAsync(); await Task.Delay(50); Logger.Trace().Message("Completed: {0} Abandoned: {1} Error: {2}", info.CompletedCount, info.AbandonCount, info.ErrorCount).Write(); Logger.Info().Message($"Work Info Stats: Completed: {info.CompletedCount} Abandoned: {info.AbandonCount} Error: {info.ErrorCount}").Write(); Assert.Equal(workItemCount, info.CompletedCount + info.AbandonCount + info.ErrorCount); // In memory queue doesn't share state. if (queue.GetType() == typeof (InMemoryQueue<SimpleWorkItem>)) { var stats = await queue.GetQueueStatsAsync(); Assert.Equal(0, stats.Working); Assert.Equal(0, stats.Timeouts); Assert.Equal(workItemCount, stats.Enqueued); Assert.Equal(workItemCount, stats.Dequeued); Assert.Equal(info.CompletedCount, stats.Completed); Assert.Equal(info.ErrorCount, stats.Errors); Assert.Equal(info.AbandonCount, stats.Abandoned - info.ErrorCount); Assert.Equal(info.AbandonCount + stats.Errors, stats.Deadletter); } else { var workerStats = new List<QueueStats>(); for (int i = 0; i < workers.Count; i++) { var stats = await workers[i].GetQueueStatsAsync(); Logger.Info().Message($"Worker#{i} Working: {stats.Working} Completed: {stats.Completed} Abandoned: {stats.Abandoned} Error: {stats.Errors} Deadletter: {stats.Deadletter}").Write(); workerStats.Add(stats); } Assert.Equal(info.CompletedCount, workerStats.Sum(s => s.Completed)); Assert.Equal(info.ErrorCount, workerStats.Sum(s => s.Errors)); Assert.Equal(info.AbandonCount, workerStats.Sum(s => s.Abandoned) - info.ErrorCount); Assert.Equal(info.AbandonCount + workerStats.Sum(s => s.Errors), (workerStats.LastOrDefault()?.Deadletter ?? 0)); } workers.ForEach(w => w.Dispose()); } }
protected async Task DoWorkAsync(QueueEntry<SimpleWorkItem> w, AsyncCountdownEvent countdown, WorkInfo info) { Trace.WriteLine($"Starting: {w.Value.Id}"); Assert.Equal("Hello", w.Value.Data); try { // randomly complete, abandon or blowup. if (RandomData.GetBool()) { Trace.WriteLine($"Completing: {w.Value.Id}"); await w.CompleteAsync(); info.IncrementCompletedCount(); } else if (RandomData.GetBool()) { Trace.WriteLine($"Abandoning: {w.Value.Id}"); await w.AbandonAsync(); info.IncrementAbandonCount(); } else { Trace.WriteLine($"Erroring: {w.Value.Id}"); info.IncrementErrorCount(); throw new ApplicationException(); } } finally { Trace.WriteLine($"Signal {countdown.CurrentCount}"); countdown.Signal(); } }
public DebugView(AsyncCountdownEvent ce) { _ce = ce; }
public async Task AddAndSave() { var log = await _dailyRepository.AddAsync(LogEventGenerator.Default, sendNotification: false); Assert.NotNull(log?.Id); var disposables = new List<IDisposable>(4); var countdownEvent = new AsyncCountdownEvent(5); // Save requires an id to be set. var addedLog = LogEventGenerator.Generate(id: ObjectId.GenerateNewId().ToString()); try { disposables.Add(_dailyRepository.DocumentsAdding.AddSyncHandler((o, args) => { Assert.Equal(addedLog, args.Documents.First()); countdownEvent.Signal(); })); disposables.Add(_dailyRepository.DocumentsAdded.AddSyncHandler((o, args) => { Assert.Equal(addedLog, args.Documents.First()); countdownEvent.Signal(); })); disposables.Add(_dailyRepository.DocumentsSaving.AddSyncHandler((o, args) => { Assert.Equal(log, args.Documents.First().Value); countdownEvent.Signal(); })); disposables.Add(_dailyRepository.DocumentsSaved.AddSyncHandler((o, args) => { Assert.Equal(log, args.Documents.First().Value); countdownEvent.Signal(); })); _messgeBus.Subscribe<EntityChanged>((msg, ct) => { Assert.Equal(nameof(LogEvent), msg.Type); Assert.Equal(log.Id, msg.Id); Assert.Equal(ChangeType.Saved, msg.ChangeType); countdownEvent.Signal(); return Task.CompletedTask; }); log.CompanyId = ObjectId.GenerateNewId().ToString(); await _dailyRepository.SaveAsync(new List<LogEvent> { log, addedLog }); await countdownEvent.WaitAsync(new CancellationTokenSource(TimeSpan.FromSeconds(2)).Token); Assert.Equal(0, countdownEvent.CurrentCount); } finally { foreach (var disposable in disposables) disposable.Dispose(); disposables.Clear(); } }
/// <summary> /// Creates a new deferral referencing the countdown event of the deferral manager. /// </summary> /// <param name="count">The countdown event of the deferral manager.</param> public Deferral(AsyncCountdownEvent count) { _count = count; }
public async Task Remove() { var log = await _dailyRepository.AddAsync(LogEventGenerator.Default); Assert.NotNull(log?.Id); var disposables = new List<IDisposable>(2); var countdownEvent = new AsyncCountdownEvent(2); try { disposables.Add(_dailyRepository.DocumentsRemoving.AddSyncHandler((o, args) => { Assert.Equal(log, args.Documents.First()); countdownEvent.Signal(); })); disposables.Add(_dailyRepository.DocumentsRemoved.AddSyncHandler((o, args) => { Assert.Equal(log, args.Documents.First()); countdownEvent.Signal(); })); await _dailyRepository.RemoveAsync(log); await countdownEvent.WaitAsync(new CancellationTokenSource(TimeSpan.FromMilliseconds(250)).Token); Assert.Equal(0, countdownEvent.CurrentCount); } finally { foreach (var disposable in disposables) disposable.Dispose(); disposables.Clear(); } }
public async Task MeasureWorkerThroughput() { var queue = GetQueue(retries: 3, workItemTimeout: TimeSpan.FromSeconds(2), retryDelay: TimeSpan.FromSeconds(1)); if (queue == null) return; using (queue) { await queue.DeleteQueueAsync(); const int workItemCount = 1; for (int i = 0; i < workItemCount; i++) { await queue.EnqueueAsync(new SimpleWorkItem { Data = "Hello" }); } Assert.Equal(workItemCount, (await queue.GetQueueStatsAsync()).Queued); var countdown = new AsyncCountdownEvent(workItemCount); var metrics = new InMemoryMetricsClient(); await queue.StartWorkingAsync(async workItem => { Assert.Equal("Hello", workItem.Value.Data); await workItem.CompleteAsync(); await metrics.CounterAsync("work"); countdown.Signal(); }); await countdown.WaitAsync(TimeSpan.FromMinutes(1)); Assert.Equal(0, countdown.CurrentCount); _logger.Trace((await metrics.GetCounterStatsAsync("work")).ToString()); var stats = await queue.GetQueueStatsAsync(); Assert.Equal(workItemCount, stats.Dequeued); Assert.Equal(workItemCount, stats.Completed); Assert.Equal(0, stats.Queued); _logger.Trace("# Keys: {0}", CountAllKeysAsync()); } }
public async Task CanPostManyEvents() { await ResetAsync(); const int batchSize = 250; const int batchCount = 10; try { var countdown = new AsyncCountdownEvent(batchCount); var messageSubscriber = IoC.GetInstance<IMessageSubscriber>(); messageSubscriber.Subscribe<EntityChanged>(ch => { if (ch.ChangeType != ChangeType.Added || ch.Type != typeof(PersistentEvent).Name) return; if (countdown.CurrentCount >= batchCount) throw new ApplicationException("Too many change notifications."); countdown.Signal(); }); await Run.InParallel(batchCount, async i => { _eventController.Request = CreateRequestMessage(new ClaimsPrincipal(new User { EmailAddress = TestConstants.UserEmail, Id = TestConstants.UserId, OrganizationIds = new[] { TestConstants.OrganizationId }, Roles = new[] { AuthorizationRoles.Client } }.ToIdentity(TestConstants.ProjectId)), true, false); var events = new RandomEventGenerator().Generate(batchSize); var compressedEvents = await Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(events)).CompressAsync(); var actionResult = await _eventController.PostAsync(compressedEvents, version: 2, userAgent: "exceptionless/2.0.0.0"); Assert.IsType<StatusCodeResult>(actionResult); }); Assert.Equal(batchCount, (await _eventQueue.GetQueueStatsAsync()).Enqueued); Assert.Equal(0, (await _eventQueue.GetQueueStatsAsync()).Completed); var processEventsJob = IoC.GetInstance<EventPostsJob>(); var sw = Stopwatch.StartNew(); await processEventsJob.RunUntilEmptyAsync(); sw.Stop(); Trace.WriteLine(sw.Elapsed); Assert.Equal(batchCount, (await _eventQueue.GetQueueStatsAsync()).Completed); Assert.Equal(batchSize * batchCount, await EventCountAsync()); //await countdown.WaitAsync(); } finally { await _eventQueue.DeleteQueueAsync(); } }
public async Task RemoveAll() { await _identityRepository.RemoveAllAsync(); var identities = new List<Identity> { IdentityGenerator.Default }; await _identityRepository.AddAsync(identities); await _client.RefreshAsync(); var disposables = new List<IDisposable>(2); var countdownEvent = new AsyncCountdownEvent(2); try { disposables.Add(_identityRepository.DocumentsRemoving.AddSyncHandler((o, args) => { countdownEvent.Signal(); })); disposables.Add(_identityRepository.DocumentsRemoved.AddSyncHandler((o, args) => { countdownEvent.Signal(); })); await _identityRepository.RemoveAllAsync(); await countdownEvent.WaitAsync(new CancellationTokenSource(TimeSpan.FromMilliseconds(250)).Token); Assert.Equal(0, countdownEvent.CurrentCount); } finally { foreach (var disposable in disposables) disposable.Dispose(); disposables.Clear(); } await _client.RefreshAsync(); Assert.Equal(0, await _identityRepository.CountAsync()); }
public void AddCount_Overflow_ThrowsException() { var ce = new AsyncCountdownEvent(int.MaxValue); AssertEx.ThrowsException<InvalidOperationException>(() => ce.AddCount()); }
public void AddCount_AfterSet_ThrowsException() { var ce = new AsyncCountdownEvent(1); ce.Signal(); AssertEx.ThrowsException<InvalidOperationException>(() => ce.AddCount()); }
public virtual async Task WillReceiveDerivedMessageTypes() { var messageBus = GetMessageBus(); if (messageBus == null) return; using (messageBus) { var countdown = new AsyncCountdownEvent(2); messageBus.Subscribe<ISimpleMessage>(msg => { Assert.Equal("Hello", msg.Data); countdown.Signal(); }); await messageBus.PublishAsync(new SimpleMessageA { Data = "Hello" }); await messageBus.PublishAsync(new SimpleMessageB { Data = "Hello" }); await messageBus.PublishAsync(new SimpleMessageC { Data = "Hello" }); await countdown.WaitAsync(TimeSpan.FromSeconds(5)); Assert.Equal(0, countdown.CurrentCount); } }
public virtual async Task CanTolerateSubscriberFailure() { var messageBus = GetMessageBus(); if (messageBus == null) return; using (messageBus) { var countdown = new AsyncCountdownEvent(2); messageBus.Subscribe<SimpleMessageA>(msg => { throw new Exception(); }); messageBus.Subscribe<SimpleMessageA>(msg => { Assert.Equal("Hello", msg.Data); countdown.Signal(); }); messageBus.Subscribe<SimpleMessageA>(msg => { Assert.Equal("Hello", msg.Data); countdown.Signal(); }); await messageBus.PublishAsync(new SimpleMessageA { Data = "Hello" }); await countdown.WaitAsync(TimeSpan.FromSeconds(2)); Assert.Equal(0, countdown.CurrentCount); } }
public virtual async Task CanCancelSubscription() { var messageBus = GetMessageBus(); if (messageBus == null) return; using (messageBus) { var countdown = new AsyncCountdownEvent(2); long messageCount = 0; var cancellationTokenSource = new CancellationTokenSource(); messageBus.Subscribe<SimpleMessageA>(msg => { _logger.Trace("SimpleAMessage received"); Interlocked.Increment(ref messageCount); cancellationTokenSource.Cancel(); countdown.Signal(); }, cancellationTokenSource.Token); messageBus.Subscribe<object>(msg => countdown.Signal()); await messageBus.PublishAsync(new SimpleMessageA { Data = "Hello" }); await countdown.WaitAsync(TimeSpan.FromSeconds(2)); Assert.Equal(0, countdown.CurrentCount); Assert.Equal(1, messageCount); countdown = new AsyncCountdownEvent(1); await messageBus.PublishAsync(new SimpleMessageA { Data = "Hello" }); await countdown.WaitAsync(TimeSpan.FromSeconds(2)); Assert.Equal(0, countdown.CurrentCount); Assert.Equal(1, messageCount); } }
public virtual async Task CanReceiveFromMultipleSubscribers() { var messageBus1 = GetMessageBus(); if (messageBus1 == null) return; using (messageBus1) { var countdown1 = new AsyncCountdownEvent(1); messageBus1.Subscribe<SimpleMessageA>(msg => { Assert.Equal("Hello", msg.Data); countdown1.Signal(); }); using (var messageBus2 = GetMessageBus()) { var countdown2 = new AsyncCountdownEvent(1); messageBus2.Subscribe<SimpleMessageA>(msg => { Assert.Equal("Hello", msg.Data); countdown2.Signal(); }); await messageBus1.PublishAsync(new SimpleMessageA { Data = "Hello" }); await countdown1.WaitAsync(TimeSpan.FromSeconds(2)); Assert.Equal(0, countdown1.CurrentCount); await countdown2.WaitAsync(TimeSpan.FromSeconds(2)); Assert.Equal(0, countdown2.CurrentCount); } } }
public void Id_EqualsTaskId() { var ce = new AsyncCountdownEvent(1); var task = ce.WaitAsync(); Assert.AreEqual(task.Id, ce.Id); }