polling for task status.

This commit is contained in:
Mark van der Wal 2020-03-25 11:39:26 +01:00
parent e6561308e5
commit 2a8f4cbb8d
3 changed files with 77 additions and 37 deletions

View File

@ -1,4 +1,7 @@
using System;
using System.Net.Http; using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using FarmmapsApi.HttpMessageHandlers; using FarmmapsApi.HttpMessageHandlers;
using FarmmapsApi.Models; using FarmmapsApi.Models;
using FarmmapsApi.Services; using FarmmapsApi.Services;
@ -9,7 +12,8 @@ namespace FarmmapsApi
{ {
public static class Extensions public static class Extensions
{ {
public static IServiceCollection AddFarmmapsServices(this IServiceCollection serviceCollection, Configuration configuration) public static IServiceCollection AddFarmmapsServices(this IServiceCollection serviceCollection,
Configuration configuration)
{ {
return serviceCollection return serviceCollection
.AddSingleton(configuration) .AddSingleton(configuration)
@ -23,7 +27,26 @@ namespace FarmmapsApi
.AddTransient<FarmmapsAuthenticationHandler>() .AddTransient<FarmmapsAuthenticationHandler>()
.AddHttpClient<FarmmapsApiService>() .AddHttpClient<FarmmapsApiService>()
.AddHttpMessageHandler<FarmmapsAuthenticationHandler>() .AddHttpMessageHandler<FarmmapsAuthenticationHandler>()
.Services;; .Services;
;
}
public static async Task PollTask(TimeSpan retryTime, Func<CancellationTokenSource, Task> callback)
{
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
do
{
try
{
await callback(tokenSource);
await Task.Delay(retryTime, token);
}
catch
{
// ignored
}
} while (!token.IsCancellationRequested);
} }
} }
} }

View File

