Create Azure TimerTrigger Durable Function in python - python

As I claimed in the title, is possible to have an azure durable app that triggers using TimerTrigger and not only httpTrigger?
I see here https://learn.microsoft.com/en-us/azure/azure-functions/durable/quickstart-python-vscode a very good example on how implement it with HttpTrigger Client and I'd like to have an example in python on how do it with a TimerTrigger Client, if it's possible.
Any help is appreciate, thanks in advance.

Just focus on the start function is ok:
__init__py
import logging
import azure.functions as func
import azure.durable_functions as df
async def main(mytimer: func.TimerRequest, starter: str) -> None:
client = df.DurableOrchestrationClient(starter)
instance_id = await client.start_new("YourOrchestratorName", None, None)
logging.info(f"Started orchestration with ID = '{instance_id}'.")
function.json
{
"scriptFile": "__init__.py",
"bindings": [
{
"name": "mytimer",
"type": "timerTrigger",
"direction": "in",
"schedule": "* * * * * *"
},
{
"name": "starter",
"type": "orchestrationClient",
"direction": "in"
}
]
}

Related

Is it possible to run two functions (one running FastAPI - ASGI, and one running Flask - WSGI), in one Azure function App?

Im trying testing if its possible to run two functions in one Azure function app one running FastAPI and the other one running Flask.
I tried to specify a different route for each function.json file but to no avail.
# FastAPI function.json
{
"scriptFile": "__init__.py",
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get",
"post",
"patch",
"delete"
],
"route": "/api/{*route}"
},
{
"type": "http",
"direction": "out",
"name": "$return"
}
]
}
# __init__.py
import logging
import azure.functions as func
from fastapi import FastAPI
app = FastAPI()
#app.get("/api/hello/")
async def hello():
return {'message': 'Hello World!'}
def main(req: func.HttpRequest, context: func.Context) -> func.HttpResponse:
return func.AsgiMiddleware(app).handle(req, context)
and
# Flask function.json
{
"scriptFile": "__init__.py",
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get",
"post",
"patch",
"delete"
],
"route": "/flask/{*route}"
},
{
"type": "http",
"direction": "out",
"name": "$return"
}
]
}
#__init__.py
import logging
import azure.functions as func
from flask import Flask
app = Flask(__name__)
#app.route("/home/")
def home():
return "<p>Hello, World!</p>"
def main(req: func.HttpRequest, context: func.Context) -> func.HttpResponse:
return func.WsgiMiddleware(app.wsgi_app).handle(req, context)
If you deploy using GitHub, you can run two functions in one Azure function app.
To do this push the required code in a GitHub repository.
Then in the azure function go to the development center section.
Then select source as GitHub it will ask you to login and for
permissions.
After granting them select the repository (the repository must be
private) and then select branch then click save.
Refresh the function app and you will see the triggers in the
function section
refer the following documentation for further explaination

Can't add more than one item to Azure Queue in function app

I have a TimerTrigger function that runs every couple minutes and adds multiple items to a queue, which a QueueTrigger function should process. But each time the QueueTrigger function is firing only once.
my TimerTrigger function:
def main(mytimer: func.TimerRequest, msg: func.Out[str]) -> None:
utc_timestamp = datetime.datetime.utcnow().replace(
tzinfo=datetime.timezone.utc).isoformat()
if mytimer.past_due:
logging.info('The timer is past due!')
logging.info('Python timer trigger function ran at %s', utc_timestamp)
msg.set("1")
msg.set("2")
QueueTrigger function:
def main(msg: func.QueueMessage) -> None:
logging.info('Python queue trigger function processed a queue item: %s',
msg.get_body().decode('utf-8'))
function.json of the TimerTrigger:
{
"scriptFile": "__init__.py",
"bindings": [
{
"name": "mytimer",
"type": "timerTrigger",
"direction": "in",
"schedule": "0 */2 * * * *"
},
{
"name": "msg",
"type": "queue",
"direction": "out",
"queueName": "js-queue-items",
"connection": "AzureWebJobsStorage"
}
]
}
function.json of the QueueTrigger:
{
"scriptFile": "__init__.py",
"bindings": [
{
"name": "msg",
"type": "queueTrigger",
"direction": "in",
"queueName": "js-queue-items",
"connection": "AzureWebJobsStorage"
}
]
}
local.settings.json:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "python"
}
}
How can I fix this?
There is no intrinsic way of connecting to the queue storage using azure time trigger i.e. the queue storage will treat the time trigger as any other console application or any other piece of program which is trying to connect to the storage and add message.
Thus, we have to add the messages the classical way by using connection strings.
connectionstring = ""
queuename = ""
messages = ""
queueClient = QueueClient.from_connection_string(connectionString, queueName)
queueClient.send_message(message)
Thus, when queue trigger will start only once during the start and remain idle because no messages are added and thus it will not be triggered.
Refer the documentation on timetrigger and queuetrigger and how to add message to queue using python.

azure function service bus python - read bunch of messages

