private async ValueTask Consume(ICollection <ProcItem <T> > items) { try { if (items.IsNullOrEmpty()) { return; } var list = items.Select(m => m.Item).ToArray(); await OnConsume.InvokeAsync(this, list).DonotCapture(); return; } catch (Exception ex) { var list = items.CastTo <IReadOnlyList <ProcItem <T> > >(); OnException.Invoke(this, ProcItem.CreateEx(list, ex, -1)); } var(retry, discard) = items.Partition(m => m.ErrorTimes < _maxRetryTimes); retry.ForEach(m => { m.ErrorTimes++; _items.TryAdd(m); }); var toDiscard = discard.Select(m => m.Item).ToArray(); if (toDiscard.Any()) { OnDiscard.Invoke(this, toDiscard); } }
public AutoRetryConsumer(int maxRetryTimes, Func <int, int> retryDelay) { if (maxRetryTimes < 0) { throw new ArgumentOutOfRangeException(nameof(maxRetryTimes)); } _maxRetryTimes = maxRetryTimes; _retryDelay = retryDelay ?? (x => x); OnConsumeInternal += async(sender, item) => { var delay = _retryDelay(item.ErrorTimes); await TaskHelper.Delay(delay); await OnConsume(sender, item.Item).DonotCapture(); }; OnExceptionInternal += (sender, args) => { var item = args.Item; OnException.Invoke(sender, ProcItem.CreateEx(item.Item, args.Exception, args.ErrorTimes)); // 以下是失败后的补救措施 if (item.ErrorTimes++ < _maxRetryTimes) { _items.TryAdd(item); } else { OnDiscard.Invoke(sender, item.Item); } return(Task.CompletedTask); }; }
protected void InvokeOnDiscard(Player player, Tile tile) { OnDiscard?.Invoke(player, tile); }