public async Task When_a_duplicate_messages_starting_a_saga_arrive_sequentially_one_of_them_fails()
        {
            var context  = CreateMessageContext();
            var sagaData = CreateNewSagaData();

            var transaction1 = await outboxPersister.BeginTransaction(context);

            var session1 = new OutboxEventStoreSynchronizedStorageSession(connection, (EventStoreOutboxTransaction)transaction1);
            await persister.Save(sagaData, new SagaCorrelationProperty(CorrelationPropName, sagaData.StringProperty), session1, context);

            await transaction1.Commit();

            var transaction2 = await outboxPersister.BeginTransaction(context);

            var session2   = new OutboxEventStoreSynchronizedStorageSession(connection, (EventStoreOutboxTransaction)transaction2);
            var loadedData = await persister.Get <SagaData>(CorrelationPropName, sagaData.StringProperty, session2, context);

            await persister.Update(loadedData, session2, context);

            try
            {
                await transaction2.Commit();

                Assert.Fail("Expected exception");
            }
            catch (Exception ex)
            {
                StringAssert.StartsWith("Append failed due to WrongExpectedVersion.", ex.Message);
            }
        }
        public void Update_DbChangedEntityWithRowVersion_ShouldSaveSaga()
        {
            // arrange
            TestSagaDataWithRowVersion newSagaData = AddSagaWithRowVersion();
            string expectedSomeProp1 = Guid.NewGuid().ToString();
            string expectedSomeProp2 = Guid.NewGuid().ToString();

            var persisterRetrievedSagaData = _persister.Get <TestSagaDataWithRowVersion>(newSagaData.Id);

            // simulates another worker updating the saga after "this" saga retrieves it's saga
            using (var dbc = new TestDbContext())
            {
                var fromDb = dbc.TestSagasWithRowVersion.Find(newSagaData.Id);
                fromDb.SomeProp1 = expectedSomeProp1;
                dbc.SaveChanges();
            }

            // act
            persisterRetrievedSagaData.SomeProp2 = expectedSomeProp2;
            _persister.Update(persisterRetrievedSagaData);

            // assert
            using (var dbc = new TestDbContext())
            {
                var fromDb = dbc.TestSagasWithRowVersion.Find(newSagaData.Id);

                fromDb.Id.Should().Be(newSagaData.Id);
                fromDb.OriginalMessageId.Should().Be(newSagaData.OriginalMessageId);
                fromDb.Originator.Should().Be(newSagaData.Originator);

                fromDb.SomeProp1.Should().Be(expectedSomeProp1);
                fromDb.SomeProp2.Should().Be(expectedSomeProp2);
            }
        }
        public async Task When_a_duplicate_messages_starting_a_saga_arrive_sequentially_both_succeed()
        {
            var context  = CreateMessageContext();
            var sagaData = CreateNewSagaData();

            var session1 = new EventStoreSynchronizedStorageSession(connection);
            await persister.Save(sagaData, new SagaCorrelationProperty(CorrelationPropName, sagaData.StringProperty), session1, context);

            var session2   = new EventStoreSynchronizedStorageSession(connection);
            var loadedData = await persister.Get <SagaData>(CorrelationPropName, sagaData.StringProperty, session2, context);

            await persister.Update(loadedData, session2, context);
        }
Beispiel #4
0
        public async Task It_should_persist_successfully()
        {
            var saga = new SagaData
            {
                Id       = Guid.NewGuid(),
                SomeId   = "test-id",
                SomeName = "Test Name"
            };

            IDocumentSession session;
            var context = this.CreateContextWithSessionPresent(out session);

            var sagaPersister = new SagaPersister();
            var synchronizedStorageSession = new MartenSynchronizedStorageSession(session, true);


            await sagaPersister.Save(saga, new SagaCorrelationProperty("SomeId", saga.SomeId), synchronizedStorageSession, context);

            await session.SaveChangesAsync().ConfigureAwait(false);

            var savedSaga = await sagaPersister.Get <SagaData>(saga.Id, synchronizedStorageSession, context);

            savedSaga.SomeName = "Another name";

            await sagaPersister.Update(saga, synchronizedStorageSession, context);

            await session.SaveChangesAsync().ConfigureAwait(false);

            var updatedSaga = await sagaPersister.Get <SagaData>(saga.Id, synchronizedStorageSession, context);

            updatedSaga.SomeName.Should().Be("Another name");
        }
    public async Task It_should_persist_successfully()
    {
        IAsyncDocumentSession session;
        var options      = this.CreateContextWithAsyncSessionPresent(out session);
        var persister    = new SagaPersister();
        var uniqueString = Guid.NewGuid().ToString();

        var saga1 = new SagaData
        {
            Id              = Guid.NewGuid(),
            UniqueString    = uniqueString,
            NonUniqueString = "notUnique"
        };

        var synchronizedSession = new RavenDBSynchronizedStorageSession(session, true);

        await persister.Save(saga1, this.CreateMetadata <SomeSaga>(saga1), synchronizedSession, options);

        await session.SaveChangesAsync().ConfigureAwait(false);

        var saga = await persister.Get <SagaData>(saga1.Id, synchronizedSession, options);

        saga.NonUniqueString = "notUnique2";
        await persister.Update(saga, synchronizedSession, options);

        await session.SaveChangesAsync().ConfigureAwait(false);
    }
