public void Add(CompositeResult result) { foreach (var request in result._Requests) { _Requests.Add(request); } foreach (var(key, value) in result._Errors) { _Errors.Add(key, value); } foreach (var(key, value) in result._Queries) { _Queries.Add(key, value); } foreach (var(key, value) in result._Results) { _Results.Add(key, value); } }
public async Task <CompositeResult> PostAsync(ICompositeRequest request) { if (request == null || request.CompositeRequests.Count <= 0) { throw new ArgumentNullException(nameof(request)); } try { var resourceName = $"{request.Prefix}composite"; if (request.AllOrNone) { var requests = request.CompositeRequests; if (requests.Count > Dnf.CompositeLimit) { throw new ArgumentOutOfRangeException(nameof(request)); } if (requests.Count(c => IsQuery(c.ResponseType)) > Dnf.CompositeQueryLimit) { throw new ArgumentOutOfRangeException(nameof(request)); } var inputObject = new JObject { ["allOrNone"] = true, ["compositeRequest"] = JToken.FromObject(requests.Select(req => Dnf.Assign(JObject.FromObject(req), new JObject { ["url"] = DecodeReference($"/services/data/{ApiVersion}/{request.Prefix}{req.Url?.TrimStart('/')}") }))) }; var result = await JsonHttp.HttpPostAsync <CompositeResultBody>(inputObject, resourceName) .ConfigureAwait(false); var results = new CompositeResult(request.CompositeRequests, result?.CompositeResponse ?? new List <CompositeSubRequestResult>()); return(results); } else { var throttler = new SemaphoreSlim(Dnf.DefaultConcurrentLimit, Dnf.DefaultConcurrentLimit); var results = new CompositeResult(); var chunks = new List <IList <CompositeSubRequest> >(); IList <CompositeSubRequest>?chunk = null; foreach (var req in request.CompositeRequests) { var added = false; if (IsQuery(req.ResponseType)) { if (chunk != null && chunk.Count(c => IsQuery(c.ResponseType)) < Dnf.CompositeQueryLimit) { chunk.Add(req); added = true; } } else if (chunk?.Count < Dnf.CompositeLimit) { chunk.Add(req); added = true; } if (added) { continue; } chunk = new List <CompositeSubRequest> { req }; chunks.Add(chunk); } var tasks = new List <Task>(); foreach (var requests in chunks) { await throttler.WaitAsync() .ConfigureAwait(false); tasks.Add(Task.Run(async() => { try { var inputObject = new JObject { ["compositeRequest"] = JToken.FromObject(requests.Select(req => Dnf.Assign(JObject.FromObject(req), new JObject { ["url"] = DecodeReference($"/services/data/{ApiVersion}/{request.Prefix}{req.Url?.TrimStart('/')}") }))) }; var result = await JsonHttp.HttpPostAsync <CompositeResultBody>(inputObject, resourceName) .ConfigureAwait(false); results.Add(requests, result?.CompositeResponse ?? new List <CompositeSubRequestResult>()); } catch (Exception ex) { var body = new JArray { ex.Message }; var responses = requests.Select(req => new CompositeSubRequestResult { Body = body, ReferenceId = req.ReferenceId, HttpStatusCode = 500 }).ToList(); results.Add(requests, responses); } finally { throttler.Release(); } })); } await Task.WhenAll(tasks) .ConfigureAwait(false); return(results); } } catch (Exception ex) { var body = new JArray { ex.Message }; var responses = request.CompositeRequests.Select(req => new CompositeSubRequestResult { Body = body, ReferenceId = req.ReferenceId, HttpStatusCode = 500 }).ToList(); var results = new CompositeResult(request.CompositeRequests, responses); return(results); } bool IsQuery(string responseType) { return(responseType == "query" || responseType == "collections"); } }