Laravel İle Dinamik Bir Görev Zamanlayıcı Sistemi Nasıl Yapılır?

Laravel İle Dinamik Bir Görev Zamanlayıcı Sistemi Nasıl Yapılır?
Laravel İle Dinamik Bir Görev Zamanlayıcı Sistemi Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Bu projeyi hayata geçirmek için sisteminizde PHP 8.2+ ve Laravel 11.x sürümünün yüklü olması gerekmektedir. Ayrıca veritabanı işlemlerini yönetmek için MySQL veya PostgreSQL kullanmanız önerilir. Laravel'in zamanlayıcı yapısı, sunucuda tek bir cron job (zamanlanmış görev) tanımlanmasını gerektirir.

  • PHP 8.2 veya üzeri sürüm.
  • Composer paket yöneticisi.
  • Laravel 11 framework kurulumu.
  • Veritabanı bağlantısının yapılandırılmış olması.

Başlamadan önce projenizin .env dosyasında veritabanı bilgilerinizin doğru olduğundan emin olun. Ayrıca, sistemin zamanlayıcıyı tetikleyebilmesi için sunucunuzda * * * * * cd /proje-yolu && php artisan schedule:run >> /dev/null 2>&1 komutunun cron tab üzerinde tanımlı olması şarttır.

Adım 1: Görevleri Saklamak İçin Veritabanı Yapısı

Dinamik bir sistemde görevlerin zamanını, komutunu ve durumunu saklayacak bir tabloya ihtiyacımız vardır. Laravel'in migration (göç) sistemini kullanarak scheduled_tasks tablosunu oluşturalım.

php artisan make:migration create_scheduled_tasks_table

Oluşturulan migration dosyasını aşağıdaki gibi düzenleyerek görevlerin detaylarını tutacak sütunları tanımlayın:

public function up(): void
{
    Schema::create('scheduled_tasks', function (Blueprint $table) {
        $table->id();
        $table->string('name'); // Görev adı
        $table->string('command'); // Çalıştırılacak komut veya sınıf
        $table->string('expression'); // Cron ifadesi (örn: * * * * *)
        $table->boolean('is_active')->default(true); // Görev durumu
        $table->timestamps();
    });
}

Bu yapı, her bir görevin ne zaman ve hangi komutla çalışacağını veritabanından çekmemize olanak tanır. expression alanı, standart cron formatını (dakika, saat, gün, ay, hafta günü) destekleyecektir.

Adım 2: Dinamik Zamanlayıcıyı Laravel'e Tanımlama

Laravel 11 ile birlikte zamanlayıcı tanımlamaları routes/console.php dosyası üzerinden yapılmaktadır. Dinamik yapıyı kurmak için veritabanındaki aktif görevleri döngüye alıp zamanlayıcıya eklememiz gerekir.

use App\Models\ScheduledTask;
use Illuminate\Support\Facades\Schedule;

// routes/console.php dosyasına ekleyin
ScheduledTask::where('is_active', true)->each(function ($task) {
    Schedule::command($task->command)
        ->cron($task->expression)
        ->name($task->name);
});

Burada yapılan işlem, uygulama her çalıştığında veritabanındaki aktif görevleri okuyup Laravel'in Schedule nesnesine dinamik olarak enjekte etmektir. Bu sayede kod değişikliği yapmadan yeni görevler ekleyebilirsiniz.

Adım 3: Görevleri Yönetmek İçin Model ve Kontrolcü

Görevlerin yönetimi için bir ScheduledTask modeli ve bu görevleri oluşturup düzenleyeceğimiz bir TaskController oluşturmalıyız. Güvenlik açısından, kullanıcı girişlerini mutlaka doğrulamanız (validation) gerekir.

namespace App\Http\Controllers;

use App\Models\ScheduledTask;
use Illuminate\Http\Request;

class TaskController extends Controller {
    public function store(Request $request) {
        $validated = $request->validate([
            'name' => 'required|string|max:255',
            'command' => 'required|string',
            'expression' => 'required|string', // Basit bir cron regex eklenebilir
        ]);

        return ScheduledTask::create($validated);
    }
}

Bu kontrolcü, kullanıcıdan gelen verileri alır ve veritabanına kaydeder. expression alanı için ileride bir doğrulama kuralı (rule) yazarak kullanıcının geçersiz cron ifadeleri girmesini engelleyebilirsiniz.

Adım 4: Güvenlik ve Hata Yönetimi

Kritik Uyarı: Dinamik olarak komut çalıştırmak, sisteminize sızılması durumunda uzaktan kod çalıştırma (RCE) zafiyetine yol açabilir. Asla kullanıcıdan gelen ham veriyi doğrudan exec() veya system() gibi fonksiyonlara göndermeyin. Sadece izin verdiğiniz (whitelist) komutların çalıştırıldığından emin olun.

Görevlerin hata alması durumunda haberdar olmak için Laravel'in onFailure metodunu kullanabilirsiniz. Bu, sistemin izlenebilirliğini artırır.

Schedule::command($task->command)
    ->cron($task->expression)
    ->onFailure(function () use ($task) {
        // Hata durumunda loglama veya bildirim gönderme
        Log::error("Görev başarısız oldu: " . $task->name);
    });

Yöntem Karşılaştırması

Yöntem Esneklik Güvenlik Bakım Kolaylığı
Statik (Kernel/Console) Düşük Yüksek Zor
Dinamik (Veritabanı) Çok Yüksek Dikkat Gerektirir Kolay