Beispiel #6
0
    public async Task It_should_persist_successfully()
    {
        using (var session = store.OpenAsyncSession().UsingOptimisticConcurrency().InContext(out var options))
        {
            var persister           = new SagaPersister();
            var uniqueString        = Guid.NewGuid().ToString();
            var anotherUniqueString = Guid.NewGuid().ToString();

            var saga1 = new SagaData
            {
                Id              = Guid.NewGuid(),
                UniqueString    = uniqueString,
                NonUniqueString = "notUnique"
            };

            var synchronizedSession = new RavenDBSynchronizedStorageSession(session);

            await persister.Save(saga1, this.CreateMetadata <SomeSaga>(saga1), synchronizedSession, options);

            await session.SaveChangesAsync().ConfigureAwait(false);

            var saga = await persister.Get <SagaData>(saga1.Id, synchronizedSession, options);

            saga.NonUniqueString = "notUnique2";
            saga.UniqueString    = anotherUniqueString;
            await persister.Update(saga, synchronizedSession, options);

            await session.SaveChangesAsync().ConfigureAwait(false);
        }
    }
    public void It_should_allow_the_update()
    {
        var factory = new RavenSessionFactory(store);
        factory.ReleaseSession();
        var persister = new SagaPersister(factory);
        var uniqueString = Guid.NewGuid().ToString();
        var saga1 = new SagaData
            {
                Id = Guid.NewGuid(),
                UniqueString = uniqueString
            };

        persister.Save(saga1);
        factory.SaveChanges();
        factory.ReleaseSession();

        var saga = persister.Get<SagaData>(saga1.Id);
        saga.UniqueString = Guid.NewGuid().ToString();
        persister.Update(saga);
        factory.SaveChanges();
        factory.ReleaseSession();

        var saga2 = new SagaData
            {
                Id = Guid.NewGuid(),
                UniqueString = uniqueString
            };

        //this should not blow since we changed the unique value in the previous saga
        persister.Save(saga2);
        factory.SaveChanges();
    }
    public void It_should_persist_successfully()
    {
        using (var store = DocumentStoreBuilder.Build())
        {
            var factory = new RavenSessionFactory(store);
            factory.ReleaseSession();
            var persister           = new SagaPersister(factory);
            var uniqueString        = Guid.NewGuid().ToString();
            var anotherUniqueString = Guid.NewGuid().ToString();

            var saga1 = new SagaData
            {
                Id              = Guid.NewGuid(),
                UniqueString    = uniqueString,
                NonUniqueString = "notUnique"
            };
            persister.Save(saga1);
            factory.SaveChanges();

            var saga = persister.Get <SagaData>(saga1.Id);
            saga.NonUniqueString = "notUnique2";
            saga.UniqueString    = anotherUniqueString;
            persister.Update(saga);
            factory.SaveChanges();
        }
    }
    public void It_should_allow_the_update()
    {
        using (var store = DocumentStoreBuilder.Build())
        {
            var factory = new RavenSessionFactory(store);
            factory.ReleaseSession();
            var persister    = new SagaPersister(factory);
            var uniqueString = Guid.NewGuid().ToString();
            var saga1        = new SagaData
            {
                Id           = Guid.NewGuid(),
                UniqueString = uniqueString
            };

            persister.Save(saga1);
            factory.SaveChanges();
            factory.ReleaseSession();

            var saga = persister.Get <SagaData>(saga1.Id);
            saga.UniqueString = Guid.NewGuid().ToString();
            persister.Update(saga);
            factory.SaveChanges();
            factory.ReleaseSession();

            var saga2 = new SagaData
            {
                Id           = Guid.NewGuid(),
                UniqueString = uniqueString
            };

            //this should not blow since we changed the unique value in the previous saga
            persister.Save(saga2);
            factory.SaveChanges();
        }
    }
        public void Update_NullSaga_Throws()
        {
            // arrange
            // act
            Action action = () => _persister.Update(null);

            // assert
            action.ShouldThrow <ArgumentNullException>()
            .WithMessage("*saga*");
        }
