Azure / Azure/azure-functions-python-worker
Support async startup and shutdown lifecycle hooks for Python Function Apps
- Dominant language
- Python
- Stars
- 357
- Forks
- 116
- Avg merge
- 32m
- Merged PRs (30d)
- 1
Description
### Binding Type
Not binding-specific. This is a Python worker / Python v2 programming-model lifecycle capability for any Function App that owns process-scoped async resources.
### Expected Behavior
Provide supported worker-process startup and shutdown hooks that Python applications and libraries can register through the v2 `FunctionApp` programming model.
The shutdown callback should:
- run once per Python language-worker process during graceful host shutdown, local `func stop`, and scale-in;
- execute on the worker's active asyncio event loop so async SDK clients can be awaited safely;
- define ordering, timeout, cancellation, and exception-handling semantics;
- not run concurrently with new invocations after shutdown begins;
- work consistently for `FunctionApp` and Durable `DFApp` applications;
- remain process-local when `FUNCTIONS_WORKER_PROCESS_COUNT` or scale-out creates multiple workers.
This enables deterministic cleanup of module-level/shared Azure SDK clients while following Azure Functions guidance to reuse SDK client instances across invocations.
### Relevant sample code snipped
```python
import azure.functions as func
app = func.FunctionApp()
@app.on_startup
async def startup() -> None:
await resources.initialize()
@app.on_shutdown
async def shutdown() -> None:
await resources.close()
```
The exact API shape is open for discussion; a registration API or worker-extension lifecycle contract would also satisfy the requirement.
### Additional Information
Azure Functions recommends sharing SDK clients across invocations to reduce latency, socket exhaustion, and SNAT pressure:
https://learn.microsoft.com/azure/azure-functions/manage-connections#manage-sdk-client-connections
Today `FunctionApp` and `DFApp` do not expose a supported async shutdown hook. Libraries must choose between per-invocation client churn, process-lifetime clients without deterministic cleanup, or fragile `atexit`/signal handling that may run after the event loop is unavailable.
A concrete example is Azure/azure-functions-agents-runtime#157 and its proposed fix in Azure/azure-functions-agents-runtime#158. Microsoft Foundry clients own both async httpx and aiohttp transports. Sharing these clients fixes steady-state connection churn, but deterministic graceful shutdown cannot be integrated safely without a worker lifecycle hook.
Suggested acceptance coverage:
- async callback executes on the worker event loop;
- exactly once per process for graceful stop and scale-in;
- callback completion is bounded by a documented timeout;
- callback errors are logged without skipping other registered callbacks;
- no new invocation begins after shutdown callbacks start;
- Core Tools integration test covers `func start` followed by graceful stop;
- multiple worker processes each invoke their own callbacks.
Contributor guide
Assessment
This issue has not been assessed yet.