public async Task A_command_is_not_marked_as_applied_if_no_handler_is_registered() { // arrange var order = CommandSchedulingTests.CreateOrder(); order.Apply( new ChargeCreditCardOn { Amount = 10, ChargeDate = Clock.Now().AddDays(10) }); await orderRepository.Save(order); // act var schedulerWithNoHandlers = new SqlCommandScheduler( new Configuration().UseSqlEventStore()); await schedulerWithNoHandlers.AdvanceClock(clockName, @by : TimeSpan.FromDays(20)); // assert using (var db = new CommandSchedulerDbContext()) { db.ScheduledCommands.Single(c => c.AggregateId == order.Id) .AppliedTime .Should() .BeNull(); } }
/// <summary> /// Allows awaiting delivery of all commands that are currently due on the command scheduler. /// </summary> /// <param name="scheduler">The command scheduler.</param> /// <param name="clockName">The name of the clock on which the commands are scheduled.</param> /// <returns></returns> public static async Task Done(this SqlCommandScheduler scheduler, string clockName = null) { clockName = clockName ?? SqlCommandScheduler.DefaultClockName; Debug.WriteLine(string.Format("SqlCommandScheduler: Waiting for clock {0}", clockName)); for (var i = 0; i < 10; i++) { using (var db = scheduler.CreateCommandSchedulerDbContext()) { var due = db.ScheduledCommands .Due() .Where(c => c.Clock.Name == clockName); if (!await due.AnyAsync()) { return; } var commands = await due.ToArrayAsync(); Debug.WriteLine(string.Format("SqlCommandScheduler: Triggering {0} commands", commands.Count())); foreach (var scheduledCommand in commands) { Debug.WriteLine(string.Format("SqlCommandScheduler: Triggering {0}:{1}", scheduledCommand.AggregateId, scheduledCommand.SequenceNumber)); await scheduler.Trigger(scheduledCommand, new SchedulerAdvancedResult(), db); } await Task.Delay(400); } } Debug.WriteLine(string.Format("SqlCommandScheduler: Done waiting for clock {0}", clockName)); }
protected override void ConfigureScheduler(Configuration configuration) { configuration.UseSqlCommandScheduling(); sqlCommandScheduler = configuration.SqlCommandScheduler(); sqlCommandScheduler.GetClockName = e => clockName; clockTrigger = sqlCommandScheduler; clockRepository = sqlCommandScheduler; }
public SessionHandler( Action <IScheduledCommand> onMessage, Action <Exception> onError, SqlCommandScheduler scheduler) { this.onMessage = onMessage; this.onError = onError; this.scheduler = scheduler; }
/// <summary> /// Initializes a new instance of the <see cref="ServiceBusCommandQueueReceiver"/> class. /// </summary> /// <param name="settings">The service bus settings.</param> /// <param name="scheduler">The command scheduler.</param> /// <exception cref="System.ArgumentNullException"> /// settings /// or /// scheduler /// </exception> public ServiceBusCommandQueueReceiver(ServiceBusSettings settings, SqlCommandScheduler scheduler) { if (settings == null) { throw new ArgumentNullException("settings"); } if (scheduler == null) { throw new ArgumentNullException("scheduler"); } this.settings = settings; this.scheduler = scheduler; #if DEBUG exceptionSubject .Where(ex => !(ex is OperationCanceledException)) .Subscribe(ex => Debug.WriteLine("ServiceBusCommandQueueReceiver error: " + ex)); #endif }
public override void SetUp() { base.SetUp(); using (VirtualClock.Start(DateTimeOffset.Now.AddMonths(1))) { disposables = new CompositeDisposable(); Settings.Sources = new ISettingsSource[] { new ConfigDirectorySettings(@"c:\dev\.config") }.Concat(Settings.Sources); serviceBusSettings = Settings.Get <ServiceBusSettings>(); serviceBusSettings.NamePrefix = "itscqrstests"; serviceBusSettings.ConfigureQueue = q => { q.AutoDeleteOnIdle = TimeSpan.FromMinutes(15); }; bus = new FakeEventBus(); orderRepository = new SqlEventSourcedRepository <Order>(bus); var configuration = new Configuration() .UseSqlEventStore(() => new EventStoreDbContext()) .UseEventBus(bus) .UseSqlCommandScheduling() .UseDependency <IEventSourcedRepository <Order> >(t => orderRepository); var clockName = Any.Paragraph(4); scheduler = new SqlCommandScheduler(configuration) { GetClockName = @event => clockName }; queueSender = new ServiceBusCommandQueueSender(serviceBusSettings) { MessageDeliveryOffsetFromCommandDueTime = TimeSpan.FromSeconds(30) }; disposables.Add(scheduler.Activity.Subscribe(s => Console.WriteLine("SqlCommandScheduler: " + s.ToJson()))); disposables.Add(queueSender.Messages.Subscribe(s => Console.WriteLine("ServiceBusCommandQueueSender: " + s.ToJson()))); disposables.Add(bus.Subscribe(scheduler)); disposables.Add(configuration); disposables.Add(ConfigurationContext.Establish(configuration)); } }
/// <summary> /// Configures the system to use SQL-backed command scheduling. /// </summary> /// <param name="configuration">The configuration.</param> /// <returns>The updated configuration.</returns> public static Configuration UseSqlCommandScheduling( this Configuration configuration, Action <ReadModelCatchup <CommandSchedulerDbContext> > configureCatchup = null) { var container = configuration.Container; container.AddFallbackToDefaultClock(); var scheduler = new SqlCommandScheduler( configuration, container.Resolve <Func <CommandSchedulerDbContext> >(), container.Resolve <GetClockName>()); if (container.All(r => r.Key != typeof(SqlCommandScheduler))) { container.Register(c => scheduler) .Register <ISchedulerClockTrigger>(c => scheduler) .Register <ISchedulerClockRepository>(c => scheduler); } var subscription = container.Resolve <IEventBus>().Subscribe(scheduler); configuration.RegisterForDisposal(subscription); container.RegisterSingle(c => scheduler); if (configureCatchup != null) { var catchup = new ReadModelCatchup <CommandSchedulerDbContext>(scheduler) { CreateReadModelDbContext = scheduler.CreateCommandSchedulerDbContext }; configureCatchup(catchup); catchup.PollEventStore(); container.RegisterSingle(c => catchup); configuration.RegisterForDisposal(catchup); } configuration.IsUsingSqlCommandScheduling(true); return(configuration); }