feat(backend): realtime event system, admin API ve metrics altyapısı
- socket.ts: ContentRealtimeEvent, CacheRealtimeEvent, MetricsRealtimeEvent
tipleri eklendi; emitContentEvent / emitCacheEvent / emitMetricsEvent
fonksiyonları ile tüm istemcilere broadcast desteği getirildi.
emitJobCompleted imzası GetInfoResponse + DataSource ile güçlendirildi.
- auth.middleware.ts: require() tabanlı env erişimi static import'a
dönüştürüldü; admin-only endpointler için adminOnlyMiddleware eklendi
(X-API-Key !== API_KEY_ADMIN → 403).
- cache.service.ts: set / delete / clearAll işlemlerinden sonra
emitCacheEvent çağrısı eklenerek cache mutasyonları anlık yayınlanıyor.
- content.service.ts: create / update / delete sonrasında emitContentEvent
çağrısı eklenerek DB yazımları Socket.IO üzerinden duyuruluyor.
- job.service.ts: async ve sync akışa MetricsService entegrasyonu eklendi;
cache hit/miss ve kaynak (cache/database/netflix) sayaçları her işlemde
artırılıyor.
- types/index.ts: AdminOverviewResponse ve AdminActionResponse tipleri
merkezi olarak tanımlandı.
- admin.service.ts (yeni): getOverview, clearCache, warmupCacheFromDatabase,
retryFailedJobs, refreshStaleContent operasyonları implement edildi.
Redis pipeline ile TTL/boyut analizi ve DB metrikleri paralel toplanıyor.
- metrics.service.ts (yeni): Redis hash tabanlı cache hit/miss ve kaynak
sayaçları; her artışta MetricsRealtimeEvent yayınlanıyor.
- api.routes.ts: Admin endpointleri eklendi:
GET /api/admin/overview
POST /api/admin/cache/clear
POST /api/admin/cache/warmup
POST /api/admin/jobs/retry-failed
POST /api/admin/content/refresh-stale
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import redis from '../config/redis.js';
|
||||
import { env } from '../config/env.js';
|
||||
import { emitCacheEvent } from '../config/socket.js';
|
||||
import logger from '../utils/logger.js';
|
||||
import type { GetInfoResponse, CacheEntry, DataSource } from '../types/index.js';
|
||||
import type { GetInfoResponse, CacheEntry } from '../types/index.js';
|
||||
|
||||
/**
|
||||
* Cache key prefix for Netflix content
|
||||
@@ -63,6 +64,12 @@ export class CacheService {
|
||||
|
||||
try {
|
||||
await redis.setex(key, ttl, JSON.stringify(entry));
|
||||
emitCacheEvent({
|
||||
action: 'written',
|
||||
key,
|
||||
ttlSeconds: ttl,
|
||||
occurredAt: new Date().toISOString(),
|
||||
});
|
||||
logger.debug('Cache set', { url, ttl });
|
||||
} catch (error) {
|
||||
logger.error('Cache set error', {
|
||||
@@ -80,6 +87,11 @@ export class CacheService {
|
||||
|
||||
try {
|
||||
await redis.del(key);
|
||||
emitCacheEvent({
|
||||
action: 'deleted',
|
||||
key,
|
||||
occurredAt: new Date().toISOString(),
|
||||
});
|
||||
logger.debug('Cache deleted', { url });
|
||||
} catch (error) {
|
||||
logger.error('Cache delete error', {
|
||||
@@ -133,6 +145,11 @@ export class CacheService {
|
||||
|
||||
if (keys.length > 0) {
|
||||
await redis.del(...keys);
|
||||
emitCacheEvent({
|
||||
action: 'cleared',
|
||||
count: keys.length,
|
||||
occurredAt: new Date().toISOString(),
|
||||
});
|
||||
logger.info('Cache cleared', { count: keys.length });
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user