Azure / azure-functions-durable-python

Python library for using the Durable Functions bindings.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

purge_instance_history_by raises exception when optional created_time_from is not passed

AndreRicardo-Zoetis opened this issue Β· comments

πŸ› Describe the bug

A clear and concise description of what the bug is.

When created_time_from: Optional[datetime] = None is not passed to purge_instance_history_by it causes an exception in delete_async_request.

image

Exception has occurred: Exception
The operation failed with an unexpected status code 400
  File "/home/andre/code/durable-function/.venv/lib/python3.10/site-packages/azure/durable_functions/models/DurableOrchestrationClient.py", line 413, in purge_instance_history_by
    return self._parse_purge_instance_history_response(response)
  File "/home/andre/code/durable-function/function_app.py", line 15, in http_clean
    result = await client.purge_instance_history_by(
  File "/home/andre/code/durable-function/.venv/lib/python3.10/site-packages/azure/durable_functions/decorators/durable_app.py", line 199, in df_client_middleware
    return await user_code(*args, **kwargs)
  File "/usr/lib/azure-functions-core-tools-4/workers/python/3.10/LINUX/X64/azure_functions_worker/extension.py", line 147, in get_async_invocation_wrapper
    result = await function(**args)
  File "/usr/lib/azure-functions-core-tools-4/workers/python/3.10/LINUX/X64/azure_functions_worker/dispatcher.py", line 758, in _run_async_func
    return await ExtensionManager.get_async_invocation_wrapper(
  File "/usr/lib/azure-functions-core-tools-4/workers/python/3.10/LINUX/X64/azure_functions_worker/dispatcher.py", line 475, in _handle__invocation_request
    call_result = await self._run_async_func(
  File "/usr/lib/azure-functions-core-tools-4/workers/python/3.10/LINUX/X64/azure_functions_worker/dispatcher.py", line 261, in _dispatch_grpc_request
    resp = await request_handler(request)
  File "/usr/lib/python3.10/asyncio/events.py", line 80, in _run
    self._context.run(self._callback, *self._args)
  File "/usr/lib/python3.10/asyncio/base_events.py", line 1909, in _run_once
    handle._run()
  File "/usr/lib/python3.10/asyncio/base_events.py", line 603, in run_forever
    self._run_once()
  File "/usr/lib/python3.10/asyncio/base_events.py", line 636, in run_until_complete
    self.run_forever()
  File "/usr/lib/python3.10/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/lib/azure-functions-core-tools-4/workers/python/3.10/LINUX/X64/azure_functions_worker/main.py", line 49, in main
    return aio_compat.run(start_async(
  File "/usr/lib/azure-functions-core-tools-4/workers/python/3.10/LINUX/X64/worker.py", line 74, in <module>
    main.main()
  File "/usr/lib/python3.10/runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "/usr/lib/python3.10/runpy.py", line 196, in _run_module_as_main
    return _run_code(code, main_globals, None,
Exception: The operation failed with an unexpected status code 400

πŸ€” Expected behavior

What should have happened?

Clean instances older than created_time_to. Or purge_instance_history_by not to allow None in created_time_to.

β˜• Steps to reproduce

What Durable Functions patterns are you using, if any?

Any minimal reproducer we can use?

Yes. function_app.py below replicates the issue.

import azure.functions as func
import azure.durable_functions as df
from datetime import datetime, timedelta

app = df.DFApp(http_auth_level=func.AuthLevel.ANONYMOUS)


@app.route(route="clean")
@app.durable_client_input(client_name="client")
async def http_clean(req: func.HttpRequest, client: df.DurableOrchestrationClient):
    now = datetime.today()
    created_time_to = now + timedelta(minutes=1)  # leave at least 1 mins

    # Clean up function
    result = await client.purge_instance_history_by(
        created_time_to=created_time_to,
    )
    return f"Cleaned {result.instances_deleted}"

For example if only created_time_from is passed, it works as expected and the entries are deleted but if only created_time_to is passed, it throws the 400 exception.

    created_time_from = now - timedelta(hours=50)
    # Clean up function
    result = await client.purge_instance_history_by(
        created_time_from=created_time_from,
    )

Are you running this locally or on Azure?

Locally.

azure-functions==1.17.0
azure-functions-durable==1.2.8

⚑If deployed to Azure

We have access to a lot of telemetry that can help with investigations. Please provide as much of the following information as you can to help us investigate!

  • Timeframe issue observed:
  • Function App name:
  • Function name(s):
  • Azure region:
  • Orchestration instance ID(s):
  • Azure storage account name:

If you don't want to share your Function App or storage account name GitHub, please at least share the orchestration instance ID. Otherwise it's extremely difficult to look up information.