Beispiel #11
0
        public void an_sagaEntity()
        {
            ((SagaEntityA)_sagaEntityA).SomeIdentifier = A_NEW_VALUE;
            SagaPersister.Update(_sagaEntityA);
            SagaPersister.DocumentSessionFactory.Current.SaveChanges();

            var loadedUpdatedSagaEntity = SagaPersister.Get <SagaEntityA>(_sagaEntityA.Id);

            Assert.That(loadedUpdatedSagaEntity.Id, Is.EqualTo(_sagaEntityA.Id));
            Assert.That(loadedUpdatedSagaEntity.SomeIdentifier, Is.EqualTo(A_NEW_VALUE));
        }
Beispiel #12
0
        public void should_also_update_its_unique_property_entity()
        {
            var saga3 = SagaPersister.Get <SagaEntityWithUniqueProperty>(Saga3.Id);

            saga3.ThisShouldBeUnique = UNIQUE_VALUE_FOUR;

            SagaPersister.Update(saga3);
            SagaPersister.DocumentSessionFactory.Current.SaveChanges();

            var persistedUniqueProperty = SagaPersister.DocumentSessionFactory.Current
                                          .Query <NServiceBus.SagaPersisters.RavenDB.UniqueProperty>()
                                          .Customize(x => x.WaitForNonStaleResults())
                                          .Where(p => p.SagaId == Saga3.Id)
                                          .SingleOrDefault();

            Assert.That(persistedUniqueProperty.Value, Is.EqualTo(UNIQUE_VALUE_FOUR));
        }
