public static void SetReadModelTrackingTo(this DbContext db,
                                                  long toEventId,
                                                  params object[] addForProjectors)
        {
            // forward all existing read model tracking
            foreach (var readModelInfo in db.Set <ReadModelInfo>())
            {
                readModelInfo.CurrentAsOfEventId = toEventId;
            }

            foreach (var projector in addForProjectors)
            {
                var projectorName = ReadModelInfo.NameForProjector(projector);

                db.Set <ReadModelInfo>().AddOrUpdate(
                    i => i.Name,
                    new ReadModelInfo
                {
                    Name = projectorName,
                    CurrentAsOfEventId = toEventId
                });
            }

            db.SaveChanges();
        }
Beispiel #2
0
        public async Task Database_command_timeouts_during_catchup_do_not_interrupt_catchup()
        {
            // reset read model tracking to 0
            ReadModelDbContext().DisposeAfter(c =>
            {
                var projectorName = ReadModelInfo.NameForProjector(new Projector <Order.CustomerInfoChanged>());
                c.Set <ReadModelInfo>()
                .SingleOrDefault(i => i.Name == projectorName)
                .IfNotNull()
                .ThenDo(i => { i.CurrentAsOfEventId = 0; });
                c.SaveChanges();
            });

            var exceptions = new Stack <Exception>(Enumerable.Range(1, 2)
                                                   .Select(_ => new InvalidOperationException("Invalid attempt to call IsDBNull when reader is closed.")));

            var count       = 0;
            var flakyEvents = new FlakyEventStream(
                Enumerable.Range(1, 1000)
                .Select(i => new StorableEvent
            {
                AggregateId = Any.Guid(),
                Body        = new Order.CustomerInfoChanged {
                    CustomerName = i.ToString()
                }.ToJson(),
                SequenceNumber = i,
                StreamName     = typeof(Order).Name,
                Timestamp      = DateTimeOffset.Now,
                Type           = typeof(Order.CustomerInfoChanged).Name,
                Id             = i
            }).ToArray(),
                startFlakingOnEnumeratorNumber: 2,
                doSomethingFlaky: i =>
            {
                if (count++ > 50)
                {
                    count = 0;
                    if (exceptions.Any())
                    {
                        throw exceptions.Pop();
                    }
                }
            });

            var names = new HashSet <string>();

            var projector = new Projector <Order.CustomerInfoChanged>
            {
                OnUpdate = (work, e) => names.Add(e.CustomerName)
            };

            using (var catchup = CreateReadModelCatchup(projector))
            {
                await catchup.Run();
            }

            projector.CallCount.Should().Be(1000);
            names.Count.Should().Be(1000);
        }
Beispiel #3
0
        /// <summary>
        /// 功能测试
        /// </summary>
        public void Testing()
        {
            ReadModelInfo RMI = new ReadModelInfo();

            RMI.Main(iSwApp);

            //Model mdl = new Model(iSwApp, "", "",0,null);
            //mdl.model2 = (ModelDoc2)iSwApp.ActiveDoc;
            //mdl.checkModel();


            return;
        }
