コード例 #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="CommandProcessor"/> class.
        /// Use this constructor when both rpc support is required
        /// </summary>
        /// <param name="subscriberRegistry">The subscriber registry.</param>
        /// <param name="handlerFactory">The handler factory.</param>
        /// <param name="requestContextFactory">The request context factory.</param>
        /// <param name="policyRegistry">The policy registry.</param>
        /// <param name="mapperRegistry">The mapper registry.</param>
        /// <param name="outBox">The outbox</param>
        /// <param name="producerRegistry">The register of producers via whom we send messages over the external bus</param>
        /// <param name="replySubscriptions">The Subscriptions for creating the reply queues</param>
        /// <param name="responseChannelFactory">If we are expecting a response, then we need a channel to listen on</param>
        /// <param name="outboxTimeout">How long should we wait to write to the outbox</param>
        /// <param name="featureSwitchRegistry">The feature switch config provider.</param>
        /// <param name="inboxConfiguration">Do we want to insert an inbox handler into pipelines without the attribute. Null (default = no), yes = how to configure</param>
        /// <param name="boxTransactionConnectionProvider">The Box Connection Provider to use when Depositing into the outbox.</param>
        public CommandProcessor(
            IAmASubscriberRegistry subscriberRegistry,
            IAmAHandlerFactory handlerFactory,
            IAmARequestContextFactory requestContextFactory,
            IPolicyRegistry <string> policyRegistry,
            IAmAMessageMapperRegistry mapperRegistry,
            IAmAnOutbox <Message> outBox,
            IAmAProducerRegistry producerRegistry,
            IEnumerable <Subscription> replySubscriptions,
            int outboxTimeout = 300,
            IAmAFeatureSwitchRegistry featureSwitchRegistry = null,
            IAmAChannelFactory responseChannelFactory       = null,
            InboxConfiguration inboxConfiguration           = null,
            IAmABoxTransactionConnectionProvider boxTransactionConnectionProvider = null)
            : this(subscriberRegistry, handlerFactory, requestContextFactory, policyRegistry)
        {
            _mapperRegistry                   = mapperRegistry;
            _featureSwitchRegistry            = featureSwitchRegistry;
            _responseChannelFactory           = responseChannelFactory;
            _inboxConfiguration               = inboxConfiguration;
            _boxTransactionConnectionProvider = boxTransactionConnectionProvider;
            _replySubscriptions               = replySubscriptions;

            InitExtServiceBus(policyRegistry, outBox, outboxTimeout, producerRegistry);

            ConfigureCallbacks(producerRegistry);
        }
コード例 #2
0
ファイル: MySqlOutboxSync.cs プロジェクト: preardon/Brighter
        public async Task AddAsync(Message message, int outBoxTimeout = -1, CancellationToken cancellationToken = default(CancellationToken),
                                   IAmABoxTransactionConnectionProvider transactionConnectionProvider = null)
        {
            var parameters = InitAddDbParameters(message);

            var connectionProvider = _connectionProvider;

            if (transactionConnectionProvider != null && transactionConnectionProvider is IMySqlTransactionConnectionProvider provider)
            {
                connectionProvider = provider;
            }

            var connection = connectionProvider.GetConnection();


            if (connection.State != ConnectionState.Open)
            {
                await connection.OpenAsync(cancellationToken).ConfigureAwait(ContinueOnCapturedContext);
            }
            using (var command = connection.CreateCommand())
            {
                var sql = GetAddSql();
                command.CommandText = sql;
                AddParamtersParamArrayToCollection(parameters.ToArray(), command);

                try
                {
                    if (connectionProvider.IsSharedConnection)
                    {
                        command.Transaction = connectionProvider.GetTransaction();
                    }
                    await command.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(ContinueOnCapturedContext);
                }
                catch (MySqlException sqlException)
                {
                    if (IsExceptionUnqiueOrDuplicateIssue(sqlException))
                    {
                        s_logger.LogWarning(
                            "MsSqlOutbox: A duplicate Message with the MessageId {Id} was inserted into the Outbox, ignoring and continuing",
                            message.Id);
                        return;
                    }

                    throw;
                }
                finally
                {
                    if (!connectionProvider.IsSharedConnection)
                    {
                        connection.Dispose();
                    }
                    else if (!connectionProvider.HasOpenTransaction)
                    {
                        connection.Close();
                    }
                }
            }
        }
