Skip to main content

Command Palette

Search for a command to run...

Code Interview 1 - Redis Cache

Published
•2 min read•View as Markdown
J

Python Django Developer | Django Rest Framework, AWS | Melbourne-based | Available for Immediate Start

import asyncio import aioredis import pickle

# Async cache decorator using Redis
redis = aioredis.from_url("redis://localhost")
def cache(ttl=60): 
    def deco(func): 
        async def wrapper(*args, **kwargs): key = func.name + ":" + str(args) data = redis.get(key) 
            if data: 
                return pickle.loads(data) 
            result = await func(*args, **kwargs) 
            redis.set(key, pickle.dumps(result), ex=ttl) 
            return result 
        return wrapper 
    return deco

@cache(ttl=120) 
async def get_user_profile(user_id):
    # Simulate a DB call
    await asyncio.sleep(1) 
    return {"id": user_id, "name": "User" + user_id)

My Answer was…

  • I think you are trying to do caching, using Redis. Without directly accessing database, you are trying to get the user profile data.

  • It’s awaited.

  • I think you need to use try-except grammar so that you can do stable exception handling. More than that, I haven’t actually coded by myself so I don’t know deeply.

Gemini’s Feedback

The Critical Error: Missing await

Looking at the code, there is a critical issue with the asynchronous flow. The redis.get(key) call is missing the await keyword. Since it’s an I/O-bound task, without await, the variable data will hold a coroutine object instead of the actual data. This will cause the application to crash when it reaches the pickle.loads() function.

Coroutines:

https://gomdoricake.hashnode.dev/coroutines

Pickle Security Risk

First, using pickle for serialization can be a security risk. It’s vulnerable to Remote Code Execution (RCE) attacks if the data is tampered with. I would recommend using JSON instead, which is much safer and more standard.

Resource Management

Second, the connection management is missing. In a production environment, we should ensure the Redis connection is properly closed or managed using a connection pool to prevent resource leaks.

Cache Key Design

Third, the cache key design could be improved. Right now, it’s just the function name and arguments, which might cause key collisions. I would add a unique namespace to ensure the keys are distinct across different functions.

Cache Stampede

Finally, this code might suffer from a ‘Cache Stampede’ if thousands of requests hit an empty cache simultaneously. To prevent overwhelming the database, I would implement a locking mechanism or a ‘single-flight’ strategy.

My Work Process

“When I review code, I follow a 3-step checklist:

  1. Purpose: What is the business goal? (e.g., Caching to reduce DB load)

  2. I/O Identification: Which parts are talking to the network or database?

  3. Async Integrity: Are all I/O operations properly awaited? Following this process helps me catch critical bugs early on.

Code Review

Part 1 of 1

Critically reviewing my code and engineering decisions to move beyond 'just working' towards production-ready excellence.