EvalueTonSavoir/test/stressTest/main.js

188 lines
6.3 KiB
JavaScript
Raw Normal View History

2024-11-27 18:36:59 -05:00
import { attemptLoginOrRegister, createRoomContainer } from './utility/apiServices.js';
2024-11-15 17:46:01 -05:00
import { Student } from './class/student.js';
import { Teacher } from './class/teacher.js';
2024-11-27 18:36:59 -05:00
import { Watcher } from './class/watcher.js';
2024-11-15 17:46:01 -05:00
const BASE_URL = 'http://localhost';
2024-11-15 19:35:41 -05:00
const user = { username: 'admin@example.com', password: 'adminPassword' };
2024-11-26 17:04:22 -05:00
const numberRooms = 20;
2024-11-27 18:36:59 -05:00
const usersPerRoom = 60;
2024-11-15 17:46:01 -05:00
const roomAssociations = {};
2024-11-27 18:36:59 -05:00
const maxMessages = 20; // Number of conversation rounds
const conversationInterval = 1000; // Interval between teacher messages (ms)
const batchSize = 10; // Number of simultaneous connections
const batchDelay = 500;
/**
* Creates rooms with controlled concurrency.
*/
async function createRoomContainers() {
console.log('Attempting login or register to get token');
const token = await attemptLoginOrRegister(BASE_URL, user.username, user.password);
if (!token) throw new Error('Failed to login or register.');
console.log('Room creation');
const roomPromises = Array.from({ length: numberRooms }, async (_, index) => {
2024-11-26 17:04:22 -05:00
try {
const room = await createRoomContainer(BASE_URL, token);
if (room?.id) {
2024-11-27 18:36:59 -05:00
roomAssociations[room.id] = { watcher: null, teacher: null, students: [] };
console.log(`Room ${index + 1} created with ID: ${room.id}`);
2024-11-26 17:04:22 -05:00
}
2024-11-27 18:36:59 -05:00
} catch (err) {
console.warn(`Failed to create room ${index + 1}:`, err.message);
2024-11-15 19:35:41 -05:00
}
});
2024-11-15 17:46:01 -05:00
2024-11-27 18:36:59 -05:00
// Use Promise.allSettled to ensure all promises complete
await Promise.allSettled(roomPromises);
2024-11-26 17:04:22 -05:00
console.log(`Total rooms created: ${Object.keys(roomAssociations).length}`);
2024-11-27 18:36:59 -05:00
console.log('Finished room creation');
2024-11-15 17:46:01 -05:00
}
2024-11-27 18:36:59 -05:00
/**
* Adds participants (teacher, watcher, students) to rooms.
*/
function addUsersToRoom() {
console.log('Adding room participants');
Object.keys(roomAssociations).forEach((roomId, roomIndex) => {
const participants = roomAssociations[roomId];
// Assign a teacher and watcher
console.log('adding users to room ' + roomId);
participants.teacher = new Teacher(`teacher_${roomIndex}`, roomId);
participants.watcher = new Watcher(`watcher_${roomIndex}`, roomId);
// Add students
for (let i = 0; i < usersPerRoom - 2; i++) {
participants.students.push(new Student(`student_${roomIndex}_${i}`, roomId));
2024-11-15 17:46:01 -05:00
}
});
2024-11-27 18:36:59 -05:00
console.log('Finished adding room participants');
}
2024-11-15 17:46:01 -05:00
2024-11-27 18:36:59 -05:00
/**
* Connects participants to their respective rooms.
*/
async function connectParticipants(baseUrl) {
console.log('Connecting participants in batches');
const batchSize = 10; // Connect 10 participants at a time
const batchDelay = 500; // Wait 500ms between batches
for (const [roomId, participants] of Object.entries(roomAssociations)) {
console.log(`Processing room ${roomId}`);
// Collect all participants for this room
const allParticipants = [
participants.teacher,
participants.watcher,
...participants.students
].filter(Boolean);
// Process participants in batches
for (let i = 0; i < allParticipants.length; i += batchSize) {
const batch = allParticipants.slice(i, i + batchSize);
const batchPromises = batch.map(participant =>
participant.connectToRoom(baseUrl)
.catch(err => {
console.warn(
`Failed to connect ${participant.username} in room ${roomId}:`,
err.message
);
return null;
})
);
await Promise.all(batchPromises);
await new Promise(resolve => setTimeout(resolve, batchDelay));
}
}
console.log('Finished connecting participants');
2024-11-15 17:46:01 -05:00
}
2024-11-27 18:36:59 -05:00
/**
* Simulates a conversation between the teacher and students in each room.
*/
async function simulateParticipants() {
const conversationPromises = Object.entries(roomAssociations).map(async ([roomId, participants]) => {
const { teacher, students } = participants;
2024-11-15 17:46:01 -05:00
2024-11-27 18:36:59 -05:00
if (!teacher || students.length === 0) {
console.warn(`Room ${roomId} has no teacher or students to simulate.`);
return;
}
2024-11-26 17:04:22 -05:00
2024-11-27 18:36:59 -05:00
console.log(`Starting simulation for room ${roomId}`);
2024-11-26 17:04:22 -05:00
2024-11-27 18:36:59 -05:00
// Wait for room creation and joins to complete
await new Promise(resolve => setTimeout(resolve, 2000));
for (let i = 0; i < maxMessages; i++) {
const teacherMessage = `Message ${i + 1} from ${teacher.username}`;
teacher.broadcastMessage(teacherMessage);
// Add delay between messages
await new Promise(resolve => setTimeout(resolve, conversationInterval));
2024-11-26 17:04:22 -05:00
}
2024-11-27 18:36:59 -05:00
console.log(`Finished simulation for room ${roomId}`);
});
await Promise.all(conversationPromises);
2024-11-15 17:46:01 -05:00
}
2024-11-27 18:36:59 -05:00
/**
* Disconnects all participants from rooms.
*/
function disconnectParticipants() {
console.time('Disconnecting participants');
Object.values(roomAssociations).forEach(participants => {
participants.teacher?.disconnect();
participants.watcher?.disconnect();
participants.students.forEach(student => student.disconnect());
2024-11-15 17:46:01 -05:00
});
2024-11-27 18:36:59 -05:00
console.timeEnd('Disconnecting participants');
console.log('All participants disconnected successfully.');
2024-11-15 17:46:01 -05:00
}
2024-11-27 18:36:59 -05:00
/**
* Main orchestration function.
*/
2024-11-15 17:46:01 -05:00
async function main() {
try {
2024-11-27 18:36:59 -05:00
await createRoomContainers();
addUsersToRoom();
await connectParticipants(BASE_URL);
await simulateParticipants();
console.log('All tasks completed successfully!');
2024-11-15 17:46:01 -05:00
} catch (error) {
2024-11-26 17:04:22 -05:00
console.error('Error:', error.message);
2024-11-15 17:46:01 -05:00
}
}
2024-11-27 18:36:59 -05:00
// Graceful shutdown handlers
2024-11-15 17:46:01 -05:00
process.on('SIGINT', () => {
2024-11-26 17:04:22 -05:00
console.log('Process interrupted (Ctrl+C).');
2024-11-27 18:36:59 -05:00
disconnectParticipants();
2024-11-15 19:35:41 -05:00
process.exit(0);
2024-11-15 17:46:01 -05:00
});
2024-11-27 18:36:59 -05:00
process.on('exit', disconnectParticipants);
process.on('uncaughtException', err => {
2024-11-26 17:04:22 -05:00
console.error('Uncaught Exception:', err);
2024-11-27 18:36:59 -05:00
disconnectParticipants();
2024-11-26 17:04:22 -05:00
process.exit(1);
});
2024-11-27 18:36:59 -05:00
2024-11-26 17:04:22 -05:00
process.on('unhandledRejection', (reason, promise) => {
2024-11-27 18:36:59 -05:00
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
disconnectParticipants();
2024-11-26 17:04:22 -05:00
process.exit(1);
});
2024-11-15 17:46:01 -05:00
2024-11-27 18:36:59 -05:00
// Execute the main function
2024-11-15 17:46:01 -05:00
main();