کش کردن پاسخ ها در GraphQl

  • مدرس : علی بیگدلی
  • تاریخ انتشار: 1404/06/24
  • تعداد بازدید: 2

کش کردن پاسخ‌ها در GraphQL

در GraphQL، کش کردن (Caching) کمی پیچیده‌تر از REST است، زیرا در REST هر endpoint ثابت است و می‌توان پاسخ آن را به راحتی روی CDN یا حافظه مرورگر نگهداری کرد. اما در GraphQL، تمام درخواست‌ها از یک endpoint عبور می‌کنند و Queryها می‌توانند ساختارهای متفاوتی داشته باشند، بنابراین نیاز به استراتژی‌های متفاوت داریم.

روش‌های کش کردن در GraphQL

  • 1. کش در سمت کلاینت
    کتابخانه‌هایی مانند Apollo Client یا Relay به صورت داخلی قابلیت کش کردن پاسخ‌ها را دارند. زمانی که یک Query مشابه دوباره ارسال شود، پاسخ از کش داخلی گرفته می‌شود و نیاز به درخواست مجدد به سرور نیست.
  • 2. کش در سمت سرور
    می‌توان با استفاده از ابزارهایی مانند FastAPI-Cache یا Redis، پاسخ‌های Queryها را بر اساس محتوا یا شناسه کاربر ذخیره کرد. این روش برای داده‌هایی که تغییرات کمی دارند مناسب است و باعث کاهش بار دیتابیس می‌شود.
  • 3. کش در سطح Field
    در بعضی کتابخانه‌ها مثل Strawberry، می‌توان کش را روی Resolverهای خاص فعال کرد. به این ترتیب فقط داده‌های پرهزینه یا پرکاربرد کش می‌شوند و بقیه Queryها به شکل عادی اجرا می‌شوند.

۱. نصب کتابخانه

pip install fastapi-cache2[redis] aioredis

۲. راه‌اندازی کش با Lifespan

# main.py
from fastapi import FastAPI
from contextlib import asynccontextmanager
from fastapi_cache import FastAPICache
from fastapi_cache.backends.redis import RedisBackend
import aioredis

@asynccontextmanager
async def lifespan(app: FastAPI):
    redis = aioredis.from_url("redis://localhost:6379", encoding="utf8", decode_responses=True)
    FastAPICache.init(RedisBackend(redis), prefix="fastapi-cache")
    yield
    await redis.close()

app = FastAPI(lifespan=lifespan)

۳. استفاده از کش در Resolverهای GraphQL

# graphql/tasks.py
import strawberry
from fastapi_cache.decorator import cache
from graphql.types import TaskType
from models.tasks import Task as TaskModel

@strawberry.type
class TaskQuery:

    @strawberry.field
    @cache(expire=60)  # کش به مدت 60 ثانیه
    def my_tasks(self, info) -> list[TaskType]:
        db = info.context["db"]
        current_user = info.context["current_user"]

        tasks = db.query(TaskModel).filter(TaskModel.user_id == current_user.id).all()
        return [
            TaskType(
                id=task.id,
                title=task.title,
                completed=task.completed,
                user_id=task.user_id,
                created_at=str(task.created_at),
                updated_at=str(task.updated_at)
            ) for task in tasks
        ]

نکات مهم

  • با Lifespan اتصال Redis به صورت خودکار مدیریت می‌شود.
  • دکوراتور @cache(expire=...) پاسخ Resolver را برای مدت مشخص کش می‌کند.
  • برای Queryهای حساس یا داده‌های شخصی، می‌توان از key_builder برای تفکیک کش بر اساس کاربر استفاده کرد.
  • استفاده از Lifespan باعث پاکیزگی و مدیریت بهتر منابع هنگام شروع و پایان اپلیکیشن می‌شود.

ثبت دیدگاه


نکته: آدرس ایمیل شما منتشر نخواهد شد

دیدگاه کاربران (0)


هیچ دیدگاهی ثبت نشده است. می‌توانید اولین نفر باشید.