|
4 | 4 | import time
|
5 | 5 | import uuid
|
6 | 6 |
|
7 |
| -from fastapi import FastAPI |
| 7 | +import aiomcache |
| 8 | +import orjson |
| 9 | +from asyncpg import PostgresError |
| 10 | +from fastapi import FastAPI, HTTPException |
8 | 11 | from fastapi.responses import ORJSONResponse, PlainTextResponse
|
9 | 12 | from prometheus_client import make_asgi_app
|
| 13 | +from pydantic import BaseModel |
10 | 14 | from pymemcache.client.base import Client
|
11 |
| -from sqlalchemy import insert |
12 |
| -from asyncer import asyncify |
13 |
| -from db import PostgresDep |
| 15 | + |
| 16 | +from db import PostgresDep, lifespan |
14 | 17 | from metrics import H
|
15 |
| -from models import Device |
16 | 18 |
|
17 |
| -app = FastAPI() |
| 19 | +app = FastAPI(lifespan=lifespan) |
18 | 20 |
|
19 | 21 | MEMCACHED_HOST = os.environ["MEMCACHED_HOST"]
|
20 |
| -cache_client = Client(MEMCACHED_HOST) |
| 22 | +cache_client = aiomcache.Client(MEMCACHED_HOST) |
21 | 23 |
|
22 | 24 | metrics_app = make_asgi_app()
|
23 | 25 | app.mount("/metrics", metrics_app)
|
@@ -75,34 +77,56 @@ def get_devices():
|
75 | 77 | return devices
|
76 | 78 |
|
77 | 79 |
|
| 80 | +class DeviceRequest(BaseModel): |
| 81 | + mac: str |
| 82 | + firmware: str |
| 83 | + |
| 84 | + |
78 | 85 | @app.post("/api/devices", status_code=201, response_class=ORJSONResponse)
|
79 |
| -async def create_device(device: Device, session: PostgresDep) -> Device: |
80 |
| - # To match Go implementation instead of using SQLAlchemy factory. |
81 |
| - now = datetime.datetime.now(datetime.timezone.utc) |
82 |
| - device_uuid = uuid.uuid4() |
83 |
| - |
84 |
| - stmt = ( |
85 |
| - insert(Device) |
86 |
| - .values( |
87 |
| - uuid=device_uuid, |
88 |
| - mac=device.mac, |
89 |
| - firmware=device.firmware, |
90 |
| - created_at=now, |
91 |
| - updated_at=now, |
| 86 | +async def create_device(device: DeviceRequest, conn: PostgresDep): |
| 87 | + try: |
| 88 | + now = datetime.datetime.now(datetime.timezone.utc) |
| 89 | + device_uuid = uuid.uuid4() |
| 90 | + |
| 91 | + insert_query = """ |
| 92 | + INSERT INTO python_device (uuid, mac, firmware, created_at, updated_at) |
| 93 | + VALUES ($1, $2, $3, $4, $5) |
| 94 | + RETURNING id, uuid, mac, firmware, created_at, updated_at; |
| 95 | + """ |
| 96 | + |
| 97 | + start_time = time.perf_counter() |
| 98 | + |
| 99 | + row = await conn.fetchrow( |
| 100 | + insert_query, device_uuid, device.mac, device.firmware, now, now |
| 101 | + ) |
| 102 | + |
| 103 | + H.labels(op="insert", db="postgres").observe(time.perf_counter() - start_time) |
| 104 | + |
| 105 | + device_dict = dict(row) |
| 106 | + |
| 107 | + # Measure cache operation |
| 108 | + start_time = time.perf_counter() |
| 109 | + |
| 110 | + await cache_client.set( |
| 111 | + device_uuid.bytes, |
| 112 | + orjson.dumps(device_dict), |
| 113 | + exptime=20, |
| 114 | + ) |
| 115 | + |
| 116 | + H.labels(op="set", db="memcache").observe(time.perf_counter() - start_time) |
| 117 | + |
| 118 | + return device_dict |
| 119 | + |
| 120 | + except PostgresError as e: |
| 121 | + raise HTTPException( |
| 122 | + status_code=500, detail="Database error occurred while creating device" |
| 123 | + ) |
| 124 | + except aiomcache.exceptions.ClientException as e: |
| 125 | + raise HTTPException( |
| 126 | + status_code=500, |
| 127 | + detail="Memcached Database error occurred while creating device", |
| 128 | + ) |
| 129 | + except Exception as e: |
| 130 | + raise HTTPException( |
| 131 | + status_code=500, detail="An unexpected error occurred while creating device" |
92 | 132 | )
|
93 |
| - .returning(Device) |
94 |
| - ) |
95 |
| - |
96 |
| - # Measure the same insert operation as in Go |
97 |
| - start_time = time.perf_counter() |
98 |
| - device_result = await session.execute(stmt) |
99 |
| - device_dict = device_result.mappings().one() |
100 |
| - await session.commit() |
101 |
| - H.labels(op="insert", db="postgres").observe(time.perf_counter() - start_time) |
102 |
| - |
103 |
| - # Measure the same set operation as in Go |
104 |
| - start_time = time.perf_counter() |
105 |
| - cache_client.set(str(device_uuid), dict(device_dict), expire=20) |
106 |
| - H.labels(op="set", db="memcache").observe(time.perf_counter() - start_time) |
107 |
| - |
108 |
| - return device_dict |
|
0 commit comments