Образец сопоставления имени BLOB-объекта с переменными функции с привязкой ввода

2

Согласно связям с хранилищем Azure Blob для документации Azure Functions, при настройке триггера blob вы можете использовать сопоставление образцов по имени blob для отображения частей пути к переменным в функции, например.

[FunctionName("BlobTriggered")]        
public static void BlobTriggered(
    [BlobTrigger("myContainer/{name}.{extension}")] Stream myBlob,
    string name,
    string extension,
    TraceWriter log)
{
    // Given the blob path "myContainer/myBlob.png":
    // name == "myBlob"
    // extension == "png"
}

Я тестировал это, и он BlobTrigger работает для моего использования, однако из-за больших задержек при стрельбе BlobTrigger (часто свыше 5 минут) это не жизнеспособный вариант. В результате я хочу сделать это триггером Event Grid вместо предложения по шкале Azure Functions и документации для хостинга:

Когда вы используете триггер blob на плане потребления, может быть до 10-минутной задержки при обработке новых блоков. Эта задержка возникает, когда приложение-приложение перестает работать. После того, как приложение функции запущено, blobs обрабатываются немедленно. Чтобы избежать этой задержки холодного запуска, используйте план обслуживания приложений с включенным включенным включением или используйте триггер Event Grid.

Есть ли способ получить такое же поведение соответствия шаблонов из привязки ввода вместо триггера?

В моей конкретной ситуации я установил подписку на EventGrid для создания blob, которая запускает функцию оркестра, вызывающую функцию активности, чтобы читать и анализировать blobs:

[FunctionName("NewBlobCreated")]
public static async Task NewBlobCreated(
    [EventGridTrigger]EventGridEvent eventGridEvent,
    [OrchestrationClient]DurableOrchestrationClient starter,
    ILogger log)
{
    // Start our orchestrator function to read the file
    string instanceId = await starter.StartNewAsync(
        "OrchestrateBlobReader",
        eventGridEvent);
}

// Orchestrator function
[FunctionName("OrchestrateBlobReader")]
public static async Task OrchestrateBlobReader(
    [OrchestrationTrigger] DurableOrchestrationContext context,
    ILogger log)
{
    var eventGridEvent = context.GetInput<EventGridEvent>();
    var parsedBlob = await context.CallActivityAsync<string>("ReadBlob", eventGridEvent.Data);        
    ...
}

[FunctionName("ReadBlob")]
public static async Task<string> ReadBlob(
    [ActivityTrigger] JObject eventData,
    [Blob("{data.url}", FileAccess.Read)]CloudBlockBlob blob,
    ILogger log)
{
    using (var blobStream = await blob.OpenReadAsync())
    {
        // Blob is able to be read from blobStream here
        ...
    }
}

В идеале я хотел бы, чтобы моя функция ReadBlob себя аналогично функции BlobTriggered из первого примера выше, чтобы сделать что-то в следующих строках:

[FunctionName("ReadBlob")]
public static async Task<string> ReadBlob(
    [ActivityTrigger] JObject eventData,
    [Blob("{data.url}", FileAccess.Read)]CloudBlockBlob blob,
    string extension,
    ILogger log)
{
    if (extension.Equals("txt", StringComparison.OrdinalIgnoreCase))
    { ... }
    else if (extension.Equals("png", StringComparison.OrdinalIgnoreCase)
    { ... }
    else
    { ... }
}

Проблема в том, что я не вижу никакого способа привязать параметр extension к связыванию ввода Blob как это делал для BlobTrigger - в BlobTrigger с тем, что путь связан с URL-адресом, предоставленным EventGridEvent в виде eventData JObject eventData JObject.

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

Теги:
azure-storage-blobs
azure-functions

1 ответ

2
Лучший ответ

BindingTemplateSource исходный код привязки триггера blob - мое "быстрое и грязное" решение заключалось в том, чтобы использовать базовый класс BindingTemplateSource который триггер использует для сопоставления пути и шаблона со словарем.

Обновленная функция ReadBlob выглядит следующим образом:

// So we can access the BindingTemplateSource class
using Microsoft.Azure.WebJobs.Host.Bindings.Path;

[FunctionName("ReadBlob")]
public static async Task<string> ReadBlob(
    [ActivityTrigger] JObject eventData,
    [Blob("{data.url}", FileAccess.Read)]CloudBlockBlob blob,
    ILogger log)
{
    // Define the pattern to match
    var blobPattern = "myContainer/{name}.{extension}";
    // Create a BindingTemplateSource from the pattern string
    var patternTemplate = BindingTemplateSource.FromString(blobPattern);
    // Use this BindingTemplateSource to create the binding data
    // This returns a IReadOnlyDictionary<string, object> with the parameters mapped
    var parameters = patternTemplate.CreateBindingData($"{blob.Container.Name}/{blob.Name}");
    // Assuming blob path was "myContainer/myBlob.png":
    // Parameters are objects so we need to ToString() them
    var name = parameters["name"].ToString(); // name == "myBlob"
    var extension = parameters["extension"].ToString(); // extension == "png"

    if (extension.Equals("txt", StringComparison.OrdinalIgnoreCase))
    { ... }
    else if (extension.Equals("png", StringComparison.OrdinalIgnoreCase))
    { 
        // This executes now!
    }
    else
    { ... }
}

Тогда эта функциональность могла бы быть обернута в пользовательскую привязку, где параметры сопоставляются для вывода привязок к функции, такой как BlobTrigger, для самого изящного решения, но взломать ее в такую функцию достигает того, что мне нужно для краткосрочной

  • 0
    Вы можете принять ответ для других, чтобы ссылаться.
  • 0
    Спасибо за напоминание. Мне пришлось ждать 48-часовой перерыв и еще не было возможности вернуться к этому

Ещё вопросы

Сообщество Overcoder
Наверх
Меню