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 saga1 = new SagaData { Id = Guid.NewGuid(), UniqueString = uniqueString }; persister.Save(saga1); factory.SaveChanges(); factory.ReleaseSession(); var saga = persister.Get <SagaData>(saga1.Id); persister.Complete(saga); factory.SaveChanges(); factory.ReleaseSession(); var saga2 = new SagaData { Id = Guid.NewGuid(), UniqueString = uniqueString }; persister.Save(saga2); factory.SaveChanges(); } }
public async Task Should_delete_the_saga_and_the_unique_doc() { var sagaId = Guid.NewGuid(); using (var session = store.OpenAsyncSession().UsingOptimisticConcurrency().InContext(out var options)) { var persister = new SagaPersister(); var entity = new SagaData { Id = sagaId }; var synchronizedSession = new RavenDBSynchronizedStorageSession(session); await persister.Save(entity, this.CreateMetadata <SomeSaga>(entity), synchronizedSession, options); await session.SaveChangesAsync().ConfigureAwait(false); var saga = await persister.Get <SagaData>(sagaId, synchronizedSession, options); await persister.Complete(saga, synchronizedSession, options); await session.SaveChangesAsync().ConfigureAwait(false); Assert.Null(await persister.Get <SagaData>(sagaId, synchronizedSession, options)); Assert.Null(await session.Query <SagaUniqueIdentity>().Customize(c => c.WaitForNonStaleResults()).SingleOrDefaultAsync(u => u.SagaId == sagaId).ConfigureAwait(false)); } }
public async Task Public_setters_and_getters_of_concrete_classes_should_be_persisted() { var entity = new SagaData { Id = Guid.NewGuid(), UniqueString = "SomeUniqueString", TestComponent = new TestComponent { Property = "Prop" } }; using (var session = store.OpenAsyncSession().UsingOptimisticConcurrency().InContext(out var options)) { var persister = new SagaPersister(new SagaPersistenceConfiguration()); var synchronizedSession = new RavenDBSynchronizedStorageSession(session, options); await persister.Save(entity, this.CreateMetadata <SomeSaga>(entity), synchronizedSession, options); await session.SaveChangesAsync().ConfigureAwait(false); var savedEntity = await persister.Get <SagaData>(entity.Id, synchronizedSession, options); Assert.AreEqual(entity.TestComponent.Property, savedEntity.TestComponent.Property); Assert.AreEqual(entity.TestComponent.AnotherProperty, savedEntity.TestComponent.AnotherProperty); } }
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 When_initiating_message_can_not_be_found_doesnot_throw() { var sagaId = Guid.NewGuid(); var timeouts = new List <SagaTimeoutMessage> { new SagaTimeoutMessage { DeliverAt = DateTime.Now, Timeout = TimeSpan.FromMinutes(1) } }; var update = new SagaUpdate { InitiatingMessage = null, OutgoingMessages = timeouts }; var sagaChanges = new List <SagaUpdate> { update }; var sagaList = new List <SagaInfo> { new SagaInfo { SagaId = sagaId } }; var sagaData = new SagaData { Changes = sagaChanges }; messageSelectionContext.SelectedMessage = new StoredMessage { InvokedSagas = sagaList }; serviceControl.GetSagaById(Arg.Is(sagaId)).Returns(sagaData); var selectedMessageChanged = new SelectedMessageChanged(); Assert.DoesNotThrowAsync(() => viewModel.Handle(selectedMessageChanged)); }
public async Task Schema_version_should_be_persisted() { // arrange var entity = new SagaData { Id = Guid.NewGuid(), UniqueString = "SomeUniqueString", }; var persister = new SagaPersister(); using (var session = store.OpenAsyncSession().UsingOptimisticConcurrency().InContext(out var context)) { var synchronizedSession = new RavenDBSynchronizedStorageSession(session); // act await persister.Save(entity, this.CreateMetadata <SomeSaga>(entity), synchronizedSession, context); await session.SaveChangesAsync(); // assert var sagaDataContainerId = SagaPersister.DocumentIdForSagaData(session, entity); var sagaDataContainer = await session.LoadAsync <SagaDataContainer>(sagaDataContainerId); var sagaDataContainerMetadata = session.Advanced.GetMetadataFor(sagaDataContainer); var sagaUniqueIdentityId = sagaDataContainer.IdentityDocId; var sagaUniqueIdentity = await session.LoadAsync <SagaUniqueIdentity>(sagaUniqueIdentityId); var sagaUniqueIdentityMetadata = session.Advanced.GetMetadataFor(sagaUniqueIdentity); Assert.AreEqual(SagaDataContainer.SchemaVersion, sagaDataContainerMetadata[SchemaVersionExtensions.SagaDataContainerSchemaVersionMetadataKey]); Assert.AreEqual(SagaUniqueIdentity.SchemaVersion, sagaUniqueIdentityMetadata[SchemaVersionExtensions.SagaUniqueIdentitySchemaVersionMetadataKey]); } }
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 }; persister.Save(saga1); factory.SaveChanges(); factory.ReleaseSession(); var saga = persister.Get<SagaData>(saga1.Id); persister.Complete(saga); factory.SaveChanges(); factory.ReleaseSession(); var saga2 = new SagaData { Id = Guid.NewGuid(), UniqueString = uniqueString }; persister.Save(saga2); 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 It_should_enforce_uniqueness() { 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(); Assert.Throws<ConcurrencyException>(() => { var saga2 = new SagaData { Id = Guid.NewGuid(), UniqueString = uniqueString }; persister.Save(saga2); factory.SaveChanges(); }); }
public async Task Should_delete_the_unique_doc_properly() { var sagaId = Guid.NewGuid(); IAsyncDocumentSession session; var options = this.CreateContextWithAsyncSessionPresent(out session); var persister = new SagaPersister(); var sagaEntity = new SagaData { Id = sagaId, SomeId = Guid.NewGuid() }; var synchronizedSession = new RavenDBSynchronizedStorageSession(session); await persister.Save(sagaEntity, this.CreateMetadata <SomeSaga>(sagaEntity), synchronizedSession, options); //session.Advanced.GetMetadataFor(sagaEntity).Remove("NServiceBus-UniqueDocId"); await session.SaveChangesAsync().ConfigureAwait(false); var saga = await persister.Get <SagaData>(sagaId, synchronizedSession, options); await persister.Complete(saga, synchronizedSession, options); await session.SaveChangesAsync().ConfigureAwait(false); Assert.Null(await session.Query <SagaUniqueIdentity>().Customize(c => c.WaitForNonStaleResults()).SingleOrDefaultAsync(u => u.SagaId == sagaId)); }
public async Task Inherited_property_classes_should_be_persisted() { using (var session = store.OpenAsyncSession().UsingOptimisticConcurrency().InContext(out var options)) { var persister = new SagaPersister(new SagaPersistenceConfiguration()); var entity = new SagaData { Id = Guid.NewGuid(), UniqueString = "SomeUniqueString", PolymorphicRelatedProperty = new PolymorphicProperty { SomeInt = 9 } }; var synchronizedSession = new RavenDBSynchronizedStorageSession(session, options); await persister.Save(entity, this.CreateMetadata <SomeSaga>(entity), synchronizedSession, options); await session.SaveChangesAsync().ConfigureAwait(false); var savedEntity = await persister.Get <SagaData>(entity.Id, synchronizedSession, options); var expected = (PolymorphicProperty)entity.PolymorphicRelatedProperty; var actual = (PolymorphicProperty)savedEntity.PolymorphicRelatedProperty; Assert.AreEqual(expected.SomeInt, actual.SomeInt); } }
public void It_should_enforce_uniqueness() { 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(); Assert.Throws <ConcurrencyException>(() => { var saga2 = new SagaData { Id = Guid.NewGuid(), UniqueString = uniqueString }; persister.Save(saga2); factory.SaveChanges(); }); } }
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); }
public async Task Public_setters_and_getters_of_concrete_classes_should_be_persisted() { var entity = new SagaData { Id = Guid.NewGuid(), UniqueString = "SomeUniqueString", TestComponent = new TestComponent { Property = "Prop" } }; IAsyncDocumentSession session; var options = this.CreateContextWithAsyncSessionPresent(out session); var persister = new SagaPersister(); var synchronizedSession = new RavenDBSynchronizedStorageSession(session, true); await persister.Save(entity, this.CreateMetadata <SomeSaga>(entity), synchronizedSession, options); await session.SaveChangesAsync().ConfigureAwait(false); var savedEntity = await persister.Get <SagaData>(entity.Id, synchronizedSession, options); Assert.AreEqual(entity.TestComponent.Property, savedEntity.TestComponent.Property); Assert.AreEqual(entity.TestComponent.AnotherProperty, savedEntity.TestComponent.AnotherProperty); }
/// <summary> /// Updates a row in the saga data table. /// </summary> /// <param name="data"></param> /// <param name="sagaName"></param> /// <returns></returns> /// <exception cref="ArgumentException"></exception> /// <exception cref="ArgumentNullException"></exception> public Task Update(SagaData data, string sagaName) { const string UpdateSagaStatement = "UPDATE [{0}].[{1}_SagaData] SET" + " [Data] = @Data " + "WHERE [Id] = @Id"; if (IsUnsafe(_schemaConfig.Schema)) { throw new ArgumentException(SchemaUnsafe); } if (IsUnsafe(sagaName)) { throw new ArgumentException(SagaNameUnsafe); } if (data == null) { throw new ArgumentNullException(nameof(data)); } if (string.IsNullOrEmpty(data.Data)) { throw new ArgumentException($"{nameof(data)}.{nameof(data.Data)} must be not null and not empty."); } var statement = string.Format(UpdateSagaStatement, _schemaConfig.Schema, sagaName); var p = new DynamicParameters(); p.Add("@Id", data.Id); p.Add("@Data", data.Data); return(_database.Connection.ExecuteAsync(statement, p, _database.Transaction)); }
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 async Task Inherited_property_classes_should_be_persisted() { IAsyncDocumentSession session; var options = this.CreateContextWithAsyncSessionPresent(out session); var persister = new SagaPersister(); var entity = new SagaData { Id = Guid.NewGuid(), UniqueString = "SomeUniqueString", PolymorphicRelatedProperty = new PolymorphicProperty { SomeInt = 9 } }; var synchronizedSession = new RavenDBSynchronizedStorageSession(session, true); await persister.Save(entity, this.CreateMetadata <SomeSaga>(entity), synchronizedSession, options); await session.SaveChangesAsync().ConfigureAwait(false); var savedEntity = await persister.Get <SagaData>(entity.Id, synchronizedSession, options); var expected = (PolymorphicProperty)entity.PolymorphicRelatedProperty; var actual = (PolymorphicProperty)savedEntity.PolymorphicRelatedProperty; Assert.AreEqual(expected.SomeInt, actual.SomeInt); }
public async Task CompensationDone <FormType>(SimpleSaga <FormType> saga, SagaStep step, string sagaId, SagaData form) where FormType : class, SagaData { var stepKey = saga.GetSagaDefinition().KeyOfStep(step); sagaDoneCompensationSteps.AddOrUpdate(sagaId, new HashSet <string>() { stepKey }, (_, oldSet) => { oldSet.Add(stepKey); return(oldSet); }); var doneCompensationSteps = sagaDoneCompensationSteps[sagaId]; var needDoCompensationStepsCount = saga.GetSagaDefinition().Steps.Count(); // 此sagaId需要执行补偿的steps count if (doneCompensationSteps.Count() >= needDoCompensationStepsCount) { // sagaStates[sagaId] = SagaState.COMPENSATION_DONE; var oldInfo = _sagaInfos[sagaId]; if (oldInfo.State != SagaState.COMPENSATION_DONE) { if (!_sagaInfos.TryUpdate(sagaId, oldInfo.SetStateClone(SagaState.COMPENSATION_DONE), oldInfo)) { throw new SagaAbortException($"saga {sagaId} CompensationDone error because of state update conflict"); } } saga.OnSagaRolledBack(sagaId, form); } return; }
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 async Task CompensationStart <FormType>(SimpleSaga <FormType> saga, string sagaId, SagaData form) where FormType : class, SagaData { if (!await SetSagaState(sagaId, SagaState.COMPENSATION_DOING, null)) { throw new SagaAbortException($"sagaId {sagaId} CompensationStart error because of set state conflict"); } }
public void TestInitialize() { dataAccess = new Mock <IBusDataAccess>(); log = new Mock <ILog <QueueReader> >(); perfCounters = new Mock <IPerfCounters>(); serializer = new Mock <ISerializer>(); clock = new Mock <ISystemClock>(); clock.SetupGet(x => x.UtcNow) .Returns(new DateTime(2022, 2, 22, 14, 22, 22, 222, DateTimeKind.Utc)); dataAccess.Setup(d => d.Update(It.IsAny <QueueMessage>(), It.IsAny <string>())) .Callback <QueueMessage, string>((m, q) => { UpdatedMessage = m; UpdatedQueue = q; }) .Returns(Task.CompletedTask); dataAccess.Setup(d => d.Insert(It.IsAny <SagaData>(), It.IsAny <string>())) .Callback <SagaData, string>((d, n) => { InsertedSagaData = d; InsertedSagaName = n; }) .Returns(Task.FromResult <long>(12345)); dataAccess.Setup(d => d.Update(It.IsAny <SagaData>(), It.IsAny <string>())) .Callback <SagaData, string>((d, n) => { UpdatedSagaData = d; UpdatedSagaName = n; }) .Returns(Task.CompletedTask); dataAccess.Setup(d => d.FailMessage(It.IsAny <QueueMessage>(), It.IsAny <string>())) .Callback <QueueMessage, string>((d, n) => { FailedMessage = d; FailedQueue = n; }) .Returns(Task.CompletedTask); dataAccess.Setup(d => d.CompleteMessage(It.IsAny <QueueMessage>(), It.IsAny <string>())) .Callback <QueueMessage, string>((d, n) => { CompletedMessage = d; CompletedQueue = n; }) .Returns(Task.CompletedTask); serializer.Setup(s => s.SerializeSaga(It.IsAny <object>(), typeof(TestSagaData))) .Returns("SerializedTestSagaData"); reader = new QueueReader(dataAccess.Object, log.Object, perfCounters.Object, serializer.Object, clock.Object); }
public async Task <SagaData> GetSagaData(string sagaId) { SagaData sagaData = null; if (!_sagaDatas.TryGetValue(sagaId, out sagaData)) { return(null); } return(sagaData); }
protected int SINGLE_STEP_COMPENSATION_TRY_COUNT = 3; // 一个步骤的补偿任务最多重试的次数 public Task CompensationException <FormType>(SimpleSaga <FormType> saga, SagaStep step, string sagaId, SagaData form, Exception e) where FormType : class, SagaData { // 记录失败信息和失败次数 var key = makeSagaIdAndStepKey(sagaId, saga, step); sagaStepsCompensationFailCount.AddOrUpdate(key, 1, (_, oldCount) => oldCount + 1); var failCount = sagaStepsCompensationFailCount[key]; if (failCount >= SINGLE_STEP_COMPENSATION_TRY_COUNT) { // 这个step的补偿任务执行失败次数太多了 Console.WriteLine($"saga {sagaId} step {saga.GetSagaDefinition().KeyOfStep(step)} compensation fail too many times error {e.Message}"); // sagaStates.TryUpdate(sagaId, SagaState.COMPENSATION_FAIL, SagaState.COMPENSATION_DOING); while (true) { if (!_sagaInfos.ContainsKey(sagaId)) { break; } var oldInfo = _sagaInfos[sagaId]; if (oldInfo.State.IsEndState()) { break; } if (_sagaInfos.TryUpdate(sagaId, oldInfo.SetStateClone(SagaState.COMPENSATION_FAIL), oldInfo)) { break; } } } else { while (true) { if (!_sagaInfos.ContainsKey(sagaId)) { break; } var oldInfo = _sagaInfos[sagaId]; if (oldInfo.State.IsEndState() || oldInfo.State == SagaState.COMPENSATION_ERROR) { break; } if (_sagaInfos.TryUpdate(sagaId, oldInfo.SetStateClone(SagaState.COMPENSATION_ERROR), oldInfo)) { break; } } } return(Task.CompletedTask); }
private async Task ProcessAsync <TMessage>(Guid?nid, Type sagaType, Type sagaDataType, TMessage message, ISagaAction <TMessage> action, ISagaContext context = null) where TMessage : class { context = context ?? SagaContext.Empty; var saga = (ISaga)action; var id = nid ?? saga.ResolveId(message, context); var sagaData = await _repository.ReadAsync(id, sagaType).ConfigureAwait(false); if (sagaData is null) { if (!(action is ISagaStartAction <TMessage>)) { return; } sagaData = SagaData.Create(id, sagaType, SagaStates.Pending, Activator.CreateInstance(sagaDataType)); } else if (sagaData.State == SagaStates.Rejected) { return; } saga.Initialize(sagaData.SagaId, sagaData.State, sagaData.Data); var isError = false; try { await action.HandleAsync(message, context); } catch { isError = true; } var newSagaData = SagaData.Create(id, sagaType, saga.State, saga.Data); var sagaLogData = SagaLogData.Create(id, sagaType, message); var persistanceTasks = new Task[2] { _repository.WriteAsync(newSagaData), _sagaLog.SaveAsync(sagaLogData) }; await Task.WhenAll(persistanceTasks).ConfigureAwait(false); if (saga.State is SagaStates.Rejected || isError) { await CompensateAsync(saga, sagaType, context); } }
public async Task <string> ProcessSomeUnfinishedSagasAsync(int limit, string lastProcessSagaId) { var sagaIds = await sagaStore.ListSagaIdsInStates(new List <SagaState>(){ SagaState.PROCESSING, SagaState.COMPENSATION_DOING, SagaState.COMPENSATION_ERROR }, limit, lastProcessSagaId); _logger.LogInformation($"there are {sagaIds.Count} unfinished sagaIds to process"); if (sagaIds.Count < 1) { return(null); } foreach (var sagaId in sagaIds) { try { var sagaInfo = await sagaStore.GetSagaInfo(sagaId); if (sagaInfo.State == SagaState.PROCESSING) { // 如果是正常处理中的sagaId,如果没有超时,则不做补偿等后续操作 if (!sagaInfo.IsExpired()) { continue; } } try { if (!await sagaStore.LockSagaProcess(sagaId, _workerId, TimeSpan.FromSeconds(60))) { throw new SagaProcessException($"worker {_workerId} lock saga {sagaId} to process error"); } _logger.LogInformation($"worker {_workerId} start process saga {sagaId}"); SagaData sagaData = await sagaStore.GetSagaData(sagaId); await ProcessUnfinishedSagaAsync(sagaId, sagaData); _logger.LogInformation($"worker {_workerId} process saga {sagaId} done"); } finally { await sagaStore.UnlockSagaProcess(sagaId, _workerId); } } catch (Exception e) { _logger.LogError($"process unifinished saga {sagaId} error {e.Message}"); } } return(sagaIds[sagaIds.Count - 1]); }
public async Task It_should_persist_successfully() { var saga1Id = Guid.NewGuid(); var uniqueString = Guid.NewGuid().ToString(); using (var session = store.OpenAsyncSession().UsingOptimisticConcurrency().InContext(out var options)) { var persister = new SagaPersister(new SagaPersistenceConfiguration()); var saga1 = new SagaData { Id = saga1Id, UniqueString = uniqueString }; var synchronizedSession = new RavenDBSynchronizedStorageSession(session, options); await persister.Save(saga1, this.CreateMetadata <SomeSaga>(saga1), synchronizedSession, options); await session.SaveChangesAsync().ConfigureAwait(false); } using (var session = store.OpenAsyncSession().UsingOptimisticConcurrency().InContext(out var options)) { var persister = new SagaPersister(new SagaPersistenceConfiguration()); var synchronizedSession = new RavenDBSynchronizedStorageSession(session, options); var saga = await persister.Get <SagaData>(saga1Id, synchronizedSession, options); await persister.Complete(saga, synchronizedSession, options); await session.SaveChangesAsync().ConfigureAwait(false); } using (var session = store.OpenAsyncSession().UsingOptimisticConcurrency().InContext(out var options)) { var persister = new SagaPersister(new SagaPersistenceConfiguration()); var synchronizedSession = new RavenDBSynchronizedStorageSession(session, options); var saga2 = new SagaData { Id = Guid.NewGuid(), UniqueString = uniqueString }; await persister.Save(saga2, this.CreateMetadata <SomeSaga>(saga2), synchronizedSession, options); await session.SaveChangesAsync().ConfigureAwait(false); } }
async Task SimulateProcessingMessage(SagaData sagaData, Action <SagaData> action, bool commitOutboxTransaction, ContextBag context) { var outboxTransaction = await outboxPersister.BeginTransaction(context); var session = new OutboxEventStoreSynchronizedStorageSession(connection, (EventStoreOutboxTransaction)outboxTransaction); sagaData = await persister.Get <SagaData>(CorrelationPropName, sagaData.StringProperty, session, context); action(sagaData); await persister.Update(sagaData, session, context); if (commitOutboxTransaction) { await outboxTransaction.Commit(); } }
public async Task ProcessUnfinishedSagaAsync(string sagaId, SagaData sagaData) { var sagaInfo = await sagaStore.GetSagaInfo(sagaId); if (sagaInfo == null) { return; } if (sagaInfo.State.IsEndState()) { return; } var sagaDefinition = sagaInfo.Definition; var saga = sagaDefinition.Saga; await saga.DoCompensationOfSaga(sagaId, sagaData); }
public void Enums_should_be_persisted() { var entity = new SagaData { Id = Guid.NewGuid(), Status = StatusEnum.AnotherStatus }; var factory = new RavenSessionFactory(store); factory.ReleaseSession(); var persister = new SagaPersister(factory); persister.Save(entity); factory.SaveChanges(); var savedEntity = persister.Get<SagaData>(entity.Id); Assert.AreEqual(entity.Status, savedEntity.Status); }
/// <summary> /// Inserts a row into a saga data table. /// </summary> /// <param name="data"></param> /// <param name="sagaName"></param> /// <returns></returns> /// <exception cref="ArgumentException"></exception> /// <exception cref="ArgumentNullException"></exception> public Task <long> Insert(SagaData data, string sagaName) { const string InsertSagaStatement = "INSERT INTO[{0}].[{1}_SagaData]" + " ([SagaId], [Key], [Data]) " + "VALUES" + " (@SagaId, @Key, @Data); " + "SELECT SCOPE_IDENTITY()"; if (IsUnsafe(_schemaConfig.Schema)) { throw new ArgumentException(SchemaUnsafe); } if (IsUnsafe(sagaName)) { throw new ArgumentException(SagaNameUnsafe); } if (data == null) { throw new ArgumentNullException(nameof(data)); } if (data.SagaId == null) { throw new ArgumentNullException($"{nameof(data)}.{nameof(data.SagaId)}"); } if (string.IsNullOrEmpty(data.Key)) { throw new ArgumentException($"{nameof(data)}.{nameof(data.Key)} must be not null and not empty."); } if (string.IsNullOrEmpty(data.Data)) { throw new ArgumentException($"{nameof(data)}.{nameof(data.Data)} must be not null and not empty."); } string statement = string.Format(InsertSagaStatement, _schemaConfig.Schema, sagaName); var p = new DynamicParameters(); p.Add("@SagaId", data.SagaId); p.Add("@Key", data.Key); p.Add("@Data", data.Data); return(_database.Connection.QueryFirstAsync <long>(statement, p, _database.Transaction)); }
public void Datetime_property_should_be_persisted() { var entity = new SagaData { Id = Guid.NewGuid(), DateTimeProperty = DateTime.Parse("12/02/2010 12:00:00.01") }; using (var store = DocumentStoreBuilder.Build()) { var factory = new RavenSessionFactory(store); factory.ReleaseSession(); var persister = new SagaPersister(factory); persister.Save(entity); factory.SaveChanges(); var savedEntity = persister.Get <SagaData>(entity.Id); Assert.AreEqual(entity.DateTimeProperty, savedEntity.DateTimeProperty); } }
public void Public_setters_and_getters_of_concrete_classes_should_be_persisted() { var entity = new SagaData { Id = Guid.NewGuid(), TestComponent = new TestComponent { Property = "Prop" } }; var factory = new RavenSessionFactory(store); factory.ReleaseSession(); var persister = new SagaPersister(factory); persister.Save(entity); factory.SaveChanges(); var savedEntity = persister.Get<SagaData>(entity.Id); Assert.AreEqual(entity.TestComponent.Property, savedEntity.TestComponent.Property); Assert.AreEqual(entity.TestComponent.AnotherProperty, savedEntity.TestComponent.AnotherProperty); }
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 Enums_should_be_persisted() { var entity = new SagaData { Id = Guid.NewGuid(), Status = StatusEnum.AnotherStatus }; using (var store = DocumentStoreBuilder.Build()) { var factory = new RavenSessionFactory(store); factory.ReleaseSession(); var persister = new SagaPersister(factory); persister.Save(entity); factory.SaveChanges(); var savedEntity = persister.Get <SagaData>(entity.Id); Assert.AreEqual(entity.Status, savedEntity.Status); } }
public async Task should_throw_a_ArgumentNullException() { var saga1 = new SagaData { Id = Guid.NewGuid(), UniqueString = null }; IAsyncDocumentSession session; var context = this.CreateContextWithAsyncSessionPresent(out session); var ravenSession = new RavenDBSynchronizedStorageSession(session, true); var persister = new SagaPersister(); var exception = await Catch <ArgumentNullException>(async() => { await persister.Save(saga1, this.CreateMetadata <SomeSaga>(saga1), ravenSession, context); await session.SaveChangesAsync().ConfigureAwait(false); }); Assert.IsNotNull(exception); }
public void Inherited_property_classes_should_be_persisted() { var factory = new RavenSessionFactory(store); factory.ReleaseSession(); var persister = new SagaPersister(factory); var entity = new SagaData { Id = Guid.NewGuid(), PolymorphicRelatedProperty = new PolymorphicProperty { SomeInt = 9 } }; persister.Save(entity); factory.SaveChanges(); var savedEntity = persister.Get<SagaData>(entity.Id); var expected = (PolymorphicProperty)entity.PolymorphicRelatedProperty; var actual = (PolymorphicProperty)savedEntity.PolymorphicRelatedProperty; Assert.AreEqual(expected.SomeInt, actual.SomeInt); }
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 It_should_persist_successfully() { 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 SagaHeader(SagaData data) { this.data = data; }
public SagaFooter(SagaData data) { this.data = data; }