/// <summary> /// 发送数据。 /// </summary> /// <param name="subject"></param> private void PublishSubject(StoredSubject subject) { var connection = GetConnection(); using (var channel = connection.CreateModel()) { var bytes = Serialize(subject); if (string.IsNullOrEmpty(Setting.ExchangeType)) { channel.QueueDeclare(subject.Name, true, false, false, null); var properties = channel.CreateBasicProperties(); properties.Persistent = true; properties.DeliveryMode = 2; channel.BasicPublish(string.Empty, subject.Name, properties, bytes); } else { var exchangeName = GetExchangeName(subject.Name); channel.ExchangeDeclare(exchangeName, Setting.ExchangeType); channel.BasicPublish(exchangeName, subject.Name, null, bytes); } } }
private void RetryPublishData(StoredSubject subject, Exception exception) { try { if (subject != null && Setting.RetryTimes > 0 && subject.AcceptRetries < Setting.RetryTimes) { if (_notification != null) { var context = new SubscribeNotificationContext(subject.Name, subject.Body, exception); _notification.OnConsumeError(context); if (!context.CanRetry) { return; } } Task.Run(() => { Thread.Sleep((int)Setting.RetryDelayTime.TotalMilliseconds); try { var client = GetConnection(null); subject.AcceptRetries++; PublishSubject(client, subject); } catch (Exception exp) { PersistSubject(subject, exp); } }); } } catch { } }
/// <summary> /// 在 Redis 服务器中添加一个订阅方法。 /// </summary> /// <param name="subjectType">主题的类型。</param> /// <param name="subscriber">读取主题的方法。</param> public void AddSubscriber(Type subjectType, Delegate subscriber) { var client = GetConnection(); var name = TopicHelper.GetTopicName(subjectType); _channels.GetOrAdd(name, () => new List <CSRedisClient.SubscribeObject>()) .Add(client.Subscribe((name, msg => { StoredSubject subject = null; try { try { subject = Deserialize <StoredSubject>(msg.Body); subscriber.DynamicInvoke(Deserialize(subjectType, subject.Body)); } catch (SerializationException) { subscriber.DynamicInvoke(Deserialize(subjectType, msg.Body)); } } catch (Exception exp) { Tracer.Error($"Throw exception when consume message of '{name}':\n{exp.Output()}"); RetryPublishData(subject, exp); } } ))); }
/// <summary> /// 在 Redis 服务器中添加一个订阅方法。 /// </summary> /// <typeparam name="TSubject"></typeparam> /// <param name="name">主题名称。</param> /// <param name="subscriber">读取主题的方法。</param> public void AddAsyncSubscriber <TSubject>(string name, Func <TSubject, Task> subscriber) where TSubject : class { var client = GetConnection(null); _channels.GetOrAdd(name, () => new List <CSRedisClient.SubscribeObject>()) .Add(client.Subscribe((name, msg => { StoredSubject subject = null; try { try { subject = Deserialize <StoredSubject>(msg.Body); subscriber(Deserialize <TSubject>(subject.Body)).AsSync(); } catch (SerializationException) { subscriber(Deserialize <TSubject>(msg.Body)).AsSync(); } } catch (Exception exp) { Tracer.Error($"Throw exception when consume message of '{name}':\n{exp.Output()}"); RetryPublishData(subject, exp); } } ))); }
private void PersistSubject(StoredSubject subject, Exception exception) { if (_persistance != null && subject.PublishRetries == 0) { if (_notification != null) { var context = new SubscribeNotificationContext(subject.Name, subject.Body, exception); _notification.OnPublishError(context); if (!context.CanRetry) { return; } } if (_persistance.SaveSubject("rabbit", subject)) { Tracer.Debug($"{_persistance} was persisted of '{subject.Name}'."); } } }
private void Publish(string name, byte[] data) { var pdata = new StoredSubject(name, data); try { PublishSubject(pdata); } catch (Exception exp) { if (Setting.RetryTimes > 0) { PersistSubject(pdata, exp); } else { throw exp; } } }
private async Task PublishAsync(CSRedisClient client, string name, byte[] data) { var pdata = new StoredSubject(name, data); try { await PublishSubjectAsync(client, pdata); } catch (Exception exp) { if (Setting.RetryTimes > 0) { PersistSubject(pdata, exp); } else { throw exp; } } }
private void RetryPublishData(CustomEventingBasicConsumer consumer, BasicDeliverEventArgs args, StoredSubject subject, Exception exception) { try { if (!consumer.Model.IsOpen) { return; } consumer.Model.BasicNack(args.DeliveryTag, false, false); if (subject != null && Setting.RetryTimes > 0 && subject.AcceptRetries < Setting.RetryTimes) { if (_notification != null) { var context = new SubscribeNotificationContext(subject.Name, subject.Body, exception); _notification.OnConsumeError(context); if (!context.CanRetry) { return; } } Task.Run(() => { Thread.Sleep((int)Setting.RetryDelayTime.TotalMilliseconds); try { subject.AcceptRetries++; PublishSubject(subject); } catch (Exception exp) { PersistSubject(subject, exp); } }); } } catch { } }
private void ConsumeData(CustomEventingBasicConsumer consumer, BasicDeliverEventArgs args) { if (!_subscribers.TryGetValue(consumer.ChannelName, out RabbitChannelCollection channels)) { return; } var found = channels.Find(consumer.Model); if (found == null || !consumer.Model.IsOpen) { return; } StoredSubject subject = null; try { object body; try { subject = Deserialize(typeof(StoredSubject), args.Body) as StoredSubject; if (subject == null) { return; } if (found.Handler.DataType == typeof(byte[])) { body = subject.Body; } else { body = Deserialize(found.Handler.DataType, subject.Body); } } catch (SerializationException) { if (found.Handler.DataType == typeof(byte[])) { body = args.Body; } else { body = Deserialize(found.Handler.DataType, args.Body); } } if (body != null) { found.Handler.Invoke(body); consumer.Model.BasicAck(args.DeliveryTag, false); } } catch (Exception exp) { Tracer.Error($"Throw exception when consume message of '{consumer.ChannelName}':\n{exp.Output()}"); RetryPublishData(consumer, args, subject, exp); } }
private async Task PublishSubjectAsync(CSRedisClient client, StoredSubject subject) { await client.PublishAsync(subject.Name, Serialize(subject)); }
private void PublishSubject(CSRedisClient client, StoredSubject subject) { client.Publish(subject.Name, Serialize(subject)); }