コード例 #3
0
 /// <summary>
 /// The <see cref="CommandProcessor"/> wants to support <see cref="CommandProcessor.Post{T}(T)"/> or <see cref="CommandProcessor.Repost"/> using an external bus.
 /// You need to provide a policy to specify how QoS issues, specifically <see cref="CommandProcessor.RETRYPOLICY "/> or <see cref="CommandProcessor.CIRCUITBREAKER "/>
 /// are handled by adding appropriate <see cref="Policies"/> when choosing this option.
 ///
 /// </summary>
 /// <param name="configuration">The Task Queues configuration.</param>
 /// <param name="outbox">The Outbox.</param>
 /// <param name="boxTransactionConnectionProvider"></param>
 /// <returns>INeedARequestContext.</returns>
 public INeedARequestContext ExternalBus(ExternalBusConfiguration configuration, IAmAnOutbox <Message> outbox, IAmABoxTransactionConnectionProvider boxTransactionConnectionProvider = null)
 {
     _useExternalBus = true;
     _producers      = configuration.ProducerRegistry;
     _outbox         = outbox;
     _overridingBoxTransactionConnectionProvider = boxTransactionConnectionProvider;
     _messageMapperRegistry = configuration.MessageMapperRegistry;
     _outboxWriteTimeout    = configuration.OutboxWriteTimeout;
     return(this);
 }
コード例 #4
0
        internal void AddToOutbox <T>(T request, Message message, IAmABoxTransactionConnectionProvider overridingTransactionConnectionProvider = null) where T : class, IRequest
        {
            CheckOutboxOutstandingLimit();

            var written = Retry(() => { OutBox.Add(message, OutboxTimeout, overridingTransactionConnectionProvider); });

            if (!written)
            {
                throw new ChannelFailureException($"Could not write request {request.Id} to the outbox");
            }
        }
コード例 #5
0
        /// <summary>
        ///     Adds the specified message.
        ///     The message must have a 'streamId' and an 'eventNumber' in the message header bag.
        ///     The 'streamId' is the name of the stream to append the message to.
        ///     The 'eventNumber' should be one greater than the last event in the stream.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="outBoxTimeout">The outBoxTimeout.</param>
        /// <returns>Task.</returns>
        public void Add(Message message, int outBoxTimeout = -1, IAmABoxTransactionConnectionProvider transactionConnectionProvider = null)
        {
            s_logger.LogDebug("Adding message to Event Store Outbox: {Request}", JsonSerializer.Serialize(message, JsonSerialisationOptions.Options));

            var headerBag             = message.Header.Bag;
            var streamId              = ExtractStreamIdFromHeader(headerBag, message.Id);
            var eventNumber           = ExtractEventNumberFromHeader(headerBag, message.Id);
            var numberOfPreviousEvent = eventNumber - 1;
            var eventData             = EventStoreMessageWriter.CreateEventData(message);

            _eventStore.AppendToStreamAsync(streamId, numberOfPreviousEvent, eventData).Wait();
        }
コード例 #6
0
        /// <summary>
        ///     Adds the specified message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="outBoxTimeout"></param>
        /// <param name="transactionConnectionProvider">Connection Provider to use for this call</param>
        /// <returns>Task.</returns>
        public void Add(Message message, int outBoxTimeout = -1, IAmABoxTransactionConnectionProvider transactionConnectionProvider = null)
        {
            var parameters = InitAddDbParameters(message);

            var connectionProvider = _connectionProvider;

            if (transactionConnectionProvider != null && transactionConnectionProvider is IMsSqlTransactionConnectionProvider provider)
            {
                connectionProvider = provider;
            }

            var connection = connectionProvider.GetConnection();

            if (connection.State != ConnectionState.Open)
            {
                connection.Open();
            }
            using (var command = InitAddDbCommand(connection, parameters))
            {
                try
                {
                    if (connectionProvider.HasOpenTransaction)
                    {
                        command.Transaction = connectionProvider.GetTransaction();
                    }
                    command.ExecuteNonQuery();
                }
                catch (SqlException sqlException)
                {
                    if (sqlException.Number == MsSqlDuplicateKeyError_UniqueIndexViolation ||
                        sqlException.Number == MsSqlDuplicateKeyError_UniqueConstraintViolation)
                    {
                        s_logger.LogWarning(
                            "MsSqlOutbox: A duplicate Message with the MessageId {Id} was inserted into the Outbox, ignoring and continuing",
                            message.Id);
                        return;
                    }

                    throw;
                }
                finally
                {
                    if (!connectionProvider.IsSharedConnection)
                    {
                        connection.Dispose();
                    }
                    else if (!connectionProvider.HasOpenTransaction)
                    {
                        connection.Close();
                    }
                }
            }
        }
