Skip to content

Commit

Permalink
added load-testing app
Browse files Browse the repository at this point in the history
  • Loading branch information
kalombos committed Mar 23, 2024
1 parent ba4e83f commit ecfc5ca
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 0 deletions.
25 changes: 25 additions & 0 deletions load-testing/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
peewee-async load testing
============

Created for help to find race conditions in the library

How to use
-------

Install requirements:

```bash
pip install requirments
```

Run the app:

```bash
uvicorn app:app
```

Run yandex-tank:

```bash
docker run -v $(pwd):/var/loadtest --net host -it yandex/yandex-tank
```
98 changes: 98 additions & 0 deletions load-testing/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import peewee
from fastapi import FastAPI
import logging
import uvicorn
import random

import peewee_async
from contextlib import asynccontextmanager
import functools

logging.basicConfig()
pg_db = peewee_async.PooledPostgresqlDatabase(None)


class Manager(peewee_async.Manager):
"""Async models manager."""

database = peewee_async.PooledPostgresqlDatabase(
database='postgres',
user='postgres',
password='postgres',
host='localhost',
port=5432,
)


manager = Manager()


def patch_manager(manager):
async def cursor(self, conn=None, *args, **kwargs):

choice = random.randint(1, 5)
if choice == 5:
raise Exception("some network error") # network error imitation

# actual code
in_transaction = conn is not None
if not conn:
conn = await self.acquire()
cursor = await conn.cursor(*args, **kwargs)
cursor.release = functools.partial(
self.release_cursor, cursor,
in_transaction=in_transaction)
return cursor

manager.database._async_conn_cls.cursor = cursor

def setup_logging():
logger = logging.getLogger("uvicorn.error")
handler = logging.FileHandler(filename="app.log", mode="w")
logger.addHandler(handler)


class MySimplestModel(peewee.Model):
id = peewee.IntegerField(primary_key=True, sequence=True)

class Meta:
database = pg_db


@asynccontextmanager
async def lifespan(app: FastAPI):
await peewee_async._run_no_result_sql( # noqa
database=manager.database,
operation='CREATE TABLE IF NOT EXISTS MySimplestModel (id SERIAL PRIMARY KEY);',
)
await peewee_async._run_no_result_sql( # noqa
database=manager.database,
operation='TRUNCATE TABLE MySimplestModel;',
)
setup_logging()
patch_manager(manager)
yield
# Clean up the ML models and release the resources
await manager.close()


app = FastAPI(lifespan=lifespan)
errors = set()


@app.get("/select")
async def test():
try:
await manager.execute(MySimplestModel.select())
except Exception as e:
errors.add(str(e))
raise
return errors


if __name__ == "__main__":
uvicorn.run(
app,
host="0.0.0.0",
access_log=True
)
11 changes: 11 additions & 0 deletions load-testing/load.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
phantom:
address: 127.0.0.1:8000 # [Target's address]:[target's port]
uris:
- /select
load_profile:
load_type: rps # schedule load by defining requests per second
schedule: const(50, 10m) # starting from 1rps growing linearly to 10rps during 10 minutes
console:
enabled: true # enable console output
telegraf:
enabled: false # let's disable telegraf monitoring for the first time
2 changes: 2 additions & 0 deletions load-testing/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
fastapi==0.110.0
uvicorn==0.29.0

0 comments on commit ecfc5ca

Please sign in to comment.