public async Task DeleteFriendInvite() { using var contextFactory = new TestTriviaGameContextFactory(); using TriviaRankContext context = contextFactory.CreateContext(); var insertedPlayer1 = new Player { Username = "******", Password = "******", Birthday = DateTime.Now, Points = 100, FirstName = "Bart", LastName = "Simpson" }; var insertedPlayer2 = new Player { Username = "******", Password = "******", Birthday = DateTime.Now, Points = 200, FirstName = "Milhouse", LastName = "Vanhouten" }; await context.Players.AddAsync(insertedPlayer1); await context.Players.AddAsync(insertedPlayer2); context.SaveChanges(); var repo = new OutboxRepository(context); await repo.createFriendInvite(insertedPlayer1.Username, insertedPlayer2.Username); await repo.deleteFriendInvite(insertedPlayer1.Username, insertedPlayer2.Username); Assert.Empty((await repo.getFriendInvites(insertedPlayer2.Id)).Where(p => p.Id == insertedPlayer1.Id)); }
public OutboxRepositoryShould() { var options = new DbContextOptionsBuilder <OutboxConsumerDbContext>().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options; dbContext = new OutboxConsumerDbContext(options); repository = new OutboxRepository(dbContext); }
public async Task ReadMessagesToProcess_should_return_empty_collection_if_no_data_available() { var dbCtx = NSubstitute.Substitute.For <IDbContext>(); var serializer = NSubstitute.Substitute.For <ISerializer>(); var sut = new OutboxRepository(dbCtx, serializer); var result = await sut.ReadMessagesToProcess(); result.Should().NotBeNull().And.BeEmpty(); }
public BusSubscriptionsWithOutboxShould() { var logger = Substitute.For <ILogger <BusSubscriptionsWithOutbox> >(); outboxRepository = Substitute.For <OutboxRepository>(new object[] { null }); timer = new RepeatingTimer(new TimerConfiguration() { DueSeconds = -1, PeriodSeconds = -1 }); busSubscriptions = new BusSubscriptionsWithOutbox(logger, outboxRepository, timer); }
public async Task CheckCreateValidGameInvite() { using var contextFactory = new TestTriviaGameContextFactory(); using TriviaRankContext context = contextFactory.CreateContext(); var insertedPlayer1 = new Player { Username = "******", Password = "******", Birthday = DateTime.Now, Points = 100, FirstName = "Bart", LastName = "Simpson" }; var insertedPlayer2 = new Player { Username = "******", Password = "******", Birthday = DateTime.Now, Points = 200, FirstName = "Milhouse", LastName = "Vanhouten" }; await context.Players.AddAsync(insertedPlayer1); await context.Players.AddAsync(insertedPlayer2); context.SaveChanges(); var game1 = new Game { GameName = "new game 1", OwnerId = insertedPlayer1.Id, StartDate = DateTimeOffset.Now, EndDate = DateTimeOffset.Now, GameMode = true, TotalQuestions = 10, IsPublic = true }; await context.Games.AddAsync(game1); context.SaveChanges(); var repo = new OutboxRepository(context); await repo.createGameInvite(game1.Id, insertedPlayer2.Id); var invitedGame = (await repo.getGameInvites(insertedPlayer2.Id)).FirstOrDefault(); Assert.Equal(game1.Id, invitedGame.Id); }
protected virtual async Task UpdateProcessedItemsInternal( OutboxProcessingResults <TUniqueIdentifier> results, OutboxProcessingOptions options ) { //Update & store the state for all Items Processed (e.g. Successful, Attempted, Failed, etc.)! var processedItems = results.GetAllProcessedItems(); options.LogDebugCallback?.Invoke($"Starting to update the Outbox for [{processedItems.Count}] items..."); if (processedItems.Count > 0) { results.ProcessingTimer.Start(); await OutboxRepository.UpdateOutboxItemsAsync(processedItems, options.ItemUpdatingBatchSize).ConfigureAwait(false); results.ProcessingTimer.Stop(); } options.LogDebugCallback?.Invoke( $"Finished updating the Outbox for [{processedItems.Count}] items in" + $" [{results.ProcessingTimer.Elapsed.ToElapsedTimeDescriptiveFormat()}]!" ); }
public virtual async Task <ISqlTransactionalOutboxProcessingResults <TUniqueIdentifier> > ProcessPendingOutboxItemsAsync( OutboxProcessingOptions processingOptions = null, bool throwExceptionOnFailure = false ) { var options = processingOptions ?? OutboxProcessingOptions.DefaultOutboxProcessingOptions; var results = new OutboxProcessingResults <TUniqueIdentifier>(); results.ProcessingTimer.Start(); //Retrieve items to e processed from the Repository (ALL Pending items available for publishing attempt!) var pendingOutboxItems = await OutboxRepository.RetrieveOutboxItemsAsync( OutboxItemStatus.Pending, options.ItemProcessingBatchSize ).ConfigureAwait(false); results.ProcessingTimer.Stop(); //Short Circuit if there is nothing to process! if (pendingOutboxItems.Count <= 0) { options.LogDebugCallback?.Invoke($"There are no outbox items to process; processing completed at [{DateTime.Now}]."); return(results); } options.LogDebugCallback?.Invoke( $"Starting Outbox Processing of [{pendingOutboxItems.Count}] outbox items, retrieved in" + $" [{results.ProcessingTimer.Elapsed.ToElapsedTimeDescriptiveFormat()}], at [{DateTime.Now}]..." ); //Attempt the acquire the Distributed Mutex Lock (if specified)! options.LogDebugCallback?.Invoke($"{nameof(options.FifoEnforcedPublishingEnabled)} = {options.FifoEnforcedPublishingEnabled}"); results.ProcessingTimer.Start(); await using var distributedMutex = options.FifoEnforcedPublishingEnabled ? await OutboxRepository.AcquireDistributedProcessingMutexAsync().ConfigureAwait(false) : new NoOpAsyncDisposable(); //The distributed Mutex will ONLY be null if it could not be acquired; otherwise our // NoOp will be successfully initialized if locking is disabled. if (distributedMutex == null) { const string mutexErrorMessage = "Distributed Mutex Lock could not be acquired; processing will not continue."; options.LogDebugCallback?.Invoke(mutexErrorMessage); if (throwExceptionOnFailure) { throw new Exception(mutexErrorMessage); } return(results); } //Now EXECUTE & PROCESS the Items and Update the Outbox appropriately... //NOTE: It's CRITICAL that we attempt to Publish BEFORE we update the results in the TransactionalOutbox, // this ensures that we guarantee at-least-once delivery because the item will be retried at a later point // if anything fails with the update. await ProcessOutboxItemsInternalAsync( pendingOutboxItems, options, results, throwExceptionOnFailure ).ConfigureAwait(false); return(results); }