Architektura
Komplexní průvodce architekturou systému CatCMS, pokrývající platformu Cloudflare Workers, životní cyklus požadavku, systém pluginů a vzory datových toků.[object Object]
Přehled
CatCMS je moderní, TypeScript-first headless CMS vytvořený specificky pro edge platformu Cloudflare. Využívá Cloudflare Workers, databázi D1, úložiště R2 a KV cache k dosažení výjimečného výkonu na okraji sítě.
Klíčové principy architektury
- Edge-First - Běží kompletně na globální edge síti Cloudflare
- Nulové studené starty - V8 izoláty zajišťují okamžité spuštění
- Nativní TypeScript - Plně typovaný pro lepší vývojářský zážitek
- Řízený pluginy - Rozšiřitelný pomocí robustního systému pluginů
- Optimalizovaný pro výkon - Tříúrovňové ukládání do mezipaměti pro submilisekundové časy odezvy
Technologický stack
Cloudflare Workers
Serverless execution at the edge with V8 isolates
D1 Database
SQLite with global replication and Drizzle ORM
R2 Storage
S3-compatible object storage for media files
KV Cache
Global key-value store for distributed caching
Hono Framework
Ultra-fast web framework for routing and middleware
Drizzle ORM
Type-safe database queries with automatic migrations
Cloudflare Workers
Model V8 izolátů
CatCMS běží ve V8 izolátech, což poskytuje:
- Okamžité spuštění (žádné studené starty)
- Izolace paměti mezi požadavky
- Automatické škálování pro zvládnutí nárazového provozu
- Globální distribuce ve více než 300 lokalitách
// Worker bindings configuration
type Bindings = {
DB: D1Database // Cloudflare D1 database
KV: KVNamespace // Key-value cache
MEDIA_BUCKET: R2Bucket // Object storage
ASSETS: Fetcher // Static assets
EMAIL_QUEUE?: Queue // Email queue (optional)
ENVIRONMENT?: string // Environment flag
}
type Variables = {
user?: {
userId: string
email: string
role: string
exp: number
iat: number
}
requestId?: string
startTime?: number
}
const app = new Hono<{ Bindings: Bindings; Variables: Variables }>()
Worker Entry Point
Vzor přístupu k prostředkům
// Accessing D1, KV, and R2 in routes
app.get('/api/data', async (c) => {
// Access D1 database
const db = c.env.DB
const result = await db.prepare('SELECT * FROM content').all()
// Access KV cache
const kv = c.env.KV
const cached = await kv.get('key', 'json')
// Access R2 storage
const bucket = c.env.MEDIA_BUCKET
const file = await bucket.get('image.jpg')
return c.json(result)
})Accessing Cloudflare Resources
Architektura systému
Přehled na vysoké úrovni
┌─────────────────────────────────────────────────────────────┐
│ Cloudflare Edge Network │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ Middleware Pipeline │ │
│ │ Bootstrap → Logging → Auth → Permissions → Plugin │ │
│ └───────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ Route Handler │ │
│ │ API Routes | Admin Routes | Auth Routes | Plugins │ │
│ └───────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ Service Layer │ │
│ │ Cache | Content | Auth | Plugin Services │ │
│ └───────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ Data Layer │ │
│ │ Memory Cache | KV Cache | D1 Database │ │
│ └───────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
Odpovědnosti vrstev
1. Middleware Pipeline
- Předzpracování požadavků
- Autentizace a autorizace
- Bezpečnostní hlavičky
- Monitorování výkonu
- Logování
2. Obsluha trasy
- Směrování požadavků
- Validace parametrů
- Formátování odpovědi
- Zpracování chyb
3. Servisní vrstva
- Byznys logika
- Transformace dat
- Správa mezipaměti
- Externí integrace
4. Datová vrstva
- Perzistence dat
- Úložiště mezipaměti
- Spouštění dotazů
Životní cyklus požadavku
Kompletní tok požadavku
- Požadavek dorazí na okraj sítě Cloudflare
- Bootstrap Middleware - Spuštění migrací, synchronizace kolekcí, bootstrap pluginů
- Logovací middleware - Generování ID požadavku, záznam času spuštění
- Bezpečnostní middleware - Kontrola podezřelých vzorů, přidání bezpečnostních hlaviček
- Autentizační middleware - Extrakce JWT, ověření tokenu, nastavení uživatelského kontextu
- Middleware pro oprávnění - Kontrola uživatelských oprávnění a rolí
- Plugin middleware - Spuštění plugin hooků
- Obsluha trasy - Spuštění logiky trasy, kontrola mezipaměti, zpracování byznys logiky
- Zpracování odpovědi - Přidání hlaviček pro cache, časových metadat, logování metrik
- Návrat klientovi
// Application middleware setup
app.use('*', bootstrapMiddleware())
app.use('*', loggingMiddleware())
app.use('*', securityLoggingMiddleware())
app.use('*', logger())
app.use('*', cors())
app.use('*', securityHeaders())
// Route-specific middleware
app.use('/admin/_', async (c, next) => {
return await requireAuth()(c, next)
})
app.use('/admin/_', requireRole(['admin', 'editor']))
// Routes
app.route('/api', apiRoutes)
app.route('/admin', adminRoutes)
app.route('/auth', authRoutes)
Middleware Configuration
Middleware Pipeline
Pořadí spuštění
- Bootstrap (Priorita: 0) - Inicializace systému
- Logování (Priorita: 1) - Sledování požadavků
- Bezpečnost (Priorita: 2) - Hlavičky, validace
- CORS (Priorita: 3) - Mezidoménový
- Autentizace (Priorita: 10) - Ověření JWT
- Autorizace (Priorita: 11) - Kontrola oprávnění
- Plugin middleware (Priorita: 50+) - Vlastní logika
- Obsluha trasy (Priorita: 100)
Bootstrap Middleware
Zajišťuje inicializaci systému při prvním požadavku:
export function bootstrapMiddleware() {
return async (c: Context<{ Bindings: Bindings }>, next: Next) => {
if (bootstrapComplete) {
return next()
}
try {
// 1. Run database migrations
const migrationService = new MigrationService(c.env.DB)
await migrationService.runPendingMigrations()
// 2. Sync collection configurations
await syncCollections(c.env.DB)
// 3. Bootstrap core plugins
const bootstrapService = new PluginBootstrapService(c.env.DB)
if (await bootstrapService.isBootstrapNeeded()) {
await bootstrapService.bootstrapCorePlugins()
await bootstrapService.installDemoPlugins()
}
bootstrapComplete = true
} catch (error) {
console.error('[Bootstrap] Error:', error)
}
return next()
}
}Bootstrap Process
Autentizační middleware
Autentizace založená na JWT s ukládáním do KV mezipaměti:
export const requireAuth = () => {
return async (c: Context, next: Next) => {
// Get token from header or cookie
let token = c.req.header('Authorization')?.replace('Bearer ', '')
if (!token) {
token = getCookie(c, 'auth_token')
}
if (!token) {
return c.json({ error: 'Authentication required' }, 401)
}
// Try KV cache first (5-minute TTL)
const kv = c.env?.KV
let payload: JWTPayload | null = null
if (kv) {
const cacheKey = `auth:${token.substring(0, 20)}`
const cached = await kv.get(cacheKey, 'json')
if (cached) {
payload = cached as JWTPayload
}
}
// Verify token if not cached
if (!payload) {
payload = await AuthManager.verifyToken(token)
// Cache for 5 minutes
if (payload && kv) {
await kv.put(cacheKey, JSON.stringify(payload), {
expirationTtl: 300
})
}
}
if (!payload) {
return c.json({ error: 'Invalid or expired token' }, 401)
}
c.set('user', payload)
return await next()
}
}
Auth Middleware
Systém pluginů
Architektura
CatCMS disponuje výkonnou architekturou pluginů:
Základní komponenty:
- Registr pluginů - Registruje a spravuje pluginy
- Systém hooků - Architektura řízená událostmi se spouštěním na základě priority
- Správce pluginů - Organizuje životní cyklus pluginů
Typy pluginů:
- Základní pluginy (automaticky instalované): auth, media, cache, database-tools, seed-data
- Demo pluginy (volitelné): workflow, FAQ, demo-login
- Vlastní pluginy - Vaše vlastní rozšíření
// Plugin lifecycle
install() -> activate() -> [running] -> deactivate() -> uninstall()
// Hook registration
export class HookSystemImpl implements HookSystem {
register(hookName: string, handler: HookHandler, priority: number = 10): void {
if (!this.hooks.has(hookName)) {
this.hooks.set(hookName, [])
}
const hooks = this.hooks.get(hookName)!
const hook: PluginHook = { name: hookName, handler, priority }
// Insert in priority order
const insertIndex = hooks.findIndex(h => h.priority! > priority)
if (insertIndex === -1) {
hooks.push(hook)
} else {
hooks.splice(insertIndex, 0, hook)
}
}
async execute(hookName: string, data: any, context?: any): Promise<any> {
const hooks = this.hooks.get(hookName)
if (!hooks || hooks.length === 0) {
return data
}
let result = data
for (const hook of hooks) {
result = await hook.handler(result, context)
}
return result
}
}Plugin Lifecycle
Strategie ukládání do mezipaměti
Tříúrovňový systém
CatCMS implementuje inteligentní ukládání do mezipaměti ve třech úrovních:
Úroveň 1: Mezipaměť v paměti
- Nejrychlejší přístup (< 1 ms)
- Limit velikosti 50 MB na workera
- Zásada odstraňování LRU
Úroveň 2: Cloudflare KV
- Globální distribuce
- Konečná konzistence
- TTL 5-60 minut
Úroveň 3: Databáze D1
- Zdroj pravdy
- Silná konzistence
- Plné možnosti dotazování
Tok mezipaměti
Request
↓
Memory Cache? ──Yes──→ Return (< 1ms)
↓ No
KV Cache? ──Yes──→ Populate Memory → Return (10-50ms)
↓ No
Database ──→ Populate KV → Populate Memory → Return (100-200ms)
export class CacheService {
async get<T>(key: string): Promise<T | null> {
this.stats.totalRequests++
// Try memory cache first (Tier 1)
if (this.config.memoryEnabled) {
const memoryValue = this.memoryCache.get<T>(key)
if (memoryValue !== null) {
this.stats.memoryHits++
return memoryValue
}
this.stats.memoryMisses++
}
// Try KV cache (Tier 2)
if (this.config.kvEnabled && this.kvNamespace) {
const kvValue = await this.kvNamespace.get(key, 'json')
if (kvValue !== null) {
this.stats.kvHits++
// Populate memory cache
if (this.config.memoryEnabled) {
this.memoryCache.set(key, kvValue as T, this.config.ttl)
}
return kvValue as T
}
this.stats.kvMisses++
}
return null
}
async set<T>(key: string, value: T): Promise<void> {
// Store in memory (Tier 1)
if (this.config.memoryEnabled) {
this.memoryCache.set(key, value, this.config.ttl)
}
// Store in KV (Tier 2)
if (this.config.kvEnabled && this.kvNamespace) {
await this.kvNamespace.put(key, JSON.stringify(value), {
expirationTtl: this.config.ttl
})
}
}
}
Cache Service
Výkon
Metriky výkonu na okraji sítě
- První požadavek (studený): 50-100 ms
- Požadavek z mezipaměti (paměť): 1-5 ms
- Požadavek z mezipaměti (KV): 10-50 ms
- Databázový dotaz: 100-200 ms
Optimalizační strategie
- Agresivní ukládání do mezipaměti - Používejte tříúrovňové ukládání do mezipaměti pro všechna často přistupovaná data
- Minimalizujte databázové dotazy - Kdykoli je to možné, používejte dávkové operace
- Používejte KV pro autentizaci - Ukládejte do mezipaměti výsledky ověření JWT
- Optimalizujte pořadí middlewaru - Rychlé kontroly jako první (mezipaměť autentizace před databází)
- Líné načítání pluginů - Načítejte pluginy pouze v případě potřeby
Performance Best Practices
- Povolte všechny tři úrovně mezipaměti pro maximální výkon - Nastavte vhodné TTL na základě volatility dat - Používejte stránkování pro velké datové sady - Implementujte správné strategie zneplatnění mezipaměti
Další kroky