جلوی بهمن‌های N+1 را بگیرید: استفاده از Laravel Strict Mode

مشکل کوئری N+1 عملکرد پایگاه داده را از بین می‌برد. این اتفاق زمانی رخ می‌دهد که لیستی از رکوردها را واکشی می‌کنید و برای دسترسی به یک رابطه (relationship)، روی آن‌ها حلقه می‌زنید، در حالی که فراموش کرده‌اید آن رابطه را از قبل بارگذاری کنید.

فرض کنید ۵۰ فاکتور را در یک داشبورد نمایش می‌دهید. برای نمایش نام مشتری، روی آن‌ها حلقه می‌زنید، اما فراموش کرده‌اید از متد with استفاده کنید. Eloquent یک کوئری برای فاکتورها اجرا می‌کند و سپس ۵۰ کوئری جداگانه برای هر مشتری اجرا می‌کند.

در محیط توسعه محلی (local development)، اجرای ۵۱ کوئری تنها ۱۰ میلی‌ثانیه زمان می‌برد و متوجه آن نخواهید شد. اما در محیط عملیاتی (production)، ترافیک سنگین این موضوع را به یک بهمن تبدیل می‌کند؛ این کار استخر اتصالات (connection pool) پایگاه داده شما را تخلیه کرده و باعث از کار افتادن سرور می‌شود.

شما نمی‌توانید تنها به بازبینی کد (code review) تکیه کنید. شما به یک حفاظ معماری نیاز دارید.

Laravel برای حل این مشکل، Strict Mode را ارائه می‌دهد. شما می‌توانید از preventLazyLoading در سطح اپلیکیشن استفاده کنید. Laravel روابط پایگاه داده شما را نظارت می‌کند و اگر در حین توسعه محلی یا تست، یک lazy load شناسایی کند، یک exception پرتاب می‌کند. این کار شما را مجبور می‌کند که بلافاصله کد را اصلاح کنید.

نحوه راه‌اندازی:

مکانیزم ایمنی را در AppServiceProvider خود پیکربندی کنید. این کار را برای محیط‌های local و testing انجام دهید. در محیط production، باید به جای از کار افتادن اپلیکیشن، خطا را لاگ (log) کنید.

از این سه تنظیم در متد boot خود استفاده کنید:

  • Model::preventLazyLoading: جلوی کوئری‌های N+1 را می‌گیرد.
  • Model::preventSilentlyDiscardingAttributes: جلوی شکست در mass assignment را می‌گیرد.
  • Model::preventAccessingMissingAttributes: جلوی نشت حافظه (memory leak) ناشی از روابط مفقود شده را می‌گیرد.

برای محیط production، از handleLazyLoadingViolationUsing استفاده کنید. این کار به شما اجازه می‌دهد تخلفات را در Slack یا یک سرویس لاگ ارسال کنید. با این روش، بدون مختل کردن تجربه کاربری، از وضعیت سیستم مطلع می‌شوید.

اعمال Strict Mode، بهینه‌سازی را به ابتدای فرآیند (pipeline) شما منتقل می‌کند. کوئری‌های N+1 نمی‌توانند از تست‌های شما عبور کنند. در نتیجه، کد شما بهینه باقی می‌ماند و پایگاه داده شما سریع عمل می‌کند.

منبع: https://dev.to/iprajapatiparesh/stop-n1-avalanches-enforce-laravel-strict-mode-2oop