Skip to content

Commit

Permalink
backend: Sent webhook when room is finished
Browse files Browse the repository at this point in the history
  • Loading branch information
CSantosM committed Jan 14, 2025
1 parent 8993b52 commit 680f9e9
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 18 deletions.
1 change: 1 addition & 0 deletions backend/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export const CALL_SECRET = process.env.CALL_SECRET || 'user';
export const CALL_ADMIN_USER = process.env.CALL_ADMIN_USER || 'admin';
export const CALL_ADMIN_SECRET = process.env.CALL_ADMIN_SECRET || 'admin';
export const CALL_PREFERENCES_STORAGE_MODE = process.env.CALL_PREFERENCES_STORAGE_MODE || 's3';
export const CALL_WEBHOOK_URL = process.env.CALL_WEBHOOK_URL || 'http://localhost:8080/';

/**
* Log levels configuration: error, warn, info, verbose, debug, silly
Expand Down
2 changes: 1 addition & 1 deletion backend/src/controllers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ export * from './global-preferences/global-preferences.controller.js';
export * from './healthcheck.controller.js';
export * from './recording.controller.js';
export * from './room.controller.js';
export * from './webhook.controller.js';
export * from './livekit-webhook.controller.js';
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { Request, Response } from 'express';
import { LoggerService } from '../services/logger.service.js';
import { WebhookService } from '../services/webhook.service.js';
import { LivekitWebhookService } from '../services/livekit-webhook.service.js';
import { RoomService } from '../services/room.service.js';
import { WebhookEvent } from 'livekit-server-sdk';
import { OpenViduWebhookService } from '../services/openvidu-webhook.service.js';

const webhookService = WebhookService.getInstance();
const lkWebhookService = LivekitWebhookService.getInstance();
const ovWebhookService = OpenViduWebhookService.getInstance();
const roomService = RoomService.getInstance();
const logger = LoggerService.getInstance();

export const webhookHandler = async (req: Request, res: Response) => {
export const lkWebhookHandler = async (req: Request, res: Response) => {
try {
const webhookEvent: WebhookEvent = await webhookService.getEventFromWebhook(
const webhookEvent: WebhookEvent = await lkWebhookService.getEventFromWebhook(
req.body,
req.get('Authorization')!
);
Expand All @@ -35,13 +37,16 @@ export const webhookHandler = async (req: Request, res: Response) => {
switch (eventType) {
case 'egress_started':
case 'egress_updated':
await webhookService.handleEgressUpdated(egressInfo!);
await lkWebhookService.handleEgressUpdated(egressInfo!);
break;
case 'egress_ended':
await webhookService.handleEgressEnded(egressInfo!);
await lkWebhookService.handleEgressEnded(egressInfo!);
break;
case 'participant_joined':
await webhookService.handleParticipantJoined(room!, participant!);
await lkWebhookService.handleParticipantJoined(room!, participant!);
break;
case 'room_finished':
await ovWebhookService.sendRoomFinishedWebhook(room!);
break;
default:
break;
Expand Down
4 changes: 2 additions & 2 deletions backend/src/routes/livekit.routes.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import express, { Router } from 'express';
import { webhookHandler } from '../controllers/webhook.controller.js';
import { lkWebhookHandler } from '../controllers/livekit-webhook.controller.js';

const livekitRouter = Router();

livekitRouter.use(express.raw({ type: 'application/webhook+json' }));
livekitRouter.post('/webhook', webhookHandler);
livekitRouter.post('/webhook', lkWebhookHandler);

export { livekitRouter };
3 changes: 2 additions & 1 deletion backend/src/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ export * from './livekit.service.js';
export * from './recording.service.js';
export * from './room.service.js';
export * from './s3.service.js';
export * from './webhook.service.js';
export * from './livekit-webhook.service.js';
export * from './openvidu-webhook.service.js';
export * from './preferences/index.js';
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import { RoomStatusData } from '../models/room.model.js';
import { BroadcastingService } from './broadcasting.service.js';
import { RecordingService } from './recording.service.js';

export class WebhookService {
private static instance: WebhookService;
export class LivekitWebhookService {
private static instance: LivekitWebhookService;
private livekitService = LiveKitService.getInstance();
private s3Service = S3Service.getInstance();
private roomService = RoomService.getInstance();
Expand All @@ -28,12 +28,12 @@ export class WebhookService {
this.webhookReceiver = new WebhookReceiver(LIVEKIT_API_KEY, LIVEKIT_API_SECRET);
}

static getInstance(): WebhookService {
if (!WebhookService.instance) {
WebhookService.instance = new WebhookService();
static getInstance(): LivekitWebhookService {
if (!LivekitWebhookService.instance) {
LivekitWebhookService.instance = new LivekitWebhookService();
}

return WebhookService.instance;
return LivekitWebhookService.instance;
}

/**
Expand Down Expand Up @@ -152,7 +152,7 @@ export class WebhookService {
}

private async sendStatusSignal(roomName: string, roomId: string, participantSid: string) {
// Get broadcsting and recording list
// Get broadcasting and recording list
const [broadcastingList, recordingInfo] = await Promise.all([
this.broadcastingService.getAllBroadcastingsByRoom(roomName, roomId),
this.recordingService.getAllRecordingsByRoom(roomName, roomId)
Expand Down
57 changes: 57 additions & 0 deletions backend/src/services/openvidu-webhook.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Room } from 'livekit-server-sdk';
import { LoggerService } from './logger.service.js';
import { CALL_WEBHOOK_URL } from '../config.js';

export class OpenViduWebhookService {
private static instance: OpenViduWebhookService;
protected logger = LoggerService.getInstance();

static getInstance(): OpenViduWebhookService {
if (!OpenViduWebhookService.instance) {
OpenViduWebhookService.instance = new OpenViduWebhookService();
}

return OpenViduWebhookService.instance;
}

async sendRoomFinishedWebhook(room: Room): Promise<void> {
this.logger.verbose(`Sending room finished webhook for room ${room.name}`);

try {
await this.fetchWithRetry(CALL_WEBHOOK_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
event: 'room_finished',
room: {
name: room.name
}
})
});
} catch (error) {
this.logger.error(`Error sending room finished webhook: ${error}`);
}
}

private async fetchWithRetry(url: string, options: RequestInit, retries = 5, delay = 300): Promise<void> {
try {
// Try to fetch the URL
const response = await fetch(url, options);

if (!response.ok) {
throw new Error(`Request failed with status ${response.status}`);
}
} catch (error) {
if (retries <= 0) {
throw new Error(`Request failed: ${error}`);
}

this.logger.verbose(`Retrying in ${delay / 1000} seconds... (${retries} retries left)`);
await new Promise((resolve) => setTimeout(resolve, delay));
// Retry the request after a delay with exponential backoff
return this.fetchWithRetry(url, options, retries - 1, delay * 2);
}
}
}

0 comments on commit 680f9e9

Please sign in to comment.