GoogleCloudPlatform / cloud-sql-python-connector

A Python library for connecting securely to your Cloud SQL instances.
Apache License 2.0
284 stars 67 forks source link

asyncpg pool support improved #1180

Closed d1manson closed 1 week ago

d1manson commented 2 weeks ago

Description

As of asyncpg v0.30.0 it is now possible to pass a custom connection function into the asyncpg.create_pool method, which means it is now possible to use the cloudsql connector without SQLAlchemy, thus maintaining the original API of the asyncpg pool (which is rather important if you are migrating an existing codebase that made heavy use of an asyncpg pool).

Might be helpful to future readers of the docs to reflect that here.

Thanks.

Potential Solution

No response

Additional Details

No response

jackwotherspoon commented 2 weeks ago

Hi @d1manson, thanks for pointing this out! (and being the one to commit this awesome feature) 😄

Do you have a working code sample handy? If so I'll test it out and get it added to our docs ASAP ✅

I assume it probably works similar to SQLAlchemy and I can just pass the getconn as the connect arg to async.create_pool?

Thanks again for this awesome feature and putting it on our radar 👍

d1manson commented 2 weeks ago

@jackwotherspoon - yes exactly. the getconn will need to have a call signature of async def getconn(dsn, **kwargs) I think, but it's up to the user to decide if they actually use those args or have some other mechanism for passing in the config to the connection.

jackwotherspoon commented 1 week ago

yes exactly. the getconn will need to have a call signature of async def getconn(dsn, **kwargs) I think, but it's up to the user to decide if they actually use those args or have some other mechanism for passing in the config to the connection.

@d1manson do you have a working sample handy? I did a quick test and am running into some issues...

jackwotherspoon commented 1 week ago

Got a working example actually 👏

import asyncpg
from google.cloud.sql.connector import Connector

async def main():
    loop = asyncio.get_running_loop()
    async with Connector(loop=loop) as connector:

        async def getconn(instance_connection_name, **kwargs) -> asyncpg.Connection:
            return await connector.connect_async(
                instance_connection_name,
                "asyncpg",
                user="my-user",
                password="my-password",
                db="my-db",
                **kwargs,
            )

        pool = await asyncpg.create_pool(
            "my-project:my-region:my-instance", connect=getconn
        )
        async with pool.acquire() as conn:
            hello = await conn.fetch("SELECT 'Hello World!'")

Will get a PR up shortly with a clean example.