main
Some checks failed
Backend Deploy 🚀 / build-and-deploy (push) Has been cancelled

This commit is contained in:
Harun CAN
2026-03-30 00:21:32 +03:00
parent 85c35c73e8
commit acb103657b
29 changed files with 11473 additions and 13081 deletions

View File

@@ -0,0 +1,205 @@
import {
WebSocketGateway,
WebSocketServer,
SubscribeMessage,
OnGatewayConnection,
OnGatewayDisconnect,
ConnectedSocket,
MessageBody,
} from '@nestjs/websockets';
import { Logger } from '@nestjs/common';
import { Server, Socket } from 'socket.io';
/**
* ContentGen AI — Gerçek Zamanlı WebSocket Gateway
*
* Frontend'e render ilerleme bildirimlerini iletir.
* C# Worker → RenderCallbackController → EventsGateway → Frontend
*
* Room yapısı: "project:{projectId}" — her proje kendi room'una abone olur
*/
@WebSocketGateway({
cors: {
origin: ['http://localhost:3001', 'http://localhost:3000', process.env.FRONTEND_URL || '*'],
credentials: true,
},
namespace: '/ws',
transports: ['websocket', 'polling'],
})
export class EventsGateway implements OnGatewayConnection, OnGatewayDisconnect {
@WebSocketServer()
server: Server;
private readonly logger = new Logger(EventsGateway.name);
private connectedClients = 0;
handleConnection(client: Socket) {
this.connectedClients++;
this.logger.log(`Client bağlandı: ${client.id} (toplam: ${this.connectedClients})`);
}
handleDisconnect(client: Socket) {
this.connectedClients--;
this.logger.log(`Client ayrıldı: ${client.id} (toplam: ${this.connectedClients})`);
}
/**
* Frontend, proje detay sayfasına girdiğinde bu event'i gönderir.
* Client ilgili proje room'una katılır.
*/
@SubscribeMessage('join:project')
handleJoinProject(
@ConnectedSocket() client: Socket,
@MessageBody() data: { projectId: string },
) {
const room = `project:${data.projectId}`;
client.join(room);
this.logger.debug(`Client ${client.id} → room: ${room}`);
return { event: 'joined', data: { room, projectId: data.projectId } };
}
/**
* Frontend, proje sayfasından ayrıldığında bu event'i gönderir.
*/
@SubscribeMessage('leave:project')
handleLeaveProject(
@ConnectedSocket() client: Socket,
@MessageBody() data: { projectId: string },
) {
const room = `project:${data.projectId}`;
client.leave(room);
this.logger.debug(`Client ${client.id} ← room: ${room}`);
return { event: 'left', data: { room } };
}
/**
* Kullanıcı kendi bildirim room'una katılır.
* Frontend login sonrası bu event'i göndererek anlık bildirimleri alır.
*/
@SubscribeMessage('join:user')
handleJoinUser(
@ConnectedSocket() client: Socket,
@MessageBody() data: { userId: string },
) {
const room = `user:${data.userId}`;
client.join(room);
this.logger.debug(`Client ${client.id} → user room: ${room}`);
return { event: 'joined', data: { room, userId: data.userId } };
}
/**
* Kullanıcı bildirim room'undan ayrılır.
*/
@SubscribeMessage('leave:user')
handleLeaveUser(
@ConnectedSocket() client: Socket,
@MessageBody() data: { userId: string },
) {
const room = `user:${data.userId}`;
client.leave(room);
this.logger.debug(`Client ${client.id} ← user room: ${room}`);
return { event: 'left', data: { room } };
}
// ═══════════════════════════════════════════════════════
// Server → Client Events (RenderCallbackController tarafından tetiklenir)
// ═══════════════════════════════════════════════════════
/**
* Render ilerleme bildirimi gönder.
* Stage: 'tts' | 'image_generation' | 'music_generation' | 'compositing' | 'encoding'
*/
emitRenderProgress(
projectId: string,
payload: {
progress: number;
stage: string;
stageLabel: string;
currentScene?: number;
totalScenes?: number;
eta?: number; // Tahmini kalan saniye
},
) {
this.server.to(`project:${projectId}`).emit('render:progress', {
projectId,
...payload,
timestamp: new Date().toISOString(),
});
}
/**
* Render tamamlandı bildirimi.
*/
emitRenderCompleted(
projectId: string,
payload: {
finalVideoUrl: string;
thumbnailUrl?: string;
processingTimeMs: number;
fileSize: number;
},
) {
this.server.to(`project:${projectId}`).emit('render:completed', {
projectId,
...payload,
timestamp: new Date().toISOString(),
});
}
/**
* Render hatası bildirimi.
*/
emitRenderFailed(
projectId: string,
payload: {
error: string;
stage: string;
attemptNumber: number;
canRetry: boolean;
},
) {
this.server.to(`project:${projectId}`).emit('render:failed', {
projectId,
...payload,
timestamp: new Date().toISOString(),
});
}
/**
* Proje durum değişikliği bildirimi (status change).
*/
emitProjectStatusChanged(projectId: string, status: string) {
this.server.to(`project:${projectId}`).emit('project:status', {
projectId,
status,
timestamp: new Date().toISOString(),
});
}
/**
* Kullanıcıya anlık bildirim gönder.
* NotificationsService.createNotification() tarafından çağrılır.
*/
emitNotification(
userId: string,
payload: {
id: string;
type: string;
title: string;
message?: string | null;
metadata?: unknown;
isRead: boolean;
createdAt: string;
},
) {
this.server.to(`user:${userId}`).emit('notification:new', {
...payload,
timestamp: new Date().toISOString(),
});
}
/** Bağlı client sayısını döndür (health check için) */
getConnectedClientsCount(): number {
return this.connectedClients;
}
}