According to the Azure Blob storage bindings for Azure Functions documentation, when configuring a blob trigger you can utilize pattern matching on the blob name to map portions of the path to variables in the function eg.
[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"
}
I have tested this and it works brilliantly for my use case, however due to the large delays in the BlobTrigger
firing (often upwards of 5 minutes) it is not a viable option. As a result, I'm looking to make this an Event Grid trigger instead as per the suggestion from the Azure Functions scale and hosting documentation:
When you're using a blob trigger on a Consumption plan, there can be up to a 10-minute delay in processing new blobs. This delay occurs when a function app has gone idle. After the function app is running, blobs are processed immediately. To avoid this cold-start delay, use an App Service plan with Always On enabled, or use the Event Grid trigger.
Is there any way to get this same pattern matching behavior from an input binding instead of a trigger?
In my specific situation I have set up an EventGrid
subscription for blob creation which runs an orchestrator function calling an activity function to read and parse the 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
...
}
}
Ideally I would like for my ReadBlob
function to behave similarly to the BlobTriggered
function from the first example example above to do something along the lines of the following:
[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
{ ... }
}
The problem is I can't see any way to bind the extension
parameter to the Blob
input binding as I was doing for the BlobTrigger
- expecially with the path being bound to the url provided by the EventGridEvent
in the form of the eventData
JObject
.
Is it possible to achieve this same pattern matching functionality in this case? Or am I going to have to parse the path string myself to extract the relevant info?