Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support stacked decorators for async workflows (#192)
Currently, You can't declare an async function to be both a FastAPI handler and a DBOS workflow: ```python @app.get("/endpoint/{var1}/{var2}") @DBOS.workflow() async def test_endpoint(var1: str, var2: str) -> str: return f"{var1}, {var2}!" ``` The problem stems from the function returned by the `@DBOS.workflow` decorator. Both the decorated function and the function returned by the decorator return a coroutine, but the function returned by the decorator is not defined with `async def`. This causes FastAPI to mis-categorize the workflow function as sync when it is actually async. The function retuned by the decorator has to appear as a coroutine to `inspect.iscoroutinefunction`. For Python 3.12 and later, any function can be marked as a coroutine using [`inspect.markcoroutinefunction`](https://docs.python.org/3/library/inspect.html#inspect.markcoroutinefunction). For Python 3.11 and earlier, we have to wrap the coroutine returning function in an async function like this: ```python def _mark_coroutine(func: Callable[P, R]) -> Callable[P, R]: @wraps(func) async def async_wrapper(*args: Any, **kwargs: Any) -> R: return await func(*args, **kwargs) # type: ignore return async_wrapper # type: ignore ```
- Loading branch information