Task.Run иногда возвращается дважды - PullRequest
0 голосов
/ 19 декабря 2018

У меня есть приложение-функция Azure, которое я вызываю из команды slack slash.Иногда функции требуется немного времени, чтобы вернуть запрошенные данные, поэтому я заставил эту функцию вернуть сообщение «Расчет ...» для немедленного ослабления и запустить фактическую обработку в Task.Run (запрос содержит веб-крючок, который я публикуюназад, когда я наконец получу данные):

Task.Run(() => opsData.GenerateQuoteCheckMessage(incomingData, context.FunctionAppDirectory, log));

Это работает в основном нормально, за исключением того, что время от времени, когда люди вызывают функцию из slack, она будет возвращать данные дважды.Таким образом, он покажет одно сообщение «Вычисление ...» и затем 2 результата, возвращенных из вышеуказанной функции.

Кстати, функции Azure начинаются с: public static async Task

Спасибо!

ОБНОВЛЕНИЕ: вот код для функции:

    [FunctionName("QuoteCheck")]
     public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Anonymous)]HttpRequestMessage req, TraceWriter log, ExecutionContext context)
     {
          var opsHelper = new OpsHelper();

          string bodyContent = await req.Content.ReadAsStringAsync();
          var parsedBody = HttpUtility.ParseQueryString(bodyContent);
          var commandName = parsedBody["command"];
          var incomingBrandId = parsedBody["text"];
          int.TryParse(incomingBrandId, out var brandId);
          var responseUrl = parsedBody["response_url"];

          var incomingData = new IncomingSlackRequestModel
          {
               UserName = parsedBody["user_name"],
               ChannelName = parsedBody["channel_name"],
               CommandName = commandName,
               ResponseUri = new Uri(responseUrl),
               BrandId = brandId
          };

          var opsData = OpsDataFactory.GetOpsData(context.FunctionAppDirectory, environment);

          Task.Run(() => opsData.GenerateQuoteCheckMessage(incomingData, context.FunctionAppDirectory, log));

          // Generate a "Calculating" response message based on the correct parameters being passed
          var calculatingMessage = opsHelper.GenerateCalculatingMessage(incomingData);

          // Return calculating message
          return req.CreateResponse(HttpStatusCode.OK, calculatingMessage, JsonMediaTypeFormatter.DefaultMediaType);
      }
 }

А затем GenerateQuoteCheckMessage вычисляет некоторые данные и в конечном итоге отправляет обратно в резерв (используя Rest Sharp):

    var client = new RestClient(responseUri);
    var request = new RestRequest(Method.POST);
    request.AddParameter("application/json; charset=utf-8", JsonConvert.SerializeObject(outgoingMessage), ParameterType.RequestBody);

    client.Execute(request);

1 Ответ

0 голосов
/ 21 декабря 2018

Используя предложение Kzrystof, я добавил вызов сервисной шины в функцию, которая отправляет сообщения в очередь, и добавил еще одну функцию, которая считывает эту очередь и обрабатывает запрос, отвечая на слабину webhook:

public void DeferProcessingToServiceBus(IncomingSlackRequestModel incomingSlackRequestModel)
{
    var serializedModel = JsonConvert.SerializeObject(incomingSlackRequestModel);
    var sbConnectionString = ConfigurationManager.AppSettings.Get("SERVICE_BUS_CONNECTION_STRING");
    var sbQueueName = ConfigurationManager.AppSettings.Get("OpsNotificationsQueueName");
    var client = QueueClient.CreateFromConnectionString(sbConnectionString, sbQueueName);
    var brokeredMessage = new BrokeredMessage(serializedModel);
    client.Send(brokeredMessage);
}
...