public void Test() { var streamer = EnvelopeStreamer.CreateDefault(typeof(SecondPassed)); var builder = new CqrsEngineBuilder(streamer); var store = FileStorage.CreateConfig(GetType().Name, reset: true); builder.Handle(store.CreateInbox("inbox"), BuildRouter(store, streamer)); builder.Handle(store.CreateInbox("process"), ie => Console.WriteLine("Message from past!")); var inboxWriter = store.CreateQueueWriter("inbox"); var futureContainer = store.CreateStreaming().GetContainer("future"); var timer = new StreamingTimerService(inboxWriter, futureContainer, streamer); builder.AddProcess(timer); builder.Handle(store.CreateInbox("timer"), timer.PutMessage); using (var engine = builder.Build()) { var bytes = streamer.SaveEnvelopeData(new SecondPassed(), c => c.DelayBy(TimeSpan.FromSeconds(4))); inboxWriter.PutMessage(bytes); Console.WriteLine("Sent message to future..."); engine.RunForever(); } }
public AssembledComponents AssembleComponents() { var documents = CreateNuclear(new DocumentStrategy()); var streamer = Streamer; var tapes = Tapes; var streaming = Streaming; var routerQueue = CreateQueueWriter(Topology.RouterQueue); var aggregates = new AggregateFactory(tapes, streamer, routerQueue); var sender = new SimpleMessageSender(streamer, routerQueue); var flow = new MessageSender(sender); var builder = new CqrsEngineBuilder(streamer); var log = tapes.GetOrCreateStream(Topology.DomainLogName); var dispatcher = new SimpleDispatcher(aggregates, streamer, log); builder.Handle(CreateInbox(Topology.RouterQueue), Topology.Route(CreateQueueWriter, streamer, tapes), "router"); builder.Handle(CreateInbox(Topology.EntityQueue), aggregates.Dispatch); var functions = new RedirectToDynamicEvent(); // documents //functions.WireToWhen(new RegistrationUniquenessProjection(atomic.Factory.GetEntityWriter<unit, RegistrationUniquenessDocument>())); // UI projections var projectionStore = CreateNuclear(new ProjectionStrategy()); foreach (var projection in BootstrapProjections.BuildProjectionsWithWhenConvention(projectionStore.Factory)) { functions.WireToWhen(projection); } // processes //functions.WireToWhen(new Domain.RecipeProcess(flow)); builder.Handle(CreateInbox(Topology.EventsQueue), aem => CallHandlers(functions, aem)); var timer = new StreamingTimerService(CreateQueueWriter(Topology.RouterQueue), streaming.GetContainer(Topology.FutureMessagesContainer), streamer); builder.Handle(CreateInbox(Topology.TimerQueue), timer.PutMessage); builder.AddProcess(timer); // GNS: just for this simple sample. In reality one would have some command handlers involved Bus.SetBus(new SimpleBus(sender, dispatcher)); return(new AssembledComponents { Builder = builder, Sender = sender, Dispatcher = dispatcher, ProjectionFactory = projectionStore.Factory, Setup = this }); }
public void Dulicate_message_is_detected() { var streamer = EnvelopeStreamer.CreateDefault(typeof(Message)); var builder = new CqrsEngineBuilder(streamer); var cfg = new MemoryStorageConfig(); var sender = cfg.CreateSimpleSender(streamer, "in"); builder.Handle(cfg.CreateInbox("in"), envelope => Console.WriteLine("Got message")); var env = new EnvelopeBuilder("fixed ID").Build(); using (var token = new CancellationTokenSource()) using (var build = builder.Build()) using (TestObserver.When <EnvelopeDuplicateDiscarded>(discarded => token.Cancel())) { sender.SendBatch(new object[] { new Message() }, IdGeneration.HashContent); sender.SendBatch(new object[] { new Message() }, IdGeneration.HashContent); build.Start(token.Token); if (Debugger.IsAttached) { token.Token.WaitHandle.WaitOne(); } else { token.Token.WaitHandle.WaitOne(10000); } Assert.IsTrue(token.IsCancellationRequested); } }
public void Run_in_test() { var streamer = EnvelopeStreamer.CreateDefault(typeof(CreateCustomer), typeof(CustomerCreated)); var builder = new CqrsEngineBuilder(streamer); var account = new MemoryAccount(); var nuclear = account.CreateNuclear(); var inbox = account.CreateInbox("input"); var sender = account.CreateSimpleSender(streamer, "input"); var handler = new MessageHandler(); handler.WireToLambda <CreateCustomer>(customer => Consume(customer, nuclear, sender)); handler.WireToLambda <CustomerCreated>(m => Console.WriteLine("Created!")); builder.Handle(inbox, handler.HandleEnvelope); using (var engine = builder.Build()) { sender.SendOne(new CreateCustomer { CustomerId = 1, CustomerName = "Rinat Abdullin" }); engine.RunForever(); } }
public void Test() { // this test will start a simple web server on port 8082 (with a CQRS engine) // You might need to reserve that port or run test as admin. Check out unit test // output for the exact command line on port reservation (or MSDN docs) // // netsh http add urlacl url=http://+:8082/ user=RINAT-R5\Rinat.Abdullin // after starting the test, navigate you browser to localhost:8082/index.htm // and try dragging the image around // in-memory structure to capture mouse movement // statistics var stats = new MouseStats(); // we accept a message just of this type, using a serializer var messages = new[] { typeof(MouseMoved), typeof(MouseClick) }; var serializer = new MyJsonSerializer(messages); var streamer = new EnvelopeStreamer(serializer); var store = new MemoryAccount(); var atomic = store.CreateNuclear().Factory; // let's configure our custom Http server to // 1. serve resources // 2. serve MouseStats View // 3. accept commands var environment = new HttpEnvironment { Port = 8082 }; var builder = new CqrsEngineBuilder(streamer); builder.AddProcess(new Listener(environment, new EmbeddedResourceHttpRequestHandler(typeof(MouseMoved).Assembly, "Snippets.HttpEndpoint"), new MouseStatsRequestHandler(stats), new HeatMapRequestHandler(atomic.GetEntityReader <unit, HeatMapView>()), new MouseEventsRequestHandler(store.CreateQueueWriter("inbox"), serializer, streamer))); builder.Handle(store.CreateInbox("inbox"), envelope => { if (envelope.Items.Any(i => i.Content is MouseMoved)) { MouseStatHandler(envelope, stats); } else if (envelope.Items.Any(i => i.Content is MouseClick)) { MouseClickHandler(envelope, atomic.GetEntityWriter <unit, PointsView>()); } }); builder.AddProcess(new HeatMapGenerateTask(atomic.GetEntityReader <unit, PointsView>(), atomic.GetEntityWriter <unit, HeatMapView>())); Process.Start("http://localhost:8082/index.htm"); // this is a test, so let's block everything builder.Build().RunForever(); }
public void Run_in_test() { var streamer = EnvelopeStreamer.CreateDefault(typeof(CreateCustomer), typeof(CustomerCreated)); var builder = new CqrsEngineBuilder(streamer); var account = new MemoryStorageConfig(); var nuclear = account.CreateNuclear(new TestStrategy()); var inbox = account.CreateInbox("input"); var sender = account.CreateSimpleSender(streamer, "input"); var handler = new RedirectToCommand(); handler.WireToLambda <CreateCustomer>(customer => Consume(customer, nuclear, sender)); handler.WireToLambda <CustomerCreated>(m => Console.WriteLine("Created!")); builder.Handle(inbox, envelope => handler.InvokeMany(envelope.SelectContents())); using (var engine = builder.Build()) { sender.SendOne(new CreateCustomer { CustomerId = 1, CustomerName = "Rinat Abdullin" }); engine.RunForever(); } }
public void Test() { var types = Assembly.GetExecutingAssembly().GetExportedTypes() .Where(t => typeof(IPS_SampleMessage).IsAssignableFrom(t)); var streamer = EnvelopeStreamer.CreateDefault(types); var builder = new CqrsEngineBuilder(streamer); // only message contracts within this class // configure in memory: // -> sub 1 // inbox -> [PubSubRouter] < // -> sub 2 // var store = new MemoryAccount(); var nuclear = store.CreateNuclear(); var router = new PubSubRouter(nuclear, store.CreateWriteQueueFactory(), streamer); router.Init(); builder.Dispatch(store.CreateInbox("sub1"), b => Console.WriteLine("sub1 hit")); builder.Dispatch(store.CreateInbox("sub2"), b => Console.WriteLine("sub2 hit")); builder.Handle(store.CreateInbox("inbox"), router.DispatchMessage); var sender = store.CreateSimpleSender(streamer, "inbox"); using (var engine = builder.Build()) using (var cts = new CancellationTokenSource()) { var task = engine.Start(cts.Token); // no handler should get these. sender.SendOne(new SomethingHappened()); sender.SendOne(new OtherHappened()); // subscribe sub1 to all messages and sub2 to specific message sender.SendControl(eb => { eb.AddString("router-subscribe:sub1", ".*"); eb.AddString("router-subscribe:sub2", "SomethingHappened"); }); sender.SendOne(new SomethingHappened()); sender.SendOne(new OtherHappened()); // unsubscribe all sender.SendControl(eb => { eb.AddString("router-unsubscribe:sub1", ".*"); eb.AddString("router-unsubscribe:sub2", "SomethingHappened"); }); sender.SendOne(new SomethingHappened()); sender.SendOne(new OtherHappened()); task.Wait(5000); } }
CqrsEngineBuilder BootstrapHandlers(Setup setup) { var builder = new CqrsEngineBuilder(_streamer); var handler = new CommandHandler(); handler.WireToLambda <FailingMessage>(am => SmartFailing(am, setup.Store)); builder.Handle(setup.Inbox, handler.HandleAll); return(builder); }
CqrsEngineBuilder BootstrapHandlers(Setup setup) { var builder = new CqrsEngineBuilder(_streamer); var writer = setup.Store.Factory.GetEntityWriter <unit, int>(); var handler = new CommandHandler(); handler.WireToLambda <AtomicMessage>(am => HandleAtomic(am, setup.Sender, writer)); handler.WireToLambda <NuclearMessage>(am => HandleNuclear(am, setup.Sender, setup.Store)); builder.Handle(setup.Inbox, handler.HandleAll); return(builder); }
CqrsEngineBuilder BootstrapHandlers(Setup setup) { var builder = new CqrsEngineBuilder(_streamer); var handler = new RedirectToCommand(); handler.WireToLambda <FailingMessage>(am => SmartFailing(am, setup.Store)); builder.Handle(setup.Inbox, envelope => { foreach (var message in envelope.Items) { handler.Invoke(message.Content); } }); return(builder); }
public AssembledComponents AssembleComponents() { // set up all the variables var routerQueue = CreateQueueWriter(Topology.RouterQueue); var commands = new RedirectToCommand(); var events = new RedirectToDynamicEvent(); IEventStore eventStore = null;// new LegacyTapeStreamEventStore(Tapes(Topology.TapesContainer), Streamer, routerQueue); var simple = new SimpleMessageSender(Streamer, routerQueue); var flow = new CommandSender(simple); var builder = new CqrsEngineBuilder(Streamer); // route queue infrastructure together builder.Handle(CreateInbox(Topology.RouterQueue), Topology.Route(CreateQueueWriter, Streamer, Tapes), "router"); builder.Handle(CreateInbox(Topology.EntityQueue), em => CallHandlers(commands, em)); builder.Handle(CreateInbox(Topology.EventsQueue), aem => CallHandlers(events, aem)); // message wiring magic DomainBoundedContext.ApplicationServices(Docs, eventStore).ForEach(commands.WireToWhen); DomainBoundedContext.Receptors(flow).ForEach(events.WireToWhen); DomainBoundedContext.Projections(Docs).ForEach(events.WireToWhen); DomainBoundedContext.Tasks(flow, Docs, false).ForEach(builder.AddTask); ClientBoundedContext.Projections(Docs).ForEach(events.WireToWhen); return(new AssembledComponents { Builder = builder, Sender = flow, Setup = this, Simple = simple }); }
CqrsEngineBuilder BootstrapHandlers(Setup setup) { var builder = new CqrsEngineBuilder(_streamer); var writer = setup.Store.Container.GetWriter <unit, int>(); var handler = new RedirectToCommand(); handler.WireToLambda <AtomicMessage>(am => HandleAtomic(am, setup.Sender, writer)); handler.WireToLambda <NuclearMessage>(am => HandleNuclear(am, setup.Sender, setup.Store)); builder.Handle(setup.Inbox, envelope => { foreach (var message in envelope.Items) { handler.Invoke(message.Content); } }); return(builder); }
public void Then_transactional_support_is_provided() { var streamer = EnvelopeStreamer.CreateDefault(typeof(Act)); var builder = new CqrsEngineBuilder(streamer); var setup = ComposeComponents(streamer); var handler = new CommandHandler(); handler.WireToLambda <Act>(act => Consume(act, setup.Storage)); builder.Handle(setup.Inbox, envelope => { using (var tx = new TransactionScope(TransactionScopeOption.RequiresNew)) { handler.HandleAll(envelope); tx.Complete(); } }); using (var source = new CancellationTokenSource()) using (TestObserver.When <EnvelopeDispatched>(e => source.Cancel())) using (var engine = builder.Build()) { setup.Sender.SendBatch(new[] { new Act(), new Act(), new Act { Fail = true } }); setup.Sender.SendBatch(new[] { new Act(), new Act(), new Act() }); var task = engine.Start(source.Token); // Trace.WriteLine("Started"); if (!task.Wait(Debugger.IsAttached ? int.MaxValue : TestSpeed)) { source.Cancel(); Assert.Fail("System should be stopped by now"); } var storage = setup.Storage; var count = storage.GetSingletonOrNew <int>(); Assert.AreEqual(3, count, "Three acts are expected"); } }
public Container Build() { var appendOnlyStore = CreateTapes(TapesContainer); var messageStore = new MessageStore(appendOnlyStore, Streamer.MessageSerializer); var toCommandRouter = new MessageSender(Streamer, CreateQueueWriter(RouterQueue)); var toFunctionalRecorder = new MessageSender(Streamer, CreateQueueWriter(FunctionalRecorderQueue)); var toEventHandlers = new MessageSender(Streamer, CreateQueueWriter(EventProcessingQueue)); var sender = new TypedMessageSender(toCommandRouter, toFunctionalRecorder); var store = new EventStore(messageStore); var quarantine = new EnvelopeQuarantine(Streamer, sender, Streaming.GetContainer(ErrorsContainer)); var builder = new CqrsEngineBuilder(Streamer, quarantine); var events = new RedirectToDynamicEvent(); var commands = new RedirectToCommand(); var funcs = new RedirectToCommand(); builder.Handle(CreateInbox(EventProcessingQueue), aem => CallHandlers(events, aem), "watch"); builder.Handle(CreateInbox(AggregateHandlerQueue), aem => CallHandlers(commands, aem)); builder.Handle(CreateInbox(RouterQueue), MakeRouter(messageStore), "watch"); // multiple service queues _serviceQueues.ForEach(s => builder.Handle(CreateInbox(s), aem => CallHandlers(funcs, aem))); builder.Handle(CreateInbox(FunctionalRecorderQueue), aem => RecordFunctionalEvent(aem, messageStore)); var viewDocs = CreateDocs(ViewStrategy); var stateDocs = new NuclearStorage(CreateDocs(DocStrategy)); var vector = new DomainIdentityGenerator(stateDocs); //var ops = new StreamOps(Streaming); var projections = new ProjectionsConsumingOneBoundedContext(); // Domain Bounded Context DomainBoundedContext.EntityApplicationServices(viewDocs, store, vector).ForEach(commands.WireToWhen); DomainBoundedContext.FuncApplicationServices().ForEach(funcs.WireToWhen); DomainBoundedContext.Ports(sender).ForEach(events.WireToWhen); DomainBoundedContext.Tasks(sender, viewDocs, true).ForEach(builder.AddTask); projections.RegisterFactory(DomainBoundedContext.Projections); // Client Bounded Context projections.RegisterFactory(ClientBoundedContext.Projections); // wire all projections projections.BuildFor(viewDocs).ForEach(events.WireToWhen); // wire in event store publisher var publisher = new MessageStorePublisher(messageStore, toEventHandlers, stateDocs, DoWePublishThisRecord); builder.AddTask(c => Task.Factory.StartNew(() => publisher.Run(c))); return(new Container { Builder = builder, Setup = this, SendToCommandRouter = toCommandRouter, MessageStore = messageStore, ProjectionFactories = projections, ViewDocs = viewDocs, Publisher = publisher, AppendOnlyStore = appendOnlyStore }); }
static void Main(string[] args) { const string integrationPath = @"temp"; ConfigureObserver(); var config = FileStorage.CreateConfig(integrationPath, "files"); var demoMessages = new List <ISampleMessage>(); var currentProcess = Process.GetCurrentProcess(); demoMessages.Add(new InstanceStarted("Inject git rev", currentProcess.ProcessName, currentProcess.Id.ToString())); { // wipe all folders config.Reset(); Console.WriteLine("Starting in funny mode"); var security = new SecurityId(0); demoMessages.Add(new CreateSecurityAggregate(security)); demoMessages.Add(new AddSecurityPassword(security, "Rinat Abdullin", "*****@*****.**", "password")); demoMessages.Add(new AddSecurityIdentity(security, "Rinat's Open ID", "http://abdullin.myopenid.org")); demoMessages.Add(new AddSecurityKey(security, "some key")); } var atomic = config.CreateNuclear(new DocumentStrategy()); var identity = new IdentityGenerator(atomic); var streamer = Contracts.CreateStreamer(); var tapes = config.CreateTape(Topology.TapesContainer); var streaming = config.CreateStreaming(); var routerQueue = config.CreateQueueWriter(Topology.RouterQueue); var aggregates = new AggregateFactory(tapes, streamer, routerQueue, atomic, identity); var sender = new SimpleMessageSender(streamer, routerQueue); var flow = new MessageSender(sender); var builder = new CqrsEngineBuilder(streamer); builder.Handle(config.CreateInbox(Topology.RouterQueue), Topology.Route(config.CreateQueueWriter, streamer, tapes), "router"); builder.Handle(config.CreateInbox(Topology.EntityQueue), aggregates.Dispatch); var functions = new RedirectToDynamicEvent(); // documents //functions.WireToWhen(new RegistrationUniquenessProjection(atomic.Factory.GetEntityWriter<unit, RegistrationUniquenessDocument>())); // UI projections var projectionStore = config.CreateNuclear(new ProjectionStrategy()); foreach (var projection in BootstrapProjections.BuildProjectionsWithWhenConvention(projectionStore.Factory)) { functions.WireToWhen(projection); } // processes //functions.WireToWhen(new BillingProcess(flow)); //functions.WireToWhen(new RegistrationProcess(flow)); functions.WireToWhen(new ReplicationProcess(flow)); builder.Handle(config.CreateInbox(Topology.EventsQueue), aem => CallHandlers(functions, aem)); var timer = new StreamingTimerService(config.CreateQueueWriter(Topology.RouterQueue), streaming.GetContainer(Topology.FutureMessagesContainer), streamer); builder.Handle(config.CreateInbox(Topology.TimerQueue), timer.PutMessage); builder.AddProcess(timer); using (var cts = new CancellationTokenSource()) using (var engine = builder.Build()) { var task = engine.Start(cts.Token); foreach (var sampleMessage in demoMessages) { sender.SendOne(sampleMessage); } Console.WriteLine(@"Press enter to stop"); Console.ReadLine(); cts.Cancel(); if (task.Wait(5000)) { Console.WriteLine(@"Terminating"); } } }