Fix Slow API Endpoints in a FastAPI App with Navie
Posted 09 Apr 2024
- python
In this scenario, the user will generate AppMap Data from their FastAPI application. Then they will use AppMap Navie to learn how to leverage Redis batching and improve the performance of the API endpoints.
👤 USER
Rewrite list_items in main.py to support redis batching.
NAVIE
To modify the list_item function in main.py to support Redis batching, you can utilize the Redis pipeline feature. Pipelining allows you to execute multiple commands in a single step, which reduces the round trip time between the client and server, effectively batching your requests for efficiency.
Here's an example of how to rewrite the list_item function to support Redis batching using a pipeline:
Here's an example of how to rewrite the list_item function to support Redis batching using a pipeline:
Current list_item
Function
# main.py:65
def list_item(item_id: int) -> dict[str, dict[str, str]]:
if not redis_client.hexists(f"item_id:{item_id}", "item_id"):
raise HTTPException(status_code=404, detail="Item not found.")
else:
return {"item": redis_client.hgetall(f"item_id:{item_id}")}
@app.get("/items/{item_id}")
Modified list_item
Function with Redis Batching
# main.py:65
def list_item(item_id: int) -> dict[str, dict[str, str]]:
# Start a Redis pipeline
pipeline = redis_client.pipeline()
# Queue up the commands to check existence and fetch the item
pipeline.hexists(f"item_id:{item_id}", "item_id")
pipeline.hgetall(f"item_id:{item_id}")
# Execute all commands in the pipeline in one go
exists, item = pipeline.execute()
# Check if the item exists before trying to return it
if not exists:
raise HTTPException(status_code=404, detail="Item not found.")
else:
return {"item": item}
@app.get("/items/{item_id}")
Explanation:
- Redis Pipeline Creation:
A Redis pipeline is created using the pipeline method of the Redis client. This object will batch together commands that are meant to be executed. - Queueing Commands:
Both the hexists (to check item existence) and hgetall (to fetch the item) commands are queued up to run in the batch. This is done by calling the respective methods on the pipeline object instead of directly on the Redis client. - Executing the Pipeline:
The pipeline.execute() command runs all queued commands in a single request to the Redis server. The results of these commands are returned in a list, preserving the order in which the commands were queued. - Handling Results:
The first item in the returned list corresponds to the result of the hexists command, and the second item corresponds to the result of the hgetall command. You check the existence of the item first, and if it exists, return its details. If it doesn't, an appropriate exception is raised.
This modification leverages Redis's ability to execute multiple commands efficiently, reducing latency that is typically involved in back-and-forth communication for individual commands.