Hi Jiale,
Thank you for your response and suggestion.
Upon testing it, however, I've noticed the time complexity between this and my previous function were the same.
Although the revision you have suggested achieves parallelism, I guess I'm limited by the fact that the program needs to wait for each of the successive responses to evaluate whether or not to make an additional recursive call.
Using your suggestion of Task.WhenAll
iteratively, instead of Parallel.For
as I was previously doing, appears to execute almost twice as fast as recursively, so I guess in the interest of speed, it is a much better approach to iterate through each of the pages/tasks, as below:
public static async Task<JArray> GetAllHumiEmployeesAsync()
{
JObject initialResponse = await getHumiEmployeesRequestAsync();
JObject pagination = initialResponse["meta"]["pagination"] as JObject;
JArray employees = new JArray(((IEnumerable<dynamic>)initialResponse["data"])
.Select(obj => JObject.FromObject(obj.attributes))
.Where(employee => employee["end_date"] == null));
int pageCount = (int)Math.Ceiling((double)pagination["total"] / (double)pagination["per_page"]);
if (pageCount > 1)
{
var recursiveTasks = Enumerable.Range(2, pageCount)
.Select(i => getHumiEmployeesRequestAsync(i))
.ToList();
await Task.WhenAll(recursiveTasks);
foreach (var task in recursiveTasks)
{
JObject response = await task;
JArray data = new JArray(((IEnumerable<dynamic>)response["data"])
.Select(obj => JObject.FromObject(obj.attributes))
.Where(employee => employee["end_date"] == null));\
lock (employees)
{
employees.Merge(data);
}
}
}
var sortedEmployees = employees.OrderBy(u => u["department"]).ThenBy(u => u["first_name"]).ToList();
return new JArray(sortedEmployees);
}
private static async Task<JObject> getHumiEmployeesAsync(int pageNum = 1)
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {Humi_API_Token}");
string requestUrl = $"{apiURL}?page[number]={pageNum}";
HttpResponseMessage response = await client.GetAsync(requestUrl);
if (response.IsSuccessStatusCode)
{
string responseData = await response.Content.ReadAsStringAsync();
dynamic jsonResponse = JsonConvert.DeserializeObject(responseData);
return jsonResponse;
}
else
{
throw new HttpRequestException($"Error: {response.StatusCode}");
}
}
}