public static TOutput AggregateResults <TOutput, TItem>(FacadeMethodInfo <TOutput, TItem> facade, SubMethodRunState[] subMethodRunStates) where TOutput : class, IBasicOutput <TItem>, new() { #region Final aggregation var succeededCount = (from mi in subMethodRunStates where mi.Succeeded select mi).Count(); var subResults = (from mi in subMethodRunStates select mi.Result).ToArray(); bool canAggregate = facade.AggregationFailOption == AggregationFailOption.FailNever || facade.AggregationFailOption == AggregationFailOption.FailOnAll && succeededCount > 0 || facade.AggregationFailOption == AggregationFailOption.FailOnAny && succeededCount == subMethodRunStates.Length; if (canAggregate) { var outputMainItem = facade.Aggregate(subResults); if (facade.IsValidResult(outputMainItem)) { Local.Admin.AddNewLog(TraceEventType.Information, BrokerContext.Current.WebMethodMessageName, TextMessages.Succeeded, null, null); var output = new TOutput(); output.SetMainItem(outputMainItem); if (succeededCount == subMethodRunStates.Length) { output.StandardRetur = StandardReturType.OK(); } else { var failedSubMethods = subMethodRunStates.Where(smi => !smi.Succeeded).Select(smi => smi.SubMethodInfo); var failedSubMethodsByReason = failedSubMethods.GroupBy(smi => smi.PossibleErrorReason()); var failuresAndReasons = failedSubMethodsByReason.ToDictionary(grp => grp.Key, grp => grp.Select(smi => smi.InputToString())); output.StandardRetur = StandardReturType.PartialSuccess(failuresAndReasons); } return(output); } else { string xml = Strings.SerializeObject(outputMainItem); Local.Admin.AddNewLog(TraceEventType.Error, BrokerContext.Current.WebMethodMessageName, TextMessages.ResultGatheringFailed, typeof(TOutput).ToString(), xml); return(new TOutput() { StandardRetur = StandardReturType.UnspecifiedError("Aggregation failed") }); } } else { // TODO: Is it possible to put details why each item has failed? return(new TOutput() { StandardRetur = StandardReturType.Create(HttpErrorCode.DATASOURCE_UNAVAILABLE) }); } #endregion }
public TOutput Aggregate <TOutput>(Element[] elements) where TOutput : IBasicOutput <TOutputElement[]>, new() { // Set output item - only copy succeeded elements var ret = new TOutput(); ret.Item = elements.Select( s => this.IsElementSucceeded(s) ? s.Output : default(TOutputElement) ).ToArray(); // Set standard return var failed = elements.Where(s => !IsElementSucceeded(s)).ToArray(); var succeededCount = elements.Length - failed.Length; if (succeededCount == 0) { ret.StandardRetur = StandardReturType.Create(HttpErrorCode.DATASOURCE_UNAVAILABLE); } else if (succeededCount < elements.Length) { var failuresAndReasons = failed .GroupBy(s => s.PossibleErrorReason) .ToDictionary( g => g.Key, g => g.ToArray() .Select(s => string.Format("{0}", s.Input)) ); ret.StandardRetur = StandardReturType.PartialSuccess(failuresAndReasons); } else { ret.StandardRetur = StandardReturType.OK(); } // final return return(ret); }
public TOutput Run <TOutput>(IEnumerable <TInterface> providers) where TOutput : IBasicOutput <TSingleOutputItem[]>, new() { foreach (var prov in providers) { var currentStates = States .Where(s => !IsSucceededStatus(s)).ToArray(); if (currentStates.Length == 0) { break; } var currentInput = currentStates .Select(kvp => kvp.Input).ToArray(); try { var currentOutput = Run(prov, currentInput); var currentSucceededStates = new List <Status>(); for (int i = 0; i < currentStates.Length; i++) { currentStates[i].Output = currentOutput[i]; if (IsSucceededStatus(currentStates[i])) { currentSucceededStates.Add(currentStates[i]); } } if (prov is IExternalDataProvider) { InvokeUpdateMethod( currentSucceededStates.Select(s => s.Input).ToArray(), currentSucceededStates.Select(s => s.Output).ToArray() ); } } catch (Exception ex) { Local.Admin.LogException(ex); } } // Now create the result var failed = States.Where(s => !IsSucceededStatus(s)).ToArray(); var result = States.Select(s => s.Output).ToArray(); var succeededCount = States.Length - failed.Length; var ret = new TOutput(); ret.SetMainItem(result); if (succeededCount == 0) { ret.StandardRetur = StandardReturType.Create(HttpErrorCode.DATASOURCE_UNAVAILABLE); } else if (succeededCount < States.Length) { var failuresAndReasons = failed .GroupBy(s => s.PossibleErrorReason) .ToDictionary( g => g.Key, g => g.ToArray() .Select(s => string.Format("{0}", s.Input)) ); ret.StandardRetur = StandardReturType.PartialSuccess(failuresAndReasons); } else { ret.StandardRetur = StandardReturType.OK(); } return(ret); }