public static Future <T> FromIterator <T>(Func <FuturePublisher <T>, IEnumerable <Future> > iteratorPattern, bool stopOnFutureErrors) { var publisher = new FuturePublisher <T>(); var result = publisher.Future; var iteratorFuture = iteratorPattern(publisher) .ExecuteSequentially(stopOnFutureErrors); iteratorFuture.OnComplete(() => { if (result.IsComplete) { return; } var error = iteratorFuture.HasError ? iteratorFuture.Error : new InvalidOperationException("The iterator pattern completed without publishing a result."); result.SetError(error); }); return(result); }
/// <summary> /// Combines the specified futures into one. If all succeed the result future will succeed. Otherwise the future will fail. /// </summary> /// <param name="futures">The futures.</param> /// <returns>A combined future.</returns> public static Future Combine(this IEnumerable <IFuture> futures) { var publisher = new FuturePublisher <int>(); bool failed = false; List <IFuture> incompleteFutures = null; foreach (var future in futures) { if (future.Status == FutureStatus.Failure) { _log.Error(future.Error); failed = true; } else { if (incompleteFutures == null) { incompleteFutures = new List <IFuture>(); } incompleteFutures.Add(future); } } if (incompleteFutures == null) { if (failed) { publisher.SetError(new ApplicationException("One or more futures failed. See log for details.")); } else { publisher.SetResult(0); } return(publisher.Future); } var latch = new CountDownLatch(incompleteFutures.Count, false); latch.Signaled += (sender, args) => { if (failed) { publisher.SetError(new ApplicationException("One or more futures failed. See log for details.")); } else { publisher.SetResult(0); } }; foreach (var future in incompleteFutures) { var temp = future; future.OnComplete(() => { if (temp.Status == FutureStatus.Failure) { failed = true; _log.Error(temp.Error); } latch.Decrement(); }); } return(publisher.Future); }