コード例 #1
0
    Guid StoreSagaDocuments()
    {
        var sagaId      = Guid.NewGuid();
        var sagaDocId   = $"CountingSagaDatas/{sagaId}";
        var uniqueDocId = "Raven3Sagas-CountingSagaData/Name/5f293261-55cf-fb70-8b0a-944ef322a598"; // Guid is hash of "Alpha"
        var typeName    = "Raven3Sagas+CountingSagaData, NServiceBus.RavenDB.Tests";

        var oldData = new CountingSagaData
        {
            Name              = "Alpha",
            Id                = sagaId,
            Counter           = 42,
            Originator        = "DoesntMatter@MACHINE",
            OriginalMessageId = Guid.NewGuid().ToString()
        };

        var uniqueDoc = new SagaUniqueIdentity
        {
            Id          = uniqueDocId,
            SagaDocId   = sagaDocId,
            SagaId      = sagaId,
            UniqueValue = "Alpha"
        };

        StoreSaga(store, sagaDocId, oldData, "CountingSagaDatas", typeName, uniqueDocId);
        StoreUniqueDoc(store, uniqueDocId, uniqueDoc);
        return(sagaId);
    }
コード例 #2
0
    public static void RenameUniqueIdentities <TOldSaga, TNewSaga>(DocumentStore store, string uniqueProperty)
        where TOldSaga : IContainSagaData
        where TNewSaga : IContainSagaData
    {
        List <string> keysToDelete      = new List <string>();
        string        oldSagaPrefix     = store.GetDocumentPrefix <TOldSaga>();
        string        newSagaPrefix     = store.GetDocumentPrefix <TNewSaga>();
        string        oldIdentityPrefix = GetIdentityPrefix <TOldSaga>(uniqueProperty);
        string        newIdentityPrefix = GetIdentityPrefix <TNewSaga>(uniqueProperty);

        using (BulkInsertOperation bulkInsert = store.BulkInsert())
        {
            foreach (StreamResult <SagaUniqueIdentity> result in store.Stream <SagaUniqueIdentity>(oldIdentityPrefix))
            {
                SagaUniqueIdentity oldIdentity = result.Document;
                keysToDelete.Add(result.Key);
                SagaUniqueIdentity newIdentity = new SagaUniqueIdentity
                {
                    Id          = oldIdentity.Id.Replace(oldIdentityPrefix, newIdentityPrefix),
                    SagaDocId   = oldIdentity.SagaDocId.Replace(oldSagaPrefix, newSagaPrefix),
                    UniqueValue = oldIdentity.UniqueValue,
                    SagaId      = oldIdentity.SagaId
                };
                bulkInsert.Store(newIdentity);
            }
        }
        store.BatchDelete(keysToDelete);
    }
    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");
    }
コード例 #4
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);

            //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));
        }
コード例 #5
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));
        }
コード例 #6
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);
        }
コード例 #7
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.");
        }
    }
コード例 #9
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));
        }
コード例 #10
0
        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;
        }
コード例 #11
0
    static void StoreUniqueDoc(IDocumentStore store, string id, SagaUniqueIdentity document)
    {
        var documentInfo = new DocumentInfo
        {
            MetadataInstance = new MetadataAsDictionary()
        };

        documentInfo.MetadataInstance[Constants.Documents.Metadata.RavenClrType] = "NServiceBus.RavenDB.Persistence.SagaPersister.SagaUniqueIdentity, NServiceBus.RavenDB";
        documentInfo.MetadataInstance[Constants.Documents.Metadata.Collection]   = "SagaUniqueIdentities";

        Console.WriteLine($"Creating unique identity: {id}");
        using (var session = store.OpenSession())
        {
            var blittableDoc = session.Advanced.EntityToBlittable.ConvertEntityToBlittable(document, documentInfo);
            var command      = new PutDocumentCommand(id, string.Empty, blittableDoc);
            session.Advanced.RequestExecutor.Execute(command, session.Advanced.Context);
            session.SaveChanges();
        }
    }
コード例 #12
0
        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");
    }
コード例 #14
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);
        }
コード例 #15
0
        public static void StoreSchemaVersionInMetadata(this IAsyncDocumentSession session, SagaUniqueIdentity entity)
        {
            var metadata = session.Advanced.GetMetadataFor(entity);

            metadata[SagaUniqueIdentitySchemaVersionMetadataKey] = SagaUniqueIdentity.SchemaVersion;
        }