private static void RunAfter(IEnumerable <IStep> steps, CancellationBoundary boundary) { foreach (var step in steps.Where(s => s.Boundary >= boundary)) { step.Trigger(); } }
private void Configure(CancellationBoundary testBoundary) { _commandHandler = new ManualCommandHandler(); _subscriber = new ManualSubscriber(); var resolver = EventFlowOptions.New() .AddCommands(typeof(ThingyPingCommand)) .AddEvents(typeof(ThingyPingEvent)) .UseInMemoryReadStoreFor <InMemoryThingyReadModel>() .Configure(c => c.CancellationBoundary = testBoundary) .RegisterServices(s => { s.Decorate <IInMemoryReadStore <InMemoryThingyReadModel>, ManualReadStore>(); s.Decorate <IEventPersistence, ManualEventPersistence>(); s.AddTransient <ICommandHandler <ThingyAggregate, ThingyId, IExecutionResult, ThingyPingCommand> >(c => _commandHandler); s.AddTransient <ISubscribeSynchronousTo <ThingyAggregate, ThingyId, ThingyPingEvent> >(c => _subscriber); s.AddTransient <IScopedContext, ScopedContext>(); }) .ServiceCollection.BuildServiceProvider(); _eventPersistence = (ManualEventPersistence)resolver.GetRequiredService <IEventPersistence>(); _readStore = (ManualReadStore)resolver.GetRequiredService <IInMemoryReadStore <InMemoryThingyReadModel> >(); _commandBus = resolver.GetRequiredService <ICommandBus>(); }
private void Configure(CancellationBoundary testBoundary) { _commandHandler = new ManualCommandHandler(); _subscriber = new ManualSubscriber(); _eventPersistence = null; _readStore = null; var resolver = EventFlowOptions .New .AddCommands(typeof(ThingyPingCommand)) .AddEvents(typeof(ThingyPingEvent)) .UseInMemoryReadStoreFor <InMemoryThingyReadModel>() .Configure(c => c.CancellationBoundary = testBoundary) .RegisterServices(s => { s.Decorate <IInMemoryReadStore <InMemoryThingyReadModel> >((c, i) => _readStore ?? (_readStore = new ManualReadStore(i))); s.Decorate <IEventPersistence>((c, i) => _eventPersistence ?? (_eventPersistence = new ManualEventPersistence(i))); s.Register <ICommandHandler <ThingyAggregate, ThingyId, IExecutionResult, ThingyPingCommand> >(c => _commandHandler); s.Register <ISubscribeSynchronousTo <ThingyAggregate, ThingyId, ThingyPingEvent> >(c => _subscriber); s.Register <IScopedContext, ScopedContext>(Lifetime.Scoped); }) .CreateResolver(); _commandBus = resolver.Resolve <ICommandBus>(); }
public Setup() { RetryCountOnOptimisticConcurrencyExceptions = 4; WaitThenTryAfterOnOptimisticConcurrencyExceptions = TimeSpan.FromMilliseconds(1000); ThrowSubscriberExceptions = false; IsAsynchronousSubscribersEnabled = false; CancellationBoundary = CancellationBoundary.BeforeCommittingEvents; }
internal EventFlowConfiguration() { PopulateReadModelEventPageSize = 200; NumberOfRetriesOnOptimisticConcurrencyExceptions = 4; DelayBeforeRetryOnOptimisticConcurrencyExceptions = TimeSpan.FromMilliseconds(100); ThrowSubscriberExceptions = false; IsAsynchronousSubscribersEnabled = false; CancellationBoundary = CancellationBoundary.BeforeCommittingEvents; }
public async Task ShouldCancelBeforeBarrierOrRunToEnd( CancellationBoundary configuredBoundary, CancellationBoundary cancelAt) { // Arrange Configure(configuredBoundary); var safetyTimeout = Debugger.IsAttached ? TimeSpan.FromDays(1) : TimeSpan.FromSeconds(1); var id = ThingyId.New; var pingId = PingId.New; var tokenSource = new CancellationTokenSource(safetyTimeout); var token = tokenSource.Token; var steps = CreateSteps(id); // Act var publishTask = _commandBus.PublishAsync(new ThingyPingCommand(id, pingId), token); RunUpTo(steps, cancelAt); tokenSource.Cancel(); RunAfter(steps, cancelAt); var publishTaskOrSafetyTimeout = await Task.WhenAny( publishTask, Task.Delay(safetyTimeout, CancellationToken.None)); if (publishTaskOrSafetyTimeout == publishTask) { try { // Command could have failed or been cancelled. await publishTask; } catch (OperationCanceledException) { // Command was cancelled. } } else { throw new Exception("Test timeout: Cancellation didn't work."); } // Assert var shouldHaveRunTo = cancelAt <= configuredBoundary ? cancelAt : CancellationBoundary.CancelAlways; // Run to end await Validate(steps, shouldHaveRunTo); }
public Step( CancellationBoundary boundary, TaskCompletionSource <bool> completionSource, Func <Task <T> > validationFactory = null, Action <T> validateHasRun = null, Action <T> validateHasNotRun = null) { Boundary = boundary; _completionSource = completionSource; _validationFactory = validationFactory ?? (() => Task.FromResult(default(T))); _validateHasRun = validateHasRun ?? (_ => { }); _validateHasNotRun = validateHasNotRun ?? (_ => { }); }
private static async Task Validate(IEnumerable <IStep> steps, CancellationBoundary shouldHaveRunTo) { foreach (var step in steps) { if (step.Boundary <= shouldHaveRunTo) { await step.ValidateHasRunAsync(); } else { await step.ValidateHasNotRunAsync(); } } }
public static CancellationToken Limit(this ICancellationConfiguration configuration, CancellationToken token, CancellationBoundary currentBoundary) { token.ThrowIfCancellationRequested(); return(currentBoundary < configuration.CancellationBoundary ? token : CancellationToken.None); }