Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .azuredevops/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Mirrored repository. We use dependabot via GitHub, not Azure DevOps.
version: 2
enable-security-updates: false
enable-campaigned-updates: false
4 changes: 2 additions & 2 deletions azurefunctions-extensions-base/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ classifiers= [
'License :: OSI Approved :: MIT License',
'Intended Audience :: Developers',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
'Programming Language :: Python :: 3.13',
'Operating System :: Microsoft :: Windows',
'Operating System :: POSIX',
'Operating System :: MacOS :: MacOS X',
Expand Down
1 change: 0 additions & 1 deletion azurefunctions-extensions-bindings-blob/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ classifiers= [
'License :: OSI Approved :: MIT License',
'Intended Audience :: Developers',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ classifiers= [
'License :: OSI Approved :: MIT License',
'Intended Audience :: Developers',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
'Programming Language :: Python :: 3.13',
'Operating System :: Microsoft :: Windows',
'Operating System :: POSIX',
'Operating System :: MacOS :: MacOS X',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ classifiers= [
'License :: OSI Approved :: MIT License',
'Intended Audience :: Developers',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
'Programming Language :: Python :: 3.13',
'Operating System :: Microsoft :: Windows',
'Operating System :: POSIX',
'Operating System :: MacOS :: MacOS X',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ classifiers= [
'License :: OSI Approved :: MIT License',
'Intended Audience :: Developers',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
app = func.FunctionApp(http_auth_level=func.AuthLevel.FUNCTION)

"""
FOLDER: servicebus_samples
FOLDER: servicebus_samples_batch
DESCRIPTION:
These samples demonstrate how to obtain a ServiceBusReceivedMessage
from a ServiceBus Trigger.
batch from a ServiceBus Trigger.
USAGE:
Set the environment variables with your own values before running the
sample:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# coding: utf-8

# -------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for
# license information.
# --------------------------------------------------------------------------

import azure.functions as func
import azurefunctions.extensions.bindings.servicebus as servicebus

from azure.identity import DefaultAzureCredential
from azure.servicebus.aio import ServiceBusClient
from azure.servicebus import ServiceBusMessage

import datetime
import logging
import os

"""
FOLDER: servicebus_samples_exponential_backoff
DESCRIPTION:
These samples demonstrate how to schedule messages with exponential backoff
retries using ServiceBus Trigger and ServiceBusMessageActions.
USAGE:
Set the environment variables with your own values before running the
sample:
For running the ServiceBus queue trigger function:
1) QUEUE_NAME - the name of the ServiceBus queue
2) SERVICEBUS_CONNECTION - the connection string for the ServiceBus entity
3) SERVICEBUS_CONNECTION__fullyQualifiedNamespace - the fully qualified
namespace for the ServiceBus entity. Add this variable if you want
to use Managed Identity authentication instead of connection string
with shared access key.
"""

app = func.FunctionApp(http_auth_level=func.AuthLevel.FUNCTION)

MAX_RETRIES = 3

@app.service_bus_queue_trigger(arg_name="received_message",
queue_name="QUEUE_NAME",
connection="SERVICEBUS_CONNECTION",
auto_complete_messages=False)
async def servicebus_queue_trigger(received_message: servicebus.ServiceBusReceivedMessage, message_actions: servicebus.ServiceBusMessageActions):
logging.info(f"Python ServiceBus queue trigger processed message.")

application_properties = received_message.application_properties or {}

logging.info(f"Received message: {received_message}. Message application properties: {application_properties}")

# Read retry count
current_retry_count = int(application_properties.get(b"retry_count", 0))
logging.info(f"Current retry count: {current_retry_count}, Max: {MAX_RETRIES}")

# If max retries exceeded -> dead-letter
if current_retry_count >= MAX_RETRIES:
logging.warning("Max retries exceeded. Dead-lettering message.")
message_actions.deadletter(received_message, deadletter_reason="MaxRetryExceeded")
return

try:
# Complete original message
logging.info(f"Completing original message {received_message}.")
message_actions.complete(received_message)
logging.info("Original message completed successfully")

# ----- Service Bus Client Setup -----
# Determine Service Bus client: connection string or Managed Identity
conn = os.getenv("SERVICEBUS_CONNECTION")
fqns = os.getenv("SERVICEBUS_CONNECTION__fullyQualifiedNamespace")
queue_name = os.getenv("QUEUE_NAME")

# ----- Create client -----
if conn and "SharedAccessKey" in conn:
logging.info("Using ServiceBus connection string with shared access key")
sb_client = ServiceBusClient.from_connection_string(conn)
elif fqns:
logging.info(f"Using Managed Identity with namespace: {fqns}")
sb_client = ServiceBusClient(
fully_qualified_namespace=fqns,
credential=DefaultAzureCredential()
)
else:
raise RuntimeError(
"Neither SERVICEBUS_CONNECTION nor SERVICEBUS_CONNECTION__fullyQualifiedNamespace is configured"
)

# Sender for the queue
sender = sb_client.get_queue_sender(queue_name=queue_name)

async with sb_client, sender:
# NEW retry count
new_retry_count = current_retry_count + 1

# Schedule the new message for +10 seconds
schedule_time = datetime.datetime.utcnow() + datetime.timedelta(seconds=10)

new_message = ServiceBusMessage(
body=str(received_message),
application_properties={
**application_properties,
"retry_count": new_retry_count,
"original_message_id": received_message.message_id,
"scheduled_at": datetime.datetime.utcnow().isoformat(),
"original_enqueue_time": received_message.enqueued_time_utc.isoformat() if received_message.enqueued_time_utc else None
},
message_id=received_message.message_id,
session_id=received_message.session_id,
content_type=received_message.content_type,
correlation_id=received_message.correlation_id,
subject=received_message.subject
)

# Send the new message
sequence_number = await sender.schedule_messages(
new_message,
schedule_time
)

logging.info(f"Message scheduled with sequence number: {sequence_number}")
logging.info(f"Retry count incremented to: {new_retry_count}")


except Exception as e:
logging.exception("Error processing message. Abandoning message.")
message_actions.abandon(received_message)
raise


Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"version": "2.0",
"logging": {
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"excludedTypes": "Request"
}
}
},
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[4.*, 5.0.0)"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"IsEncrypted": false,
"Values": {
"FUNCTIONS_WORKER_RUNTIME": "python",
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"QUEUE_NAME": "",
"SERVICEBUS_CONNECTION": "",
"SERVICEBUS_CONNECTION__fullyQualifiedNamespace": ""
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# DO NOT include azure-functions-worker in this file
# The Python Worker is managed by Azure Functions platform
# Manually managing azure-functions-worker may cause unexpected issues

azure-functions
azurefunctions-extensions-bindings-servicebus
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
app = func.FunctionApp(http_auth_level=func.AuthLevel.FUNCTION)

"""
FOLDER: servicebus_samples
FOLDER: servicebus_samples_settlement
DESCRIPTION:
These samples demonstrate how to complete a message using the
optional ServiceBusMessageActions argument.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
app = func.FunctionApp(http_auth_level=func.AuthLevel.FUNCTION)

"""
FOLDER: servicebus_samples
FOLDER: servicebus_samples_single
DESCRIPTION:
These samples demonstrate how to obtain a ServiceBusReceivedMessage
from a ServiceBus Trigger.
Expand Down
4 changes: 2 additions & 2 deletions azurefunctions-extensions-http-fastapi/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ classifiers= [
'License :: OSI Approved :: MIT License',
'Intended Audience :: Developers',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
'Programming Language :: Python :: 3.13',
'Operating System :: Microsoft :: Windows',
'Operating System :: POSIX',
'Operating System :: MacOS :: MacOS X',
Expand Down
Loading