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 }); }
public static void Rebuild(IDocumentStore targetContainer, ITapeStream stream) { var strategy = targetContainer.Strategy; var memory = new MemoryStorageConfig(); var memoryContainer = memory.CreateNuclear(strategy).Container; var tracked = new ProjectionInspectingContainer(memoryContainer); var projections = new List <object>(); projections.AddRange(DomainBoundedContext.Projections(tracked)); projections.AddRange(ClientBoundedContext.Projections(tracked)); //projections.AddRange(ApiOpsBoundedContext.Projections(tracked)); if (tracked.Buckets.Count != projections.Count()) { throw new InvalidOperationException("Count mismatch"); } var storage = new NuclearStorage(targetContainer); var hashes = storage.GetSingletonOrNew <ProjectionHash>().Entries; var memoryProjections = projections.Select((projection, i) => { var bucketName = tracked.Buckets[i]; var viewType = tracked.Views[i]; var projectionHash = GetClassHash(projection.GetType()) + "\r\n" + GetClassHash(viewType); bool needsRebuild = !hashes.ContainsKey(bucketName) || hashes[bucketName] != projectionHash; return(new { bucketName, projection, hash = projectionHash, needsRebuild }); }).ToArray(); foreach (var memoryProjection in memoryProjections) { if (memoryProjection.needsRebuild) { SystemObserver.Notify("[warn] {0} needs rebuild", memoryProjection.bucketName); } else { SystemObserver.Notify("[good] {0} is up-to-date", memoryProjection.bucketName); } } var needRebuild = memoryProjections.Where(x => x.needsRebuild).ToArray(); if (needRebuild.Length == 0) { return; } var watch = Stopwatch.StartNew(); var wire = new RedirectToDynamicEvent(); needRebuild.ForEach(x => wire.WireToWhen(x.projection)); var handlersWatch = Stopwatch.StartNew(); Observe(stream, wire); var timeTotal = watch.Elapsed.TotalSeconds; var handlerTicks = handlersWatch.ElapsedTicks; var timeInHandlers = Math.Round(TimeSpan.FromTicks(handlerTicks).TotalSeconds, 1); Console.WriteLine("Total Elapsed: {0}sec ({1}sec in handlers)", Math.Round(timeTotal, 0), timeInHandlers); // delete projections that were rebuilt var bucketNames = needRebuild.Select(x => x.bucketName).ToArray(); foreach (var name in bucketNames) { targetContainer.Reset(name); var contents = memoryContainer.EnumerateContents(name); targetContainer.WriteContents(name, contents); } var allBuckets = new HashSet <string>(memoryProjections.Select(p => p.bucketName)); var obsolete = hashes.Keys.Where(s => !allBuckets.Contains(s)).ToArray(); foreach (var name in obsolete) { SystemObserver.Notify("[warn] {0} is obsolete", name); targetContainer.Reset(name); } storage.UpdateSingletonEnforcingNew <ProjectionHash>(x => { x.Entries.Clear(); foreach (var prj in memoryProjections) { x.Entries[prj.bucketName] = prj.hash; } }); }