public static IAsyncObserver <TSource> DistinctUntilChanged <TSource, TKey>(IAsyncObserver <TSource> observer, Func <TSource, Task <TKey> > keySelector, IEqualityComparer <TKey> comparer) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } if (keySelector == null) { throw new ArgumentNullException(nameof(keySelector)); } if (comparer == null) { throw new ArgumentNullException(nameof(comparer)); } var hasCurrentKey = false; var currentKey = default(TKey); return(Create <TSource>( async x => { var key = default(TKey); try { key = await keySelector(x).ConfigureAwait(false); } catch (Exception ex) { await observer.OnErrorAsync(ex).ConfigureAwait(false); return; } var equals = default(bool); if (hasCurrentKey) { try { equals = comparer.Equals(currentKey, key); } catch (Exception ex) { await observer.OnErrorAsync(ex).ConfigureAwait(false); return; } } if (!hasCurrentKey || !equals) { hasCurrentKey = true; currentKey = key; await observer.OnNextAsync(x).ConfigureAwait(false); } }, observer.OnErrorAsync, observer.OnCompletedAsync )); }
public static IAsyncObserver <decimal?> AverageNullableDecimal(IAsyncObserver <decimal?> observer) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } var sum = 0m; var count = 0L; return(Create <decimal?>( async x => { try { if (x.HasValue) { checked { sum += x.GetValueOrDefault(); count++; } } } catch (Exception ex) { await observer.OnErrorAsync(ex).ConfigureAwait(false); } }, observer.OnErrorAsync, async() => { if (count > 0) { var res = default(decimal); try { checked { res = sum / count; } } catch (Exception ex) { await observer.OnErrorAsync(ex).ConfigureAwait(false); return; } await observer.OnNextAsync(res).ConfigureAwait(false); await observer.OnCompletedAsync().ConfigureAwait(false); } else { await observer.OnNextAsync(null).ConfigureAwait(false); await observer.OnCompletedAsync().ConfigureAwait(false); } } )); }
public static (IAsyncObserver <TSource>, IAsyncObserver <TUntil>) SkipUntil <TSource, TUntil>(IAsyncObserver <TSource> observer) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } var gate = new AsyncLock(); var open = false; return ( Create <TSource>( async x => { using (await gate.LockAsync().ConfigureAwait(false)) { if (open) { await observer.OnNextAsync(x).ConfigureAwait(false); } } }, async ex => { using (await gate.LockAsync().ConfigureAwait(false)) { await observer.OnErrorAsync(ex).ConfigureAwait(false); } }, async() => { using (await gate.LockAsync().ConfigureAwait(false)) { await observer.OnCompletedAsync().ConfigureAwait(false); } } ), Create <TUntil>( async y => { using (await gate.LockAsync().ConfigureAwait(false)) { open = true; } }, async ex => { using (await gate.LockAsync().ConfigureAwait(false)) { await observer.OnErrorAsync(ex).ConfigureAwait(false); } }, () => default ) ); }
public static IAsyncObserver <TSource> Max <TSource>(IAsyncObserver <TSource> observer, IComparer <TSource> comparer) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } if (comparer == null) { throw new ArgumentNullException(nameof(comparer)); } var max = default(TSource); var found = false; return(Create <TSource>( async x => { if (found) { bool isGreater; try { isGreater = comparer.Compare(x, max) > 0; } catch (Exception ex) { await observer.OnErrorAsync(ex).ConfigureAwait(false); return; } if (isGreater) { max = x; } } else { max = x; found = true; } }, observer.OnErrorAsync, async() => { if (!found) { await observer.OnErrorAsync(new InvalidOperationException("The sequence is empty.")).ConfigureAwait(false); } else { await observer.OnNextAsync(max).ConfigureAwait(false); await observer.OnCompletedAsync().ConfigureAwait(false); } } )); }
public static IAsyncObserver <int> AverageInt32(IAsyncObserver <double> observer) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } var sum = 0L; var count = 0L; return(Create <int>( async x => { try { checked { sum += x; count++; } } catch (Exception ex) { await observer.OnErrorAsync(ex).ConfigureAwait(false); } }, observer.OnErrorAsync, async() => { if (count > 0) { var res = default(double); try { checked { res = (double)sum / count; } } catch (Exception ex) { await observer.OnErrorAsync(ex).ConfigureAwait(false); return; } await observer.OnNextAsync(res).ConfigureAwait(false); await observer.OnCompletedAsync().ConfigureAwait(false); } else { await observer.OnErrorAsync(new InvalidOperationException("The sequence is empty.")).ConfigureAwait(false); } } )); }
public static IAsyncObserver <TSource> Do <TSource>(IAsyncObserver <TSource> observer, IAsyncObserver <TSource> witness) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } if (witness == null) { throw new ArgumentNullException(nameof(witness)); } return(Create <TSource>( async x => { try { await witness.OnNextAsync(x).ConfigureAwait(false); } catch (Exception ex) { await observer.OnErrorAsync(ex).ConfigureAwait(false); return; } await observer.OnNextAsync(x).ConfigureAwait(false); }, async error => { try { await witness.OnErrorAsync(error).ConfigureAwait(false); } catch (Exception ex) { await observer.OnErrorAsync(ex).ConfigureAwait(false); return; } await observer.OnErrorAsync(error).ConfigureAwait(false); }, async() => { try { await witness.OnCompletedAsync().ConfigureAwait(false); } catch (Exception ex) { await observer.OnErrorAsync(ex).ConfigureAwait(false); return; } await observer.OnCompletedAsync().ConfigureAwait(false); } )); }
public static IAsyncObserver <TSource> Aggregate <TSource>(IAsyncObserver <TSource> observer, Func <TSource, TSource, Task <TSource> > func) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } if (func == null) { throw new ArgumentNullException(nameof(func)); } var hasValue = false; var value = default(TSource); return(Create <TSource>( async x => { if (hasValue) { try { value = await func(value, x).ConfigureAwait(false); } catch (Exception ex) { await observer.OnErrorAsync(ex).ConfigureAwait(false); return; } } else { value = x; hasValue = true; } }, observer.OnErrorAsync, async() => { if (!hasValue) { await observer.OnErrorAsync(new InvalidOperationException("The sequence is empty.")).ConfigureAwait(false); } else { await observer.OnNextAsync(value).ConfigureAwait(false); await observer.OnCompletedAsync().ConfigureAwait(false); } } )); }
public static IAsyncObserver <TSource> Aggregate <TSource, TAccumulate, TResult>(IAsyncObserver <TResult> observer, TAccumulate seed, Func <TAccumulate, TSource, Task <TAccumulate> > func, Func <TAccumulate, Task <TResult> > resultSelector) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } if (resultSelector == null) { throw new ArgumentNullException(nameof(resultSelector)); } if (func == null) { throw new ArgumentNullException(nameof(func)); } var value = seed; return(Create <TSource>( async x => { try { value = await func(value, x).ConfigureAwait(false); } catch (Exception ex) { await observer.OnErrorAsync(ex).ConfigureAwait(false); return; } }, observer.OnErrorAsync, async() => { var res = default(TResult); try { res = await resultSelector(value).ConfigureAwait(false); } catch (Exception ex) { await observer.OnErrorAsync(ex).ConfigureAwait(false); return; } await observer.OnNextAsync(res).ConfigureAwait(false); await observer.OnCompletedAsync().ConfigureAwait(false); } )); }
public static IAsyncObserver <TSource> Scan <TSource, TResult>(IAsyncObserver <TResult> observer, TResult seed, Func <TResult, TSource, Task <TResult> > func) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } if (func == null) { throw new ArgumentNullException(nameof(func)); } var value = seed; return(Create <TSource>( async x => { try { value = await func(value, x).ConfigureAwait(false); } catch (Exception ex) { await observer.OnErrorAsync(ex).ConfigureAwait(false); return; } await observer.OnNextAsync(value).ConfigureAwait(false); }, observer.OnErrorAsync, observer.OnCompletedAsync )); }
public static IAsyncObserver <TSource> Select <TSource, TResult>(IAsyncObserver <TResult> observer, Func <TSource, TResult> selector) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } if (selector == null) { throw new ArgumentNullException(nameof(selector)); } return(Create <TSource>( async x => { TResult res; try { res = selector(x); } catch (Exception ex) { await observer.OnErrorAsync(ex).ConfigureAwait(false); return; } await observer.OnNextAsync(res).ConfigureAwait(false); }, observer.OnErrorAsync, observer.OnCompletedAsync )); }
public static IAsyncObserver <TSource> SingleOrDefault <TSource>(IAsyncObserver <TSource> observer) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } var hasValue = false; var value = default(TSource); return(Create <TSource>( async x => { if (hasValue) { await observer.OnErrorAsync(new InvalidOperationException("The sequence contains more than one element.")).ConfigureAwait(false); return; } hasValue = true; value = x; }, observer.OnErrorAsync, async() => { await observer.OnNextAsync(hasValue ? value : default(TSource)).ConfigureAwait(false); await observer.OnCompletedAsync().ConfigureAwait(false); } )); }
public static IAsyncObserver <TSource> Last <TSource>(IAsyncObserver <TSource> observer) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } var hasValue = false; var lastValue = default(TSource); return(Create <TSource>( x => { hasValue = true; lastValue = x; return Task.CompletedTask; }, observer.OnErrorAsync, async() => { if (!hasValue) { await observer.OnErrorAsync(new InvalidOperationException("The sequence is empty.")).ConfigureAwait(false); } else { await observer.OnNextAsync(lastValue).ConfigureAwait(false); await observer.OnCompletedAsync().ConfigureAwait(false); } } )); }
public static IAsyncObserver <long> SumInt64(IAsyncObserver <long> observer) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } var sum = 0L; return(Create <long>( async x => { try { checked { sum += x; } } catch (Exception ex) { await observer.OnErrorAsync(ex).ConfigureAwait(false); } }, observer.OnErrorAsync, async() => { await observer.OnNextAsync(sum).ConfigureAwait(false); await observer.OnCompletedAsync().ConfigureAwait(false); } )); }
public static IAsyncObserver <TSource> Synchronize <TSource>(IAsyncObserver <TSource> observer, AsyncLock gate) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } if (gate == null) { throw new ArgumentNullException(nameof(gate)); } return(Create <TSource>( async x => { using (await gate.LockAsync().ConfigureAwait(false)) { await observer.OnNextAsync(x).ConfigureAwait(false); } }, async ex => { using (await gate.LockAsync().ConfigureAwait(false)) { await observer.OnErrorAsync(ex).ConfigureAwait(false); } }, async() => { using (await gate.LockAsync().ConfigureAwait(false)) { await observer.OnCompletedAsync().ConfigureAwait(false); } } )); }
public static IAsyncObserver <long?> SumNullableInt64(IAsyncObserver <long?> observer) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } var sum = (long?)0L; return(Create <long?>( async x => { try { checked { if (x != null) { sum += x.GetValueOrDefault(); } } } catch (Exception ex) { await observer.OnErrorAsync(ex).ConfigureAwait(false); } }, observer.OnErrorAsync, async() => { await observer.OnNextAsync(sum).ConfigureAwait(false); await observer.OnCompletedAsync().ConfigureAwait(false); } )); }
public static IAsyncObserver <TSource> LongCount <TSource>(IAsyncObserver <long> observer) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } var count = 0L; return(Create <TSource>( async x => { try { checked { count++; } } catch (Exception ex) { await observer.OnErrorAsync(ex).ConfigureAwait(false); return; } }, observer.OnErrorAsync, async() => { await observer.OnNextAsync(count).ConfigureAwait(false); await observer.OnCompletedAsync().ConfigureAwait(false); } )); }
public static IAsyncObserver <TSource> ElementAt <TSource>(IAsyncObserver <TSource> observer, int index) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } if (index < 0) { throw new ArgumentOutOfRangeException(nameof(index)); } return(Create <TSource>( async x => { if (index-- == 0) { await observer.OnNextAsync(x).ConfigureAwait(false); await observer.OnCompletedAsync().ConfigureAwait(false); } }, observer.OnErrorAsync, async() => { await observer.OnErrorAsync(new ArgumentOutOfRangeException("The element at the specified index was not found.")).ConfigureAwait(false); } )); }
public static ValueTask <IAsyncDisposable> SubscribeSafeAsync <T>(this IAsyncObservable <T> source, IAsyncObserver <T> observer) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (observer == null) { throw new ArgumentNullException(nameof(observer)); } return(CoreAsync()); async ValueTask <IAsyncDisposable> CoreAsync() { try { return(await source.SubscribeAsync(observer).ConfigureAwait(false)); } catch (Exception ex) { await observer.OnErrorAsync(ex).ConfigureAwait(false); return(AsyncDisposable.Nop); } } }
public static IAsyncObserver <TSource> Where <TSource>(IAsyncObserver <TSource> observer, Func <TSource, bool> predicate) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } if (predicate == null) { throw new ArgumentNullException(nameof(predicate)); } return(Create <TSource>( async x => { bool b; try { b = predicate(x); } catch (Exception ex) { await observer.OnErrorAsync(ex).ConfigureAwait(false); return; } if (b) { await observer.OnNextAsync(x).ConfigureAwait(false); } }, observer.OnErrorAsync, observer.OnCompletedAsync )); }
public async Task <IAsyncDisposable> SubscribeAsync(IAsyncObserver <T> observer) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } bool hasValue; T value; bool done; Exception error; lock (_gate) { done = _done; error = _error; hasValue = _hasValue; value = _value; if (!done && error == null) { _observers.Add(observer); } } if (error != null) { await observer.OnErrorAsync(error).ConfigureAwait(false); return(AsyncDisposable.Nop); } else if (done) { if (hasValue) { await observer.OnNextAsync(value).ConfigureAwait(false); } await observer.OnCompletedAsync().ConfigureAwait(false); return(AsyncDisposable.Nop); } return(AsyncDisposable.Create(() => { lock (_gate) { var i = _observers.LastIndexOf(observer); if (i >= 0) { _observers.RemoveAt(i); } } return Task.CompletedTask; })); }
/// <summary> /// Invokes the observer's method corresponding to the notification. /// </summary> /// <param name="observer">Observer to invoke the notification on.</param> /// <returns>Task indicating the completion of invoking the observer method.</returns> public override Task AcceptAsync(IAsyncObserver <T> observer) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } return(observer.OnErrorAsync(Exception)); }
public async ValueTask SubscribeAsync(IAsyncObserver <T> observer) { var disposable = new BooleanDisposable(); await observer.OnSubscribeAsync(disposable).ConfigureAwait(false); if (!disposable.IsDisposed) { await observer.OnErrorAsync(_exception).ConfigureAwait(false); } await observer.OnFinallyAsync().ConfigureAwait(false); }
public async Task OnErrorAsync(Exception ex) { var activity = CreateActivity($"{Constants.ConsumeActivityName}-{nameof(OnErrorAsync)}"); activity.Start(); var span = _tracer?.StartSpanFromActivity($"{Constants.SpanConsumeOperationNamePrefix}-{nameof(OnErrorAsync)}", activity, SpanKind.Internal); await _observer.OnErrorAsync(ex); activity.Stop(); span?.End(); }
public static ValueTask <IAsyncDisposable> Throw <TSource>(IAsyncObserver <TSource> observer, Exception error, IAsyncScheduler scheduler) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } if (scheduler == null) { throw new ArgumentNullException(nameof(scheduler)); } return(scheduler.ScheduleAsync(async ct => { if (!ct.IsCancellationRequested) { await observer.OnErrorAsync(error).RendezVous(scheduler, ct); } })); }
public static IAsyncObserver <long> MinInt64(IAsyncObserver <long> observer) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } var min = 0L; var found = false; return(Create <long>( x => { if (found) { if (x < min) { min = x; } } else { min = x; found = true; } return Task.CompletedTask; }, observer.OnErrorAsync, async() => { if (!found) { await observer.OnErrorAsync(new InvalidOperationException("The sequence is empty.")).ConfigureAwait(false); } else { await observer.OnNextAsync(min).ConfigureAwait(false); await observer.OnCompletedAsync().ConfigureAwait(false); } } )); }
public static IAsyncObserver <double> MinDouble(IAsyncObserver <double> observer) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } var min = 0.0; var found = false; return(Create <double>( x => { if (found) { if (x < min || double.IsNaN(x)) { min = x; } } else { min = x; found = true; } return default; }, observer.OnErrorAsync, async() => { if (!found) { await observer.OnErrorAsync(new InvalidOperationException("The sequence is empty.")).ConfigureAwait(false); } else { await observer.OnNextAsync(min).ConfigureAwait(false); await observer.OnCompletedAsync().ConfigureAwait(false); } } )); }
public static IAsyncObserver <decimal> MaxDecimal(IAsyncObserver <decimal> observer) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } var max = 0m; var found = false; return(Create <decimal>( x => { if (found) { if (x > max) { max = x; } } else { max = x; found = true; } return Task.CompletedTask; }, observer.OnErrorAsync, async() => { if (!found) { await observer.OnErrorAsync(new InvalidOperationException("The sequence is empty.")).ConfigureAwait(false); } else { await observer.OnNextAsync(max).ConfigureAwait(false); await observer.OnCompletedAsync().ConfigureAwait(false); } } )); }
public static IAsyncObserver <float?> SumNullableSingle(IAsyncObserver <float?> observer) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } var sum = 0.0; return(Create <float?>( x => { if (x != null) { sum += x.GetValueOrDefault(); } return default; }, observer.OnErrorAsync, async() => { var res = default(float); try { checked { res = (float)sum; } } catch (Exception ex) { await observer.OnErrorAsync(ex).ConfigureAwait(false); return; } await observer.OnNextAsync(res).ConfigureAwait(false); await observer.OnCompletedAsync().ConfigureAwait(false); } )); }
public static IAsyncObserver <TSource> First <TSource>(IAsyncObserver <TSource> observer) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } return(Create <TSource>( async x => { await observer.OnNextAsync(x).ConfigureAwait(false); await observer.OnCompletedAsync().ConfigureAwait(false); }, observer.OnErrorAsync, async() => { await observer.OnErrorAsync(new InvalidOperationException("The sequence is empty.")).ConfigureAwait(false); } )); }
public async ValueTask SubscribeAsync(IAsyncObserver <T> observer) { var disposable = new BooleanDisposable(); try { await observer.OnSubscribeAsync(disposable).ConfigureAwait(false); var items = await _enumerable.ConfigureAwait(false); foreach (var item in items) { if (disposable.IsDisposed) { break; } var t = observer.OnNextAsync(item); try { await t.ConfigureAwait(false); } catch (Exception ex) { await observer.OnErrorAsync(ex).ConfigureAwait(false); break; } } if (!disposable.IsDisposed) { await observer.OnCompletedAsync().ConfigureAwait(false); } } finally { await observer.OnFinallyAsync().ConfigureAwait(false); } }