Beispiel #13
0
    public void It_should_set_the_attribute_and_allow_the_update()
    {
        using (var store = DocumentStoreBuilder.Build())
        {
            var factory = new RavenSessionFactory(store);
            factory.ReleaseSession();
            var persister    = new SagaPersister(factory);
            var uniqueString = Guid.NewGuid().ToString();

            var anotherUniqueString = Guid.NewGuid().ToString();

            var saga1 = new SagaData
            {
                Id              = Guid.NewGuid(),
                UniqueString    = uniqueString,
                NonUniqueString = "notUnique"
            };

            persister.Save(saga1);
            factory.SaveChanges();
            factory.ReleaseSession();

            using (var session = store.OpenSession())
            {
                //fake that the attribute was just added by removing the metadata
                session.Advanced.GetMetadataFor(saga1).Remove(SagaPersister.UniqueValueMetadataKey);
                session.SaveChanges();
            }

            var saga = persister.Get <SagaData>(saga1.Id);
            saga.UniqueString = anotherUniqueString;
            persister.Update(saga);
            factory.SaveChanges();
            factory.ReleaseSession();

            using (var session = store.OpenSession())
            {
                var value = session.Advanced.GetMetadataFor(saga1)[SagaPersister.UniqueValueMetadataKey].ToString();
                Assert.AreEqual(anotherUniqueString, value);
            }
        }
    }
    public void It_should_persist_successfully()
    {
        var factory = new RavenSessionFactory(store);
        factory.ReleaseSession();
        var persister = new SagaPersister(factory);
        var uniqueString = Guid.NewGuid().ToString();

        var saga1 = new SagaData
        {
            Id = Guid.NewGuid(),
            UniqueString = uniqueString,
            NonUniqueString = "notUnique"
        };

        persister.Save(saga1);
        factory.SaveChanges();

        var saga = persister.Get<SagaData>(saga1.Id);
        saga.NonUniqueString = "notUnique2";
        persister.Update(saga);
        factory.SaveChanges();
    }
    public void It_should_set_the_attribute_and_allow_the_update()
    {
        var factory = new RavenSessionFactory(store);
        factory.ReleaseSession();
        var persister = new SagaPersister(factory);
        var uniqueString = Guid.NewGuid().ToString();

        var anotherUniqueString = Guid.NewGuid().ToString();

        var saga1 = new SagaData
            {
                Id = Guid.NewGuid(),
                UniqueString = uniqueString,
                NonUniqueString = "notUnique"
            };

        persister.Save(saga1);
        factory.SaveChanges();
        factory.ReleaseSession();

        using (var session = store.OpenSession())
        {
            //fake that the attribute was just added by removing the metadata
            session.Advanced.GetMetadataFor(saga1).Remove(SagaPersister.UniqueValueMetadataKey);
            session.SaveChanges();
        }

        var saga = persister.Get<SagaData>(saga1.Id);
        saga.UniqueString = anotherUniqueString;
        persister.Update(saga);
        factory.SaveChanges();
        factory.ReleaseSession();

        using (var session = store.OpenSession())
        {
            var value = session.Advanced.GetMetadataFor(saga1)[SagaPersister.UniqueValueMetadataKey].ToString();
            Assert.AreEqual(anotherUniqueString, value);
        }
    }
        public void Invoke(BehaviorContext context, Action next)
        {
            currentContext = context;

            activeSagaInstances = DetectSagas(context).ToList();

            foreach (var sagaInstanceState in activeSagaInstances)
            {
                var saga = sagaInstanceState.Instance;

                var loadedEntity = TryLoadSagaEntity(saga, sagaInstanceState.MessageToProcess);


                if (loadedEntity == null)
                {
                    //if this message are not allowed to start the saga
                    if (!Features.Sagas.ShouldMessageStartSaga(sagaInstanceState.SagaType,
                                                               sagaInstanceState.MessageToProcess.MessageType))
                    {
                        sagaInstanceState.MarkAsNotFound();

                        InvokeSagaNotFoundHandlers(sagaInstanceState);
                        continue;
                    }

                    sagaInstanceState.AttachNewEntity(CreateNewSagaEntity(sagaInstanceState.SagaType));
                }
                else
                {
                    sagaInstanceState.AttachExistingEntity(loadedEntity);
                }

                if (IsTimeoutMessage(sagaInstanceState.MessageToProcess))
                {
                    sagaInstanceState.Handler.Invocation = HandlerInvocationCache.InvokeTimeout;
                }
            }

            //so that other behaviors can access the sagas
            context.Set(new ActiveSagaInstances(activeSagaInstances));

            next();

            foreach (var sagaInstanceState in activeSagaInstances)
            {
                if (sagaInstanceState.NotFound)
                {
                    continue;
                }

                var saga = sagaInstanceState.Instance;

                if (saga.Completed)
                {
                    if (!sagaInstanceState.IsNew)
                    {
                        SagaPersister.Complete(saga.Entity);
                    }

                    if (saga.Entity.Id != Guid.Empty)
                    {
                        NotifyTimeoutManagerThatSagaHasCompleted(saga);
                    }

                    logger.Debug(string.Format("{0} {1} has completed.", saga.GetType().FullName, saga.Entity.Id));
                }
                else
                {
                    if (sagaInstanceState.IsNew)
                    {
                        SagaPersister.Save(saga.Entity);
                    }
                    else
                    {
                        SagaPersister.Update(saga.Entity);
                    }
                }
            }
        }
        public async Task TestStoringSagas(ConventionType seedType)
        {
            using (var db = new ReusableDB())
            {
                List<TestSagaData> sagas;

                using (var store = db.NewStore())
                {
                    ApplyPrefillConventions(store, seedType);
                    store.Initialize();

                    sagas = await Prefill(store, seedType);
                }

                using (var store = db.NewStore())
                {
                    Console.WriteLine($"Testing saga updates with DocumentStore initially configured for {seedType} conventions.");
                    ApplyTestConventions(store, seedType);
                    store.Initialize();

                    // Update each saga, once by id and once by correlation property
                    foreach (var saga in sagas)
                    {
                        var persister = new SagaPersister();
                        Console.WriteLine($"Retrieving SagaId {saga.Id} by SagaId");
                        using (var session = store.OpenAsyncSession())
                        {
                            var ravenDBSynchronizedStorageSession = new RavenDBSynchronizedStorageSession(session, false);
                            var byId = await persister.Get<TestSagaData>(saga.Id, ravenDBSynchronizedStorageSession, null);
                            Assert.IsNotNull(byId);

                            byId.Counter++;
                            await persister.Update(byId, ravenDBSynchronizedStorageSession, null);
                            await session.SaveChangesAsync();

                            Console.WriteLine($"Retrieving SagaId {saga.Id} by Correlation Property OrderId={saga.OrderId}");
                            var byOrderId = await persister.Get<TestSagaData>("OrderId", saga.OrderId, ravenDBSynchronizedStorageSession, new ContextBag());
                            Assert.IsNotNull(byOrderId);

                            byOrderId.Counter++;
                            await persister.Update(byOrderId, ravenDBSynchronizedStorageSession, null);
                            await session.SaveChangesAsync();
                        }
                    }

                    Console.WriteLine("Retrieving each saga again by SagaId and making sure Counter == 3");
                    foreach (var saga in sagas)
                    {
                        var persister = new SagaPersister();
                        using (var session = store.OpenAsyncSession())
                        {
                            Console.WriteLine($"Retrieving SagaId {saga.Id} by SagaId");
                            var byId = await persister.Get<TestSagaData>(saga.Id, new RavenDBSynchronizedStorageSession(session, false), null);
                            Assert.IsNotNull(byId);
                            Assert.AreEqual(3, byId.Counter);
                        }
                    }
                }
            }
        }