Beispiel #4
0
        public async Task When_initial_catchup_has_completed_then_time_elapsed_does_not_increases_as_time_passes()
        {
            var startTime = DateTimeOffset.Parse("2016-01-01 12:00am +00:00");

            var readModelInfo = new ReadModelInfo
            {
                InitialCatchupStartTime = startTime,
                InitialCatchupEndTime   = startTime.AddHours(52),
                BatchRemainingEvents    = 1000
            };

            new EventHandlerProgress(readModelInfo, startTime.AddDays(4))
            .InitialCatchupTimeElapsed
            .Should()
            .Be(52.Hours());
        }
        public void Rolling_catchup_can_be_run_based_on_event_store_polling()
        {
            var numberOfEvents = 50;

            Console.WriteLine("writing " + numberOfEvents + " starting at " + HighestEventId);

            // start the catchup in polling mode
            Projector <Order.ItemAdded> projector = null;
            var reading = Task.Run(() =>
            {
                projector = new Projector <Order.ItemAdded>(() => new ReadModels1DbContext());
                using (var catchup = CreateReadModelCatchup <ReadModels1DbContext>(projector).PollEventStore())
                {
                    catchup.Progress
                    .Do(s => Console.WriteLine(s))
                    .FirstAsync(s => s.IsEndOfBatch && s.CurrentEventId == numberOfEvents + HighestEventId)
                    .Timeout(DefaultTimeout)
                    .Wait();
                }
            });

            // now start writing a bunch of new events
            var writing = Task.Run(() => Enumerable.Range(1, numberOfEvents).ForEach(_ =>
            {
                // add a little variation into the intervals at which new events are written
                Thread.Sleep(Any.PositiveInt(1000));
                Events.Write(1);
            }));

            writing.Wait();
            reading.Wait();

            using (var db = new ReadModels1DbContext())
            {
                var readModelInfoName = ReadModelInfo.NameForProjector(projector);
                db.Set <ReadModelInfo>()
                .Single(i => i.Name == readModelInfoName)
                .CurrentAsOfEventId
                .Should()
                .Be(HighestEventId + numberOfEvents);
            }
        }
        public void Events_committed_to_the_event_store_are_caught_up_by_multiple_independent_read_model_stores()
        {
            var productName = Any.Paragraph(4);

            var projector1 = new Projector <Order.ItemAdded>(() => new ReadModels1DbContext())
            {
                OnUpdate = (work, e) => new ReadModels1DbContext().DisposeAfter(db => UpdateReservedInventory(db, e))
            };
            var projector2 = new Projector <Order.ItemAdded>(() => new ReadModels2DbContext())
            {
                OnUpdate = (work, e) => new ReadModels2DbContext().DisposeAfter(db => UpdateReservedInventory(db, e))
            };
            var numberOfEvents = Any.Int(10, 50);

            using (var disposables = new CompositeDisposable())
                using (var catchup1 = CreateReadModelCatchup <ReadModels1DbContext>(projector1))
                    using (var catchup2 = CreateReadModelCatchup <ReadModels2DbContext>(projector2))
                    {
                        catchup1.Progress.ForEachAsync(p => Console.WriteLine("catchup1: " + p));
                        catchup2.Progress.ForEachAsync(p => Console.WriteLine("catchup2: " + p));

                        Action <string, ThreadStart> startThread =
                            (name, start) =>
                        {
                            var thread = new Thread(() =>
                            {
                                Console.WriteLine("starting thread (" + Thread.CurrentThread.ManagedThreadId + ")");
                                start();
                                Console.WriteLine("ended thread (" + Thread.CurrentThread.ManagedThreadId + ")");
                            });
                            thread.Name = name;
                            thread.Start();
                            disposables.Add(Disposable.Create(thread.Abort));
                        };

                        Events.Write(numberOfEvents, i => new Order.ItemAdded
                        {
                            ProductName = productName,
                            Quantity    = 1,
                            AggregateId = Any.Guid()
                        });

                        // TODO: (Events_committed_to_the_event_store_are_caught_up_by_multiple_independent_read_model_stores) is this leading to intermittent test failures by leaving a dangling app lock?
                        startThread("catchup1", () =>
                        {
                            catchup1.Run();
                            catchup1.Dispose();
                        });
                        startThread("catchup2", () =>
                        {
                            catchup2.Run();
                            catchup2.Dispose();
                        });

                        Console.WriteLine("Waiting on catchups to complete");

                        // wait on both catchups to complete
                        catchup1
                        .Progress
                        .Merge(catchup2.Progress)
                        .Where(p => p.IsEndOfBatch)
                        .Take(2)
                        .Timeout(DefaultTimeout)
                        .Wait();
                    }

            Action <DbContext> verify = db =>
            {
                var readModelInfoName = ReadModelInfo.NameForProjector(projector1);

                var readModelInfos = db.Set <ReadModelInfo>();
                Console.WriteLine(new { readModelInfos }.ToLogString());
                readModelInfos
                .Single(i => i.Name == readModelInfoName)
                .CurrentAsOfEventId
                .Should()
                .Be(HighestEventId + numberOfEvents);

                var productInventories = db.Set <ProductInventory>();
                Console.WriteLine(new { productInventories }.ToLogString());
                productInventories
                .Single(pi => pi.ProductName == productName)
                .QuantityReserved
                .Should()
                .Be(numberOfEvents);
            };

            Console.WriteLine("verifying ReadModels1DbContext...");
            new ReadModels1DbContext().DisposeAfter(r => verify(r));

            Console.WriteLine("verifying ReadModels2DbContext...");
            new ReadModels2DbContext().DisposeAfter(r => verify(r));
        }
