backend: enhance bulk room deletion logic to ensure proper handling of active meetings and update tests for consistency
This commit is contained in:
parent
3ef546488f
commit
fd7260863f
@ -193,7 +193,8 @@ export class RoomService {
|
||||
/**
|
||||
* Deletes multiple rooms in bulk, with the option to force delete or gracefully handle rooms with active participants.
|
||||
* For rooms with participants, when `forceDelete` is false, the method performs a "graceful deletion"
|
||||
* by marking the room as deleted without disrupting active sessions.
|
||||
* by marking the room for deletion without disrupting active sessions.
|
||||
* However, if `forceDelete` is true, it will also end the meetings by removing the rooms from LiveKit.
|
||||
*
|
||||
* @param roomIds - Array of room identifiers to be deleted
|
||||
* @param forceDelete - If true, deletes rooms even if they have active participants.
|
||||
@ -210,7 +211,6 @@ export class RoomService {
|
||||
const { toDelete, toMark } = await this.classifyRoomsForDeletion(roomIds, forceDelete);
|
||||
|
||||
// Process each group in parallel
|
||||
|
||||
const [deletedRooms, markedRooms] = await Promise.all([
|
||||
this.batchDeleteRooms(toDelete),
|
||||
this.batchMarkRoomsForDeletion(toMark)
|
||||
@ -368,8 +368,8 @@ export class RoomService {
|
||||
const classificationResults = await Promise.allSettled(
|
||||
roomIds.map(async (roomId) => {
|
||||
try {
|
||||
const hasParticipants = await this.livekitService.roomHasParticipants(roomId);
|
||||
const shouldDelete = forceDelete || !hasParticipants;
|
||||
const activeMeeting = await this.livekitService.roomExists(roomId);
|
||||
const shouldDelete = forceDelete || !activeMeeting;
|
||||
|
||||
return {
|
||||
roomId,
|
||||
@ -419,11 +419,37 @@ export class RoomService {
|
||||
this.logger.info(`Batch deleting ${roomIds.length} rooms`);
|
||||
|
||||
try {
|
||||
await Promise.all([
|
||||
this.storageService.deleteMeetRooms(roomIds),
|
||||
this.livekitService.batchDeleteRooms(roomIds)
|
||||
]);
|
||||
// Check which rooms have an active LiveKit room (active meeting)
|
||||
const activeRoomChecks = await Promise.all(
|
||||
roomIds.map(async (roomId) => ({
|
||||
roomId,
|
||||
activeMeeting: await this.livekitService.roomExists(roomId)
|
||||
}))
|
||||
);
|
||||
|
||||
const withActiveMeeting = activeRoomChecks.filter((r) => r.activeMeeting).map((r) => r.roomId);
|
||||
const withoutActiveMeeting = activeRoomChecks.filter((r) => !r.activeMeeting).map((r) => r.roomId);
|
||||
|
||||
// Mark all rooms with active meetings for deletion (in batch)
|
||||
// This must be done before deleting the LiveKit rooms to ensure
|
||||
// the rooms are marked when 'room_finished' webhook is sent
|
||||
if (withActiveMeeting.length > 0) {
|
||||
await this.batchMarkRoomsForDeletion(withActiveMeeting);
|
||||
}
|
||||
|
||||
// Delete all LiveKit rooms for rooms with active meetings (in batch)
|
||||
const livekitDeletePromise =
|
||||
withActiveMeeting.length > 0
|
||||
? this.livekitService.batchDeleteRooms(withActiveMeeting)
|
||||
: Promise.resolve();
|
||||
|
||||
// Delete Meet rooms that do not have an active meeting (in batch)
|
||||
const meetRoomsDeletePromise =
|
||||
withoutActiveMeeting.length > 0
|
||||
? this.storageService.deleteMeetRooms(withoutActiveMeeting)
|
||||
: Promise.resolve();
|
||||
|
||||
await Promise.all([livekitDeletePromise, meetRoomsDeletePromise]);
|
||||
return roomIds;
|
||||
} catch (error) {
|
||||
this.logger.error(`Batch deletion failed for rooms: ${roomIds.join(', ')}`, error);
|
||||
|
||||
@ -6,6 +6,7 @@ import {
|
||||
disconnectFakeParticipants,
|
||||
getRoom,
|
||||
joinFakeParticipant,
|
||||
sleep,
|
||||
startTestServer
|
||||
} from '../../../helpers/request-helpers.js';
|
||||
|
||||
@ -157,25 +158,26 @@ describe('Room API Tests', () => {
|
||||
});
|
||||
|
||||
it('should delete rooms when force=true and participants exist', async () => {
|
||||
// Create a test room
|
||||
// Create test rooms
|
||||
const [room1, room2] = await Promise.all([
|
||||
createRoom({ roomIdPrefix: 'test-bulk-1' }),
|
||||
createRoom({ roomIdPrefix: 'test-bulk-2' })
|
||||
]);
|
||||
|
||||
// Join a participant to the room
|
||||
// Join a participant to the rooms
|
||||
await Promise.all([
|
||||
joinFakeParticipant(room1.roomId, 'test-participant-1'),
|
||||
joinFakeParticipant(room2.roomId, 'test-participant-2')
|
||||
]);
|
||||
|
||||
// Attempt to delete the room with force=false
|
||||
// Attempt to delete the rooms with force=false
|
||||
const response = await bulkDeleteRooms([room1.roomId, room2.roomId], true);
|
||||
|
||||
expect(response.status).toBe(204);
|
||||
expect(response.body).toStrictEqual({});
|
||||
|
||||
// Verify that the room is deleted
|
||||
// Verify that the rooms are deleted
|
||||
await sleep('1s'); // Wait a bit for the meetings to be closed and the rooms deleted
|
||||
const deletedRoom1 = await getRoom(room1.roomId);
|
||||
const deletedRoom2 = await getRoom(room2.roomId);
|
||||
expect(deletedRoom1.status).toBe(404);
|
||||
|
||||
@ -176,6 +176,7 @@ describe('Room API Tests', () => {
|
||||
expect(response.status).toBe(204);
|
||||
|
||||
// Try to retrieve the room again
|
||||
await sleep('1s'); // Wait a bit for the meeting to be closed and the room deleted
|
||||
const responseAfterDelete = await getRoom(roomId);
|
||||
expect(responseAfterDelete.status).toBe(404);
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user