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:
2026-02-28 11:59:59 +03:00
parent 97fb289fe7
commit 5c496277f2
9 changed files with 932 additions and 10 deletions

View File

@@ -1,6 +1,7 @@
import { Server as HttpServer } from 'http';
import { Server, Socket } from 'socket.io';
import logger from '../utils/logger.js';
import type { DataSource, GetInfoResponse } from '../types/index.js';
/**
* Socket.IO Server singleton
@@ -11,6 +12,32 @@ export interface SocketData {
subscribedJobs: Set<string>;
}
export interface ContentRealtimeEvent {
action: 'created' | 'updated' | 'deleted';
url: string;
content?: GetInfoResponse;
occurredAt: string;
}
export interface CacheRealtimeEvent {
action: 'written' | 'deleted' | 'cleared';
key?: string;
ttlSeconds?: number;
count?: number;
occurredAt: string;
}
export interface MetricsRealtimeEvent {
cacheHits: number;
cacheMisses: number;
sourceCounts: {
cache: number;
database: number;
netflix: number;
};
occurredAt: string;
}
/**
* Initialize Socket.IO server
*/
@@ -86,8 +113,8 @@ export function emitJobProgress(
*/
export function emitJobCompleted(
jobId: string,
data: unknown,
source: string
data: GetInfoResponse,
source: DataSource
): void {
if (io) {
io.to(`job:${jobId}`).emit('job:completed', {
@@ -98,6 +125,33 @@ export function emitJobCompleted(
}
}
/**
* Emit realtime content mutation event to all clients
*/
export function emitContentEvent(event: ContentRealtimeEvent): void {
if (io) {
io.emit('content:event', event);
}
}
/**
* Emit realtime cache event to all clients
*/
export function emitCacheEvent(event: CacheRealtimeEvent): void {
if (io) {
io.emit('cache:event', event);
}
}
/**
* Emit realtime metrics event to all clients
*/
export function emitMetricsEvent(event: MetricsRealtimeEvent): void {
if (io) {
io.emit('metrics:updated', event);
}
}
/**
* Emit job error event
*/