コード例 #7
0
ファイル: InMemoryOutbox.cs プロジェクト: preardon/Brighter
        /// <summary>
        /// Adds the specified message
        /// </summary>
        /// <param name="message"></param>
        /// <param name="outBoxTimeout"></param>
        /// <param name="transactionConnectionProvider">This is not used for the In Memory Outbox.</param>
        public void Add(Message message, int outBoxTimeout = -1, IAmABoxTransactionConnectionProvider transactionConnectionProvider = null)
        {
            ClearExpiredMessages();
            EnforceCapacityLimit();

            var key = OutboxEntry.ConvertKey(message.Id);

            if (!_requests.ContainsKey(key))
            {
                if (!_requests.TryAdd(key, new OutboxEntry {
                    Message = message, WriteTime = DateTime.UtcNow
                }))
                {
                    throw new Exception($"Could not add message with Id: {message.Id} to outbox");
                }
            }
        }
コード例 #8
0
ファイル: SqliteOutboxSync.cs プロジェクト: preardon/Brighter
        /// <summary>
        ///     Adds the specified message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="outBoxTimeout"></param>
        /// <returns>Task.</returns>
        public void Add(Message message, int outBoxTimeout = -1, IAmABoxTransactionConnectionProvider transactionConnectionProvider = null)
        {
            var parameters = InitAddDbParameters(message);

            var connectionProvider = _connectionProvider;

            if (transactionConnectionProvider != null && transactionConnectionProvider is ISqliteTransactionConnectionProvider provider)
            {
                connectionProvider = provider;
            }

            var connection = connectionProvider.GetConnection();

            if (connection.State != ConnectionState.Open)
            {
                connection.Open();
            }
            var sql = GetAddSql();

            using (var command = connection.CreateCommand())
            {
                command.CommandText = sql;
                AddParamtersParamArrayToCollection(parameters.ToArray(), command);

                try
                {
                    if (connectionProvider.HasOpenTransaction)
                    {
                        command.Transaction = connectionProvider.GetTransaction();
                    }
                    command.ExecuteNonQuery();
                }
                catch (SqliteException sqlException)
                {
                    if (IsExceptionUnqiueOrDuplicateIssue(sqlException))
                    {
                        s_logger.LogWarning(
                            "MsSqlOutbox: A duplicate Message with the MessageId {Id} was inserted into the Outbox, ignoring and continuing",
                            message.Id);
                        return;
                    }

                    throw;
                }
            }
        }
コード例 #9
0
        private IPostgreSqlConnectionProvider GetConnectionProvider(IAmABoxTransactionConnectionProvider transactionConnectionProvider = null)
        {
            var connectionProvider = _connectionProvider ?? new PostgreSqlNpgsqlConnectionProvider(_configuration);

            if (transactionConnectionProvider != null)
            {
                if (transactionConnectionProvider is IPostgreSqlTransactionConnectionProvider provider)
                {
                    connectionProvider = provider;
                }
                else
                {
                    throw new Exception($"{nameof(transactionConnectionProvider)} does not implement interface {nameof(IPostgreSqlTransactionConnectionProvider)}.");
                }
            }

            return(connectionProvider);
        }
コード例 #10
0
        private Guid DepositPost <T>(T request, IAmABoxTransactionConnectionProvider connectionProvider) where T : class, IRequest
        {
            s_logger.LogInformation("Save request: {RequestType} {Id}", request.GetType(), request.Id);

            if (!_bus.HasOutbox())
            {
                throw new InvalidOperationException("No outbox defined.");
            }

            var messageMapper = _mapperRegistry.Get <T>();

            if (messageMapper == null)
            {
                throw new ArgumentOutOfRangeException($"No message mapper registered for messages of type: {typeof(T)}");
            }

            var message = messageMapper.MapToMessage(request);

            _bus.AddToOutbox(request, message, connectionProvider);

            return(message.Id);
        }