Beispiel #18
0
        public void Invoke(HandlerInvocationContext context, Action next)
        {
            var saga = context.MessageHandler.Instance as ISaga;

            if (saga == null)
            {
                next();
                return;
            }

            currentContext = context;

            var sagaInstanceState = new ActiveSagaInstance(saga);

            //so that other behaviors can access the saga
            context.Set(sagaInstanceState);

            var loadedEntity = TryLoadSagaEntity(saga, context.LogicalMessage);

            if (loadedEntity == null)
            {
                //if this message are not allowed to start the saga
                if (!Features.Sagas.ShouldMessageStartSaga(sagaInstanceState.SagaType, context.LogicalMessage.MessageType))
                {
                    sagaInstanceState.MarkAsNotFound();

                    InvokeSagaNotFoundHandlers();
                    return;
                }

                sagaInstanceState.AttachNewEntity(CreateNewSagaEntity(sagaInstanceState.SagaType));
            }
            else
            {
                sagaInstanceState.AttachExistingEntity(loadedEntity);
            }


            if (IsTimeoutMessage(context.LogicalMessage))
            {
                context.MessageHandler.Invocation = HandlerInvocationCache.InvokeTimeout;
            }


            next();

            if (sagaInstanceState.NotFound)
            {
                return;
            }

            if (saga.Completed)
            {
                if (!sagaInstanceState.IsNew)
                {
                    SagaPersister.Complete(saga.Entity);
                }

                if (saga.Entity.Id != Guid.Empty)
                {
                    NotifyTimeoutManagerThatSagaHasCompleted(saga);
                }

                logger.Debug(string.Format("Saga: '{0}' with Id: '{1}' has completed.", sagaInstanceState.SagaType.FullName, saga.Entity.Id));
            }
            else
            {
                if (sagaInstanceState.IsNew)
                {
                    SagaPersister.Save(saga.Entity);
                }
                else
                {
                    SagaPersister.Update(saga.Entity);
                }
            }
        }
        public async Task TestStoringSagas(ConventionType seedType)
        {
            using (var db = new ReusableDB())
            {
                List <TestSagaData> sagas;

                using (var store = db.NewStore())
                {
                    ApplyPrefillConventions(store, seedType);
                    store.Initialize();

                    sagas = await Prefill(store, seedType);
                }

                using (var store = db.NewStore())
                {
                    Console.WriteLine($"Testing saga updates with DocumentStore initially configured for {seedType} conventions.");
                    ApplyTestConventions(store, seedType);
                    store.Initialize();

                    // Update each saga, once by id and once by correlation property
                    foreach (var saga in sagas)
                    {
                        var persister = new SagaPersister();
                        Console.WriteLine($"Retrieving SagaId {saga.Id} by SagaId");
                        using (var session = store.OpenAsyncSession())
                        {
                            var ravenDBSynchronizedStorageSession = new RavenDBSynchronizedStorageSession(session, false);
                            var byId = await persister.Get <TestSagaData>(saga.Id, ravenDBSynchronizedStorageSession, null);

                            Assert.IsNotNull(byId);

                            byId.Counter++;
                            await persister.Update(byId, ravenDBSynchronizedStorageSession, null);

                            await session.SaveChangesAsync();

                            Console.WriteLine($"Retrieving SagaId {saga.Id} by Correlation Property OrderId={saga.OrderId}");
                            var byOrderId = await persister.Get <TestSagaData>("OrderId", saga.OrderId, ravenDBSynchronizedStorageSession, new ContextBag());

                            Assert.IsNotNull(byOrderId);

                            byOrderId.Counter++;
                            await persister.Update(byOrderId, ravenDBSynchronizedStorageSession, null);

                            await session.SaveChangesAsync();
                        }
                    }

                    Console.WriteLine("Retrieving each saga again by SagaId and making sure Counter == 3");
                    foreach (var saga in sagas)
                    {
                        var persister = new SagaPersister();
                        using (var session = store.OpenAsyncSession())
                        {
                            Console.WriteLine($"Retrieving SagaId {saga.Id} by SagaId");
                            var byId = await persister.Get <TestSagaData>(saga.Id, new RavenDBSynchronizedStorageSession(session, false), null);

                            Assert.IsNotNull(byId);
                            Assert.AreEqual(3, byId.Counter);
                        }
                    }
                }
            }
        }