public Task PublishAsync <TEvent>(TEvent @event) where TEvent : EventBase { Check.NotNull(@event, nameof(@event)); if (!_connection.IsConnected) { _connection.TryConnect(); } var policy = Policy.Handle <BrokerUnreachableException>() .Or <SocketException>() .WaitAndRetry(_options.RetryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) => { _logger.LogWarning(ex, $"Could not publish event: {@event.EventId} after {time.TotalSeconds:n1}s ({ex.Message})"); }); IModel channel = null; try { var eventName = @event.GetType().GetEventName(); var bytes = Encoding.UTF8.GetBytes(Default.JsonHelper.Serialize(@event)); policy.Execute(() => { if (channel == null) { channel = _connection.CreateModel(); _logger.LogTrace($"Declaring RabbitMQ exchange to publish event: {@event.EventId}"); channel.ExchangeDeclare(_options.Exchange, "direct"); } var properties = channel.CreateBasicProperties(); properties.DeliveryMode = 2; // persistent _logger.LogTrace($"Publishing event to RabbitMQ: {@event.EventId}"); channel.BasicPublish(_options.Exchange, eventName, true, properties, bytes); channel.Dispose(); }); } finally { // channel.Close(); channel?.Dispose(); } return(Task.CompletedTask); }
public override async ValueTask Publish(IIntegrationEvent @event) { if (!PersistentConnection.IsConnected) { PersistentConnection.TryConnect(); } var policy = Policy.Handle <BrokerUnreachableException>() .Or <SocketException>() .Or <Exception>() .WaitAndRetryForever(retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) => { Logger.LogWarning(ex.ToString()); }); using var channel = PersistentConnection.CreateModel(); var routingKey = @event.RoutingKey; channel.ExchangeDeclare(ExchangeDeclareParameters.ExchangeName, ExchangeDeclareParameters.ExchangeType, ExchangeDeclareParameters.ExchangeDurable, ExchangeDeclareParameters.ExchangeAutoDelete); await using var ms = new MemoryStream(); Serializer.Serialize(ms, @event); var body = ms.ToArray(); policy.Execute(() => { var properties = channel.CreateBasicProperties(); properties.DeliveryMode = 1; //2 = persistent, write on disk properties.CorrelationId = _correlationId; properties.ReplyTo = _queueNameReply; channel.BasicPublish(ExchangeDeclareParameters.ExchangeName, routingKey, true, properties, body); }); }
private void SubsManager_OnEventReplyRemoved(object sender, string eventName) { if (!PersistentConnection.IsConnected) { PersistentConnection.TryConnect(); } using (var channel = PersistentConnection.CreateModel()) { channel.QueueUnbind(QueueName, ExchangeDeclareParameters.ExchangeName, eventName); channel.QueueUnbind(_queueNameReply, ExchangeDeclareParameters.ExchangeName, eventName); } if (!SubsManager.IsReplyEmpty) { return; } QueueName = string.Empty; ConsumerChannel?.Close(); //ToDo _queueNameReply = string.Empty; _consumerChannelReply?.Close(); }
private void DoInternalSubscriptionRpc(string eventName, string eventNameResult) { var containsKey = SubsManager.HasSubscriptionsForEvent(eventName); if (containsKey) { return; } if (!PersistentConnection.IsConnected) { PersistentConnection.TryConnect(); } using var channel = PersistentConnection.CreateModel(); channel.QueueBind(QueueName, ExchangeDeclareParameters.ExchangeName, eventName); channel.QueueBind(_queueNameReply, ExchangeDeclareParameters.ExchangeName, eventNameResult); }
public async Task <TR> CallAsync <TR>(IIntegrationEvent @event, CancellationToken cancellationToken = default) where TR : IIntegrationEventReply { if (!PersistentConnection.IsConnected) { PersistentConnection.TryConnect(); } var policy = Policy.Handle <BrokerUnreachableException>() .Or <SocketException>() .Or <Exception>() .WaitAndRetryForever(retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) => { Logger.LogWarning(ex.ToString()); }); using var channel = PersistentConnection.CreateModel(); var routingKey = @event.RoutingKey; channel.ExchangeDeclare(ExchangeDeclareParameters.ExchangeName, ExchangeDeclareParameters.ExchangeType, ExchangeDeclareParameters.ExchangeDurable, ExchangeDeclareParameters.ExchangeAutoDelete); await using var ms = new MemoryStream(); Serializer.Serialize(ms, @event); var body = ms.ToArray(); var correlationId = Guid.NewGuid().ToString(); var tcs = new TaskCompletionSource <dynamic>(); _callbackMapper.TryAdd(correlationId, tcs); policy.Execute(() => { var properties = channel.CreateBasicProperties(); properties.DeliveryMode = 1; //2 = persistent, write on disk properties.CorrelationId = correlationId; properties.ReplyTo = QueueName; channel.BasicPublish(ExchangeDeclareParameters.ExchangeName, routingKey, true, properties, body); }); cancellationToken.Register(() => _callbackMapper.TryRemove(correlationId, out var tmp)); return(await tcs.Task); }
/// <summary> /// /// </summary> /// <param name="services"></param> /// <param name="connectionString"></param> /// <param name="eventBusOptionAction"></param> /// <returns></returns> public static void AddRabbitMQEventBus(this Container container, string connectionString, Action <ConnectionConfigurationBuild> eventBusOptionAction) { ConnectionConfiguration configuration = new ConnectionConfiguration(); ConnectionConfigurationBuild configurationBuild = new ConnectionConfigurationBuild(configuration); eventBusOptionAction?.Invoke(configurationBuild); container.RegisterSingleton <IPersistentConnection>(() => { IConnectionFactory factory = new ConnectionFactory { AutomaticRecoveryEnabled = configuration.AutomaticRecoveryEnabled, NetworkRecoveryInterval = configuration.NetworkRecoveryInterval, Uri = new Uri(connectionString), }; var connection = new PersistentConnection(configuration, factory); connection.TryConnect(); return(connection); }); container.RegisterSingleton <IEventHandlerModuleFactory, EventHandlerModuleFactory>(); container.RegisterSingleton <RabbitMqCore, RabbitMqCore>(); foreach (Type mType in typeof(IEvent).GetAssemblies()) { container.Register(mType); foreach (Type hType in typeof(IEventHandler <>).GetMakeGenericType(mType)) { container.Register(hType); } } }
private IModel CreateConsumerChannelReply(CancellationToken cancel = default) { if (!PersistentConnection.IsConnected) { PersistentConnection.TryConnect(); } var channel = PersistentConnection.CreateModel(); channel.ExchangeDeclare(ExchangeDeclareParameters.ExchangeName, ExchangeDeclareParameters.ExchangeType, ExchangeDeclareParameters.ExchangeDurable, ExchangeDeclareParameters.ExchangeAutoDelete); channel.QueueDeclare(_queueNameReply, QueueDeclareParameters.QueueDurable, QueueDeclareParameters.QueueExclusive, QueueDeclareParameters.QueueAutoDelete, null); channel.BasicQos(0, 1, false); channel.CallbackException += (sender, ea) => { Logger.LogError("CallbackException Rpc: " + ea.Exception.Message); _consumerChannelReply.Dispose(); _consumerChannelReply = CreateConsumerChannelReply(cancel); StartBasicConsumeReply(); }; return(channel); }
public async Task <TIntegrationEventReply> CallAsync <TIntegrationEventReply>(IIntegrationEvent @event, CancellationToken cancellationToken = default) where TIntegrationEventReply : IIntegrationEventReply { try { if (!PersistentConnection.IsConnected) { PersistentConnection.TryConnect(); } var policy = Policy.Handle <BrokerUnreachableException>() .Or <SocketException>() .Or <Exception>() .WaitAndRetryForever(retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) => { Logger.LogWarning(ex.ToString()); }); var correlationId = Guid.NewGuid().ToString(); var tcs = new TaskCompletionSource <dynamic>(TaskCreationOptions.RunContinuationsAsynchronously); _callbackMapper.TryAdd(correlationId, tcs); using (var channel = PersistentConnection.CreateModel()) { var routingKey = @event.RoutingKey; channel.ExchangeDeclare(ExchangeDeclareParameters.ExchangeName, ExchangeDeclareParameters.ExchangeType, ExchangeDeclareParameters.ExchangeDurable, ExchangeDeclareParameters.ExchangeAutoDelete); await using var ms = new MemoryStream(); Serializer.Serialize(ms, @event); var body = ms.ToArray(); policy.Execute(() => { var properties = channel.CreateBasicProperties(); //properties.ContentType = "application/protobuf"; properties.DeliveryMode = 1; //2 = persistent, write on disk properties.CorrelationId = correlationId; //properties.ReplyTo = QueueName; properties.ReplyTo = _queueNameReply; //ToDo channel.BasicPublish(ExchangeDeclareParameters.ExchangeName, routingKey, true, properties, body); }); } cancellationToken.Register(() => _callbackMapper.TryRemove(correlationId, out var tmp)); var result = await tcs.Task.ConfigureAwait(false); return((TIntegrationEventReply)result); } catch (Exception ex) { Logger.LogError("CallAsync: " + ex.Message + " " + ex.StackTrace); } return(default);