Kurumsal

Commerce CMS

Bir mağazayı ve editoryal sayfalarını tek uygulamadan işleten içerik ve ticaret sistemi. Önbelleğe alınan her ekranın ömrü yazılı duruyor.

Tek uygulamada on dört alan

Kod, dosya türüne göre değil neyle ilgili olduğuna göre gruplanıyor: commerce, inventory, content, messaging, analytics, branding, tracking ve yedi tane daha. Her biri kendi arayüzlerini, servislerini ve tiplerini tutuyor.

Alternatif, paketlerden oluşan bir workspace’ti. Tek bir deploy edilebilir uygulama için bu size build konfigürasyonu getiriyor ve pek bir şey getirmiyor; asıl istenen sınır import sınırı, onu da bir klasörle bir lint kuralı zaten veriyor. Oyunun ekip paneli paketlerden oluşan bir workspace kullanıyor; orada çekirdeğin bir sonraki oyuna taşınması gerekiyor ve sınır konfigürasyonuna değiyor.

Ömrü yazılı önbellek

Her önbellek anahtarı bir sunucu TTL’i ve bir istemci max-age’i taşıyor, ikisi de tek config dosyasında duruyor, Cache-Control başlığı da route başına yazılmak yerine buradan türetiliyor. Taze kalması gereken ekran bunu, beş dakika bayatlayabilen ekranla aynı yerde söylüyor.

Önbellek nesnesinin kendisi globalThis üzerinde duruyor. Next.js birden fazla modül grafiği kuruyor, modül kapsamındaki bir nesne de sessizce birbirinin yazdığını görmeyen birkaç önbelleğe dönüşüyor. Kestirme gibi görünüyor, oysa tam tersini yapıyor.

GöstergeDoğrudan yol
  1. İstemciler

    • Mağaza yüzü

      Next.js · React · TypeScript

    • Yönetim yüzü

      Next.js · React · TypeScript

  2. Uygulama

    • On dört alan

      TypeScript

      Neden

      Alanlar konuya göre ayrılıyor: commerce, inventory, content, messaging, analytics, branding, tracking ve yedi tane daha. Her biri kendi arayüzlerini, servislerini ve tiplerini tutuyor.

    • Olay hattı

      TypeScript

      Neden

      Bir yazma neyin değiştiğini yayınlıyor, etkilenen önbellek anahtarları da düşürülüyor. Bu olmazsa tek süre dolduran şey TTL kalıyor ve editör kendi düzenlemesini görmek için beş dakika bekliyor.

  3. Adaptörler

    • Repository'ler

      Prisma · TypeScript

  4. Durum

    • İlişkisel veritabanı

      PostgreSQL · Prisma

    • Okuma önbelleği

      Redis · TypeScript

      Neden

      Anahtar başına ömrü olan, süreç içi bir LRU çalışıyor; yeniden başlatmayı atlatması gereken durum için arkasında Redis duruyor. Her anahtar sunucu TTL'ini ve istemci max-age'ini tek bir config dosyasında bildiriyor.

Tek önbellek, modül grafiği başına bir tane değilTypeScriptOkuma önbelleği düğümünden
/** * Cache Service - Robust in-memory caching with LRU eviction * * Features: * - Max size limit (1000 entries by default) - prevents unbounded growth * - LRU eviction - automatically removes least recently used entries when full * - TTL support - per-entry expiration from config * - Proactive cleanup - automatically purges expired entries * - Type-safe API - generic get/set operations *//** * Global LRU cache instance using globalThis * Ensures same instance across all module graphs in Next.js Turbopack */declare global {  // eslint-disable-next-line no-var  var __appCache: LRUCache<string, object> | undefined;}function getOrCreateCache(): LRUCache<string, object> {  if (!globalThis.__appCache) {    globalThis.__appCache = new LRUCache<string, object>({      max: MAX_CACHE_SIZE,      ttl: DEFAULT_TTL_MS,      ttlAutopurge: true, // Proactively remove expired entries      updateAgeOnGet: true, // Reset TTL on access (true LRU behavior)      allowStale: false, // Don't return stale entries    });    console.log(      `[Cache] Initialized LRU cache (max: ${MAX_CACHE_SIZE}, defaultTTL: ${DEFAULT_SERVER_TTL}s, autoPurge: enabled)`    );  }  return globalThis.__appCache;}
Önbellek sınırlı büyüyor, en az kullanılandan başlayarak eleme yapıyor ve süresi dolan kayıtları kendisi temizliyor. Bir süreç içi önbelleğin bir mağazaya emanet edilmeden önce yapması gereken üç iş bunlar. Nesnenin globalThis üzerinde durmasının söylenmeye değer bir sebebi var: Next.js birden fazla modül grafiği kuruyor, modül kapsamındaki bir nesne de birbirinin yazdığını hiç görmeyen birkaç önbelleğe dönüşüyor.

commerce-cms3d1d112src/domain/system/cache/service/cache.service.tsSatır 1 – 4734 satır

/**
 * Cache Service - Robust in-memory caching with LRU eviction
 *
 * Features:
 * - Max size limit (1000 entries by default) - prevents unbounded growth
 * - LRU eviction - automatically removes least recently used entries when full
 * - TTL support - per-entry expiration from config
 * - Proactive cleanup - automatically purges expired entries
 * - Type-safe API - generic get/set operations
 */
/**
 * Global LRU cache instance using globalThis
 * Ensures same instance across all module graphs in Next.js Turbopack
 */
declare global {
  // eslint-disable-next-line no-var
  var __appCache: LRUCache<string, object> | undefined;
}

function getOrCreateCache(): LRUCache<string, object> {
  if (!globalThis.__appCache) {
    globalThis.__appCache = new LRUCache<string, object>({
      max: MAX_CACHE_SIZE,
      ttl: DEFAULT_TTL_MS,
      ttlAutopurge: true, // Proactively remove expired entries
      updateAgeOnGet: true, // Reset TTL on access (true LRU behavior)
      allowStale: false, // Don't return stale entries
    });
    console.log(
      `[Cache] Initialized LRU cache (max: ${MAX_CACHE_SIZE}, defaultTTL: ${DEFAULT_SERVER_TTL}s, autoPurge: enabled)`
    );
  }
  return globalThis.__appCache;
}
  • Önbelleğin cevaplayabildiği bir okuma repository'ye hiç gitmiyor. Oraya bir önbellek koymanın tüm sebebi bu, ve önbelleğin tek bir sorgunun önüne değil veritabanının yanına oturmasının sebebi de aynı.

Düzenlemenin görünmesi

Tek başına TTL, editörün değişikliği yayınlayıp beklemesi demek. Bu yüzden yazmalar bir olay hattına yayın yapıyor ve etkilenen anahtarlar anında düşüyor. TTL de hattın haberi olmayan her şey için emniyet payı olarak kalıyor.

Kurulum

npm run cli ilk kurulumun tamamını zincirliyor: Docker daemon’ını denetliyor, Postgres, Redis ve Mailpit’i ayağa kaldırıyor, health check’i bekliyor, şemayı basıyor, seed teklif ediyor. Altı adım. Hiçbiri kurulu olmayan bir makinede bunları doğru sırayla yapmak gerekiyor.

Katkı

Yazılan commit
545

18 haftanın 17 tanesi aktif · 22 Ara 2025 – 26 Nis 2026

En uzun seri · 14 hafta · Ara – Mar

Geçmişinde ikinci bir geliştirici bulunan ilk proje ve altyapıdan önce yazılan son proje.

Ölçüm 2026-09-08