Is there any chance to read a bunch of messages in my python Azure Function (using the serviceBusTrigger)?
The question is fair simple as it is. I did many tries but it seems that the Azure Function Framework after reading the messages coming from Azure Service Bus, calls the trigger function one message at time, no matter how great the prefetch value is or any parameter is set.
I would like to handle the entire fetch of messages, because when you have to handle million of messages, one at time or many at time makes a difference.
This is my configuration:
function.json
{
"scriptFile": "main.py",
"entryPoint": "function_handler",
"bindings": [{
"name": "msg",
"type": "serviceBusTrigger",
"direction": "in",
"topicName": "topic-name",
"subscriptionName": "topic-subscription-name"
}]
}
main.py
import azure.functions as func
import json
def function_handler(msg: func.ServiceBusMessage):
print(str(msg))
host.json
{
"version": "2.0",
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[1.*, 2.0.0)"
},
"extensions": {
"serviceBus": {
"prefetchCount": 100,
"messageHandlerOptions": {
"autoComplete": true,
"maxConcurrentCalls": 6,
"maxAutoRenewDuration": "00:05:00"
}
}
}
}
I think you may be need a async service bus trigger:
__init__.py
import logging
import asyncio
import azure.functions as func
async def hello():
await asyncio.sleep(2)
async def main(msg: func.ServiceBusMessage):
logging.info('Python ServiceBus queue trigger processed message: %s',
msg.get_body().decode('utf-8'))
await asyncio.gather(hello(), hello())
logging.info(msg.get_body().decode('utf-8')+" is been done.")
host.json
{
"version": "2.0",
"logging": {
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"excludedTypes": "Request"
}
}
},
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[1.*, 2.0.0)"
},
"extensions": {"serviceBus": {"messageHandlerOptions": {"maxConcurrentCalls": 5}}}
}
And I can get:

Azure function: System.InvalidOperationException: Storage account connection string 'does not exist

I have written an azure function, currently the azure function is acting as Webhook Consumer. The job of the function is to read Webhook events and save into azure storage.
I am using an HTTP trigger template to get the job done. I am able to receive the events from the Webhook, but when I try to write to azure storage it is giving me below error.
I tried the option mentioned in this post, but no luck still getting the same error.
System.InvalidOperationException: Storage account connection string 'AzureWebJobs<AzureStorageAccountName>' does not exist. Make sure that it is a defined App Setting.
Below is my function.json file
{
"scriptFile": "__init__.py",
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get",
"post"
]
},
{
"type": "blob",
"name": "outputblob",
"path": "test/demo",
"direction": "out",
"connection": "<AzureStorageAccountName>"
}
]
}
init.py
import logging
import azure.functions as func
def main(req: func.HttpRequest,outputblob: func.Out[str]) -> func.HttpResponse:
logging.info('Python HTTP trigger function processed a request.')
name = 'some_name'
if not name:
try:
req_body = 'req_body_test'#req.get_json()
except ValueError:
pass
else:
name = 'name'#req_body.get('name')
print(str(req.get_json()))
outputblob.set(str(req.get_json()))
Please make sure you have already add the connection string to the local.settings.json on local or configuration settings on azure.
Please test below code and settings files:
__init__.py
import logging
import azure.functions as func
def main(req: func.HttpRequest,outputblob: func.Out[func.InputStream]) -> func.HttpResponse:
outputblob.set("this is a test.")
return func.HttpResponse(
"Test.",
status_code=200
)
function.json
{
"scriptFile": "__init__.py",
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "$return"
},
{
"name": "outputblob",
"type": "blob",
"path": "test/demo",
"connection": "MyStorageConnectionAppSetting",
"direction": "out"
}
]
}
local.settings.json
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "python",
"MyStorageConnectionAppSetting":"DefaultEndpointsProtocol=https;AccountName=0730bowmanwindow;AccountKey=xxxxxx;EndpointSuffix=core.windows.net"
}
}
On azure:

Remote Build Azure Function w/Timer in Python

I'm working with Timer Azure Function in python, it's a linux based function, and looking to write to blob.
# __init__.py
import datetime
import logging
import random
import azure.functions as func
import os, sys
def main(mytimer: func.TimerRequest, outputBlob: func.Out[str]):
utc_timestamp = datetime.datetime.utcnow().replace(
tzinfo=datetime.timezone.utc).isoformat()
if mytimer.past_due:
logging.info('The timer is past due!')
logging.info('Python timer2 trigger function ran at %s %d' % (utc_timestamp, random.randint(1, 21)))
output = "Hello World!"
outputblob.set(output)
here is the function.json
{
"scriptFile": "__init__.py",
"bindings": [
{
"name": "mytimer",
"type": "timerTrigger",
"direction": "in",
"schedule": "0 */5 * * * *"
},
{
"type": "blob",
"name": "outputBlob",
"path": "lakesensecontainer/clear.txt",
"direction": "out",
"connection": "DefaultEndpointsProtocol=conectionstring"
}
]
}
Get this error: Extensions command requires dotnet on your path. Please make sure to install dotnet (.NET Core SDK) for your system from https://www.microsoft.com/net/download. I've installed on my local, but that seems is irrelevant as it's trying to write to remote. What am I missing here?
We’re trying to make this default in all tools / templates but it’s saying it doesn’t have the “extension” for the timer trigger and trying to use dotnet to install it. The easiest fix (and what defaults should be moving forward) is to copy the content from this doc into your host.json letting the azure function use a “bundle” that has a bunch of extensible functionality like timers:
https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-register#extension-bundles
{
"version": "2.0",
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[1.*, 2.0.0)"
}
}

Categories

Resources