Пример #1
0
    public async Task Monitor(
        [QueueTrigger(CommandHandler.MonitorQueue)] QueueMessage commandMessage,
        [Queue(CommandHandler.ProcessorQueue)] IAsyncCollector <ICommand> commandQueue,
        [Queue(CommandHandler.MonitorQueue)] QueueClient commandMonitor,
        [DurableClient] IDurableClient durableClient,
        ILogger log)
    {
        if (commandMessage is null)
        {
            throw new ArgumentNullException(nameof(commandMessage));
        }

        if (commandQueue is null)
        {
            throw new ArgumentNullException(nameof(commandQueue));
        }

        if (commandMonitor is null)
        {
            throw new ArgumentNullException(nameof(commandMonitor));
        }

        if (durableClient is null)
        {
            throw new ArgumentNullException(nameof(durableClient));
        }

        if (Guid.TryParse(commandMessage.Body.ToString(), out var commandId))
        {
            try
            {
                var command = await durableClient
                              .GetCommandAsync(commandId)
                              .ConfigureAwait(false);

                if (command is null)
                {
                    // we could not find a command based on the enqueued command id - warn and forget

                    log.LogWarning($"Monitoring command failed: Could not find command {commandId}");
                }
                else
                {
                    var commandResult = await durableClient
                                        .GetCommandResultAsync(commandId)
                                        .ConfigureAwait(false);

                    await commandAuditWriter
                    .WriteAsync(command, commandResult)
                    .ConfigureAwait(false);

                    if (commandResult?.RuntimeStatus.IsActive() ?? false)
                    {
                        // the command result is still not in a final state - as we want to monitor the command until it is done,
                        // we are going to re-enqueue the command ID with a visibility offset to delay the next result lookup.

                        await commandMonitor
                        .SendMessageAsync(commandId.ToString(), TimeSpan.FromSeconds(3))
                        .ConfigureAwait(false);
                    }
                }
            }
            catch (Exception exc)
            {
                log.LogError(exc, $"Monitoring command failed: {exc.Message}");

                throw;
            }
        }
        else
        {
            // we expect that the queue message is a valid guid (command ID) - warn and forget

            log.LogWarning($"Monitoring command failed: Invalid command ID ({commandMessage.Body})");
        }
    }
Пример #2
0
        public async Task RunCommandMonitorQueue(
            [QueueTrigger(CommandMonitorQueue)] CloudQueueMessage commandMessage,
            [Queue(CommandMonitorQueue)] CloudQueue commandMonitor,
            [DurableClient] IDurableClient durableClient,
            ILogger log)
        {
            if (commandMessage is null)
            {
                throw new ArgumentNullException(nameof(commandMessage));
            }

            if (commandMonitor is null)
            {
                throw new ArgumentNullException(nameof(commandMonitor));
            }

            if (durableClient is null)
            {
                throw new ArgumentNullException(nameof(durableClient));
            }

            log ??= NullLogger.Instance;

            // there is no error handler on purpose - this way we can leverage
            // the function runtime capabilities for poisened message queues
            // and don't need to handle this on our own.

            if (Guid.TryParse(commandMessage.AsString, out var commandId))
            {
                var command = await durableClient
                              .GetCommandAsync(commandId)
                              .ConfigureAwait(false);

                if (command is null)
                {
                    // we could find a command based on the enqueued command id - warn and forget

                    log.LogWarning($"Monitoring command failed: Could not find command {commandId}");
                }
                else
                {
                    var commandResult = await durableClient
                                        .GetCommandResultAsync(commandId)
                                        .ConfigureAwait(false);

                    await commandAuditWriter
                    .AuditAsync(command, commandResult)
                    .ConfigureAwait(false);

                    if (!(commandResult?.RuntimeStatus.IsFinal() ?? false))
                    {
                        // the command result is still not in a final state - as we want to monitor the command until it is done,
                        // we are going to re-enqueue the command ID with a visibility offset to delay the next result lookup.

                        await commandMonitor
                        .AddMessageAsync(new CloudQueueMessage(commandId.ToString()), null, TimeSpan.FromSeconds(10), null, null)
                        .ConfigureAwait(false);
                    }
                }
            }
            else
            {
                // we expect that the queue message is a valid guid (command ID) - warn and forget

                log.LogWarning($"Monitoring command failed: Invalid command ID ({commandMessage.AsString})");
            }
        }