تیپ #۴۳

مهلت‌ها، تلاش دوباره و فراخوانی تکرارپذیر ابزار

هر فراخوانی ابزار در ایجنت باید یک مهلت مشخص داشته باشد، وگرنه یک درخواست معلق کل حلقه‌ی استدلال را قفل می‌کند. اما تلاش دوباره‌ی کورکورانه می‌تواند از تلاش نکردن خطرناک‌تر باشد: اگر ابزار کارش را انجام داده باشد و فقط پاسخ گم شده باشد، درخواست دوم همان عملیات را دوباره اجرا می‌کند. راه‌حل این است که هر ابزار را با یک کلید یکتای سمت کلاینت تکرارپذیر کنید تا سرور درخواست تکراری را تشخیص بدهد و همان نتیجه‌ی قبلی را برگرداند 🔁، و بعد فقط روی timeout و خطاهای 429 و 5xx با backoff نمایی و jitter دوباره تلاش کنید.

توضیح کامل‌تر

در ساخت ایجنت، هر فراخوانی ابزار یک مرز شبکه‌ای است و شبکه همیشه کند، قطع یا نامطمئن است. اگر برای فراخوانی ابزار مهلت تعیین نکنید، یک اتصال بی‌پاسخ می‌تواند حلقه‌ی ایجنت را دقیقه‌ها بلوکه کند و در همین حین توکن هم بسوزاند. از طرف دیگر، تلاش دوباره‌ی بدون احتیاط می‌تواند یک عملیات را دو بار اجرا کند؛ مثلاً ارسال دوباره‌ی ایمیل یا کسر دوباره‌ی وجه. مفهوم تکرارپذیری (idempotency) دقیقاً همین را می‌گوید: اجرای چندباره‌ی یک عملیات باید همان اثر اجرای یک‌باره را داشته باشد. در HTTP این کار معمولاً با هدر Idempotency-Key انجام می‌شود؛ کلاینت یک شناسه‌ی یکتا می‌سازد، سرور نتیجه‌ی آن کلید را ذخیره می‌کند و در درخواست تکراری همان پاسخ اول را برمی‌گرداند. در سمت ایجنت هم بهتر است فقط خطاهای گذرا مثل timeout، 429 و 5xx را دوباره تلاش کنید، آن هم با backoff نمایی و jitter تا موجی از تلاش‌های دوباره سرویس را زمین نزند، و برای عملیات غیرتکرارپذیر اصلاً retry نکنید. یک مثال ساده: ابزار «ثبت سفارش» را با کلید idempotency بسازید تا اگر پاسخش در شبکه گم شد، تلاش دوباره به سفارش دوم منجر نشود.

نکته پیشرفته
← بازگشت به همهٔ نکته‌های روز