CosmosDB can be used as a trigger and an output for Azure Functions. The trigger is for created and edited documents, but the potential scale of CosmosDB means each call to the function could have multiple documents, so the logic needs to allow for that. In some cases you want to use the same database collection for input and output, but that also needs careful thinking about.
In this lab we’ll use CosmosDB as the trigger and the output for a function.
The scenario is a translation engine. When documents are saved to CosmosDB with an English language message, the function translates them to Spanish and stores the translated document in the same CosmosDB database. The code is in the CosmosToCosmos
directory:
These attributes wire up the function:
[CosmosDBTrigger]
fires with a read-only set of documents when there are additions or updates to the posts
collection
[CosmosDB]
is an output binding which will write a set of documents to the same posts
collection
The logic is a little more complex than previous labs, but only because of the multiple inputs. The document collection is iterated, and if there’s a match on the message and language then the translator fires and adds a new document to the output, which will be created in CosmosDB.
For reference</summary>
Here’s how the function was created:
func init CosmosToCosmos --dotnet
cd CosmosToCosmos
func new --name Translator --template "CosmosDBTrigger"
dotnet add package Microsoft.Azure.WebJobs.Extensions.CosmosDB --version 3.0.10
</details>
There is a CosmosDB emulator you can run locally, but it is fiddly to set up. If you use CosmosDB a lot then it’s worth going through the steps, but it’s a bit much for this lab.
Instead create a CosmosDB account in Azure:
Test
posts
/id
for the collectionThen write the CosmosDB connection string into a new file at labs/functions/cosmos/CosmosToCosmos/local.settings.json
:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"CosmosDbConnectionString" : "",
"DatabaseName" : "Test"
}
}
The rest of the components will run locally. Start the Azure Storage emulator:
docker run -d -p 10000-10002:10000-10002 --name azurite mcr.microsoft.com/azure-storage/azurite
Run the function:
cd labs/functions/cosmos/CosmosToCosmos
func start
Open the CosmosDB Data Explorer in the Portal and insert some new items:
{
"id": "123",
"message": "goodbye",
"lang" : "en"
}
{
"id": "897",
"message": "hello",
"lang" : "en"
}
You should see output like this:
[2022-11-08T05:24:58.366Z] Processing: 1 documents
[2022-11-08T05:24:58.366Z] Translating message for document ID: test02
[2022-11-08T05:24:58.571Z] Added translated document ID: 62e768b9-1eb1-44bf-8985-ab4cb2386295
[2022-11-08T05:24:58.580Z] Executed 'Translator' (Succeeded, Id=9c74627b-3f01-4747-9930-005aa0fa1133, Duration=238ms)
Check the documents in Cosmos, and you should see a translated ‘hola’ document for each ‘hello’ document.
Note that inserting the new item causes the function to run again :)
For the Azure run you can use your existing CosmosDB database or create a new one. Here’s the core setup:
az group create -n labs-functions-cosmos --tags courselabs=azure -l eastus
az storage account create -g labs-functions-cosmos --sku Standard_LRS -l eastus -n <sa-name>
az functionapp create -g labs-functions-cosmos --runtime dotnet --functions-version 4 --consumption-plan-location eastus --storage-account <sa-name> -n <function-name>
The pre-reqs for the function are:
Prod
with a collection called posts
CosmosDbConnectionString
DatabaseName
When you’re ready you can deploy:
func azure functionapp publish <function-name>
Test the function with some new documents in the Prod database.
How would you design the database to avoid triggering the function twice when a document to translate gets inserted? If your logic was different, could you end up with an infinite loop of triggered functions?
Stuck? Try suggestions.
Stop the Azure Storage emulator:
docker rm -f azurite
Delete the lab RG:
az group delete -y --no-wait -n labs-functions-cosmos