diff --git a/frameworks/Python/granian/app_asgi.py b/frameworks/Python/granian/app_asgi.py index 7799b5f9064..9fd2ff4f6d0 100644 --- a/frameworks/Python/granian/app_asgi.py +++ b/frameworks/Python/granian/app_asgi.py @@ -3,7 +3,7 @@ from operator import itemgetter from pathlib import Path -from random import randint +from random import randint, sample from urllib.parse import parse_qs import asyncpg @@ -83,34 +83,27 @@ async def route_json(scope, receive, send): async def route_db(scope, receive, send): row_id = randint(1, 10000) - connection = await pool.acquire() - try: + async with pool.acquire() as connection: number = await connection.fetchval(SQL_SELECT, row_id) - world = {'id': row_id, 'randomNumber': number} - finally: - await pool.release(connection) await send(JSON_RESPONSE) await send({ 'type': 'http.response.body', - 'body': json_dumps(world), + 'body': json_dumps({'id': row_id, 'randomNumber': number}), 'more_body': False }) async def route_queries(scope, receive, send): num_queries = get_num_queries(scope) - row_ids = [randint(1, 10000) for _ in range(num_queries)] + row_ids = sample(range(1, 10000), num_queries) worlds = [] - connection = await pool.acquire() - try: + async with pool.acquire() as connection: statement = await connection.prepare(SQL_SELECT) for row_id in row_ids: number = await statement.fetchval(row_id) worlds.append({'id': row_id, 'randomNumber': number}) - finally: - await pool.release(connection) await send(JSON_RESPONSE) await send({ @@ -121,11 +114,8 @@ async def route_queries(scope, receive, send): async def route_fortunes(scope, receive, send): - connection = await pool.acquire() - try: + async with pool.acquire() as connection: fortunes = await connection.fetch('SELECT * FROM Fortune') - finally: - await pool.release(connection) fortunes.append(ROW_ADD) fortunes.sort(key=key) @@ -140,17 +130,17 @@ async def route_fortunes(scope, receive, send): async def route_updates(scope, receive, send): num_queries = get_num_queries(scope) - updates = [(randint(1, 10000), randint(1, 10000)) for _ in range(num_queries)] + updates = list(zip( + sorted(sample(range(1, 10000), num_queries)), + sample(range(1, 10000), num_queries) + )) worlds = [{'id': row_id, 'randomNumber': number} for row_id, number in updates] - connection = await pool.acquire() - try: + async with pool.acquire() as connection: statement = await connection.prepare(SQL_SELECT) for row_id, _ in updates: await statement.fetchval(row_id) await connection.executemany(SQL_UPDATE, updates) - finally: - await pool.release(connection) await send(JSON_RESPONSE) await send({ diff --git a/frameworks/Python/granian/app_rsgi.py b/frameworks/Python/granian/app_rsgi.py index 00b7683abc7..c434a581374 100644 --- a/frameworks/Python/granian/app_rsgi.py +++ b/frameworks/Python/granian/app_rsgi.py @@ -3,15 +3,13 @@ from operator import itemgetter from pathlib import Path -from random import randint +from random import randint, sample from urllib.parse import parse_qs import asyncpg import jinja2 import orjson -from granian.rsgi import Response - async def pg_setup(): global pool @@ -28,9 +26,9 @@ async def pg_setup(): SQL_UPDATE = 'UPDATE "world" SET "randomnumber"=$1 WHERE id=$2' ROW_ADD = [0, 'Additional fortune added at request time.'] -JSON_HEADERS = {'content-type': 'application/json'} -HTML_HEADERS = {'content-type': 'text/html; charset=utf-8'} -PLAINTEXT_HEADERS = {'content-type': 'text/plain; charset=utf-8'} +JSON_HEADERS = [('content-type', 'application/json')] +HTML_HEADERS = [('content-type', 'text/html; charset=utf-8')] +PLAINTEXT_HEADERS = [('content-type', 'text/plain; charset=utf-8')] pool = None key = itemgetter(1) @@ -56,74 +54,92 @@ def get_num_queries(scope): async def route_json(scope, proto): - return Response.bytes(json_dumps({'message': 'Hello, world!'}), 200, JSON_HEADERS) + proto.response_bytes( + 200, + JSON_HEADERS, + json_dumps({'message': 'Hello, world!'}) + ) async def route_db(scope, proto): row_id = randint(1, 10000) - connection = await pool.acquire() - try: + async with pool.acquire() as connection: number = await connection.fetchval(SQL_SELECT, row_id) - world = {'id': row_id, 'randomNumber': number} - finally: - await pool.release(connection) - return Response.bytes(json_dumps(world), 200, JSON_HEADERS) + proto.response_bytes( + 200, + JSON_HEADERS, + json_dumps({'id': row_id, 'randomNumber': number}) + ) async def route_queries(scope, proto): num_queries = get_num_queries(scope) - row_ids = [randint(1, 10000) for _ in range(num_queries)] + row_ids = sample(range(1, 10000), num_queries) worlds = [] - connection = await pool.acquire() - try: + async with pool.acquire() as connection: statement = await connection.prepare(SQL_SELECT) for row_id in row_ids: number = await statement.fetchval(row_id) worlds.append({'id': row_id, 'randomNumber': number}) - finally: - await pool.release(connection) - return Response.bytes(json_dumps(worlds), 200, JSON_HEADERS) + proto.response_bytes( + 200, + JSON_HEADERS, + json_dumps(worlds) + ) async def route_fortunes(scope, proto): - connection = await pool.acquire() - try: + async with pool.acquire() as connection: fortunes = await connection.fetch('SELECT * FROM Fortune') - finally: - await pool.release(connection) fortunes.append(ROW_ADD) fortunes.sort(key=key) content = template.render(fortunes=fortunes) - return Response.str(content, 200, HTML_HEADERS) + proto.response_str( + 200, + HTML_HEADERS, + content + ) async def route_updates(scope, proto): num_queries = get_num_queries(scope) - updates = [(randint(1, 10000), randint(1, 10000)) for _ in range(num_queries)] + updates = list(zip( + sorted(sample(range(1, 10000), num_queries)), + sample(range(1, 10000), num_queries) + )) worlds = [{'id': row_id, 'randomNumber': number} for row_id, number in updates] - connection = await pool.acquire() - try: + async with pool.acquire() as connection: statement = await connection.prepare(SQL_SELECT) for row_id, _ in updates: await statement.fetchval(row_id) await connection.executemany(SQL_UPDATE, updates) - finally: - await pool.release(connection) - return Response.bytes(json_dumps(worlds), 200, JSON_HEADERS) + proto.response_bytes( + 200, + JSON_HEADERS, + json_dumps(worlds) + ) async def route_plaintext(scope, proto): - return Response.bytes(b'Hello, world!', 200, PLAINTEXT_HEADERS) + proto.response_bytes( + 200, + PLAINTEXT_HEADERS, + b'Hello, world!' + ) async def handle_404(scope, proto): - return Response.bytes(b'Not found', 404, PLAINTEXT_HEADERS) + proto.response_bytes( + 404, + PLAINTEXT_HEADERS, + b'Not found' + ) routes = { diff --git a/frameworks/Python/granian/requirements.txt b/frameworks/Python/granian/requirements.txt index 6914cae94b1..f1c9194a3f3 100644 --- a/frameworks/Python/granian/requirements.txt +++ b/frameworks/Python/granian/requirements.txt @@ -1,5 +1,4 @@ asyncpg==0.25.0 -granian==0.1.0a3 +granian==0.1.0 jinja2==3.1.2 -orjson==3.7.2 -uvloop==0.16.0 +orjson==3.8.1 diff --git a/frameworks/Python/granian/run.py b/frameworks/Python/granian/run.py index e129daa067d..20b3e51a1cf 100644 --- a/frameworks/Python/granian/run.py +++ b/frameworks/Python/granian/run.py @@ -6,14 +6,12 @@ if __name__ == '__main__': interface = sys.argv[1] - threads = 1 if interface == "asgi" else None Granian( f"app_{interface}:main", address="0.0.0.0", port=8080, workers=multiprocessing.cpu_count(), - threads=threads, backlog=2048, interface=interface, websockets=False