Skip to content

Conversation

@hallvictoria
Copy link
Contributor

@hallvictoria hallvictoria commented Dec 5, 2025

Adding support for durabletask-azurefunctions.

  1. Identify which package is being used
  2. Based on package, we call the appropriate decorators
  3. Based on package, we assign the appropriate converter

using_legacy = True
_logger.warning("`azure-functions-durable` is deprecated. " \
"Please migrate to the new `durabletask-azurefunctions` package. " \
"See <AKA.MS LINK HERE> for more details.")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Log a warning if azure-functions-durable is being used.


if using_durable_task and using_legacy:
# Both packages are installed; prefer `durabletask-azurefunctions`.
_logger.warning("Both `azure-functions-durable` and " \
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the case that the customer has both durable packages, log a warning & prioritize durabletask-azurefunctions.

raise Exception(error_message)
_logger.info("Getting Durable Functions blueprint.")
df = get_durable_package()
df_bp = df.Blueprint()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

df here will now be either azure-functions-durable or durabletask-azurefunctions

class LegacyOrchestrationTriggerConverter(meta.InConverter,
meta.OutConverter,
binding='orchestrationTrigger',
binding=None,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previous converters are renamed to "Legacy" with no changes. binding is set to None so that they are not automatically registered


# ---------------- Durable Task Durable Functions Converters ---------------- #
# Durable Function Orchestration Trigger
class OrchestrationTriggerConverter(meta.InConverter,
Copy link
Contributor Author

@hallvictoria hallvictoria Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, converters for durable task package are named OrchestrationTrigger Converter, EntityTriggerConverter, ActivityTriggerConverter, and DurableClientConverter - open to renaming if preferable

def encode(cls, obj: typing.Any, *,
expected_type: typing.Optional[type]) -> meta.Datum:
# Durable function context should be a string
return meta.Datum(type='string', value=obj)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New converters for durable task are currently identical to legacy converters except for this change based on microsoft/durabletask-python#75 (comment).

Will update these converters as needed to be compatible with durable task

_logger.info("Durable Functions package loaded: %s", pkg.__name__)
_logger.info("Current bindings before registration: %s", meta._ConverterMeta._bindings)
# Clear existing bindings if they exist
meta._ConverterMeta._bindings.pop("orchestrationTrigger", None)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should never happen, but just in case - if there are bindings already registered for durable, remove them. Then we add the appropriate converter (Legacy vs. new) based on the durable package brought by the customer

"Attempted to use a Durable Functions decorator, " \
"but the `azure-functions-durable` SDK package could not be " \
"found. Please install `azure-functions-durable` to use " \
"but the `durabletask-azurefunctions` SDK package could not be " \
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the case where the customer tries to use a DF decorator (func.FunctionApp) but doesn't have either package installed. df is None, so we raise an error

# Licensed under the MIT License.
import logging

_logger = logging.getLogger('azure.functions.AsgiMiddleware')
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of the info logs will be removed in the future, just for debugging purposes now

# Licensed under the MIT License.
import logging

_logger = logging.getLogger('azure.functions.AsgiMiddleware')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why AsgiMiddleware is used in durable for logging?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Temporary, will be updated later

If neither package is installed, we return None.
"""
_logger.info("Attempting to import Durable Functions package.")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we make this log debug?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These logs are just for debugging, will be removed / moved to debug later

"Please migrate to the new `durabletask-azurefunctions` package. " \
"See <AKA.MS LINK HERE> for more details.")
except ImportError:
_logger.info("`azure-functions-durable` package not found.")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be a debug too

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These logs are just for debugging, will be removed / moved to debug later

_logger.info("`azure-functions-durable` package not found.")
pass
try:
import durabletask.azurefunctions as durable_functions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to check for both? If durabletask is added, lets directly use it and just add a log that durable task is being used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We still need to maintain backwards compatibility with azure-functions-durable. We have to check for both to determine which converter / decorator is being used. This check is only done once though - after that, the df variable will save which module is being used

"Durable Functions."
raise Exception(error_message)


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT; extra line added

from . import mysql # NoQA


register_durable_converters()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This goes inside the all block

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

register_durable_converters is not exposed to the worker. It's called at init, whenever azure-functions is imported by the worker.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants