# Scheduler: Otomatik Görev Yönetimi

TYPO3 Scheduler ile zamanlanmış görevlerin yönetimi — kurulum, DDEV cron yapılandırması, özel görev oluşturma ve izleme.

---

## Scheduler Nedir? (Basit Anlatım)

**Scheduler** = TYPO3'ün dahili **cron yöneticisi**

Linux/Mac cron job mantığıyla çalışır ama admin panelinden kontrol edilir:

```
Cron job (sunucu)
   ↓  her N dakikada tetikler
vendor/bin/typo3 scheduler:run
   ↓  sıradaki zamanlanmış görevi çalıştırır
TYPO3 Scheduler Görevleri
   ↓
✓ Cache temizleme  ✓ Sitemap güncelleme  ✓ Özel görevler
```

**Ne işe yarar?**
- Her gün gece cache temizliği
- Her saat sitemap yenileme
- Haftada bir eski log kayıtlarını silme
- Periyodik içerik yayını

---

## Kurulum

### Extension Yükle (Bu Projede Yapıldı ✓)

```bash
ddev composer require typo3/cms-scheduler
ddev exec vendor/bin/typo3 extension:setup
ddev exec vendor/bin/typo3 cache:flush
```

**Kurulum sonrası:** Admin panelde **System → Scheduler** modülü görünür.

---

## DDEV Cron Yapılandırması (Bu Projede Yapıldı ✓)

DDEV v1.22+ native cron desteği sunar. `.ddev/config.scheduler.yaml` dosyası oluşturulur:

```yaml
# .ddev/config.scheduler.yaml
crons:
  typo3-scheduler:
    schedule: "*/15 * * * *"
    exec: "cd /var/www/html && vendor/bin/typo3 scheduler:run"
```

Değişikliği uygula:

```bash
ddev restart
```

**Doğrulama:**

```bash
# Manuel çalıştırma testi
ddev exec vendor/bin/typo3 scheduler:run
# Çıktı: boş veya görev yok = başarılı ✓

# DDEV crontab kontrol
ddev exec crontab -l
```

### Sunucu (Production) Cron

```bash
crontab -e
```

```cron
# TYPO3 Scheduler — Her 15 dakika
*/15 * * * * cd /var/www/html && vendor/bin/typo3 scheduler:run >> /dev/null 2>&1

# TYPO3 Scheduler — Her dakika (yüksek hassasiyet)
* * * * * cd /var/www/html && vendor/bin/typo3 scheduler:run >> /dev/null 2>&1
```

---

## Backend'de Görev Oluşturma

### Adım Adım

1. **System → Scheduler** modülüne git
2. **+** (Yeni görev) butonuna tıkla
3. Görev türünü seç
4. Ayarları yapılandır:

| Alan | Açıklama | Örnek |
|------|----------|-------|
| **Disable** | Görevi devre dışı bırak | ☐ (aktif bırak) |
| **Task** | Görev sınıfı | Site Temizlik Görevi |
| **Type** | Tek / Tekrarlayan | Recurring |
| **Frequency** | Cron formatı veya saniye | `0 2 * * *` |
| **Multiple** | Paralel çalışmaya izin ver | ☐ (hayır) |
| **Description** | Açıklama | Gece cache temizliği |

### Cron Format Referansı

```
┌─────────── dakika (0-59)
│ ┌───────── saat (0-23)
│ │ ┌─────── gün (1-31)
│ │ │ ┌───── ay (1-12)
│ │ │ │ ┌─── haftanın günü (0=Pazar, 1=Pazartesi, ...)
│ │ │ │ │
* * * * *

*/15 * * * *    → Her 15 dakika
0 * * * *       → Her saat başı
0 2 * * *       → Her gün saat 02:00
0 0 * * 1       → Her Pazartesi gece yarısı
0 3 1 * *       → Her ayın 1'i saat 03:00
30 1 * * 1-5    → Hafta içi her gün 01:30
```

---

## Yerleşik Görevler

| Görev | Kullanım | Önerilen Saat |
|-------|----------|---------------|
| **Caching framework garbage collection** | Süresi dolmuş cache'leri siler | `0 3 * * *` |
| **File abstraction layer: Extract metadata** | Dosya meta verilerini günceller | `0 4 * * *` |
| **Table garbage collection** | Eski kayıtları temizler | `0 5 * * *` |
| **Recycler: Cleanup deleted records** | Soft-deleted kayıtları kalıcı siler | `0 2 * * 0` |
| **Redirects: Cleanup** | Süresi geçmiş yönlendirmeleri temizler | `0 4 * * *` |
| **Sitemap: Generate XML** | XML sitemap yeniler | `0 1 * * *` |

---

## Özel Görev: CleanupTask (Bu Projede Hazır ✓)

`packages/testproject/Classes/Task/CleanupTask.php` oluşturuldu.

**Özellikleri:**
- `sys_log` tablosundan 30 günden eski kayıtları siler
- `tt_content`, `pages`, `sys_file_reference` tablolarındaki `deleted=1` kayıtları kaldırır
- Backend'de `logRetentionDays` alanı ile yapılandırılabilir

**Backend'e Ekle:**
1. System → Scheduler → **+**
2. Task: **Site Temizlik Görevi**
3. Frequency: `0 2 * * *`
4. Kaydet

---

