1- from functools import partial
21from operator import attrgetter , itemgetter
32from pathlib import Path
4- from random import randint
3+ from random import randint , sample
54
65import jinja2
7- import ujson
8- from aiohttp .web import Response , json_response
6+ import orjson
7+ from aiohttp .web import Response
98from sqlalchemy import select
9+ from sqlalchemy .orm .attributes import flag_modified
1010
1111from .models import sa_fortunes , sa_worlds , Fortune , World
1212
1616READ_SELECT_ORM = select (World .randomnumber )
1717WRITE_ROW_SQL = 'UPDATE "world" SET "randomnumber"=$2 WHERE id=$1'
1818
19- json_response = partial (json_response , dumps = ujson .dumps )
2019template_path = Path (__file__ ).parent / 'templates' / 'fortune.jinja'
2120template = jinja2 .Template (template_path .read_text ())
2221sort_fortunes_orm = attrgetter ('message' )
@@ -34,6 +33,11 @@ def get_num_queries(request):
3433 return 500
3534 return num_queries
3635
36+ def json_response (payload ):
37+ return Response (
38+ body = orjson .dumps (payload ),
39+ content_type = "application/json" ,
40+ )
3741
3842async def json (request ):
3943 """
@@ -74,7 +78,7 @@ async def multiple_database_queries_orm(request):
7478 result = []
7579 async with request .app ['db_session' ]() as sess :
7680 for id_ in ids :
77- num = await sess .scalar (READ_SELECT_ORM .filter_by ( id = id_ ))
81+ num = await sess .scalar (READ_SELECT_ORM .where ( World . id == id_ ))
7882 result .append ({'id' : id_ , 'randomNumber' : num })
7983 return json_response (result )
8084
@@ -128,30 +132,38 @@ async def updates(request):
128132 Test 5 ORM
129133 """
130134 num_queries = get_num_queries (request )
131- updates = [(randint (1 , 10000 ), randint (1 , 10000 )) for _ in range (num_queries )]
132- updates .sort ()
133- worlds = [{'id' : row_id , 'randomNumber' : number } for row_id , number in updates ]
135+
136+ ids = sample (range (1 , 10000 + 1 ), num_queries )
137+ ids .sort ()
138+ worlds = []
134139
135140 async with request .app ['db_session' ].begin () as sess :
136- for id_ , number in updates :
137- world = await sess .get (World , id_ , populate_existing = True )
138- world .randomnumber = number
141+ for row_id in ids :
142+ random_number = randint (1 , 10000 )
143+ world = await sess .get (World , row_id , populate_existing = True )
144+ world .randomnumber = random_number
145+ # force sqlalchemy to UPDATE entry even if the value has not changed
146+ # doesn't make sense in a real application, added only for pass `tfb verify`
147+ flag_modified (world , "randomnumber" )
148+ worlds .append ({'id' : row_id , 'randomNumber' : random_number })
149+
139150 return json_response (worlds )
140151
141152async def updates_raw (request ):
142153 """
143154 Test 5 RAW
144155 """
145156 num_queries = get_num_queries (request )
146- updates = [(randint (1 , 10000 ), randint (1 , 10000 )) for _ in range (num_queries )]
147- updates .sort ()
157+ ids = sample (range (1 , 10000 + 1 ), num_queries )
158+ ids .sort ()
159+ updates = [(row_id , randint (1 , 10000 )) for row_id in ids ]
148160 worlds = [{'id' : row_id , 'randomNumber' : number } for row_id , number in updates ]
149161
150162 async with request .app ['pg' ].acquire () as conn :
151163 stmt = await conn .prepare (READ_ROW_SQL )
152- for id_ , _ in updates :
164+ for row_id in ids :
153165 # the result of this is the int previous random number which we don't actually use
154- await stmt .fetchval (id_ )
166+ await stmt .fetchval (row_id )
155167 await conn .executemany (WRITE_ROW_SQL , updates )
156168
157169 return json_response (worlds )
0 commit comments