backend: Rename handleRoomFinished to handleMeetingFinished and improve recording lock management
This commit is contained in:
parent
f089ad6e67
commit
da5d513d01
@ -39,7 +39,7 @@ export const lkWebhookHandler = async (req: Request, res: Response) => {
|
|||||||
await lkWebhookService.handleParticipantJoined(room!, participant!);
|
await lkWebhookService.handleParticipantJoined(room!, participant!);
|
||||||
break;
|
break;
|
||||||
case 'room_finished':
|
case 'room_finished':
|
||||||
await lkWebhookService.handleRoomFinished(room!);
|
await lkWebhookService.handleMeetingFinished(room!);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -127,7 +127,10 @@ export class LivekitWebhookService {
|
|||||||
*/
|
*/
|
||||||
async handleMeetingFinished(room: Room) {
|
async handleMeetingFinished(room: Room) {
|
||||||
try {
|
try {
|
||||||
await this.openViduWebhookService.sendRoomFinishedWebhook(room);
|
await Promise.all([
|
||||||
|
this.recordingService.releaseRoomRecordingActiveLock(room.name),
|
||||||
|
this.openViduWebhookService.sendRoomFinishedWebhook(room)
|
||||||
|
]);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(`Error handling room finished event: ${error}`);
|
this.logger.error(`Error handling room finished event: ${error}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,7 +26,6 @@ import { OpenViduComponentsAdapterHelper } from '../helpers/ov-components-adapte
|
|||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class RecordingService {
|
export class RecordingService {
|
||||||
protected readonly RECORDING_ACTIVE_LOCK_TTL = ms('6h');
|
|
||||||
constructor(
|
constructor(
|
||||||
@inject(S3Service) protected s3Service: S3Service,
|
@inject(S3Service) protected s3Service: S3Service,
|
||||||
@inject(LiveKitService) protected livekitService: LiveKitService,
|
@inject(LiveKitService) protected livekitService: LiveKitService,
|
||||||
@ -43,8 +42,7 @@ export class RecordingService {
|
|||||||
|
|
||||||
if (!room) throw errorRoomNotFound(roomId);
|
if (!room) throw errorRoomNotFound(roomId);
|
||||||
|
|
||||||
// Attempt to acquire lock.
|
// Attempt to acquire lock. If the lock is not acquired, the recording is already active.
|
||||||
// Note: using a high TTL to prevent expiration during a long recording.
|
|
||||||
acquiredLock = await this.acquireRoomRecordingActiveLock(roomId);
|
acquiredLock = await this.acquireRoomRecordingActiveLock(roomId);
|
||||||
|
|
||||||
if (!acquiredLock) throw errorRecordingAlreadyStarted(roomId);
|
if (!acquiredLock) throw errorRecordingAlreadyStarted(roomId);
|
||||||
@ -53,8 +51,6 @@ export class RecordingService {
|
|||||||
const output = this.generateFileOutputFromRequest(roomId);
|
const output = this.generateFileOutputFromRequest(roomId);
|
||||||
const egressInfo = await this.livekitService.startRoomComposite(roomId, output, options);
|
const egressInfo = await this.livekitService.startRoomComposite(roomId, output, options);
|
||||||
|
|
||||||
// Return recording info without releasing the lock here,
|
|
||||||
// as it will be released in handleEgressEnded on successful completion.
|
|
||||||
return RecordingHelper.toRecordingInfo(egressInfo);
|
return RecordingHelper.toRecordingInfo(egressInfo);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(`Error starting recording in room ${roomId}: ${error}`);
|
this.logger.error(`Error starting recording in room ${roomId}: ${error}`);
|
||||||
@ -270,12 +266,20 @@ export class RecordingService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Acquires a Redis-based lock to indicate that a recording is active for a specific room.
|
* Acquires a Redis-based lock to indicate that a recording is active for a specific room.
|
||||||
|
*
|
||||||
|
* This lock will be used to prevent multiple recording start requests from being processed
|
||||||
|
* simultaneously for the same room.
|
||||||
|
*
|
||||||
|
* The active recording lock will be released when the recording ends (handleEgressEnded) or when the room is finished (handleMeetingFinished).
|
||||||
|
*
|
||||||
|
* @param roomName - The name of the room to acquire the lock for.
|
||||||
*/
|
*/
|
||||||
async acquireRoomRecordingActiveLock(roomName: string): Promise<RedisLock | null> {
|
async acquireRoomRecordingActiveLock(roomName: string): Promise<RedisLock | null> {
|
||||||
const lockName = `${roomName}_${RedisLockName.RECORDING_ACTIVE}`;
|
const lockName = `${roomName}_${RedisLockName.RECORDING_ACTIVE}`;
|
||||||
|
const LOCK_TTL = ms('6h');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const lock = await this.mutexService.acquire(lockName, this.RECORDING_ACTIVE_LOCK_TTL);
|
const lock = await this.mutexService.acquire(lockName, LOCK_TTL);
|
||||||
return lock;
|
return lock;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.warn(`Error acquiring lock ${lockName} on egress started: ${error}`);
|
this.logger.warn(`Error acquiring lock ${lockName} on egress started: ${error}`);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user