| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| --> |
| |
| # Apache Hamilton + Async |
| |
| This is currently an experimental feature, allowing one to run a hamilton DAG composed (entirely or partially) of async functions. |
| |
| ## How to use |
| |
| See the [example](fastapi.py) for the example. The difference from a normal driver is two-fold: |
| |
| 1. You call it using the `AsyncDriver` rather than the standard driver |
| 2. `raw_execute`, and `execute` are both coroutines, meaning they should be called with `await`. |
| 3. It allows for tasks as inputs -- they'll get properly awaited |
| |
| To run the example, make sure to install `requirements.txt`. |
| |
| Then run `uvicorn fastapi_example:app` in one terminal. |
| |
| Then curl with: |
| |
| ```bash |
| curl -X 'POST' \ |
| 'http://localhost:8000/execute' \ |
| -H 'accept: application/json' \ |
| -d '{}' |
| ``` |
| |
| You should get the following result: |
| |
| ```json |
| {"pipeline":{"computation1":false,"computation2":true}} |
| ``` |
| |
| ## Tracking |
| |
| This has an additional endpoint that will use the async tracker if the [ui](https://hamilton.apache.org/concepts/ui/) |
| is running on port 8241 -- see [fastapi_example.py](fastapi_example.py) for the code. |
| If it is not running it will proceed anyway without tracking. |
| |
| You can run it with: |
| |
| ```bash |
| curl -X 'POST' \ |
| 'http://localhost:8000/execute' \ |
| -H 'accept: application/json' \ |
| -d '{}' |
| ``` |
| |
| Recall, to get the server running, you'll have to run the following: |
| |
| ```bash |
| pip install sf-hamilton[ui] |
| hamilton ui |
| ``` |
| |
| This assumes a project (1) exists -- if you want a different one you can go the the UI and create one and/or set it in the code. |
| |
| |
| ## How it works |
| |
| Behind the scenes, we create a [GraphAdapter](../../hamilton/experimental/h_async.py) |
| that turns every function into a coroutine. The function graph then executes, creating tasks for each node, |
| that are awaited at the end. Thus no computation is complete until a final node |
| is awaited. |
| |
| Any node inputs are awaited on prior to node computation if they are awaitable, so you can pass |
| in external tasks as inputs if you want. |
| |
| Here is the execution visualized: |
| |
|  |
| |
| ## Data Quality with Async |
| |
| Data quality validators (`@check_output`, `@check_output_custom`) work with `AsyncDriver`. You can use: |
| |
| - **Sync validators** on async functions — they work as-is. |
| - **Async validators** (`AsyncDataValidator`, `AsyncBaseDefaultValidator`) for validation logic that requires `await` (e.g., async database lookups, async API calls). These define `async def validate()` and are automatically detected and awaited by the async execution engine. |
| - **Mixed** sync and async validators in a single `@check_output_custom` call. |
| |
| See `hamilton/data_quality/base.py` for the async base classes. |
| |
| ## Caveats |
| |
| 1. This will break in certain cases when decorating an async function (E.G. with `extract_outputs`). |
| This is because the output of that function is never awaited during delegation. We are looking into ways to fix this, |
| but for now be careful. We will at least be adding validation so the errors are clearer. |
| 2. Performance *should* be close to optimal but we have not benchmarked. We welcome contributions. |
| |
| We want feedback! We can determine how to make this part of the core API once we get userse who are happy, |
| so have some fun! |
| |
| Fixing the caveats will be the first order of business, and adding validations when things won't work. |