public Task Store(OutboxMessage message, OutboxTransaction transaction, ContextBag context)
        {
            var session = ((RavenDBOutboxTransaction)transaction).AsyncSession;

            var operations = new OutboxRecord.OutboxOperation[message.TransportOperations.Length];

            var index = 0;
            foreach (var transportOperation in message.TransportOperations)
            {
                operations[index] = new OutboxRecord.OutboxOperation
                {
                    Message = transportOperation.Body,
                    Headers = transportOperation.Headers,
                    MessageId = transportOperation.MessageId,
                    Options = transportOperation.Options
                };
                index++;
            }

            return session.StoreAsync(new OutboxRecord
            {
                MessageId = message.MessageId,
                Dispatched = false,
                TransportOperations = operations
            }, GetOutboxRecordId(message.MessageId));
        }
        public async Task Should_return_the_next_time_of_retrieval()
        {
            query.CleanupGapFromTimeslice = TimeSpan.FromSeconds(1);
            query.TriggerCleanupEvery = TimeSpan.Zero;

            var nextTime = DateTime.UtcNow.AddHours(1);
            var context = new ContextBag();

            await persister.Add(new TimeoutData
            {
                Time = nextTime,
                Destination = "timeouts@" + RuntimeEnvironment.MachineName,
                SagaId = Guid.NewGuid(),
                State = new byte[]
                {
                    0,
                    0,
                    133
                },
                Headers = new Dictionary<string, string>
                {
                    {"Bar", "34234"},
                    {"Foo", "aString1"},
                    {"Super", "aString2"}
                },
                OwningTimeoutManager = "MyTestEndpoint"
            }, context);

            WaitForIndexing(store);

            var nextTimeToRunQuery = (await query.GetNextChunk(DateTime.UtcNow.AddYears(-3))).NextTimeToQuery;

            Assert.IsTrue((nextTime - nextTimeToRunQuery).TotalSeconds < 1);
        }
 public async Task<OutboxTransaction> BeginTransaction(ContextBag context)
 {
     var connection = connectionBuilder();
     await connection.OpenAsync();
     var transaction = connection.BeginTransaction();
     return new SqlOutboxTransaction(transaction, connection);
 }
 public static ContextBag CreateContextWithAsyncSessionPresent(this RavenDBPersistenceTestBase testBase, out IAsyncDocumentSession session)
 {
     var context = new ContextBag();
     session = testBase.OpenAsyncSession();
     context.Set(session);
     return context;
 }
 public async Task<CompletableSynchronizedStorageSession> OpenSession(ContextBag contextBag)
 {
     var connection = connectionBuilder();
     await connection.OpenAsync();
     var transaction = connection.BeginTransaction();
     return new StorageSession(connection, transaction,true);
 }
        public async Task<OutboxMessage> Get(string messageId, ContextBag options)
        {
            OutboxRecord result;
            using (var session = documentStore.OpenAsyncSession())
            {
                session.Advanced.AllowNonAuthoritativeInformation = false;

                // We use Load operation and not queries to avoid stale results
                var possibleIds = GetPossibleOutboxDocumentIds(messageId);
                var docs = await session.LoadAsync<OutboxRecord>(possibleIds).ConfigureAwait(false);
                result = docs.FirstOrDefault(o => o != null);
            }

            if (result == null)
            {
                return default(OutboxMessage);
            }

            if (result.Dispatched || result.TransportOperations.Length == 0)
            {
                return new OutboxMessage(result.MessageId, emptyTransportOperations);
            }

            var transportOperations = new TransportOperation[result.TransportOperations.Length];
            var index = 0;
            foreach (var op in result.TransportOperations)
            {
                transportOperations[index] = new TransportOperation(op.MessageId, op.Options, op.Message, op.Headers);
                index++;
            }

            return new OutboxMessage(result.MessageId, transportOperations);
        }
        public async Task It_should_successfully_remove_the_saga()
        {
            var id = Guid.NewGuid();
            var sagaData = new SagaWithoutUniquePropertyData
            {
                Id = id,
                NonUniqueString = "whatever"
            };

            var persister = new InMemorySagaPersister();
            var savingSession = new InMemorySynchronizedStorageSession();

            await persister.Save(sagaData, null, savingSession, new ContextBag());
            await savingSession.CompleteAsync();

            // second session
            var completingSession = new InMemorySynchronizedStorageSession();
            var completingContextBag = new ContextBag();

            var saga = await persister.Get<SagaWithoutUniquePropertyData>(id, completingSession, completingContextBag);
            await persister.Complete(saga, completingSession, completingContextBag);
            await completingSession.CompleteAsync();

            var result = await persister.Get<SagaWithoutUniquePropertyData>(sagaData.Id, savingSession, new ContextBag());

            Assert.That(result, Is.Null);
        }
    public async Task<TimeoutData> Peek(string timeoutId, ContextBag context)
    {
        using (var connection = connectionBuilder())
        {
            await connection.OpenAsync();
            using (var command = connection.CreateCommand())
            {
                command.CommandText = timeoutCommands.Peek;
                command.AddParameter("Id", timeoutId);
                using (var reader = await command.ExecuteReaderAsync(CommandBehavior.SingleRow))
                {
                    if (!await reader.ReadAsync())
                    {
                        return null;
                    }

                    var headers = ReadHeaders(reader);
                    return new TimeoutData
                    {
                        Id = timeoutId,
                        Destination = reader.GetString(0),
                        SagaId = reader.GetGuid(1),
                        State = (byte[]) reader.GetValue(2),
                        Time = reader.GetDateTime(3),
                        Headers = headers,
                    };
                }
            }
        }
    }
        public async Task<bool> DeduplicateMessage(string messageId, DateTime timeReceived, ContextBag context)
        {
            using (var session = documentStore.OpenAsyncSession())
            {
                session.Advanced.UseOptimisticConcurrency = true;
                session.Advanced.AllowNonAuthoritativeInformation = false;

                await session.StoreAsync(new GatewayMessage
                {
                    Id = EscapeMessageId(messageId),
                    TimeReceived = timeReceived
                }).ConfigureAwait(false);

                try
                {
                    await session.SaveChangesAsync().ConfigureAwait(false);
                }
                catch (ConcurrencyException)
                {
                    return false;
                }

                return true;
            }
        }
        public async Task Save_fails_when_data_changes_between_read_and_update_on_same_thread()
        {
            var sagaId = Guid.NewGuid();
            var saga = new TestSagaData
            {
                Id = sagaId,
                SomeId = sagaId.ToString()
            };
            var persister = new InMemorySagaPersister();
            var insertSession = new InMemorySynchronizedStorageSession();
            await persister.Save(saga, SagaMetadataHelper.GetMetadata<TestSaga>(saga), insertSession, new ContextBag());
            await insertSession.CompleteAsync();

            var winningContext = new ContextBag();
            var record = await persister.Get<TestSagaData>(saga.Id, new InMemorySynchronizedStorageSession(), winningContext);
            var losingContext = new ContextBag();
            var staleRecord = await persister.Get<TestSagaData>("SomeId", sagaId.ToString(), new InMemorySynchronizedStorageSession(), losingContext);

            var winningSaveSession = new InMemorySynchronizedStorageSession();
            var losingSaveSession = new InMemorySynchronizedStorageSession();

            await persister.Update(record, winningSaveSession, winningContext);
            await persister.Update(staleRecord, losingSaveSession, losingContext);

            await winningSaveSession.CompleteAsync();

            Assert.That(async () => await losingSaveSession.CompleteAsync(), Throws.InstanceOf<Exception>().And.Message.StartsWith($"InMemorySagaPersister concurrency violation: saga entity Id[{saga.Id}] already saved."));
        }
        public void EnsureMappingFailsWithoutIndex()
        {
            var context = new ContextBag();

            using (var db = new ReusableDB())
            {
                using (var store = db.NewStore())
                {
                    ApplyTestConventions(store, ConventionType.RavenDefault);
                    store.Initialize();

                    // Remove the index to make sure the conventions will throw
                    store.DatabaseCommands.DeleteIndex("Raven/DocumentsByEntityName");

                    var persister = new TimeoutPersister(store);
                   
                    var exception = Assert.Throws<AggregateException>(() =>
                    {
                        persister.Add(new TimeoutData
                        {
                            Destination = EndpointName,
                            Headers = new Dictionary<string, string>(),
                            OwningTimeoutManager = EndpointName,
                            SagaId = Guid.NewGuid(),
                            Time = DateTime.UtcNow
                        }, context).Wait();
                    });

                    Assert.IsInstanceOf<InvalidOperationException>(exception.GetBaseException());
                    Console.WriteLine($"Got expected Exception: {exception.Message}");
                }
            }
        }
        public async Task It_should_successfully_update_the_saga()
        {
            var id = Guid.NewGuid();
            var sagaData = new SagaWithoutUniquePropertyData
            {
                Id = id,
                NonUniqueString = "whatever"
            };

            var persister = new InMemorySagaPersister();

            // first session
            var session = new InMemorySynchronizedStorageSession();

            await persister.Save(sagaData, SagaCorrelationProperty.None, session, new ContextBag());

            await session.CompleteAsync();

            // second session
            var session2 = new InMemorySynchronizedStorageSession();

            var ctx = new ContextBag();
            var saga = await persister.Get<SagaWithoutUniquePropertyData>(id, session2, ctx);
            saga.NonUniqueString = "asdfasdf";

            await persister.Update(saga, session2, ctx);

            await session2.CompleteAsync();

            var result = await persister.Get<SagaWithoutUniquePropertyData>(sagaData.Id, new InMemorySynchronizedStorageSession(), new ContextBag());

            Assert.That(result, Is.Not.Null);
            Assert.That(result.NonUniqueString, Is.EqualTo("asdfasdf"));
        }
        public async Task Should_return_the_complete_list_of_timeouts()
        {
            const int numberOfTimeoutsToAdd = 10;
            var context = new ContextBag();
            for (var i = 0; i < numberOfTimeoutsToAdd; i++)
            {
                await persister.Add(new TimeoutData
                {
                    Time = DateTime.UtcNow.AddHours(-1),
                    Destination = "timeouts@" + RuntimeEnvironment.MachineName,
                    SagaId = Guid.NewGuid(),
                    State = new byte[]
                    {
                        0,
                        0,
                        133
                    },
                    Headers = new Dictionary<string, string>
                    {
                        {"Bar", "34234"},
                        {"Foo", "aString1"},
                        {"Super", "aString2"}
                    },
                    OwningTimeoutManager = "MyTestEndpoint"
                }, context);
            }

            WaitForIndexing(store);

            Assert.AreEqual(numberOfTimeoutsToAdd, (await query.GetNextChunk(DateTime.UtcNow.AddYears(-3))).DueTimeouts.Count());
        }
        public async Task Should_allow_old_timeouts_without_machine_name()
        {
            var headers = new Dictionary<string, string>
            {
                {"Bar", "34234"},
                {"Foo", "aString1"},
                {"Super", "aString2"}
            };

            var timeout = new LegacyTimeoutData
            {
                Time = DateTime.UtcNow.AddHours(-1),
                Destination = new LegacyAddress("timeouts", null),
                SagaId = Guid.NewGuid(),
                State = new byte[]
                {
                    1,
                    1,
                    133,
                    200
                },
                Headers = headers,
                OwningTimeoutManager = "MyTestEndpoint"
            };
            var context = new ContextBag();

            var session = store.OpenAsyncSession();
            await session.StoreAsync(timeout);
            await session.SaveChangesAsync();

            Assert.True(await persister.TryRemove(timeout.Id, context));
        }
        public void EnsureMappingDocumentIsUsed()
        {
            var context = new ContextBag();

            using (var db = new ReusableDB())
            {
                for (var i = 0; i < 5; i++)
                {
                    using (var store = db.NewStore())
                    {
                        ApplyTestConventions(store, ConventionType.RavenDefault);
                        store.Initialize();

                        if (i > 0)
                        {
                            // On every iteration after the first, remove the index so that operations
                            // will throw if the mapping document does not exist.
                            store.DatabaseCommands.DeleteIndex("Raven/DocumentsByEntityName");
                        }

                        var persister = new TimeoutPersister(store);

                        persister.Add(new TimeoutData
                        {
                            Destination = EndpointName,
                            Headers = new Dictionary<string, string>(),
                            OwningTimeoutManager = EndpointName,
                            SagaId = Guid.NewGuid(),
                            Time = DateTime.UtcNow
                        }, context).Wait();
                    }
                }
            }
        }
        public Task Subscribe(Subscriber subscriber, MessageType messageType, ContextBag context)
        {
            var dict = storage.GetOrAdd(messageType, type => new ConcurrentDictionary<string, Subscriber>(StringComparer.OrdinalIgnoreCase));

            dict.AddOrUpdate(subscriber.TransportAddress, _ => subscriber, (_, __) => subscriber);
            return TaskEx.CompletedTask;
        }
 public async Task Unsubscribe(Subscriber subscriber, MessageType messageType, ContextBag context)
 {
     using (var connection = connectionBuilder())
     {
         await connection.OpenAsync();
         await Unsubscribe(subscriber, connection, messageType);
     }
 }
 public Task<IEnumerable<UnicastRoutingStrategy>> Route(Type messageType, IDistributionPolicy distributionPolicy, ContextBag contextBag)
 {
     IEnumerable<UnicastRoutingStrategy> unicastRoutingStrategies = new List<UnicastRoutingStrategy>
     {
         new UnicastRoutingStrategy("Fake")
     };
     return Task.FromResult(unicastRoutingStrategies);
 }
 public Task<TimeoutData> Peek(string timeoutId, ContextBag context)
 {
     ThrowExceptionUntilWaitTimeReached();
     if (storage.ContainsKey(timeoutId))
     {
         return Task.FromResult(storage[timeoutId]);
     }
     return Task.FromResult<TimeoutData>(null);
 }
 async Task SaveSaga(SagaWithUniquePropertyData saga)
 {
     using (var session = new InMemorySynchronizedStorageSession())
     {
         var ctx = new ContextBag();
         await persister.Save(saga, SagaMetadataHelper.GetMetadata<SagaWithUniqueProperty>(saga), session, ctx);
         await session.CompleteAsync();
     }
 }
