that-depends icon indicating copy to clipboard operation
that-depends copied to clipboard

Resources are created twice if used in different async contexts

Open vrslev opened this issue 6 months ago • 2 comments

Caught a regression after 1.15.0 (via #67). Works fine on 1.14.1.

If an async resource has any IO in creator function, this function will be caused twice resulting in different resources.

Consider the following example:

import asyncio
import typing
from dataclasses import dataclass

import that_depends
from that_depends.providers import AsyncResource


@dataclass
class Client: ...


async def create_client() -> typing.AsyncIterator[Client]:
    print("created client")  # noqa: T201
    await asyncio.sleep(0)
    yield Client()


class IOCContainer(that_depends.BaseContainer):
    client = AsyncResource(create_client)


@that_depends.inject
async def uses_client(_: Client = that_depends.Provide[IOCContainer.client]) -> None: ...


async def main() -> None:
    async with asyncio.TaskGroup() as task_group:
        task_group.create_task(uses_client())  # Can be reproduced only if background_task goes first
        await uses_client()


asyncio.run(main())

It prints "created client" twice, though expected once.

vrslev avatar Aug 22 '24 13:08 vrslev