|
| 1 | +--- |
| 2 | +order: 2 |
| 3 | +--- |
| 4 | + |
| 5 | +# Taskiq + AioHTTP |
| 6 | + |
| 7 | +AioHTTP is a framework for building robust applications. We created several libraries to make the experience with AioHTTP even better. |
| 8 | + |
| 9 | +# Dependency inecjeciton for AioHTTP |
| 10 | + |
| 11 | +We created a library [aiohttp-deps](https://pypi.org/project/aiohttp-deps/) to add FastAPI-like dependency injection in AioHTTP. |
| 12 | + |
| 13 | +To install it, simply run: |
| 14 | + |
| 15 | +```python |
| 16 | +pip install "aiohttp-deps" |
| 17 | +``` |
| 18 | + |
| 19 | +After the installation, please add startup event to your application to initialize dependencies context. |
| 20 | + |
| 21 | +```python |
| 22 | +from aiohttp import web |
| 23 | +import aiohttp_deps |
| 24 | + |
| 25 | + |
| 26 | +app = web.Application() |
| 27 | + |
| 28 | +# This startup event makes all the magic happen. |
| 29 | +# It parses current handlers and create dependency graphs for them. |
| 30 | +app.on_startup.append(aiohttp_deps.init) |
| 31 | + |
| 32 | +web.run_app(app) |
| 33 | +``` |
| 34 | + |
| 35 | +You can read more about dependency injection and available dependencies in the project's [README.md](https://github.com/taskiq-python/aiohttp-deps). |
| 36 | + |
| 37 | + |
| 38 | + |
| 39 | +## Adding taskiq integration |
| 40 | + |
| 41 | +We highly recommend using aiohttp with aiohttp-deps because it allows us to reuse the same dependencies for your handlers and tasks. First of all, you should install the [taskiq-aiohttp](https://pypi.org/project/taskiq-aiohttp/) library. |
| 42 | + |
| 43 | +```python |
| 44 | +pip install "taskiq-aiohttp" |
| 45 | +``` |
| 46 | + |
| 47 | +After the installation is complete, add an initialization function call to your broker's main file so it becomes something like this: |
| 48 | + |
| 49 | +```python |
| 50 | +import taskiq_aiohttp |
| 51 | + |
| 52 | +broker = MyBroker() |
| 53 | + |
| 54 | +# The second argument is a path to web.Application variable. |
| 55 | +# Also you can provide here a factory function that takes no |
| 56 | +# arguments and returns an application. This function can be async. |
| 57 | +taskiq_aiohttp.init(broker, "my_project.main:app") |
| 58 | +``` |
| 59 | + |
| 60 | +From this point, you'll be able to reuse the same dependencies as with `aiohttp-deps`. |
| 61 | +Let's take a look at this function: |
| 62 | + |
| 63 | +```python |
| 64 | +from aiohttp import web |
| 65 | +from taskiq import TaskiqDepends |
| 66 | +from my_project.tkq import broker |
| 67 | + |
| 68 | +@broker.task |
| 69 | +async def my_task(app: web.Application = TaskiqDepends()): |
| 70 | + ... |
| 71 | + |
| 72 | +``` |
| 73 | + |
| 74 | +In this example, we depend on the current application. We can use its state in a current task or any other dependency. We can take db_pool from your application's state, which is the same pool, as the one you've created on AiohTTP's startup. |
| 75 | +But this application is only a mock of your application. It has correct types and all your variables that you filled on startup, but it doesn't handle any request. |
| 76 | +This integration adds two main dependencies: |
| 77 | +* web.Application - current application. |
| 78 | +* web.Request - mocked request. This request only exists to be able to use the same dependencies. |
| 79 | + |
| 80 | +You can find more detailed examples in the [examples repo](https://github.com/taskiq-python/examples). |
| 81 | + |
| 82 | +## Testing |
| 83 | + |
| 84 | +Writing tests for AioHTTP with taskiq is as easy as writing tests for the aiohttp application. The only difference is that, if you want to use InMemoryBroker, then you need to add context for dependency injection. It's easier to call `populate_context` when creating a `test_client` fixture. |
| 85 | + |
| 86 | +```python |
| 87 | +import taskiq_aiohttp |
| 88 | + |
| 89 | +@pytest.fixture |
| 90 | +async def test_client( |
| 91 | + app: web.Application, |
| 92 | +) -> AsyncGenerator[TestClient, None]: |
| 93 | + """ |
| 94 | + Create a test client. |
| 95 | +
|
| 96 | + This function creates a TestServer |
| 97 | + and a test client for the application. |
| 98 | +
|
| 99 | + Also this fixture populates context |
| 100 | + with needed variables. |
| 101 | +
|
| 102 | + :param app: current application. |
| 103 | + :yield: ready to use client. |
| 104 | + """ |
| 105 | + loop = asyncio.get_running_loop() |
| 106 | + server = TestServer(app) |
| 107 | + client = TestClient(server, loop=loop) |
| 108 | + |
| 109 | + await client.start_server() |
| 110 | + |
| 111 | + # This is important part. |
| 112 | + # Since InMemoryBroker doesn't |
| 113 | + # run as a worker process, we have to populate |
| 114 | + # broker's context by hand. |
| 115 | + taskiq_aiohttp.populate_context( |
| 116 | + broker=broker, |
| 117 | + server=server.runner.server, |
| 118 | + app=app, |
| 119 | + loop=loop, |
| 120 | + ) |
| 121 | + |
| 122 | + yield client |
| 123 | + |
| 124 | + broker.custom_dependency_context = {} |
| 125 | + await client.close() |
| 126 | +``` |
0 commit comments