Beispiel #7
0
        public async Task Insertion_of_new_events_during_catchup_does_not_interrupt_catchup()
        {
            var barrier = new Barrier(2);

            // preload some events for the catchup. replay will hit the barrier on the last one.
            var    order    = new Order();
            Action addEvent = () => order.Apply(new AddItem
            {
                Quantity    = 1,
                ProductName = "Penny candy",
                Price       = .01m
            });

            Enumerable.Range(1, 100).ForEach(_ => addEvent());
            var repository = new SqlEventSourcedRepository <Order>(new FakeEventBus());
            await repository.Save(order);

            // queue the catchup on a background task
#pragma warning disable 4014
            // don't await
            Task.Run(() =>
#pragma warning restore 4014
            {
                var projector = new Projector1
                {
                    OnUpdate = (work, e) =>
                    {
                        if (e.SequenceNumber == 10)
                        {
                            Console.WriteLine("pausing read model catchup");
                            barrier.SignalAndWait(MaxWaitTime); //1
                            barrier.SignalAndWait(MaxWaitTime); //2
                            Console.WriteLine("resuming read model catchup");
                        }
                    }
                };

                using (var db = EventStoreDbContext())
                    using (var catchup = CreateReadModelCatchup(projector))
                    {
                        var events = db.Events.Where(e => e.Id > HighestEventId);
                        Console.WriteLine(string.Format("starting read model catchup for {0} events", events.Count()));
                        catchup.Run().Wait();
                        Console.WriteLine("done with read model catchup");
                        barrier.SignalAndWait(MaxWaitTime); //3
                    }
            });

            Console.WriteLine("queued read model catchup task");
            barrier.SignalAndWait(MaxWaitTime); //1

            EventStoreDbContext().DisposeAfter(c =>
            {
                Console.WriteLine("adding one more event, bypassing read model tracking");
                c.Events.Add(new Order.ItemAdded
                {
                    AggregateId    = Guid.NewGuid(),
                    SequenceNumber = 1
                }.ToStorableEvent());
                c.SaveChanges();
                Console.WriteLine("done adding one more event");
            });

            barrier.SignalAndWait(MaxWaitTime); //2
            barrier.SignalAndWait(MaxWaitTime); //3

            // check that everything worked:
            var projector2    = new Projector1();
            var projectorName = ReadModelInfo.NameForProjector(projector2);
            using (var readModels = ReadModelDbContext())
            {
                var readModelInfo = readModels.Set <ReadModelInfo>().Single(i => i.Name == projectorName);

                readModelInfo.CurrentAsOfEventId.Should().Be(HighestEventId + 101);

                using (var catchup = CreateReadModelCatchup(projector2))
                {
                    await catchup.Run();
                }

                readModels.Entry(readModelInfo).Reload();
                readModelInfo.CurrentAsOfEventId.Should().Be(HighestEventId + 102);
            }
        }
Beispiel #8
0
        private void RunCadCode(CADTaskCode code)
        {
            switch (code.CadCodeId)
            {
            case Const.CAD_MSG_OPEN_MODEL:
            {
                System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
                stopwatch.Start();
                //
                Model mdl = new Model(iSwApp, code.Para1, string.Empty);
                mdl.OpenModel();

                stopwatch.Stop();
                WriteLog("打开模型耗时:" + stopwatch.ElapsedTicks.ToString(), 2);
            }
            break;

            case Const.CAD_MSG_GET_CFGS:
            {
                //CADCFGS cfgs;
                //cfgs.nModelID = _wtoi(stuComm.m_pstrPC_PARA1);
                //res = ::SendMessage (m_wndCad,nCadRunMessage,CAD_MSG_GET_CFGS,LPARAM(&cfgs));
                //if(!res) return FALSE;

                //ArrayToString2(cfgs.arrayCfgs,stuComm.m_pstrPC_PARA2);
            }
            break;

            case Const.CAD_MSG_GET_ITEMS:
            {
                System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
                stopwatch.Start();

                String        resault = string.Empty;
                ReadModelInfo RMI     = new ReadModelInfo();

                if (code.Para2 == "2")
                {
                    //读取模型中的尺寸列表
                    resault = RMI.getdimlist(iSwApp, null);
                }
                else if (code.Para2 == "4")
                {
                    //读取模型中的特征列表
                    resault = RMI.getFeatureList(iSwApp, null);
                }
                else if (code.Para2 == "5")
                {
                    //读取模型中的零部件列表
                    resault = RMI.getFeatureList(iSwApp, null);
                }
                else if (code.Para2 == "50")
                {
                    //图层列表
                    resault = string.Empty;
                }
                code.Para3 = resault;
                stopwatch.Stop();
                WriteLog(string.Format("读取模型属性{0}耗时:{1}", code.Para2, stopwatch.ElapsedTicks.ToString()), 2);
            }
            break;

            default:
                break;
            }
        }