## Kendi Görevini Oluşturma

### Adım 1: PHP Sınıfı

`packages/testproject/Classes/Task/MyCustomTask.php`:

```php
<?php

declare(strict_types=1);

namespace Gfdhfhgfgg\Testproject\Task;

use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Scheduler\Task\AbstractTask;

class MyCustomTask extends AbstractTask
{
    /** Backend'den yapılandırılabilir alan */
    public int $daysToKeep = 30;

    /**
     * true = başarılı, false = başarısız
     */
    public function execute(): bool
    {
        try {
            $this->doMyWork();
            return true;
        } catch (\Throwable $e) {
            $this->logger->error('MyCustomTask failed: ' . $e->getMessage());
            return false;
        }
    }

    protected function doMyWork(): void
    {
        $cutoff = time() - ($this->daysToKeep * 86400);
        $conn = GeneralUtility::makeInstance(ConnectionPool::class)
            ->getConnectionForTable('sys_log');
        $conn->delete('sys_log', ['tstamp < ' . $cutoff], [\PDO::PARAM_INT]);
    }

    /** Scheduler listesinde gösterilir */
    public function getAdditionalInformation(): string
    {
        return sprintf('%d günden eski kayıtlar silinir', $this->daysToKeep);
    }
}
```

### Adım 2: Services.yaml

```yaml
Gfdhfhgfgg\Testproject\Task\MyCustomTask:
  public: true
  tags:
    - name: 'scheduler.task'
      title: 'Özel Görev Adı'
      description: 'Ne yaptığını açıkla'
```

### Adım 3: Cache Temizle

```bash
ddev exec vendor/bin/typo3 cache:flush
```

---

## Console Command ile Scheduler (v13 Modern Yöntem)

`AbstractTask` yerine daha temiz bir Symfony Command alternatifi:

`packages/testproject/Classes/Command/CleanupCommand.php`:

```php
<?php

declare(strict_types=1);

namespace Gfdhfhgfgg\Testproject\Command;

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use TYPO3\CMS\Core\Database\ConnectionPool;

#[AsCommand(
    name: 'testproject:cleanup',
    description: 'Eski log kayıtlarını temizler'
)]
class CleanupCommand extends Command
{
    public function __construct(
        private readonly ConnectionPool $connectionPool
    ) {
        parent::__construct();
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $cutoff = time() - (30 * 86400);
        $conn = $this->connectionPool->getConnectionForTable('sys_log');
        $deleted = $conn->delete('sys_log', ['tstamp < ' . $cutoff], [\PDO::PARAM_INT]);

        $output->writeln(sprintf('<info>%d</info> sys_log kaydı silindi.', $deleted));

        return Command::SUCCESS;
    }
}
```

`Services.yaml`:

```yaml
Gfdhfhgfgg\Testproject\Command\CleanupCommand:
  tags:
    - name: 'console.command'
      command: 'testproject:cleanup'
      schedulable: true   # ← Scheduler'dan da çalıştırılabilir
```

CLI testi:

```bash
ddev exec vendor/bin/typo3 testproject:cleanup
```

---

## CLI Kullanımı

```bash
# Tüm görevleri çalıştır
ddev exec vendor/bin/typo3 scheduler:run

# Belirli görevi çalıştır (backend'deki UID ile)
ddev exec vendor/bin/typo3 scheduler:run --task=1

# Zamanlama gözetmeksizin zorla çalıştır
ddev exec vendor/bin/typo3 scheduler:run --force

# Verbose çıktı
ddev exec vendor/bin/typo3 scheduler:run -v

# Kayıtlı görevleri listele
ddev exec vendor/bin/typo3 list scheduler
```

---

## İzleme ve Hata Ayıklama

### Görev Durumları

Backend **System → Scheduler** listesinde:

| İkon | Anlam |
|------|-------|
| ✅ Yeşil | Son çalışma başarılı |
| ❌ Kırmızı | Son çalışma başarısız (`false` döndü) |
| ⏳ Sarı | Şu anda çalışıyor |
| ⏸ Gri | Devre dışı |

### Sorun Giderme

**Görev listede görünmüyor:**
```bash
ddev exec vendor/bin/typo3 cache:flush
# Services.yaml'da 'public: true' eklendiğinden emin ol
```

**"Task is already running" hatası:**
```bash
# Scheduler kilitli kalmış
ddev exec vendor/bin/typo3 scheduler:run --force
```

**Cron job tetiklenmiyor:**
```bash
ddev exec crontab -l          # DDEV cron var mı?
ddev restart                  # config.scheduler.yaml için yeniden başlat
```

---

## Dosya Yapısı

```
packages/testproject/
├── Classes/
│   ├── Task/
│   │   └── CleanupTask.php        ← AbstractTask tabanlı özel görev ✓
│   └── Command/
│       └── CleanupCommand.php     ← Console Command (schedulable)
└── Configuration/
    └── Services.yaml               ← Görev kaydı ✓

.ddev/
└── config.scheduler.yaml           ← DDEV cron (*/15 dakika) ✓
```

---

## Kaynaklar

- [TYPO3 Scheduler Reference](https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ApiOverview/Scheduler/)
- [Console Commands](https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ApiOverview/CommandControllers/Index.html)
- [DDEV Crons](https://ddev.readthedocs.io/en/stable/users/configuration/config/#crons)