コード例 #11
0
        /// <summary>
        /// Initializes a new instance of the <see cref="CommandProcessor"/> class.
        /// Use this constructor when only posting messages to an external bus is required
        /// </summary>
        /// <param name="requestContextFactory">The request context factory.</param>
        /// <param name="policyRegistry">The policy registry.</param>
        /// <param name="mapperRegistry">The mapper registry.</param>
        /// <param name="outBox">The outbox</param>
        /// <param name="producerRegistry">The register of producers via whom we send messages over the external bus</param>
        /// <param name="outboxTimeout">How long should we wait to write to the outbox</param>
        /// <param name="featureSwitchRegistry">The feature switch config provider.</param>
        /// <param name="inboxConfiguration">Do we want to insert an inbox handler into pipelines without the attribute. Null (default = no), yes = how to configure</param>
        /// <param name="boxTransactionConnectionProvider">The Box Connection Provider to use when Depositing into the outbox.</param>
        public CommandProcessor(
            IAmARequestContextFactory requestContextFactory,
            IPolicyRegistry <string> policyRegistry,
            IAmAMessageMapperRegistry mapperRegistry,
            IAmAnOutbox <Message> outBox,
            IAmAProducerRegistry producerRegistry,
            int outboxTimeout = 300,
            IAmAFeatureSwitchRegistry featureSwitchRegistry = null,
            InboxConfiguration inboxConfiguration           = null,
            IAmABoxTransactionConnectionProvider boxTransactionConnectionProvider = null)
        {
            _requestContextFactory            = requestContextFactory;
            _policyRegistry                   = policyRegistry;
            _mapperRegistry                   = mapperRegistry;
            _featureSwitchRegistry            = featureSwitchRegistry;
            _inboxConfiguration               = inboxConfiguration;
            _boxTransactionConnectionProvider = boxTransactionConnectionProvider;

            InitExtServiceBus(policyRegistry, outBox, outboxTimeout, producerRegistry);

            ConfigureCallbacks(producerRegistry);
        }
コード例 #12
0
        private async Task <Guid> DepositPostAsync <T>(T request, IAmABoxTransactionConnectionProvider connectionProvider, bool continueOnCapturedContext = false,
                                                       CancellationToken cancellationToken = default(CancellationToken)) where T : class, IRequest
        {
            s_logger.LogInformation("Save request: {RequestType} {Id}", request.GetType(), request.Id);

            if (!_bus.HasAsyncOutbox())
            {
                throw new InvalidOperationException("No async outbox defined.");
            }

            var messageMapper = _mapperRegistry.Get <T>();

            if (messageMapper == null)
            {
                throw new ArgumentOutOfRangeException($"No message mapper registered for messages of type: {typeof(T)}");
            }

            var message = messageMapper.MapToMessage(request);

            await _bus.AddToOutboxAsync(request, continueOnCapturedContext, cancellationToken, message, connectionProvider);

            return(message.Id);
        }
コード例 #13
0
        private static INeedARequestContext AddExternalBusMaybe(
            IBrighterOptions options,
            IAmAProducerRegistry producerRegistry,
            INeedMessaging messagingBuilder,
            MessageMapperRegistry messageMapperRegistry,
            InboxConfiguration inboxConfiguration,
            IAmAnOutboxSync <Message> outbox,
            IAmABoxTransactionConnectionProvider overridingConnectionProvider,
            IUseRpc useRequestResponse)
        {
            ExternalBusType externalBusType = GetExternalBusType(producerRegistry, useRequestResponse);

            if (externalBusType == ExternalBusType.None)
            {
                return(messagingBuilder.NoExternalBus());
            }
            else if (externalBusType == ExternalBusType.FireAndForget)
            {
                return(messagingBuilder.ExternalBus(
                           new ExternalBusConfiguration(producerRegistry, messageMapperRegistry, useInbox: inboxConfiguration),
                           outbox,
                           overridingConnectionProvider));
            }
            else if (externalBusType == ExternalBusType.RPC)
            {
                return(messagingBuilder.ExternalRPC(
                           new ExternalBusConfiguration(
                               producerRegistry,
                               messageMapperRegistry,
                               responseChannelFactory: options.ChannelFactory,
                               useInbox: inboxConfiguration),
                           outbox,
                           useRequestResponse.ReplyQueueSubscriptions));
            }

            throw new ArgumentOutOfRangeException("The external bus type requested was not understood");
        }
コード例 #14
0
 public void Add(Message message, int outBoxTimeout = -1, IAmABoxTransactionConnectionProvider transactionConnectionProvider = null)
 {
     //discard message
 }
