internal RedisLogger(string key, ILog log, IRedisConnectionFactory redisConnectionFactory) { this.key = string.Format(CultureInfo.InvariantCulture, "{0}:{1}", log.Logger.Name, key); this.log = log; this.messagesSubject = new ReplaySubject<Tuple<string, string>>(100, TimeSpan.FromSeconds(5)); this.retry = new BehaviorSubject<bool>(false); var redisOnConnectionAction = new Action<Task<RedisConnection>>(task => { if (task.IsCompleted && !task.IsFaulted) { Interlocked.CompareExchange<RedisConnection>(ref this.redisConnection, task.Result, null); subscription = messagesSubject.TakeUntil(retry.Skip(1)).Subscribe((item) => { redisConnection.Publish(item.Item1, item.Item2).ContinueWith(taskWithException => { taskWithException.Exception.Handle(ex => true); }, TaskContinuationOptions.OnlyOnFaulted); }); } }); var redisOnErrorAction = new Action<ErrorEventArgs>(ex => { if (ex.IsFatal) { retry.OnNext(true); Interlocked.Exchange<RedisConnection>(ref this.redisConnection, null); } }); Action subscribeAction = () => { var connectionTask = redisConnectionFactory.CreateRedisConnection(); connectionTask.ContinueWith(taskConnection => { if (!taskConnection.IsFaulted) { taskConnection.ContinueWith(redisOnConnectionAction); taskConnection.Result.Error += (_, err) => redisOnErrorAction(err); } else { taskConnection.Exception.Handle(_ => true); this.retry.OnNext(true); } }); }; retry.Subscribe(val => { if (val) Observable.Timer(TimeSpan.FromSeconds(10)).Subscribe(_ => subscribeAction()); else subscribeAction(); }); }