azure-functions-host icon indicating copy to clipboard operation
azure-functions-host copied to clipboard

Blob-triggered functions execute several times even thoug maxDequeueCount is set to 1

Open mdddev opened this issue 2 years ago • 4 comments

Please provide the following:

  • Timestamp: 2022-07-12T15:58:41.180Z
  • Function App version: 4
  • Function App name: cannot disclose publicly
  • Function name(s) (as appropriate): cannot disclose publicly
  • Invocation ID: efc37408-a985-4f8f-b280-0885248a4d57
  • Region: West-Europe

Repro steps

Blob-triggered functions under the hood work with queues. In the host.json there is a section to set the maximum dequeue count. This is respected for queue-triggered functions. It is not for blob-triggered functions. No equivalent section exists for the blobs extension in the host.json.

{
    "version": "2.0",
    "extensions": {
        "queues": {
            "maxDequeueCount": 1,
            "maxPollingInterval": "00:00:10"
        }
}

Expected behavior

Functions triggers once, completes either sucessfully or unsucessfully after one execution. No retries.

Actual behavior

In this case the function failed. There were 4 additional retries.

2022-07-12T15:58:41.180 [Information] Trigger Details: MessageId: 7191b747-4718-45c9-9c0e-90a687a37136, DequeueCount: 1, InsertedOn: 2022-07-12T15:58:39.000+00:00, BlobCreated: 2022-07-12T15:55:35.000+00:00, BlobLastModified: 2022-07-12T15:58:38.000+00:00

2022-07-12T15:58:45.937 [Information] Trigger Details: MessageId: 7191b747-4718-45c9-9c0e-90a687a37136, DequeueCount: 2, InsertedOn: 2022-07-12T15:58:39.000+00:00, BlobCreated: 2022-07-12T15:55:35.000+00:00, BlobLastModified: 2022-07-12T15:58:38.000+00:00

2022-07-12T15:58:46.620 [Information] Trigger Details: MessageId: 7191b747-4718-45c9-9c0e-90a687a37136, DequeueCount: 3, InsertedOn: 2022-07-12T15:58:39.000+00:00, BlobCreated: 2022-07-12T15:55:35.000+00:00, BlobLastModified: 2022-07-12T15:58:38.000+00:00

2022-07-12T15:58:47.332 [Information] Trigger Details: MessageId: 7191b747-4718-45c9-9c0e-90a687a37136, DequeueCount: 4, InsertedOn: 2022-07-12T15:58:39.000+00:00, BlobCreated: 2022-07-12T15:55:35.000+00:00, BlobLastModified: 2022-07-12T15:58:38.000+00:00

2022-07-12T15:58:48.040 [Information] Trigger Details: MessageId: 7191b747-4718-45c9-9c0e-90a687a37136, DequeueCount: 5, InsertedOn: 2022-07-12T15:58:39.000+00:00, BlobCreated: 2022-07-12T15:55:35.000+00:00, BlobLastModified: 2022-07-12T15:58:38.000+00:00

Executed 'cannot_disclose_publicly' (Failed, Id=2751b523-bd95-4752-a75a-c7d6af2c28d5, Duration=330ms)

Known workarounds

None.

mdddev avatar Jul 12 '22 16:07 mdddev

I imagine a workaround could look like this:

  • blob-triggered function A triggers on new blob in container C
  • function A pushes the blob-event's meta data via queue message onto a storage queue Q
  • queue-triggered function B listens for new messages on Q
  • since now the business logic is handled by function B, any failures should respect the maxDequeueCount property in host.json

Tradeoffs:

  • Function A must pass on metadata of blob payload to function B
  • Function A must be authenticated to push to Q
  • Function B must be authenticated to read from C

This obviously is hacky.

mdddev avatar Aug 01 '22 08:08 mdddev

Another workaround

  • go to the hosting storage account's Events section
  • create a EventGrid subscription, listening for BLOB CREATED events
  • have these delivered to a queue of your liking

Obviously, the queue-triggered function must be authorized for blob access to do anything with its payload, however, in this way you don't need a function as handler.

mdddev avatar Aug 08 '22 07:08 mdddev

Hi @mdddev, @kshyju , I am experiencing the same issue..

Mentioned workarounds seem a bit tricky to me. I would like to ask, if you have found an easy way to handle the issue?

garashov avatar Oct 10 '22 13:10 garashov

Unfortunately not, from the above I think the event grid option is still the ~okayest

mdddev avatar Oct 11 '22 17:10 mdddev

I am running into the same issue using the below configuration in my hosts.json file

{
  "version": "2.0",
  "functionTimeout": "00:10:00",
  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle",
    "version": "[3.3.0, 4.0.0)"
  },
  "extensions": {
    "queues": {
      "maxDequeueCount": 1,
      "batchSize": 1
    }
  }
}

aborremans avatar Oct 24 '22 21:10 aborremans

Closing this now, since the way to go over Event Grid has not only proven to be stable and effective, but also more cost efficient in my scenario. Since my company deployed mandatory Advanced Threat Protection policies via Azure Defender, the transactions and traffic between the blob-triggered function and the storage account holding the blobs became ATP-billable. And since the blob-trigger polls excessively behind the scenes my cost skyrocketed. At the peak. adding almost 15 EUR/day in incremental cost. And this for only a handful of blob-triggered functions. Switching over to the Event Grid method cut that cost down by 98.8%. Also the cost for storage transactions (no polling naymore) went down by 97%.

mdddev avatar Jun 15 '23 06:06 mdddev