コード例 #15
0
        internal async Task AddToOutboxAsync <T>(T request, bool continueOnCapturedContext, CancellationToken cancellationToken, Message message, IAmABoxTransactionConnectionProvider overridingTransactionConnectionProvider = null)
            where T : class, IRequest
        {
            CheckOutboxOutstandingLimit();

            var written = await RetryAsync(async ct => { await AsyncOutbox.AddAsync(message, OutboxTimeout, ct, overridingTransactionConnectionProvider).ConfigureAwait(continueOnCapturedContext); },
                                           continueOnCapturedContext, cancellationToken).ConfigureAwait(continueOnCapturedContext);

            if (!written)
            {
                throw new ChannelFailureException($"Could not write request {request.Id} to the outbox");
            }
        }
コード例 #16
0
        /// <summary>
        /// Awaitable add the specified message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="outBoxTimeout">The time allowed for the write in milliseconds; on a -1 default</param>
        /// <param name="cancellationToken">Allows the sender to cancel the request pipeline. Optional</param>
        /// <returns><see cref="Task"/>.</returns>
        public async Task AddAsync(Message message, int outBoxTimeout  = -1,
                                   CancellationToken cancellationToken = default(CancellationToken), IAmABoxTransactionConnectionProvider transactionConnectionProvider = null)
        {
            s_logger.LogDebug("Adding message to Event Store Outbox: {Request}", JsonSerializer.Serialize(message, JsonSerialisationOptions.Options));

            var streamId              = ExtractStreamIdFromHeader(message.Header.Bag, message.Id);
            var eventNumber           = ExtractEventNumberFromHeader(message.Header.Bag, message.Id);
            var numberOfPreviousEvent = eventNumber - 1;
            var eventData             = EventStoreMessageWriter.CreateEventData(message);

            await _eventStore.AppendToStreamAsync(streamId, numberOfPreviousEvent, eventData);
        }
コード例 #17
0
        public Task AddAsync(Message message, int outBoxTimeout = -1, CancellationToken cancellationToken = default(CancellationToken), IAmABoxTransactionConnectionProvider transactionConnectionProvider = null)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(Task.FromCanceled(cancellationToken));
            }

            Add(message, outBoxTimeout);

            return(Task.FromResult(0));
        }
コード例 #18
0
 public void Add(Message message, int outBoxTimeout = -1, IAmABoxTransactionConnectionProvider transactionConnectionProvider = null)
 {
     _posts.Add(new OutboxEntry {
         Message = message, TimeDeposited = DateTime.UtcNow
     });
 }
コード例 #19
0
ファイル: InMemoryOutbox.cs プロジェクト: preardon/Brighter
        /// <summary>
        /// Adds the specified message
        /// </summary>
        /// <param name="message"></param>
        /// <param name="outBoxTimeout"></param>
        /// <param name="cancellationToken"></param>
        /// <param name="transactionConnectionProvider">This is not used for the In Memory Outbox.</param>
        /// <returns></returns>
        public Task AddAsync(Message message, int outBoxTimeout = -1, CancellationToken cancellationToken = default(CancellationToken), IAmABoxTransactionConnectionProvider transactionConnectionProvider = null)
        {
            var tcs = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously);

            if (cancellationToken.IsCancellationRequested)
            {
                tcs.SetCanceled();
                return(tcs.Task);
            }

            Add(message, outBoxTimeout);

            tcs.SetResult(new object());
            return(tcs.Task);
        }
コード例 #20
0
 /// <inheritdoc />
 /// <summary>
 ///     Adds a message to the store
 /// </summary>
 /// <param name="message">The message to be stored</param>
 /// <param name="outBoxTimeout">Timeout in milliseconds; -1 for default timeout</param>
 public void Add(Message message, int outBoxTimeout = -1, IAmABoxTransactionConnectionProvider transactionConnectionProvider = null)
 {
     AddAsync(message, outBoxTimeout).ConfigureAwait(ContinueOnCapturedContext).GetAwaiter().GetResult();
 }
コード例 #21
0
        /// <inheritdoc />
        /// <summary>
        ///     Adds a message to the store
        /// </summary>
        /// <param name="message">The message to be stored</param>
        /// <param name="outBoxTimeout">Timeout in milliseconds; -1 for default timeout</param>
        /// <param name="cancellationToken">Allows the sender to cancel the request pipeline. Optional</param>
        public async Task AddAsync(Message message, int outBoxTimeout = -1, CancellationToken cancellationToken = default(CancellationToken), IAmABoxTransactionConnectionProvider transactionConnectionProvider = null)
        {
            var messageToStore = new MessageItem(message);

            await _context.SaveAsync(
                messageToStore,
                new DynamoDBOperationConfig { OverrideTableName = _configuration.TableName },
                cancellationToken)
            .ConfigureAwait(ContinueOnCapturedContext);
        }