0

My scenario: with a message coming from an Azure Storage Queue I want to either create or update a document in DocumentDB

  • I set the DocumentDB consistency to Strong, so that it is guaranteed that the document is updated
  • I use a Singleton/Listener, so that only one Queue entry is processed at a time

Here is my code:

function.json

{
  "disabled": false,
  "bindings": [
    {
      "name": "updateEntry",
      "type": "queueTrigger",
      "direction": "in",
      "queueName": "update-log",
      "connection": "AzureWebJobsStorage"
    },
    {
      "type": "documentDB",
      "name": "inputDocument",
      "databaseName": "logging",
      "collectionName": "messages",
      "id": "{id}",
      "connection": "documentDB",
      "direction": "in"
    },
    {
      "type": "documentDB",
      "name": "outputDocument",
      "databaseName": "logging",
      "collectionName": "messages",
      "createIfNotExists": true,
      "connection": "documentDB",
      "direction": "out"
    }
  ]
}

run.csx

#r "Newtonsoft.Json"

using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

[Singleton(Mode = SingletonMode.Listener)]
public static void Run(UpdateEntryType updateEntry, TraceWriter log, DocumentType inputDocument, out DocumentType outputDocument)
{
    log.Info($"update entry:{updateEntry.id} {updateEntry.created} {updateEntry.Event.ToString()}");

    outputDocument = new DocumentType();
    outputDocument.Events = new List<JObject>();

    if (inputDocument == null)
    {
        outputDocument.id = updateEntry.id;
        outputDocument.created = updateEntry.created;
    }
    else
    {
        log.Info($"input document:{inputDocument.id} {inputDocument.created} {inputDocument.Events.Count}");
        outputDocument.id = inputDocument.id;
        outputDocument.created = updateEntry.created.CompareTo(inputDocument.created) < 0 ? updateEntry.created : inputDocument.created;
        outputDocument.Events.AddRange(inputDocument.Events);
    }

    outputDocument.Events.Add(updateEntry.Event);

    log.Info($"output document:{outputDocument.id} {outputDocument.created} {outputDocument.Events.Count}");
}

public class UpdateEntryType
{
    public string id { get; set; }
    public string created { get; set; }
    public JObject Event { get; set; }
}

public class DocumentType
{
    public string id { get; set; }
    public string created { get; set; }
    public List<JObject> Events { get; set; }
}

My problem: most of the times an actual existing document is found with id and hence updated - but not for at least 5% of the time

My questions (before I open a case @MSFT support): What am I missing? Is this the right approach or is it destined to fail anyway?

2 Answers 2

1

not for at least 5% of the time

From my experience, If it is a dedicated plan, we need to turn on Always On setting for our Function App.

The Function runtime will go idle after a few minutes of inactivity, so only HTTP triggers will actually "wake up" your functions. This is similar to how WebJobs must have Always On enabled.

More detail info about Consumption Plan & Dedicated App Service Plan and how to set appsetting, please refer to Enable Always On when running on dedicated App Service Plan.

enter image description here

Sign up to request clarification or add additional context in comments.

3 Comments

As I have this Function App on a Consumption pricing tier you would suggest to re-create it with a Dedicated App Service Plan?
Thanks @Tom Sun - I did some thorough testing: application re-activation / startup was not the issue.I solved the Problem with batchSize 1 on my queue listener.
Congratulates. Please help to mark your answer that will help more communities that have the same issue.
1

Using Queue batchSize 1 instead of SingletonMode.Listener made the problem disappear.

hosts.json

{
  "queues": {
    "batchSize": 1
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.