> ## Documentation Index
> Fetch the complete documentation index at: https://docs.diyanet.pro/llms.txt
> Use this file to discover all available pages before exploring further.

# BuildingBlocks.Hangfire.MediatR.Extensions

> MediatR IRequest'lerini Hangfire job olarak serialize edip arka planda Send() ile çalıştırma köprüsü.

`BuildingBlocks.Hangfire.MediatR.Extensions`, MediatR komut/event'lerini Hangfire arka plan job'u olarak çalıştırmayı sağlar. Hangfire payload'ı `Type`'ı bilmeden serialize edemediği için paket iki şeyi çözer: (1) Hangfire serializer'ını `TypeNameHandling` ile yapılandırma, (2) MediatR mesajını `MediatorSerializedObject`'e paketleyip job içinde tekrar deserialize edip `_mediator.Send(...)` ile dispatch etme.

<Info>
  Çalışan Hangfire altyapısı (PostgreSQL storage `hangfire` şeması, dashboard `/jobs`, server kuyrukları, DLX) için bkz. [Hangfire servisi](/services/hangfire). Bu sayfa MediatR köprüsüne odaklanır.
</Info>

## `UseMediatR` — Hangfire serializer kurulumu

Hangfire'ın global JSON ayarlarını, polimorfik tip bilgisini koruyacak şekilde yapılandırır. `TypeNameHandling.All` sayesinde serialize edilen MediatR komutu, worker tarafında doğru concrete tipe geri çözülebilir.

```csharp theme={null}
public static IGlobalConfiguration UseMediatR(this IGlobalConfiguration configuration, IServiceCollection services)
{
    var jsonSettings = new JsonSerializerSettings
    {
        TypeNameHandling = TypeNameHandling.All
    };
    configuration.UseSerializerSettings(jsonSettings);
    return configuration;
}
```

```csharp theme={null}
// Program.cs — Hangfire kurulumu içinde
GlobalConfiguration.Configuration
    .UsePostgreSqlStorage(/* ... */)
    .UseMediatR(builder.Services);
```

## Köprü bileşenleri

MediatR mesajı doğrudan değil, `MediatorSerializedObject` zarfıyla taşınır. Bu zarf job storage'da güvenle saklanır ve worker'da yeniden kurulur.

| Tip                                     | Rol                                                                    |
| --------------------------------------- | ---------------------------------------------------------------------- |
| `IBusMessage`                           | İşaretleyici (marker) — taşınabilir mesaj                              |
| `IBusCommand : IRequest, IBusMessage`   | Job olarak çalıştırılacak MediatR komutu                               |
| `ICommandBus`                           | Komut enqueue/schedule API'si                                          |
| `IEventBus`                             | Event publish API'si                                                   |
| `ICommandExecuter` / `IEventDispatcher` | Worker tarafı — deserialize edip `_mediator.Send` çağırır              |
| `MediatorSerializedObject`              | `FullTypeName`, `AssemblyName`, `Data` (JSON), `AdditionalDescription` |

### `ICommandBus`

| Metot                                                                                      | Amaç                                         |
| ------------------------------------------------------------------------------------------ | -------------------------------------------- |
| `string Send<T>(T request, string description = null, ...)`                                | Komutu hemen kuyruğa alır; job id döner      |
| `string Send<T>(T request, string parentJobId, JobContinuationOptions, ...)`               | Başka bir job'ın **devamı** olarak zincirler |
| `void Schedule<T>(T request, DateTimeOffset scheduleAt, ...)`                              | Belirli zamanda çalıştır                     |
| `void Schedule<T>(T request, TimeSpan delay, ...)`                                         | Gecikmeli çalıştır                           |
| `void ScheduleRecurring<T>(T request, string name, string cron, RecurringJobOptions, ...)` | Cron tabanlı tekrarlı job                    |

`IEventBus`: `void Publish<T>(...)` ve `Task PublishAsync<T>(...)` — event'i `IEventDispatcher` üzerinden enqueue eder.