Exemplo n.º 21
0
        public Task<OutboxMessage> Get(string messageId, ContextBag options)
        {
            if (ExistingMessage != null && ExistingMessage.MessageId == messageId)
            {
                return Task.FromResult(ExistingMessage);
            }

            return Task.FromResult(default(OutboxMessage));
        }
        public async Task Subscribe(Subscriber subscriber, MessageType messageType, ContextBag context)
        {
            //When the subscriber is running V6 and UseLegacyMessageDrivenSubscriptionMode is enabled at the subscriber the 'subcriber.Endpoint' value is null
            var endpoint = subscriber.Endpoint ?? subscriber.TransportAddress.Split('@').First();
            var subscriptionClient = new SubscriptionClient { TransportAddress = subscriber.TransportAddress, Endpoint = endpoint };

            var attempts = 0;

            //note: since we have a design that can run into concurrency exceptions we perform a few retries
            // we should redesign this in the future to use a separate doc per subscriber and message type
            do
            {
                try
                {
                    using (var session = OpenAsyncSession())
                    {
                        var subscriptionDocId = Subscription.FormatId(messageType);

                        var subscription = await session.LoadAsync<Subscription>(subscriptionDocId).ConfigureAwait(false);

                        if (subscription == null)
                        {
                            subscription = new Subscription
                            {
                                Id = subscriptionDocId,
                                MessageType = messageType,
                                Subscribers = new List<SubscriptionClient>()
                            };

                            await session.StoreAsync(subscription).ConfigureAwait(false);
                        }

                        if (!subscription.Subscribers.Contains(subscriptionClient))
                        {
                            subscription.Subscribers.Add(subscriptionClient);
                        }
                        else
                        {
                            var savedSubscription = subscription.Subscribers.Single(s => s.Equals(subscriptionClient));
                            if (savedSubscription.Endpoint != subscriber.Endpoint)
                            {
                                savedSubscription.Endpoint = subscriber.Endpoint;
                            }
                        }

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

                    return;
                }
                catch (ConcurrencyException)
                {
                    attempts++;
                }
            } while (attempts < 5);
        }
 public Task<CompletableSynchronizedStorageSession> TryAdapt(OutboxTransaction transaction, ContextBag context)
 {
     var inMemOutboxTransaction = transaction as InMemoryOutboxTransaction;
     if (inMemOutboxTransaction != null)
     {
         CompletableSynchronizedStorageSession session = new InMemorySynchronizedStorageSession(inMemOutboxTransaction.Transaction);
         return Task.FromResult(session);
     }
     return EmptyTask;
 }
 public Task<CompletableSynchronizedStorageSession> TryAdapt(OutboxTransaction transaction, ContextBag context)
 {
     var ravenTransaction = transaction as RavenDBOutboxTransaction;
     if (ravenTransaction != null)
     {
         CompletableSynchronizedStorageSession session = new RavenDBSynchronizedStorageSession(ravenTransaction.AsyncSession, false);
         return Task.FromResult(session);
     }
     return EmptyResult;
 }
Exemplo n.º 25
0
 public Task<CompletableSynchronizedStorageSession> TryAdapt(OutboxTransaction transaction, ContextBag context)
 {
     var outboxTransaction = transaction as SqlOutboxTransaction;
     if (outboxTransaction != null)
     {
         CompletableSynchronizedStorageSession session = new StorageSession(outboxTransaction.Connection, outboxTransaction.Transaction, false);
         return Task.FromResult(session);
     }
     return EmptyResult;
 }
Exemplo n.º 26
0
        public Task<OutboxTransaction> BeginTransaction(ContextBag context)
        {
            var session = documentStore.OpenAsyncSession();

            session.Advanced.UseOptimisticConcurrency = true;

            context.Set(session);
            var transaction = new RavenDBOutboxTransaction(session);
            return Task.FromResult<OutboxTransaction>(transaction);
        }
Exemplo n.º 27
0
        public async Task<IEnumerable<UnicastRoutingStrategy>> Route(Type messageType, IDistributionPolicy distributionPolicy, ContextBag contextBag)
        {
            var typesToRoute = messageMetadataRegistry.GetMessageMetadata(messageType).MessageHierarchy;

            var subscribers = await GetSubscribers(contextBag, typesToRoute).ConfigureAwait(false);

            var selectedDestinations = SelectDestinationsForEachEndpoint(distributionPolicy, subscribers);

            return selectedDestinations.Select(destination => new UnicastRoutingStrategy(destination));
        }
 public Task Unsubscribe(Subscriber subscriber, MessageType messageType, ContextBag context)
 {
     ConcurrentDictionary<string, Subscriber> dict;
     if (storage.TryGetValue(messageType, out dict))
     {
         Subscriber _;
         dict.TryRemove(subscriber.TransportAddress, out _);
     }
     return TaskEx.CompletedTask;
 }
Exemplo n.º 29
0
        public Task<OutboxMessage> Get(string messageId, ContextBag context)
        {
            StoredMessage storedMessage;
            if (!storage.TryGetValue(messageId, out storedMessage))
            {
                return NoOutboxMessageTask;
            }

            return Task.FromResult(new OutboxMessage(messageId, storedMessage.TransportOperations));
        }
Exemplo n.º 30
0
        public void ShouldAllowMonkeyPatching()
        {
            var contextBag = new ContextBag();

            contextBag.Set("MonkeyPatch", "some string");

            string theValue;

            ((ReadOnlyContextBag) contextBag).TryGet("MonkeyPatch", out theValue);
            Assert.AreEqual("some string", theValue);
        }
            internal override async Task <CompletableSynchronizedStorageSession> TryAdaptTransportConnection(TransportTransaction transportTransaction, ContextBag context, IConnectionManager connectionBuilder, Func <DbConnection, DbTransaction, bool, StorageSession> storageSessionFactory)
            {
                // Transport supports DTC and uses TxScope owned by the transport
                var scopeTx = Transaction.Current;

                if (transportTransaction.TryGet(out Transaction transportTx) &&
                    scopeTx != null &&
                    transportTx != scopeTx)
                {
                    throw new Exception("A TransactionScope has been opened in the current context overriding the one created by the transport. "
                                        + "This setup can result in inconsistent data because operations done via connections enlisted in the context scope won't be committed "
                                        + "atomically with the receive transaction. To manually control the TransactionScope in the pipeline switch the transport transaction mode "
                                        + $"to values lower than '{nameof(TransportTransactionMode.TransactionScope)}'.");
                }
                var ambientTransaction = transportTx ?? scopeTx;

                if (ambientTransaction == null)
                {
                    //Other modes handled by creating a new session.
                    return(null);
                }

                var connection = await connectionBuilder.OpenConnection(context.GetIncomingMessage()).ConfigureAwait(false);

                connection.EnlistTransaction(ambientTransaction);
                return(storageSessionFactory(connection, null, true));
            }
        public Task <TSagaData> Get <TSagaData>(string propertyName, object propertyValue, SynchronizedStorageSession session, ContextBag context)
            where TSagaData : class, IContainSagaData
        {
            var key = new CorrelationId(typeof(TSagaData), propertyName, propertyValue);

            if (byCorrelationId.TryGetValue(key, out var id))
            {
                // this isn't updated atomically and may return null for an entry that has been indexed but not inserted yet
                return(Get <TSagaData>(id, session, context));
            }

            return(CachedSagaDataTask <TSagaData> .Default);
        }
        public Task Complete(IContainSagaData sagaData, SynchronizedStorageSession session, ContextBag context)
        {
            ((InMemorySynchronizedStorageSession)session).Enlist(() =>
            {
                var entry = GetEntry(context, sagaData.Id);

                if (sagasCollection.Remove(new KeyValuePair <Guid, Entry>(sagaData.Id, entry)) == false)
                {
                    throw new Exception("Saga can't be completed as it was updated by another process.");
                }

                // saga removed
                // clean the index
                if (Equals(entry.CorrelationId, NoCorrelationId) == false)
                {
                    byCorrelationIdCollection.Remove(new KeyValuePair <CorrelationId, Guid>(entry.CorrelationId, sagaData.Id));
                }
            });

            return(TaskEx.CompletedTask);
        }
 public Task <OutboxTransaction> BeginTransaction(ContextBag context)
 {
     return(Task.FromResult <OutboxTransaction>(new NoOpOutboxTransaction()));
 }
Exemplo n.º 35
0
 public Task <CompletableSynchronizedStorageSession> TryAdapt(TransportTransaction transportTransaction, ContextBag context)
 {
     return(EmptyResult);
 }
Exemplo n.º 36
0
        public Task Update(IContainSagaData sagaData, SynchronizedStorageSession session, ContextBag context)
        {
            // store the schema version in case it has changed
            var container       = context.Get <SagaDataContainer>($"{SagaContainerContextKeyPrefix}{sagaData.Id}");
            var documentSession = session.RavenSession();

            documentSession.StoreSchemaVersionInMetadata(container);

            // dirty tracking will do the rest for us
            return(Task.CompletedTask);
        }
Exemplo n.º 37
0
        public async Task Save(IContainSagaData sagaData, SagaCorrelationProperty correlationProperty, SynchronizedStorageSession session, ContextBag context)
        {
            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).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).ConfigureAwait(false);

            documentSession.StoreSchemaVersionInMetadata(sagaUniqueIdentity);
        }
 public Task <ICompletableSynchronizedStorageSession> TryAdapt(IOutboxTransaction transaction, ContextBag context, CancellationToken cancellationToken = default)
 {
     if (transaction is NonDurableOutboxTransaction inMemOutboxTransaction)
     {
         ICompletableSynchronizedStorageSession session = new NonDurableSynchronizedStorageSession(inMemOutboxTransaction.Transaction);
         return(Task.FromResult(session));
     }
     return(EmptyTask);
 }
    public Task <IEnumerable <Subscriber> > GetSubscriberAddressesForMessage(IEnumerable <MessageType> messageTypes, ContextBag context)
    {
        var result = new HashSet <Subscriber>();

        foreach (var m in messageTypes)
        {
            if (storage.TryGetValue(m, out var list))
            {
                result.UnionWith(list.Values);
            }
        }
        return(Task.FromResult((IEnumerable <Subscriber>)result));
    }
 public Task Dispatch(TransportOperations outgoingMessages, TransportTransaction transaction, ContextBag context)
 {
     return(DispatcherAction(outgoingMessages));
 }
