static void CreateLegacySagaDocuments(IDocumentStore store, string unique) { var sagaId = Guid.NewGuid(); var saga = new SagaWithUniqueProperty { Id = sagaId, UniqueString = unique }; var sagaDocId = $"SagaWithUniqueProperty/{sagaId}"; var typeName = Regex.Replace(typeof(SagaWithUniqueProperty).AssemblyQualifiedName, ", Version=.*", ""); DirectStore(store, sagaDocId, saga, "SagaWithUniqueProperty", typeName, unique); var uniqueIdentity = new SagaUniqueIdentity { Id = SagaUniqueIdentity.FormatId(typeof(SagaWithUniqueProperty), "UniqueString", unique), SagaId = sagaId, SagaDocId = sagaDocId, UniqueValue = unique }; DirectStore(store, uniqueIdentity.Id, uniqueIdentity, "SagaUniqueIdentity", "NServiceBus.Persistence.Raven.SagaPersister.SagaUniqueIdentity, NServiceBus.Core"); }
public async Task <T> Get <T>(string propertyName, object propertyValue, SynchronizedStorageSession session, ContextBag context) where T : class, IContainSagaData { var documentSession = session.RavenSession(); var lookupId = SagaUniqueIdentity.FormatId(typeof(T), propertyName, propertyValue); //store it in the context to be able to optimize deletes for legacy sagas that don't have the id in metadata context.Set(UniqueDocIdKey, lookupId); var lookup = await documentSession .Include("SagaDocId") //tell raven to pull the saga doc as well to save us a round-trip .LoadAsync <SagaUniqueIdentity>(lookupId) .ConfigureAwait(false); if (lookup != null) { documentSession.Advanced.Evict(lookup); return(lookup.SagaDocId != null ? await documentSession.LoadAsync <T>(lookup.SagaDocId).ConfigureAwait(false) //if we have a saga id we can just load it : await Get <T>(lookup.SagaId, session, context).ConfigureAwait(false)); //if not this is a saga that was created pre 3.0.4 so we fallback to a get instead } return(default(T)); }
public async Task <T> Get <T>(string propertyName, object propertyValue, SynchronizedStorageSession session, ContextBag context) where T : class, IContainSagaData { var documentSession = session.RavenSession(); var lookupId = SagaUniqueIdentity.FormatId(typeof(T), propertyName, propertyValue); var lookup = await documentSession .Include("SagaDocId") //tell raven to pull the saga doc as well to save us a round-trip .LoadAsync <SagaUniqueIdentity>(lookupId) .ConfigureAwait(false); if (lookup != null) { documentSession.Advanced.Evict(lookup); // If we have a saga id we can just load it, should have been included in the round-trip already var container = await documentSession.LoadAsync <SagaDataContainer>(lookup.SagaDocId).ConfigureAwait(false); if (container != null) { if (container.IdentityDocId == null) { container.IdentityDocId = lookupId; } context.Set($"{SagaContainerContextKeyPrefix}{container.Data.Id}", container); return((T)container.Data); } } return(default(T)); }
public async Task Save(IContainSagaData sagaData, SagaCorrelationProperty correlationProperty, SynchronizedStorageSession session, ContextBag context) { var documentSession = session.RavenSession(); if (sagaData == null) { return; } var container = new SagaDataContainer { Id = DocumentIdForSagaData(documentSession, sagaData), Data = sagaData }; if (correlationProperty == null) { return; } container.IdentityDocId = SagaUniqueIdentity.FormatId(sagaData.GetType(), correlationProperty.Name, correlationProperty.Value); await documentSession.StoreAsync(container, string.Empty, container.Id).ConfigureAwait(false); await documentSession.StoreAsync(new SagaUniqueIdentity { Id = container.IdentityDocId, SagaId = sagaData.Id, UniqueValue = correlationProperty.Value, SagaDocId = container.Id }, changeVector : string.Empty, id : container.IdentityDocId).ConfigureAwait(false); }
void DeleteUniqueProperty(IContainSagaData saga, KeyValuePair <string, object> uniqueProperty) { var id = SagaUniqueIdentity.FormatId(saga.GetType(), uniqueProperty); sessionProvider.Session.Advanced.Defer(new DeleteCommandData { Key = id }); }
public async Task Improperly_converted_saga_can_be_fixed() { var sagaId = Guid.NewGuid(); var sagaDocId = $"SagaWithUniqueProperty/{sagaId}"; var uniqueString = "abcd"; var identityDocId = SagaUniqueIdentity.FormatId(typeof(SagaWithUniqueProperty), "UniqueString", uniqueString); var sagaData = new SagaWithUniqueProperty { Id = Guid.Empty, // Improperly converted UniqueString = uniqueString }; var sagaContainer = new SagaDataContainer { Id = sagaDocId, Data = sagaData, IdentityDocId = identityDocId }; var uniqueIdentity = new SagaUniqueIdentity { Id = SagaUniqueIdentity.FormatId(typeof(SagaWithUniqueProperty), "UniqueString", uniqueString), SagaId = sagaId, SagaDocId = sagaDocId, UniqueValue = uniqueString }; using (var session = store.OpenAsyncSession().UsingOptimisticConcurrency().InContext(out var _)) { await session.StoreAsync(sagaContainer); await session.StoreAsync(uniqueIdentity); await session.SaveChangesAsync(); } using (var session = store.OpenAsyncSession().UsingOptimisticConcurrency().InContext(out var options)) { var persister = new SagaPersister(new SagaPersistenceConfiguration()); var synchronizedSession = new RavenDBSynchronizedStorageSession(session, options); var loadedSaga = await persister.Get <SagaWithUniqueProperty>("UniqueString", uniqueString, synchronizedSession, options); Assert.IsNotNull(loadedSaga, "Saga is null"); Assert.AreNotEqual(Guid.Empty, loadedSaga.Id, "Id is Guid.Empty"); Assert.AreEqual(sagaId, loadedSaga.Id, "Saga Id is not the correct value."); } }
T GetByUniqueProperty <T>(string property, object value) where T : IContainSagaData { var lookupId = SagaUniqueIdentity.FormatId(typeof(T), new KeyValuePair <string, object>(property, value)); var lookup = sessionProvider.Session .Include("SagaDocId") //tell raven to pull the saga doc as well to save us a round-trip .Load <SagaUniqueIdentity>(lookupId); if (lookup != null) { return(lookup.SagaDocId != null ? sessionProvider.Session.Load <T>(lookup.SagaDocId) //if we have a saga id we can just load it : Get <T>(lookup.SagaId)); //if not this is a saga that was created pre 3.0.4 so we fallback to a get instead } return(default(T)); }
static async Task CreateSagaUniqueIdentity(IContainSagaData sagaData, SagaCorrelationProperty correlationProperty, IAsyncDocumentSession documentSession) { var sagaDocId = documentSession.Advanced.DocumentStore.Conventions.FindFullDocumentKeyFromNonStringIdentifier(sagaData.Id, sagaData.GetType(), false); var sagaUniqueIdentityDocId = SagaUniqueIdentity.FormatId(sagaData.GetType(), correlationProperty.Name, correlationProperty.Value); await documentSession.StoreAsync(new SagaUniqueIdentity { Id = sagaUniqueIdentityDocId, SagaId = sagaData.Id, UniqueValue = correlationProperty.Value, SagaDocId = sagaDocId }, id : sagaUniqueIdentityDocId, etag : Etag.Empty).ConfigureAwait(false); var metadata = await documentSession.Advanced.GetMetadataForAsync(sagaData).ConfigureAwait(false); metadata[UniqueDocIdKey] = sagaUniqueIdentityDocId; }
public async Task Save(IContainSagaData sagaData, SagaCorrelationProperty correlationProperty, SynchronizedStorageSession session, ContextBag context, CancellationToken cancellationToken = default) { var documentSession = session.RavenSession(); if (sagaData == null) { return; } if (correlationProperty == null) { return; } var container = new SagaDataContainer { Id = DocumentIdForSagaData(documentSession, sagaData), Data = sagaData, IdentityDocId = SagaUniqueIdentity.FormatId(sagaData.GetType(), correlationProperty.Name, correlationProperty.Value), }; await documentSession.StoreAsync(container, string.Empty, container.Id, cancellationToken).ConfigureAwait(false); documentSession.StoreSchemaVersionInMetadata(container); var sagaUniqueIdentity = new SagaUniqueIdentity { Id = container.IdentityDocId, SagaId = sagaData.Id, UniqueValue = correlationProperty.Value, SagaDocId = container.Id }; await documentSession.StoreAsync(sagaUniqueIdentity, changeVector : string.Empty, id : container.IdentityDocId, token : cancellationToken).ConfigureAwait(false); documentSession.StoreSchemaVersionInMetadata(sagaUniqueIdentity); }
static void CreateLegacySagaDocuments(IDocumentStore store, string unique) { var sagaId = Guid.NewGuid(); var saga = new SagaWithUniqueProperty { Id = sagaId, UniqueString = unique }; var sagaDocId = $"SagaWithUniqueProperty/{sagaId}"; DirectStore(store, sagaDocId, saga, "SagaWithUniqueProperty", ReflectionUtil.GetFullNameWithoutVersionInformation(typeof(SagaWithUniqueProperty)), unique); var uniqueIdentity = new SagaUniqueIdentity { Id = SagaUniqueIdentity.FormatId(typeof(SagaWithUniqueProperty), "UniqueString", unique), SagaId = sagaId, SagaDocId = sagaDocId, UniqueValue = unique }; DirectStore(store, uniqueIdentity.Id, uniqueIdentity, "SagaUniqueIdentity", "NServiceBus.Persistence.Raven.SagaPersister.SagaUniqueIdentity, NServiceBus.Core"); }
void StoreUniqueProperty(IContainSagaData saga) { var uniqueProperty = UniqueAttribute.GetUniqueProperty(saga); if (!uniqueProperty.HasValue) { return; } var id = SagaUniqueIdentity.FormatId(saga.GetType(), uniqueProperty.Value); var sagaDocId = sessionProvider.Session.Advanced.DocumentStore.Conventions.FindFullDocumentKeyFromNonStringIdentifier(saga.Id, saga.GetType(), false); sessionProvider.Session.Store(new SagaUniqueIdentity { Id = id, SagaId = saga.Id, UniqueValue = uniqueProperty.Value.Value, SagaDocId = sagaDocId }); SetUniqueValueMetadata(saga, uniqueProperty.Value); }