## Serialize → enqueue → execute

`CommandBus`, mesajı `MediatorSerializedObject`'e paketleyip `BackgroundJob.Enqueue<ICommandExecuter>(...)` ile kuyruğa alır:

```csharp theme={null}
// CommandBus (kütüphane içi)
public string Send<T>(T request, string description = null, ...) where T : IBusMessage
{
    var serialized = SerializeObject(request, description);   // FullTypeName + AssemblyName + JSON
    return BackgroundJob.Enqueue<ICommandExecuter>(x => x.ExecuteCommand(serialized));
}
```

Worker tarafında `CommandExecuter` zarfı çözer, tipi assembly'den bulur, JSON'u o tipe deserialize eder ve MediatR'a verir:

```csharp theme={null}
// CommandExecuter (kütüphane içi) — "command-queue" kuyruğunda çalışır
public async Task ExecuteCommand(MediatorSerializedObject obj)
{
    var assembly = AppDomain.CurrentDomain.GetAssemblyByName(obj.AssemblyName);
    var type = assembly?.GetType(obj.FullTypeName);
    if (type is null) return;

    dynamic req = JsonConvert.DeserializeObject(obj.Data, type);
    await _mediator.Send(req as IRequest);   // pipeline behavior'lar dahil normal akış
}
```

<Note>
  `ICommandExecuter.ExecuteCommand` `[Queue("command-queue")]` ile işaretlidir; bu işler Hangfire'da ayrı bir kuyrukta çalışır. Job dashboard'da `MediatorSerializedObject.ToString()` çıktısıyla (komut adı + açıklama) görünür.
</Note>

## Kullanım

```csharp theme={null}
// 1) Job olarak çalışacak komut
public sealed record SendMonthlyReportCommand(Guid OrganizationId) : IBusCommand;

// 2) Hemen enqueue
public class ReportController(ICommandBus bus)
{
    [HttpPost("api/admin/reports/monthly/{orgId:guid}")]
    public IActionResult Trigger(Guid orgId)
    {
        string jobId = bus.Send(new SendMonthlyReportCommand(orgId), description: $"org:{orgId}");
        return Accepted(new { jobId });
    }
}

// 3) Gecikmeli
bus.Schedule(new SendMonthlyReportCommand(orgId), TimeSpan.FromMinutes(30));

// 4) Cron tabanlı tekrarlı (her ayın 1'i 03:00)
bus.ScheduleRecurring(
    new SendMonthlyReportCommand(orgId),
    name: "monthly-report",
    cronExpression: "0 3 1 * *",
    recurringJobOption: new RecurringJobOptions());
```

Komut, normal MediatR pipeline'ından geçer — yani `SendMonthlyReportCommandHandler` ve tüm pipeline behavior'lar (validation, exception, authorization) arka planda da uygulanır.

<Warning>
  Komut payload'ını **küçük ve serileştirilebilir** tutun (id'ler, primitive'ler). Job storage'a entity grafiği yazmayın; handler içinde repository'den taze veriyi çekin. Polimorfik tip bilgisi (`TypeNameHandling.All`) güvenilmeyen kaynaktan gelen veri için risklidir — yalnızca uygulamanın kendi ürettiği job'lar enqueue edilmelidir.
</Warning>

## İlgili

<CardGroup cols={2}>
  <Card title="Hangfire servisi" icon="clock-rotate-left" href="/services/hangfire">
    PostgreSQL storage, dashboard ve server kuyrukları.
  </Card>

  <Card title="Application (CQRS)" icon="diagram-project" href="/application/overview">
    Command/handler ve pipeline behavior'lar.
  </Card>

  <Card title="Event-Driven akış" icon="paper-plane" href="/events/overview">
    Domain/integration event'lerle karşılaştırma.
  </Card>

  <Card title="Email servisi" icon="envelope" href="/services/email">
    SendBackground ile arka plan gönderim deseni.
  </Card>
</CardGroup>