Exemplo n.º 41
0
        public async Task <T> Get <T>(Guid sagaId, SynchronizedStorageSession session, ContextBag context)
            where T : class, IContainSagaData
        {
            var documentSession = session.RavenSession();
            var docId           = DocumentIdForSagaData(documentSession, typeof(T), sagaId);
            var container       = await documentSession.LoadAsync <SagaDataContainer>(docId).ConfigureAwait(false);

            if (container == null)
            {
                return(default);
    async Task <IEnumerable <Subscriber> > GetAddressesForEndpoint(string endpoint, MessageType messageType, ContextBag emptyContext)
    {
        var messageTypes = new List <MessageType>
        {
            messageType
        };
        var addressesForMessage = await subscriptionStorage.GetSubscriberAddressesForMessage(messageTypes, emptyContext)
                                  .ConfigureAwait(false);

        return(addressesForMessage
               .Where(subscriber =>
        {
            return string.Equals(subscriber.Endpoint, endpoint, StringComparison.OrdinalIgnoreCase);
        }));
    }
 public Task SetAsDispatched(string messageId, ContextBag options)
 {
     return(TaskEx.CompletedTask);
 }
    Task UnsubscribeFromEndpoint(IEnumerable <Subscriber> addressesForEndpoint, MessageType messageType, ContextBag emptyContext)
    {
        var tasks = addressesForEndpoint
                    .Select(address => subscriptionStorage.Unsubscribe(
                                subscriber: address,
                                messageType: messageType,
                                context: emptyContext
                                ));

        return(Task.WhenAll(tasks));
    }
 public Task <OutboxMessage> Get(string messageId, ContextBag options)
 {
     return(NoOutboxMessageTask);
 }
Exemplo n.º 46
0
 public Task <ICompletableSynchronizedStorageSession> OpenSession(ContextBag contextBag, CancellationToken cancellationToken = default) =>
 Task.FromResult <ICompletableSynchronizedStorageSession>(new NonDurableSynchronizedStorageSession());
        public Task <TSagaData> Get <TSagaData>(Guid sagaId, SynchronizedStorageSession session, ContextBag context)
            where TSagaData : class, IContainSagaData
        {
            if (sagas.TryGetValue(sagaId, out var value))
            {
                SetEntry(context, sagaId, value);

                var data = value.GetSagaCopy();
                return(Task.FromResult((TSagaData)data));
            }

            return(CachedSagaDataTask <TSagaData> .Default);
        }
Exemplo n.º 48
0
 public CosmosOutboxTransaction(ContainerHolderResolver resolver, ContextBag context)
 {
     StorageSession = new StorageSession(resolver, context, false);
 }
Exemplo n.º 49
0
        public async Task SendLocal(IFullMessage message, IDictionary <string, string> headers = null)
        {
            Logger.Write(LogLevel.Debug, () => $"Sending local message of type [{message.Message.GetType().FullName}]");

            while (!Bus.BusOnline)
            {
                await Task.Delay(100).ConfigureAwait(false);
            }

            headers = headers ?? new Dictionary <string, string>();

            var contextBag = new ContextBag();

            // Hack to get all the events to invoker without NSB deserializing
            contextBag.Set(Defaults.LocalHeader, message.Message);


            var processed = false;
            var numberOfDeliveryAttempts = 0;

            var messageId = Guid.NewGuid().ToString();
            var corrId    = "";

            if (message?.Headers?.ContainsKey(Headers.CorrelationId) ?? false)
            {
                corrId = message.Headers[Headers.CorrelationId];
            }

            while (!processed)
            {
                var transportTransaction = new TransportTransaction();
                var tokenSource          = new CancellationTokenSource();

                var messageType = message.Message.GetType();
                if (!messageType.IsInterface)
                {
                    messageType = _mapper.GetMappedTypeFor(messageType) ?? messageType;
                }

                var finalHeaders = message.Headers.Merge(headers);
                finalHeaders[Headers.EnclosedMessageTypes] = messageType.AssemblyQualifiedName;
                finalHeaders[Headers.MessageIntent]        = MessageIntentEnum.Send.ToString();
                finalHeaders[Headers.MessageId]            = messageId;
                finalHeaders[Headers.CorrelationId]        = corrId;


                try
                {
                    // Don't re-use the event id for the message id
                    var messageContext = new MessageContext(messageId,
                                                            finalHeaders,
                                                            Marker, transportTransaction, tokenSource,
                                                            contextBag);
                    await Bus.OnMessage(messageContext).ConfigureAwait(false);

                    _metrics.Mark("Dispatched Messages", Unit.Message);
                    processed = true;
                }
                catch (ObjectDisposedException)
                {
                    // NSB transport has been disconnected
                    throw new OperationCanceledException();
                }
                catch (Exception ex)
                {
                    _metrics.Mark("Dispatched Errors", Unit.Errors);

                    ++numberOfDeliveryAttempts;

                    // Don't retry a cancelation
                    if (tokenSource.IsCancellationRequested)
                    {
                        numberOfDeliveryAttempts = Int32.MaxValue;
                    }

                    var messageBytes = _serializer.Serialize(message.Message);

                    var errorContext = new ErrorContext(ex, finalHeaders,
                                                        messageId,
                                                        messageBytes, transportTransaction,
                                                        numberOfDeliveryAttempts);
                    if (await Bus.OnError(errorContext).ConfigureAwait(false) ==
                        ErrorHandleResult.Handled || tokenSource.IsCancellationRequested)
                    {
                        break;
                    }
                }
            }
        }
Exemplo n.º 50
0
 public abstract Task <IContainSagaData> Find(IBuilder builder, SagaFinderDefinition finderDefinition, SynchronizedStorageSession storageSession, ContextBag context, object message);
Exemplo n.º 51
0
        public async Task SendLocal(IFullMessage[] messages, IDictionary <string, string> headers = null)
        {
            Logger.Write(LogLevel.Debug, () => $"Sending {messages.Length} bulk local messages");

            while (!Bus.BusOnline)
            {
                await Task.Delay(100).ConfigureAwait(false);
            }

            headers = headers ?? new Dictionary <string, string>();

            await messages.GroupBy(x => x.Message.GetType()).ToArray().StartEachAsync(3, async(group) =>
            {
                var groupedMessages = group.Select(x => x.Message as IDelayedMessage).ToArray();

                var contextBag = new ContextBag();
                // Hack to get all the events to invoker without NSB deserializing
                contextBag.Set(Defaults.LocalBulkHeader, groupedMessages);


                var processed = false;
                var numberOfDeliveryAttempts = 0;

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

                while (!processed)
                {
                    var transportTransaction = new TransportTransaction();
                    var tokenSource          = new CancellationTokenSource();

                    var messageType = group.Key;
                    if (!messageType.IsInterface)
                    {
                        messageType = _mapper.GetMappedTypeFor(messageType) ?? messageType;
                    }

                    var finalHeaders = headers.Merge(new Dictionary <string, string>()
                    {
                        [Headers.EnclosedMessageTypes] = messageType.AssemblyQualifiedName,
                        [Headers.MessageIntent]        = MessageIntentEnum.Send.ToString(),
                        [Headers.MessageId]            = messageId
                    });


                    try
                    {
                        // Don't re-use the event id for the message id
                        var messageContext = new MessageContext(messageId,
                                                                finalHeaders,
                                                                Marker, transportTransaction, tokenSource,
                                                                contextBag);
                        await Bus.OnMessage(messageContext).ConfigureAwait(false);
                        _metrics.Mark("Dispatched Messages", Unit.Message, groupedMessages.Length);
                        processed = true;
                    }
                    catch (ObjectDisposedException)
                    {
                        // NSB transport has been disconnected
                        throw new OperationCanceledException();
                    }
                    catch (Exception ex)
                    {
                        _metrics.Mark("Dispatched Errors", Unit.Errors, groupedMessages.Length);

                        ++numberOfDeliveryAttempts;

                        // Don't retry a cancelation
                        if (tokenSource.IsCancellationRequested)
                        {
                            numberOfDeliveryAttempts = Int32.MaxValue;
                        }

                        var messageList = groupedMessages.ToList();
                        foreach (var message in groupedMessages)
                        {
                            var messageBytes = _serializer.Serialize(message.Message);
                            var errorContext = new ErrorContext(ex, message.Headers.Merge(finalHeaders),
                                                                messageId,
                                                                messageBytes, transportTransaction,
                                                                numberOfDeliveryAttempts);
                            if (await Bus.OnError(errorContext).ConfigureAwait(false) == ErrorHandleResult.Handled)
                            {
                                messageList.Remove(message);
                            }
                        }
                        if (messageList.Count == 0)
                        {
                            break;
                        }
                        groupedMessages = messageList.ToArray();
                    }
                }
            }).ConfigureAwait(false);
        }
Exemplo n.º 52
0
 public async Task <IContainSagaData> Load(ISagaPersister persister, string sagaId, SynchronizedStorageSession storageSession, ContextBag context)
 {
     return(await persister.Get <T>(Guid.Parse(sagaId), storageSession, context).ConfigureAwait(false));
 }
        public Task Dispatch(TransportOperations outgoingMessages, TransportTransaction transaction, ContextBag context)
        {
            foreach (var operation in outgoingMessages.UnicastTransportOperations)
            {
                var destinationBasePath = DirectoryBuilder.BuildBasePath(operation.Destination);
                var nativeMessageId     = Guid.NewGuid().ToString();
                var bodyPath            = Path.Combine(destinationBasePath, ".bodies", $"{nativeMessageId}.xml");

                var bodyDirectory = Path.GetDirectoryName(bodyPath);
                if (bodyDirectory != null)
                {
                    if (!Directory.Exists(bodyDirectory))
                    {
                        Directory.CreateDirectory(bodyDirectory);
                    }
                }

                File.WriteAllBytes(bodyPath, operation.Message.Body);

                var messageContents = new List <string>
                {
                    bodyPath,
                    HeaderSerializer.Serialize(operation.Message.Headers)
                };

                var messagePath = Path.Combine(destinationBasePath, $"{nativeMessageId}.txt");

                // Write to a temp file first so an atomic move can be done.
                // This avoids the file being locked when the receiver triest to process it.
                var tempFilePath = Path.GetTempFileName();
                File.WriteAllLines(tempFilePath, messageContents);
                File.Move(tempFilePath, messagePath);
            }

            return(Task.CompletedTask);
        }
Exemplo n.º 54
0
 public Task <bool> TryRemove(string timeoutId, ContextBag context)
 {
     throw new Exception("Simulated exception on removing timeout data.");
 }
Exemplo n.º 55
0
    public Task <IEnumerable <Subscriber> > GetSubscriberAddressesForMessage(IEnumerable <MessageType> messageHierarchy, ContextBag context)
    {
        var types = messageHierarchy.ToList();

        if (cacheFor == null)
        {
            return(GetSubscriptions(types));
        }

        var key = GetKey(types);

        var cacheItem = Cache.GetOrAdd(key,
                                       valueFactory: _ => new CacheItem
        {
            Stored      = DateTime.UtcNow,
            Subscribers = GetSubscriptions(types)
        });

        var age = DateTime.UtcNow - cacheItem.Stored;

        if (age >= cacheFor)
        {
            cacheItem.Subscribers = GetSubscriptions(types);
            cacheItem.Stored      = DateTime.UtcNow;
        }
        return(cacheItem.Subscribers);
    }
Exemplo n.º 56
0
 public Task RemoveTimeoutBy(Guid sagaId, ContextBag context)
 {
     throw new NotImplementedException();
 }
Exemplo n.º 57
0
    public async Task <TSagaData> Get <TSagaData>(Guid sagaId, SynchronizedStorageSession session, ContextBag context, CancellationToken cancellationToken = default)
        where TSagaData : class, IContainSagaData
    {
        var result = await Get <TSagaData>(sagaId, session, cancellationToken).ConfigureAwait(false);

        return(SetConcurrency(result, context));
    }
 public Task Store(OutboxMessage message, OutboxTransaction transaction, ContextBag options)
 {
     return(TaskEx.CompletedTask);
 }
 public Task <ICompletableSynchronizedStorageSession> TryAdapt(TransportTransaction transportTransaction, ContextBag context, CancellationToken cancellationToken = default)
 {
     if (transportTransaction.TryGet(out Transaction ambientTransaction))
     {
         var transaction = new NonDurableTransaction();
         ICompletableSynchronizedStorageSession session = new NonDurableSynchronizedStorageSession(transaction);
         ambientTransaction.EnlistVolatile(new EnlistmentNotification2(transaction), EnlistmentOptions.None);
         return(Task.FromResult(session));
     }
     return(EmptyTask);
 }
Exemplo n.º 60
0
        public override async Task <IContainSagaData> Find(IServiceProvider builder, SagaFinderDefinition finderDefinition, SynchronizedStorageSession storageSession, ContextBag context, object message, IReadOnlyDictionary <string, string> messageHeaders)
        {
            var customFinderType = (Type)finderDefinition.Properties["custom-finder-clr-type"];

            var finder = (IFindSagas <TSagaData> .Using <TMessage>)builder.GetService(customFinderType);

            return(await finder
                   .FindBy((TMessage)message, storageSession, context)
                   .ThrowIfNull()
                   .ConfigureAwait(false));
        }