Native Async Client (Pre-release)
This is a pre-release for testing and feedback on the new native async client built on aiohttp. Closes #141.
If you're using the sync client and have been looking for a reason to go async, this is a good opportunity to give it a shot. If you're already using AsyncClient, this is a drop-in upgrade. The API surface is identical but under the hood it's completely redesigned.
Previously, the AsyncClient was just the sync urllib3 client wrapped in a thread executor. This is a from-scratch async implementation with real async I/O, proper connection pooling, and a pipelined architecture that streams and processes response data concurrently rather than a read-then-parse pattern, providing a potentially significant performance increase depending on your workload. The old executor-based path still works but is now deprecated and will be removed after release candidate testing and benchmarking is completed.
Install
aiohttp is now a required dependency for using the native async client, but its installation is not included by default. To install this release candidate with the required aiohttp for async use, install clickhouse_connect as follows:
pip install clickhouse-connect[async]==0.12.0rc1
Usage
import asyncio
import clickhouse_connect
async def main():
async with await clickhouse_connect.get_async_client(host="localhost") as client:
# create a test table
await client.command(
"CREATE TABLE IF NOT EXISTS test_example "
"(id UInt32, name String) "
"ENGINE MergeTree ORDER BY id"
)
# insert
data = [[1, "foo"], [2, "bar"]]
await client.insert("test_example", data, column_names=["id", "name"])
# query
result = await client.query("SELECT id, name FROM test_example")
print(result.result_rows)
# cleanup
await client.command("DROP TABLE IF EXISTS test_example")
asyncio.run(main())As you can see, the method names and signatures are the same as the sync client, you just await them. And for users of the the original async client, you don't have to change anything.
Migrating from the previous AsyncClient
If you're creating your async client like this, you're already on the new native implementation and no changes are needed:
client = await clickhouse_connect.get_async_client(host="localhost")The only case where you'll still get the old executor-based wrapper is if you're explicitly constructing it from a sync client:
from clickhouse_connect.driver import AsyncClient
sync_client = clickhouse_connect.get_client(host="localhost")
async_client = AsyncClient(client=sync_client) # legacy path, now deprecatedIf you're doing this, it will continue to work for a very short time but you'll see a DeprecationWarning. We recommend switching to get_async_client() when you get a chance so that you're using the native async client, not the deprecated executor-based client. The legacy path has been left in temporarily so users can benchmark it against the native version if they desire, as significant unexpected performance degradation would be very helpful feedback before we remove it entirely.
What we're looking for
- General stability feedback
- Performance compared to the sync client and legacy async client in your workloads
- Any issues with connection pooling, streaming, or concurrent usage
- Edge cases we haven't hit yet
Please report issues on this repo with [async] in the title.
Note
This release also includes everything from v0.11.0 release.