コード例 #1
0
 public bool OnPong()
 {
     using (locker.CreateLock())
     {
         if (current == null)
         {
             return(false);
         }
         current.Pong();
         last    = current;
         current = null;
         return(true);
     }
 }
        public void Repo_Should_Failed_To_Updated_Aggregate_When_Used_NonSequentialy_WithOut_Protection_By_Two_Thread()
        {
            /// Arrange
            var param1               = GetArg(1);
            var param2               = GetArg(2);
            var aggregate            = _repo.GetNewAggregate();
            var processElemCreation1 = new FirstSubProcess(param1.ProcessName, param1.ExpectedProcessId, param1.ExpectedDateCreated);
            var processElemCreation2 = new FirstSubProcess(param2.ProcessName, param2.ExpectedProcessId, param2.ExpectedDateCreated);
            var pingPong             = new PingPong();
            var mre3 = new ManualResetEvent(false);

            void DoNothing()
            {
                return;
            }

            Action finalAction = DoNothing;

            void Thread1Work()
            {
                Thread.CurrentThread.Name = "Thread1Work";
                var _aggregate1 = _repo.GetById(param1.ExpectedStreamId);

                pingPong.WaitPing();
                _aggregate1.RaiseEvent(new ProcessElementEntityCreated(param1.ExpectedStreamId, processElemCreation1));
                _aggregate1.RaiseEvent(new ProcessElemStarted(param1.ExpectedStreamId, param1.ExpectedProcessId,
                                                              param1.ExpectedRunningService, param1.ExpectedDateStarted));
                _repo.Save(_aggregate1);
                pingPong.Ping();
                _aggregate1.RaiseEvent(new ProcessElemStoped(param1.ExpectedStreamId, param1.ExpectedProcessId, param1.ExpectedDateStoped));
                _repo.Save(_aggregate1);
                pingPong.SetOnlyPong();
            }

            void Thread2Work()
            {
                Thread.CurrentThread.Name = "Thread2Work";
                var _aggregate2 = _repo.GetById(param1.ExpectedStreamId);

                pingPong.WaitPong();
                _aggregate2.RaiseEvent(new ProcessElementEntityCreated(param2.ExpectedStreamId, processElemCreation2));
                _aggregate2.RaiseEvent(new ProcessElemStarted(param2.ExpectedStreamId, param2.ExpectedProcessId,
                                                              param2.ExpectedRunningService, param2.ExpectedDateStarted));
                pingPong.Pong();
                _aggregate2.RaiseEvent(new ProcessElemStoped(param2.ExpectedStreamId, param2.ExpectedProcessId, param2.ExpectedDateStoped));
                _repo.Save(_aggregate2);
            }

            void finalTask(Task t)
            {
                if (t.IsFaulted)
                {
                    var ex = t.Exception;
                    finalAction = () => throw ex;
                }
                mre3.Set();
            }

            // Act
            aggregate.RaiseEvent(new InputAggregateCreated(param1.ExpectedStreamId));
            _repo.Save(aggregate);
            var t1    = Task.Factory.StartNew(Thread1Work);
            var t2    = Task.Factory.StartNew(Thread2Work);
            var tasks = new[] { t1, t2 };

            Task.WhenAll(tasks).ContinueWith(finalTask);
            mre3.WaitOne();
            /// Assert
            var _aggregate = _repo.GetById(param1.ExpectedStreamId);

            _aggregate.GetProcessElementById(param1.ExpectedProcessId).ShouldBeAsExpected(param1);
            finalAction.Should().Throw <AggregateException>();
        }
        public void Repo_Should_Rollback_Save_If_Not_on_The_Rigth_Version()
        {
            /// Arrange
            var param1               = GetArg(1);
            var param2               = GetArg(2);
            var aggregate            = _repo.GetNewAggregate();
            var processElemCreation1 = new FirstSubProcess(param1.ProcessName, param1.ExpectedProcessId, param1.ExpectedDateCreated);
            var processElemCreation2 = new FirstSubProcess(param2.ProcessName, param2.ExpectedProcessId, param2.ExpectedDateCreated);
            var pingPong             = new PingPong();
            var mre3 = new ManualResetEvent(false);
            var firstThreadFirstTaskHaveBeenRollbacked  = false;
            var firstThreadSecondTaskHaveBeenRollbacked = false;
            var secondThreadFirstTaskHaveBeenRollbacked = false;

            void DoNothing()
            {
                return;
            }

            Action finalAction = DoNothing;

            void Thread1Work()
            {
                Thread.CurrentThread.Name = "Thread1Work";
                var _aggregate1 = _repo.GetById(param1.ExpectedStreamId);

                using (var uow1 = new BasicUnitOfWork <InputAggregate, int>())
                {
                    uow1.OnRollback += () => firstThreadFirstTaskHaveBeenRollbacked = true;
                    pingPong.WaitPing();
                    _aggregate1.RaiseEvent(new ProcessElementEntityCreated(param1.ExpectedStreamId, processElemCreation1));
                    _aggregate1.RaiseEvent(new ProcessElemStarted(param1.ExpectedStreamId, param1.ExpectedProcessId,
                                                                  param1.ExpectedRunningService, param1.ExpectedDateStarted));
                    _aggregate1 = _saver.Save(_aggregate1, uow1);
                }
                pingPong.Ping();
                using (var uow2 = new BasicUnitOfWork <InputAggregate, int>())
                {
                    uow2.OnRollback += () => firstThreadSecondTaskHaveBeenRollbacked = true;
                    _aggregate1.RaiseEvent(new ProcessElemStoped(param1.ExpectedStreamId, param1.ExpectedProcessId, param1.ExpectedDateStoped));
                    _aggregate1 = _saver.Save(_aggregate1, uow2);
                }
                pingPong.SetOnlyPong();
            }

            void Thread2Work()
            {
                Thread.CurrentThread.Name = "Thread2Work";
                var _aggregate2 = _repo.GetById(param1.ExpectedStreamId);

                using (var uow1 = new BasicUnitOfWork <InputAggregate, int>())
                {
                    uow1.OnRollback += () => secondThreadFirstTaskHaveBeenRollbacked = true;
                    pingPong.WaitPong();
                    _aggregate2.RaiseEvent(new ProcessElementEntityCreated(param2.ExpectedStreamId, processElemCreation2));
                    _aggregate2.RaiseEvent(new ProcessElemStarted(param2.ExpectedStreamId, param2.ExpectedProcessId,
                                                                  param2.ExpectedRunningService, param2.ExpectedDateStarted));
                    pingPong.Pong();
                    _aggregate2.RaiseEvent(new ProcessElemStoped(param2.ExpectedStreamId, param2.ExpectedProcessId, param2.ExpectedDateStoped));
                    _aggregate2 = _saver.Save(_aggregate2, uow1);
                }
            }

            void finalTask(Task t)
            {
                if (t.IsFaulted)
                {
                    var ex = t.Exception;
                    finalAction = () => throw ex;
                }
                mre3.Set();
            }

            // Act
            aggregate.RaiseEvent(new InputAggregateCreated(param1.ExpectedStreamId));
            _repo.Save(aggregate);
            var t1    = Task.Factory.StartNew(Thread1Work);
            var t2    = Task.Factory.StartNew(Thread2Work);
            var tasks = new[] { t1, t2 };

            Task.WhenAll(tasks).ContinueWith(finalTask);
            mre3.WaitOne();
            /// Assert
            var _aggregate = _repo.GetById(param1.ExpectedStreamId);

            _aggregate.GetProcessElementById(param1.ExpectedProcessId).ShouldBeAsExpected(param1);
            _aggregate.GetProcessElementById(param2.ExpectedProcessId).Should().BeNull();
            finalAction.Should().NotThrow();
            firstThreadFirstTaskHaveBeenRollbacked.Should().BeFalse();
            firstThreadSecondTaskHaveBeenRollbacked.Should().BeFalse();
            secondThreadFirstTaskHaveBeenRollbacked.Should().BeTrue();
        }