> ## 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.Caching

> Hibrit L1+L2 cache, tag-based invalidation ve Redis distributed cache/lock.

İki paket birlikte hibrit cache stratejisini oluşturur:

* **`BuildingBlocks.Caching`** — `IHybridRequestCache` soyutlaması; `Microsoft.Extensions.Caching.Hybrid` (HybridCache) üzerine stampede protection + tag-based invalidation + multi-instance broadcast hook ekler.
* **`BuildingBlocks.Caching.Redis`** — L2 backend'i; `IDistributedCache` implementasyonları ve distributed lock sağlar.

<Info>
  Üst seviye cache mimarisi (L1/L2 stratejisi, invalidation, multi-instance) [Cache Mimarisi](/caching/overview) grubunda anlatılır. Bu sayfa paket arayüzlerine odaklanır.
</Info>

## `IHybridRequestCache`

HybridCache'i doğrudan inject etmek yerine bu arayüz kullanılır — domain-friendly imza ve multi-instance broadcast hook için.

| Metot                     | İmza                                                                                                                                                                                                          | Amaç                                                                                                         |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `GetOrCreateAsync<T>`     | `ValueTask<T> GetOrCreateAsync<T>(string key, Func<CancellationToken, ValueTask<T>> factory, HybridCacheEntryOptions? options = null, IReadOnlyCollection<string>? tags = null, CancellationToken = default)` | Cache'te varsa döner, yoksa factory'yi çağırır (stampede-safe)                                               |
| `RemoveAsync`             | `ValueTask RemoveAsync(string key, CancellationToken = default)`                                                                                                                                              | Tek key'i L1+L2'den siler (diğer instance'ların L1'ini etkilemez)                                            |
| `RemoveByTagAsync`        | `ValueTask RemoveByTagAsync(string tag, CancellationToken = default)`                                                                                                                                         | Bir tag'e bağlı tüm entry'leri invalidate eder (lazy); broadcast açıksa diğer node'lara yayılır              |
| `RemoveByTagsAsync`       | `ValueTask RemoveByTagsAsync(IReadOnlyCollection<string> tags, CancellationToken = default)`                                                                                                                  | Toplu tag invalidation                                                                                       |
| `RemoveByTagLocallyAsync` | `ValueTask RemoveByTagLocallyAsync(string tag, CancellationToken = default)`                                                                                                                                  | Sadece local invalidation — tekrar broadcast yapmaz (loop önleme; integration event handler'ında kullanılır) |

### `CacheOptions`

`Cache` bölümüne bind edilir. Yalnızca **spec/DB query cache**'ini (`CachedRepository`) etkiler; auth/token cache'leri (UserContext, JWKS, PKCE) HybridCache'i doğrudan kullanır ve bu bayraklardan etkilenmez.

| Üye                        | Tip                | Varsayılan   | Açıklama                                                                             |
| -------------------------- | ------------------ | ------------ | ------------------------------------------------------------------------------------ |
| `Enabled`                  | `bool`             | —            | Spec/DB query cache kill-switch'i. `false` ise `CachedRepository` raw EFCore'a düşer |
| `L1`                       | `CacheTierOptions` | `Ttl = 1 dk` | In-process memory katmanı                                                            |
| `L2`                       | `CacheTierOptions` | `Ttl = 5 dk` | Redis katmanı (spec `WithCacheTtl(...)` ile per-entry override edebilir)             |
| `BroadcastTagInvalidation` | `bool`             | `false`      | Multi-instance L1 senkronu için integration event yayını                             |

`IRemoteTagBroadcaster` çok-instance tag broadcast kontratıdır; varsayılan `NoopRemoteTagBroadcaster` (tek-node). Multi-pod'da Application katmanı bunu MassTransit/Redis pub-sub implementasyonuyla değiştirir.

### DI kaydı — `AddCache`

```csharp theme={null}
public static IServiceCollection AddCache(this IServiceCollection services, IConfiguration configuration)
{
    services.Configure<CacheOptions>(o => configuration.GetSection("Cache").Bind(o));
    services.AddMemoryCache();
    services.AddSingleton<IHybridRequestCache, HybridRequestCache>();
    services.TryAddSingleton<IRemoteTagBroadcaster, NoopRemoteTagBroadcaster>();
    return services;
}
```

```json theme={null}
{
  "Cache": {
    "Enabled": true,
    "L1": { "Ttl": "00:01:00" },
    "L2": { "Ttl": "00:05:00" },
    "BroadcastTagInvalidation": false
  }
}
```

<Warning>
  **Kayıt sırası kritiktir.** HybridCache, L2 backend'i (`IDistributedCache`, Redis) önceden register edilmiş olmasını bekler. Doğru sıra:

  ```csharp theme={null}
  builder.Services.AddRedisCache(builder.Configuration);   // 1. L2 backend (IDistributedCache)
  builder.Services.AddCache(builder.Configuration);        // 2. IHybridRequestCache + CacheOptions
  builder.Services.AddHybridCache(...);                    // 3. HybridCache — L2'yi görür
  ```

  `AddCache` HybridCache'i kendisi register **etmez** — `Program.cs` `AddHybridCache(...)`'ı `AddRedisCache`'ten sonra çağırır. Sıra bozulursa HybridCache L2'yi göremez ve L1-only çalışır.
</Warning>

## `BuildingBlocks.Caching.Redis`

L2 backend'i ve distributed lock sağlayan paket.

| Arayüz                      | Amaç                                                     |
| --------------------------- | -------------------------------------------------------- |
| `IDistributedCache`         | Generic tipli get/set; pattern bazlı toplu get           |
| `IDistributedRequestCache`  | Request-scoped cache                                     |
| `IDistributedDatabaseCache` | DB query sonucu cache'i                                  |
| `IDistributedSocketCache`   | WebSocket/SignalR mesaj cache'i                          |
| `IDistributedLockMutexer`   | `IDistributedLock` üreten distributed mutex (auto-renew) |
| `RedisDatabaseEnum`         | Mantıksal Redis DB seçimi (0-15)                         |

`DistributedLockOptions`: `RedisDistributedLocking` (aç/kapa), `Expiry` (lock TTL — `Expiry/2`'de auto-renew).

### DI kaydı — `AddRedisCache`

```csharp theme={null}
builder.Services.AddRedisCache(builder.Configuration);
```

```json theme={null}
{
  "ConnectionStrings": { "RedisConnection": "redis:6379" },
  "Redis": {
    "InstanceName": "dca:",
    "DistributedLock": { "RedisDistributedLocking": true, "Expiry": 30 }
  }
}
```

## Kullanım

```csharp theme={null}
// Spec üzerinde cache (Repository.ListAsync ile)
var spec = new GetActiveFaqsSpecification()
    .EnableCache("faqs:active")
    .WithCacheTtl(TimeSpan.FromMinutes(10))
    .WithTags("faq");

var faqs = await _readRepository.ListAsync(spec, ct);

// Doğrudan IHybridRequestCache
var profile = await _cache.GetOrCreateAsync(
    key: $"user:{id}:profile",
    factory: async ct => await _db.GetProfileAsync(id, ct),
    tags: new[] { $"user:{id}" },
    cancellationToken: ct);

// Tag invalidation (domain event handler içinde)
await _cache.RemoveByTagAsync("faq", ct);

// Distributed lock
await using var @lock = await _locker.AcquireLockAsync("batch:123", TimeSpan.FromSeconds(30));
// kritik bölüm — lock dispose'a kadar auto-renew olur
```

## İlgili

<CardGroup cols={2}>
  <Card title="Hibrit cache" icon="layer-group" href="/caching/hybrid-cache">
    L1/L2 katman davranışı ve stampede protection.
  </Card>

  <Card title="Invalidation" icon="eraser" href="/caching/invalidation">
    Tag-based eviction ve domain event entegrasyonu.
  </Card>

  <Card title="Multi-instance" icon="server" href="/caching/multi-instance">
    Broadcast ile node'lar arası L1 senkronu.
  </Card>

  <Card title="Specification" icon="filter" href="/building-blocks/specification">
    Spec üzerinde EnableCache/WithTags entegrasyonu.
  </Card>
</CardGroup>
