Eloquent'te N+1'i erken yakalamak için Model::preventLazyLoading'i yalnızca lokalde mi yoksa production'da da mı açmalıyım?
Soru
Laravel 11 ile bir API geliştiriyorum ve N+1 sorgularını release'e çıkmadan yakalamak istiyorum. `Model::preventLazyLoading()` bunun için doğru araç gibi duruyor ama tam olarak nerede açacağıma karar veremedim. Endişem şu: bu ayarı production'da açarsam, test'lerimin kaçırdığı bir kod yolunda gerçek bir kullanıcıya fatal hata (500) dönmesinden korkuyorum. Sadece lokalde mi açmalıyım, yoksa production'da da güvenle çalıştırmanın bir yolu var mı?
Cevap
Kısa cevap: Lokal ve CI’da tam katı (throw) çalıştırın; production’da açık tutun ama fatal fırlatmak yerine log’layan bir handler’a bağlayın. Endişeniz haklı — ham hâliyle production’a soğuk açmak, latent bir bug’ı anında outage’a çevirir.
Buradaki tuzak, bunu ikili bir “lokal mı, production mı” anahtarı gibi düşünmektir. İşe yarayan sürüm, aynı ayarın ortama göre farklı davranmasıdır — bir geliştiricinin düzeltebileceği yerde gürültülü, gerçek bir kullanıcının 500 yiyeceği yerde sessiz.
- Ayarın ne yaptığını netleştirin.
Model::preventLazyLoading()herhangi bir lazy load denemesindeLazyLoadingViolationExceptionfırlatır. Geliştirmede harikadır; ama test’lerinizin görmediği bir yolda gerçek bir kullanıcıya 500 döndürürse felakettir. - Ortama göre koşullayın.
AppServiceProvider::boot()içindeModel::preventLazyLoading(! $this->app->isProduction())deyin. Böylece production dışında her yerde katı, production’da ise throw kapalı olur. - Production’da throw yerine handler ile log’layın.
Model::handleLazyLoadingViolationUsing(...)ile ihlali Sentry/log’a model + ilişki adıyla raporlayın ama isteği çökertmeyin. N+1’i production telemetrisinde görmeye devam eder, kullanıcıyı cezalandırmazsınız. - Bu üç katı ayardan biridir.
preventSilentlyDiscardingAttributesvepreventAccessingMissingAttributesile birlikteModel::shouldBeStrict()altında paketlenir.shouldBeStrict()üçünü birden açar; hepsini bilinçli açın, körlemesine değil. Diğer ikisi production’da daha düşük risklidir; ama gerçek bir kullanıcı isteğinde fırlatabilen tek ayarpreventLazyLoading’dir, ayrı handler muamelesini o hak eder. - Yalnızca lazy load’ları yakalar, her N+1’i değil. Döngü içinde çalışan, ilişki lazy-load’u olmayan bir sorgu bu mekanizmaya takılmaz. Bu yüzden test’lerinizde Telescope/Clockwork veya sorgu sayısı assertion’ları hâlâ gerekir.
- Kademeli açın. Production’da doğrudan throw’a geçmeden önce birkaç hafta log-only modda tutun; telemetri temizlendikten sonra istersen throw’a terfi ettirin.
// app/Providers/AppServiceProvider.php
public function boot(): void
{
Model::preventLazyLoading(! $this->app->isProduction());
Model::handleLazyLoadingViolationUsing(function ($model, $relation) {
report(new \RuntimeException(
"Lazy loading tespit edildi: ".$model::class."::".$relation
));
// fırlatma yok — istek normal akışına devam eder
});
}
Sonuç: Ben olsam lokal + CI’da tam katı, production’da ise ilk haftalarda log-only handler ile açardım. Telemetri temizlendikten sonra bile production’ı log-only bırakmak çoğu ekip için yeterli; oradaki N+1’leri görüyorsunuz ama kimseyi 500 ile vurmuyorsunuz. Asıl kural: production’a katı fırlatmayı asla soğuk açmayın — önce ölçün, sonra sıkın.
İlgili Yazılar
Yorumlar
Yorum yapmak için GitHub hesabınızla giriş yapmanız yeterli. Yorumlar GitHub Discussions üzerinde saklanır.