Sıkça Sorulan Sorular

Dinamik görevler ne kadar güvenli?

Dinamik görevler, sadece izin verdiğiniz (whitelist) komut sınıflarını çalıştırdığınız sürece güvenlidir. Kullanıcıdan gelen string değerleri doğrudan çalıştırmaktan kaçının.

Cron ifadesini nasıl doğrularım?

dragon-code/cron-expression gibi popüler paketleri kullanarak kullanıcının girdiği cron ifadesinin geçerli olup olmadığını kontrol edebilirsiniz.

Sistem performansı etkilenir mi?

Her istekte veritabanına sorgu atmak yerine, bu görevleri bir cache (önbellek) mekanizmasında tutarak performansı optimize edebilirsiniz.

Geçmiş görevleri nasıl takip ederim?

Her görev çalıştırıldığında bir task_logs tablosuna kayıt atarak çalıştırılma zamanını ve sonucunu kaydedebilirsiniz.

Laravel 11'de zamanlayıcı nerede tanımlanır?

Laravel 11 ile birlikte zamanlayıcı tanımlamaları doğrudan routes/console.php dosyası içerisinde yapılmaktadır.

İleri Seviye İpuçları: Zamanlanmış Görevlerde Performans Optimizasyonu

Dinamik görev zamanlayıcı sistemleri, veritabanı sorgularının sıklığı nedeniyle ölçeklenebilirlik sorunları yaratabilir. Her dakika tüm görevleri veritabanından çekmek yerine, sisteminizi optimize etmek için şu stratejileri izleyebilirsiniz:

  • Caching (Önbellekleme): Aktif görevleri her döngüde veritabanından çekmek yerine, Cache mekanizmasını kullanarak verileri bellekte tutun. Görev güncellendiğinde önbelleği temizlemeyi unutmayın.
  • Queue (Kuyruk) Kullanımı: Zamanlayıcıyı sadece tetikleyici olarak kullanın. Görev tetiklendiğinde ağır işleri doğrudan çalıştırmak yerine, işi bir kuyruğa (Redis veya SQS) göndererek ana zamanlayıcı döngüsünü serbest bırakın.
// routes/console.php içerisinde kuyruk kullanımı
use App\Models\ScheduledTask;
use Illuminate\Support\Facades\Schedule;

Schedule::call(function () {
    $tasks = ScheduledTask::where('is_active', true)->get();
    foreach ($tasks as $task) {
        // Görevi doğrudan çalıştırmak yerine kuyruğa atıyoruz
        dispatch(new \App\Jobs\ExecuteDynamicTask($task));
    }
})->everyMinute();

Hata Ayıklama ve İzleme (Monitoring)

Dinamik görevlerin neden çalışmadığını veya neden başarısız olduğunu anlamak için merkezi bir loglama mekanizması şarttır. Laravel'in onFailure ve onSuccess metodlarını kullanarak her görevin çıktısını veritabanına kaydedebilirsiniz.

Görev Başarısızlıklarını Yakalama

Her görevin hata çıktısını yakalamak için modelinizde bir last_error sütunu bulundurmak, sistemin sağlığını izlemenize yardımcı olur:

// routes/console.php içerisinde hata yönetimi
Schedule::call(function () {
    try {
        // Görev mantığı
    } catch (\Exception $e) {
        $task->update([
            'last_error' => $e->getMessage(),
            'status' => 'failed'
        ]);
    }
})->everyMinute()->onFailure(function () {
    // Bildirim gönder (Slack, Mail, Telegram)
});

Alternatif: Spatie Laravel-Schedule-Monitor

Kendi sisteminizi yazmak yerine, Laravel topluluğunun standart kabul ettiği spatie/laravel-schedule-monitor paketini kullanabilirsiniz. Bu paket, görevlerin zamanında çalışıp çalışmadığını izlemek ve başarısızlık durumunda uyarı almak için profesyonel bir çözüm sunar.

Özellik Özel Sistem Spatie Paket
Geliştirme Süresi Uzun Kısa
Esneklik Yüksek Orta
Bakım Maliyeti Yüksek Düşük

Eğer uygulamanızda çok sayıda ve karmaşık zamanlanmış görev varsa, hazır paketler üzerinden ilerlemek uzun vadede teknik borç yükünüzü azaltacaktır.

Sonuç

Laravel ile dinamik bir görev zamanlayıcı sistemi kurmak, uygulamanıza büyük bir esneklik kazandırır. Bu rehberde, veritabanı tabanlı bir mimari kurarak görevlerin nasıl yönetileceğini, güvenlik önlemlerini ve hata yönetimini inceledik. Bir sonraki adım olarak, bu görevlerin çalıştırılma loglarını tutan bir raporlama arayüzü geliştirebilir ve görevlerin durumunu gerçek zamanlı olarak izleyebilirsiniz.

Sorumluluk Reddi: Bu makalede paylaşılan kod örnekleri eğitim amaçlıdır. Üretim ortamında (production) kullanmadan önce mutlaka detaylı güvenlik testlerinden geçirin ve sunucu izinlerini (permission) yapılandırın.
Bu yazıya tepkinizi paylaşın:
Emre Güneş

Teknik çözümler ve ev gereçleri kullanımı konusunda deneyimli bir editörüm. Kullanıcı hatalarını minimize eden, yalın ve çözüm odaklı rehberler hazırlıyorum.

Yorumlar (0)

Yorum Yaz