@ -11,8 +11,9 @@ using System.Threading.Tasks;
using System.Web; using System.Web;
using FarmmapsApi.Models; using FarmmapsApi.Models;
using IdentityModel; using IdentityModel;
using Microsoft.AspNetCore.Http.Connections;
using Microsoft.AspNetCore.SignalR.Client; using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
@ -20,6 +21,7 @@ namespace FarmmapsApi.Services
{ {
public class FarmmapsApiService public class FarmmapsApiService
{ {
private readonly ILogger<FarmmapsApiService> _logger;
private readonly HttpClient _httpClient; private readonly HttpClient _httpClient;
private readonly OpenIdConnectService _openIdConnectService; private readonly OpenIdConnectService _openIdConnectService;
private readonly Configuration _configuration; private readonly Configuration _configuration;
@ -28,9 +30,10 @@ namespace FarmmapsApi.Services
public event Action<EventMessage> EventCallback; public event Action<EventMessage> EventCallback;
public FarmmapsApiService(HttpClient httpClient, public FarmmapsApiService(HttpClient httpClient, ILogger<FarmmapsApiService> logger,
OpenIdConnectService openIdConnectService, Configuration configuration) OpenIdConnectService openIdConnectService, Configuration configuration)
{ {
_logger = logger;
_httpClient = httpClient; _httpClient = httpClient;
_openIdConnectService = openIdConnectService; _openIdConnectService = openIdConnectService;
_configuration = configuration; _configuration = configuration;
@ -65,13 +68,21 @@ namespace FarmmapsApi.Services
var uri = new Uri(_configuration.Endpoint); var uri = new Uri(_configuration.Endpoint);
var eventEndpoint = $"{uri.Scheme}://{uri.Host}:{uri.Port}/EventHub"; var eventEndpoint = $"{uri.Scheme}://{uri.Host}:{uri.Port}/EventHub";
_hubConnection = new HubConnectionBuilder() _hubConnection = new HubConnectionBuilder()
.WithUrl(eventEndpoint) .WithUrl(eventEndpoint, HttpTransportType.WebSockets,
options => options.SkipNegotiation = true)
.ConfigureLogging(log => log.AddConsole())
.WithAutomaticReconnect() .WithAutomaticReconnect()
.AddJsonProtocol()
.Build(); .Build();
_hubConnection.On("Event", (EventMessage @event) => EventCallback?.Invoke(@event));
await _hubConnection.StartAsync(); await _hubConnection.StartAsync();
await AuthenticateEventHub(accessToken);
_hubConnection.Reconnected += async s => await AuthenticateEventHub(accessToken);
_hubConnection.On("event", (Object @event) => _logger.LogInformation(@event.ToString()));
}
private async Task AuthenticateEventHub(string accessToken)
{
await _hubConnection.SendAsync("authenticate", accessToken); await _hubConnection.SendAsync("authenticate", accessToken);
} }

View File

@ -5,6 +5,7 @@ using FarmmapsApi.Models;
using FarmmapsApi.Services; using FarmmapsApi.Services;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using static FarmmapsApi.Extensions;
namespace FarmmapsApiSamples namespace FarmmapsApiSamples
{ {
@ -44,30 +45,10 @@ namespace FarmmapsApiSamples
if (myDriveRoot != null) if (myDriveRoot != null)
{ {
// create or get a cropfield var cropfieldItem = await GetOrCreateCropfieldItem(myDriveRoot.Code);
var cropfieldItem = await GetCreateCropfieldItem(myDriveRoot.Code); var targetN = await CalculateTargetN(cropfieldItem, 60);
// create or get target n item _logger.LogInformation($"TargetN: {targetN}");
var targetNItems = await
_farmmapsApiService.GetItemChildrenAsync(myDriveRoot.Code, USERINPUT_ITEMTYPE);
Item targetNItem;
if (targetNItems.Count == 0)
{
_logger.LogInformation("Creating targetN item");
var itemRequest = CreateTargetNItemRequest(myDriveRoot.Code);
targetNItem = await _farmmapsApiService.CreateItemAsync(itemRequest);
}
else
{
targetNItem = targetNItems[0];
}
await CalculateTargetN(cropfieldItem, targetNItem, 60);
await Task.Delay(2000);
} }
} }
catch (Exception ex) catch (Exception ex)
@ -76,7 +57,7 @@ namespace FarmmapsApiSamples
} }
} }
private async Task<Item> GetCreateCropfieldItem(string parentItemCode) private async Task<Item> GetOrCreateCropfieldItem(string parentItemCode)
{ {
var cropfieldItems = await var cropfieldItems = await
_farmmapsApiService.GetItemChildrenAsync(parentItemCode, "vnd.farmmaps.itemtype.cropfield"); _farmmapsApiService.GetItemChildrenAsync(parentItemCode, "vnd.farmmaps.itemtype.cropfield");
@ -101,8 +82,25 @@ namespace FarmmapsApiSamples
return await _farmmapsApiService.CreateItemAsync(cropfieldItemRequest); return await _farmmapsApiService.CreateItemAsync(cropfieldItemRequest);
} }
private async Task<Item> CalculateTargetN(Item cropfieldItem, Item targetNItem, int targetYield) private async Task<double> CalculateTargetN(Item cropfieldItem, int targetYield)
{ {
var targetNItems = await
_farmmapsApiService.GetItemChildrenAsync(cropfieldItem.ParentCode, USERINPUT_ITEMTYPE);
Item targetNItem;
if (targetNItems.Count == 0)
{
_logger.LogInformation("Creating targetN item");
var itemRequest = CreateTargetNItemRequest(cropfieldItem.ParentCode);
targetNItem = await _farmmapsApiService.CreateItemAsync(itemRequest);
}
else
{
targetNItem = targetNItems[0];
}
_logger.LogInformation($"Calculating targetN with targetYield: {targetYield}");
var nbsTargetNRequest = new TaskRequest {TaskType = VRANBS_TASK}; var nbsTargetNRequest = new TaskRequest {TaskType = VRANBS_TASK};
nbsTargetNRequest.attributes["operation"] = "targetn"; nbsTargetNRequest.attributes["operation"] = "targetn";
nbsTargetNRequest.attributes["inputCode"] = targetNItem.Code; nbsTargetNRequest.attributes["inputCode"] = targetNItem.Code;
@ -111,11 +109,19 @@ namespace FarmmapsApiSamples
nbsTargetNRequest.attributes["targetYield"] = targetYield.ToString(); nbsTargetNRequest.attributes["targetYield"] = targetYield.ToString();
string itemTaskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, nbsTargetNRequest); string itemTaskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, nbsTargetNRequest);
// poll task await PollTask(TimeSpan.FromSeconds(3), async (tokenSource) =>
{
// get target N item again var itemTask = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, itemTaskCode);
return targetNItem; if (itemTask.State != ItemTaskState.Processing && itemTask.State != ItemTaskState.Scheduled)
tokenSource.Cancel();
});
var item = await _farmmapsApiService.GetItemAsync(targetNItem.Code);
if (item.Data.ContainsKey("TargetN"))
return item.Data["TargetN"].Value<double>();
return 0;
} }
private ItemRequest CreateTargetNItemRequest(string parentItemCode) private ItemRequest CreateTargetNItemRequest(string parentItemCode)