Browse Source

Update python sanic tests (#5103)

Diogo Dutra 5 years ago
parent
commit
811d7b821a

+ 120 - 0
frameworks/Python/sanic/app.py

@@ -1,3 +1,10 @@
+import asyncpg
+import os
+import jinja2
+from logging import getLogger
+from random import randint
+from operator import itemgetter
+
 import multiprocessing
 import multiprocessing
 from wsgiref.handlers import format_date_time
 from wsgiref.handlers import format_date_time
 
 
@@ -5,14 +12,127 @@ import sanic
 from sanic import response
 from sanic import response
 
 
 
 
+logger = getLogger(__name__)
+
+
+READ_ROW_SQL = 'SELECT "randomnumber" FROM "world" WHERE id = $1'
+READ_ROW_SQL_TO_UPDATE = 'SELECT "id", "randomnumber" FROM "world" WHERE id = $1'
+WRITE_ROW_SQL = 'UPDATE "world" SET "randomnumber"=$1 WHERE id=$2'
+ADDITIONAL_ROW = [0, 'Additional fortune added at request time.']
+
+
+def load_fortunes_template():
+    path = os.path.join('templates', 'fortune.html')
+    with open(path, 'r') as template_file:
+        template_text = template_file.read()
+        return jinja2.Template(template_text)
+
+
+def get_num_queries(queries):
+    try:
+        query_count = int(queries)
+    except (ValueError, TypeError):
+        return 1
+
+    if query_count < 1:
+        return 1
+    if query_count > 500:
+        return 500
+    return query_count
+
+
+connection_pool = None
+sort_fortunes_key = itemgetter(1)
+template = load_fortunes_template()
+
 app = sanic.Sanic()
 app = sanic.Sanic()
 
 
 
 
[email protected]('before_server_start')
+async def setup_database(app, loop):
+        global connection_pool
+        connection_pool = await asyncpg.create_pool(
+            user=os.getenv('PGUSER', 'benchmarkdbuser'),
+            password=os.getenv('PGPASS', 'benchmarkdbpass'),
+            database='hello_world',
+            host='tfb-database',
+            port=5432
+        )
+
+
 @app.get('/json')
 @app.get('/json')
 def json_view(request):
 def json_view(request):
     return response.json({'message': 'Hello, world!'}, headers=get_headers())
     return response.json({'message': 'Hello, world!'}, headers=get_headers())
 
 
 
 
[email protected]('/db')
+async def single_database_query_view(request):
+    row_id = randint(1, 10000)
+
+    async with connection_pool.acquire() as connection:
+        number = await connection.fetchval(READ_ROW_SQL, row_id)
+
+    return response.json(
+        {'id': row_id, 'randomNumber': number},
+        headers=get_headers()
+    )
+
+
[email protected]('/queries')
+async def multiple_database_queries_view(request):
+    num_queries = get_num_queries(request.args.get('queries', 1))
+    row_ids = [randint(1, 10000) for _ in range(num_queries)]
+    worlds = []
+
+    async with connection_pool.acquire() as connection:
+        statement = await connection.prepare(READ_ROW_SQL)
+        for row_id in row_ids:
+            number = await statement.fetchval(row_id)
+            worlds.append(
+                dict(
+                    id=row_id,
+                    randomNumber=number
+                )
+            )
+
+    return response.json(worlds, headers=get_headers())
+
+
[email protected]('/fortunes')
+async def fortunes_view(request):
+    async with connection_pool.acquire() as connection:
+        fortunes = await connection.fetch('SELECT * FROM Fortune')
+
+    fortunes.append(ADDITIONAL_ROW)
+    fortunes.sort(key=sort_fortunes_key)
+    content = template.render(fortunes=fortunes)
+    return response.html(content, headers=get_headers())
+
+
+
[email protected]('/updates')
+async def database_updates_view(request):
+    worlds = []
+    updates = set()
+    queries = request.args.get('queries', 1)
+
+    async with connection_pool.acquire() as connection:
+        statement = await connection.prepare(READ_ROW_SQL_TO_UPDATE)
+
+        for _ in range(get_num_queries(queries)):
+            record = await statement.fetchrow(randint(1, 10000))
+            world = dict(
+                id=record['id'], randomNumber=record['randomnumber']
+            )
+            world['randomNumber'] = randint(1, 10000)
+            worlds.append(world)
+            updates.add((world['id'], world['randomNumber']))
+
+        await connection.executemany(WRITE_ROW_SQL, updates)
+
+    return response.json(worlds, headers=get_headers())
+
+
 @app.get('/plaintext')
 @app.get('/plaintext')
 def plaintext_view(request):
 def plaintext_view(request):
     return response.text('Hello, world!', headers=get_headers())
     return response.text('Hello, world!', headers=get_headers())

+ 26 - 19
frameworks/Python/sanic/benchmark_config.json

@@ -1,23 +1,30 @@
 {
 {
   "framework": "sanic",
   "framework": "sanic",
-  "tests": [{
-    "default": {
-      "json_url": "/json",
-      "plaintext_url": "/plaintext",
-      "port": 8080,
-      "approach": "Realistic",
-      "classification": "Micro",
-      "framework": "sanic",
-      "language": "Python",
-      "flavor": "Python3",
-      "platform": "None",
-      "webserver": "None",
-      "os": "Linux",
-      "orm": "Raw",
-      "database_os": "Linux",
-      "database": "None",
-      "display_name": "Sanic",
-      "notes": ""
+  "tests": [
+    {
+      "default": {
+        "json_url": "/json",
+        "fortune_url": "/fortunes",
+        "plaintext_url": "/plaintext",
+        "db_url": "/db",
+        "query_url": "/queries?queries=",
+        "update_url": "/updates?queries=",
+        "port": 8080,
+        "approach": "Realistic",
+        "classification": "Micro",
+        "database": "Postgres",
+        "framework": "sanic",
+        "language": "Python",
+        "flavor": "Python3",
+        "orm": "Raw",
+        "platform": "None",
+        "webserver": "None",
+        "os": "Linux",
+        "database_os": "Linux",
+        "display_name": "Sanic",
+        "notes": "",
+        "versus": "None"
+      }
     }
     }
-  }]
+  ]
 }
 }

+ 2 - 0
frameworks/Python/sanic/requirements.txt

@@ -1 +1,3 @@
+asyncpg==0.18.2
+jinja2==2.10.1
 sanic==0.7.0
 sanic==0.7.0

+ 4 - 2
frameworks/Python/sanic/sanic.dockerfile

@@ -1,9 +1,11 @@
 FROM python:3.6.6-stretch
 FROM python:3.6.6-stretch
 
 
+ADD ./requirements.txt /sanic/requirements.txt
+
+RUN pip3 install -r /sanic/requirements.txt
+
 ADD ./ /sanic
 ADD ./ /sanic
 
 
 WORKDIR /sanic
 WORKDIR /sanic
 
 
-RUN pip3 install -r /sanic/requirements.txt
-
 CMD python3 app.py
 CMD python3 app.py

+ 10 - 0
frameworks/Python/sanic/templates/fortune.html

@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head><title>Fortunes</title></head>
+<body>
+<table>
+<tr><th>id</th><th>message</th></tr>
+{% for fortune in fortunes %}<tr><td>{{ fortune[0] }}</td><td>{{ fortune[1]|e }}</td></tr>
+{% endfor %}</table>
+</body>
+</html>