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));
        }
示例#3
0
        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));
        }
示例#4
0
        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);
        }
示例#5
0
        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.");
        }
    }
示例#7
0
        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");
    }
示例#11
0
        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);
        }