From 2a8f4cbb8d6f0e7f1d6f2474d5bac4f9842e7206 Mon Sep 17 00:00:00 2001 From: Mark van der Wal Date: Wed, 25 Mar 2020 11:39:26 +0100 Subject: [PATCH] polling for task status. --- FarmmapsApi/Extensions.cs | 27 ++++++++- FarmmapsApi/Services/FarmmapsApiService.cs | 21 +++++-- FarmmapsApiSamples/NbsApp.cs | 66 ++++++++++++---------- 3 files changed, 77 insertions(+), 37 deletions(-) diff --git a/FarmmapsApi/Extensions.cs b/FarmmapsApi/Extensions.cs index 0f5f774..0c63b4d 100644 --- a/FarmmapsApi/Extensions.cs +++ b/FarmmapsApi/Extensions.cs @@ -1,4 +1,7 @@ +using System; using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; using FarmmapsApi.HttpMessageHandlers; using FarmmapsApi.Models; using FarmmapsApi.Services; @@ -9,7 +12,8 @@ namespace FarmmapsApi { public static class Extensions { - public static IServiceCollection AddFarmmapsServices(this IServiceCollection serviceCollection, Configuration configuration) + public static IServiceCollection AddFarmmapsServices(this IServiceCollection serviceCollection, + Configuration configuration) { return serviceCollection .AddSingleton(configuration) @@ -23,7 +27,26 @@ namespace FarmmapsApi .AddTransient() .AddHttpClient() .AddHttpMessageHandler() - .Services;; + .Services; + ; + } + + public static async Task PollTask(TimeSpan retryTime, Func callback) + { + var tokenSource = new CancellationTokenSource(); + var token = tokenSource.Token; + do + { + try + { + await callback(tokenSource); + await Task.Delay(retryTime, token); + } + catch + { + // ignored + } + } while (!token.IsCancellationRequested); } } } \ No newline at end of file diff --git a/FarmmapsApi/Services/FarmmapsApiService.cs b/FarmmapsApi/Services/FarmmapsApiService.cs index b422d89..b997c26 100644 --- a/FarmmapsApi/Services/FarmmapsApiService.cs +++ b/FarmmapsApi/Services/FarmmapsApiService.cs @@ -11,8 +11,9 @@ using System.Threading.Tasks; using System.Web; using FarmmapsApi.Models; using IdentityModel; +using Microsoft.AspNetCore.Http.Connections; using Microsoft.AspNetCore.SignalR.Client; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -20,6 +21,7 @@ namespace FarmmapsApi.Services { public class FarmmapsApiService { + private readonly ILogger _logger; private readonly HttpClient _httpClient; private readonly OpenIdConnectService _openIdConnectService; private readonly Configuration _configuration; @@ -28,9 +30,10 @@ namespace FarmmapsApi.Services public event Action EventCallback; - public FarmmapsApiService(HttpClient httpClient, + public FarmmapsApiService(HttpClient httpClient, ILogger logger, OpenIdConnectService openIdConnectService, Configuration configuration) { + _logger = logger; _httpClient = httpClient; _openIdConnectService = openIdConnectService; _configuration = configuration; @@ -65,13 +68,21 @@ namespace FarmmapsApi.Services var uri = new Uri(_configuration.Endpoint); var eventEndpoint = $"{uri.Scheme}://{uri.Host}:{uri.Port}/EventHub"; _hubConnection = new HubConnectionBuilder() - .WithUrl(eventEndpoint) + .WithUrl(eventEndpoint, HttpTransportType.WebSockets, + options => options.SkipNegotiation = true) + .ConfigureLogging(log => log.AddConsole()) .WithAutomaticReconnect() - .AddJsonProtocol() .Build(); - _hubConnection.On("Event", (EventMessage @event) => EventCallback?.Invoke(@event)); 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); } diff --git a/FarmmapsApiSamples/NbsApp.cs b/FarmmapsApiSamples/NbsApp.cs index ef74708..b344698 100644 --- a/FarmmapsApiSamples/NbsApp.cs +++ b/FarmmapsApiSamples/NbsApp.cs @@ -5,6 +5,7 @@ using FarmmapsApi.Models; using FarmmapsApi.Services; using Microsoft.Extensions.Logging; using Newtonsoft.Json.Linq; +using static FarmmapsApi.Extensions; namespace FarmmapsApiSamples { @@ -44,30 +45,10 @@ namespace FarmmapsApiSamples if (myDriveRoot != null) { - // create or get a cropfield - var cropfieldItem = await GetCreateCropfieldItem(myDriveRoot.Code); - - // create or get target n item - - 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); + var cropfieldItem = await GetOrCreateCropfieldItem(myDriveRoot.Code); + var targetN = await CalculateTargetN(cropfieldItem, 60); + + _logger.LogInformation($"TargetN: {targetN}"); } } catch (Exception ex) @@ -76,7 +57,7 @@ namespace FarmmapsApiSamples } } - private async Task GetCreateCropfieldItem(string parentItemCode) + private async Task GetOrCreateCropfieldItem(string parentItemCode) { var cropfieldItems = await _farmmapsApiService.GetItemChildrenAsync(parentItemCode, "vnd.farmmaps.itemtype.cropfield"); @@ -101,8 +82,25 @@ namespace FarmmapsApiSamples return await _farmmapsApiService.CreateItemAsync(cropfieldItemRequest); } - private async Task CalculateTargetN(Item cropfieldItem, Item targetNItem, int targetYield) + private async Task 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}; nbsTargetNRequest.attributes["operation"] = "targetn"; nbsTargetNRequest.attributes["inputCode"] = targetNItem.Code; @@ -111,11 +109,19 @@ namespace FarmmapsApiSamples nbsTargetNRequest.attributes["targetYield"] = targetYield.ToString(); string itemTaskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, nbsTargetNRequest); - // poll task - - // get target N item again + await PollTask(TimeSpan.FromSeconds(3), async (tokenSource) => + { + 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(); + + return 0; } private ItemRequest CreateTargetNItemRequest(string parentItemCode)