mirror of
https://github.com/ets-cfuhrman-pfe/EvalueTonSavoir.git
synced 2025-08-11 21:23:54 -04:00
working
This commit is contained in:
parent
71353669ca
commit
ec15909d55
5 changed files with 104 additions and 70 deletions
|
|
@ -9,60 +9,71 @@ export class RoomParticipant {
|
||||||
this.retryDelay = 1000;
|
this.retryDelay = 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
async connectToRoom(baseUrl, onConnectCallback) {
|
async connectToRoom(baseUrl) {
|
||||||
let retries = 0;
|
let retries = 0;
|
||||||
|
const maxRetries = 2;
|
||||||
|
const retryDelay = 2000;
|
||||||
|
|
||||||
const connect = () => {
|
const cleanup = () => {
|
||||||
return new Promise((resolve, reject) => {
|
if (this.socket) {
|
||||||
try {
|
this.socket.removeAllListeners();
|
||||||
const socket = io(baseUrl, {
|
this.socket.disconnect();
|
||||||
path: `/api/room/${this.roomName}/socket`,
|
this.socket = null;
|
||||||
transports: ['websocket'],
|
}
|
||||||
timeout: 5000,
|
};
|
||||||
reconnection: true,
|
|
||||||
reconnectionAttempts: 3,
|
|
||||||
reconnectionDelay: 1000,
|
|
||||||
});
|
|
||||||
|
|
||||||
const connectionTimeout = setTimeout(() => {
|
while (retries < maxRetries) {
|
||||||
socket.close();
|
try {
|
||||||
|
const socket = io(baseUrl, {
|
||||||
|
path: `/api/room/${this.roomName}/socket`,
|
||||||
|
transports: ['websocket'],
|
||||||
|
timeout: 8000,
|
||||||
|
reconnection: false,
|
||||||
|
forceNew: true
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await new Promise((resolve, reject) => {
|
||||||
|
const timeout = setTimeout(() => {
|
||||||
|
cleanup();
|
||||||
reject(new Error('Connection timeout'));
|
reject(new Error('Connection timeout'));
|
||||||
}, 5000);
|
}, 8000);
|
||||||
|
|
||||||
socket.on('connect', () => {
|
socket.on('connect', () => {
|
||||||
clearTimeout(connectionTimeout);
|
clearTimeout(timeout);
|
||||||
this.socket = socket;
|
this.socket = socket;
|
||||||
if (onConnectCallback) {
|
this.onConnected(); // Add this line
|
||||||
onConnectCallback();
|
|
||||||
}
|
|
||||||
resolve(socket);
|
resolve(socket);
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('connect_error', (error) => {
|
socket.on('connect_error', (error) => {
|
||||||
clearTimeout(connectionTimeout);
|
clearTimeout(timeout);
|
||||||
|
cleanup();
|
||||||
reject(new Error(`Connection error: ${error.message}`));
|
reject(new Error(`Connection error: ${error.message}`));
|
||||||
});
|
});
|
||||||
|
|
||||||
} catch (error) {
|
socket.on('error', (error) => {
|
||||||
reject(error);
|
clearTimeout(timeout);
|
||||||
}
|
cleanup();
|
||||||
});
|
reject(new Error(`Socket error: ${error.message}`));
|
||||||
};
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
while (retries < this.maxRetries) {
|
|
||||||
try {
|
|
||||||
return await connect();
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
retries++;
|
retries++;
|
||||||
if (retries === this.maxRetries) {
|
if (retries === maxRetries) {
|
||||||
throw new Error(`Failed to connect ${this.username} after ${this.maxRetries} attempts: ${error.message}`);
|
throw error;
|
||||||
}
|
}
|
||||||
console.warn(`Retry ${retries}/${this.maxRetries} for ${this.username}`);
|
await new Promise(resolve => setTimeout(resolve, retryDelay));
|
||||||
await new Promise(resolve => setTimeout(resolve, this.retryDelay));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onConnected() {
|
||||||
|
// To be implemented by child classes
|
||||||
|
}
|
||||||
|
|
||||||
disconnect() {
|
disconnect() {
|
||||||
if (this.socket) {
|
if (this.socket) {
|
||||||
this.socket.disconnect();
|
this.socket.disconnect();
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,20 @@
|
||||||
import { RoomParticipant } from './roomParticipant.js';
|
import { RoomParticipant } from './roomParticipant.js';
|
||||||
|
|
||||||
export class Student extends RoomParticipant {
|
export class Student extends RoomParticipant {
|
||||||
|
|
||||||
|
nbrMessageReceived = 0;
|
||||||
|
|
||||||
constructor(username, roomName) {
|
constructor(username, roomName) {
|
||||||
super(username, roomName);
|
super(username, roomName);
|
||||||
}
|
}
|
||||||
|
|
||||||
connectToRoom(baseUrl) {
|
connectToRoom(baseUrl) {
|
||||||
return super.connectToRoom(baseUrl, () => {
|
return super.connectToRoom(baseUrl);
|
||||||
this.joinRoom();
|
}
|
||||||
this.listenForTeacherMessage();
|
|
||||||
});
|
onConnected() {
|
||||||
|
this.joinRoom();
|
||||||
|
this.listenForTeacherMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
joinRoom() {
|
joinRoom() {
|
||||||
|
|
@ -25,6 +30,7 @@ export class Student extends RoomParticipant {
|
||||||
listenForTeacherMessage() {
|
listenForTeacherMessage() {
|
||||||
if (this.socket) {
|
if (this.socket) {
|
||||||
this.socket.on('message-sent-teacher', ({ message }) => {
|
this.socket.on('message-sent-teacher', ({ message }) => {
|
||||||
|
this.nbrMessageReceived++;
|
||||||
this.respondToTeacher(message);
|
this.respondToTeacher(message);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,21 @@
|
||||||
import { RoomParticipant } from './roomParticipant.js';
|
import { RoomParticipant } from './roomParticipant.js';
|
||||||
|
|
||||||
export class Teacher extends RoomParticipant {
|
export class Teacher extends RoomParticipant {
|
||||||
|
|
||||||
|
nbrMessageReceived = 0;
|
||||||
|
|
||||||
constructor(username, roomName) {
|
constructor(username, roomName) {
|
||||||
super(username, roomName);
|
super(username, roomName);
|
||||||
this.ready = false;
|
this.ready = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
connectToRoom(baseUrl) {
|
connectToRoom(baseUrl) {
|
||||||
return super.connectToRoom(baseUrl, () => {
|
return super.connectToRoom(baseUrl);
|
||||||
this.createRoom();
|
}
|
||||||
this.listenForStudentMessage();
|
|
||||||
|
onConnected() {
|
||||||
// Add room creation confirmation listener
|
this.createRoom();
|
||||||
this.socket.on('create-success', () => {
|
this.listenForStudentMessage();
|
||||||
console.log(`Room ${this.roomName} created by teacher ${this.username}`);
|
|
||||||
this.ready = true;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
createRoom() {
|
createRoom() {
|
||||||
|
|
@ -26,7 +25,7 @@ export class Teacher extends RoomParticipant {
|
||||||
}
|
}
|
||||||
|
|
||||||
broadcastMessage(message) {
|
broadcastMessage(message) {
|
||||||
if (this.socket && this.ready) {
|
if (this.socket) {
|
||||||
this.socket.emit('message-from-teacher', {
|
this.socket.emit('message-from-teacher', {
|
||||||
roomName: this.roomName,
|
roomName: this.roomName,
|
||||||
message
|
message
|
||||||
|
|
@ -40,6 +39,7 @@ export class Teacher extends RoomParticipant {
|
||||||
if (this.socket) {
|
if (this.socket) {
|
||||||
this.socket.on('message-sent-student', ({ message }) => {
|
this.socket.on('message-sent-student', ({ message }) => {
|
||||||
//console.log(`Teacher ${this.username} received: "${message}"`);
|
//console.log(`Teacher ${this.username} received: "${message}"`);
|
||||||
|
this.nbrMessageReceived++;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,11 @@ export class Watcher extends RoomParticipant {
|
||||||
super(username, roomName);
|
super(username, roomName);
|
||||||
}
|
}
|
||||||
|
|
||||||
async connectToRoom(baseUrl) {
|
connectToRoom(baseUrl) {
|
||||||
await super.connectToRoom(baseUrl);
|
return super.connectToRoom(baseUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
onConnected() {
|
||||||
this.startCheckingResources();
|
this.startCheckingResources();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -29,7 +32,7 @@ export class Watcher extends RoomParticipant {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
startCheckingResources(intervalMs = 500) {
|
startCheckingResources(intervalMs = 250) {
|
||||||
if (this.checkRessourceInterval) {
|
if (this.checkRessourceInterval) {
|
||||||
console.warn(`Resource checking is already running for room ${this.roomName}.`);
|
console.warn(`Resource checking is already running for room ${this.roomName}.`);
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -7,18 +7,19 @@ import dotenv from 'dotenv';
|
||||||
// Load environment variables
|
// Load environment variables
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
|
||||||
const BASE_URL = process.env.BASE_URL || 'http://localhost';
|
const BASE_URL = process.env.BASE_URL || 'http://msevignyl.duckdns.org';
|
||||||
const user = {
|
const user = {
|
||||||
username: process.env.USER_EMAIL || 'admin@admin.com',
|
username: process.env.USER_EMAIL || 'admin@admin.com',
|
||||||
password: process.env.USER_PASSWORD || 'admin'
|
password: process.env.USER_PASSWORD || 'admin'
|
||||||
};
|
};
|
||||||
const numberRooms = parseInt(process.env.NUMBER_ROOMS || '5');
|
const numberRooms = parseInt(process.env.NUMBER_ROOMS || '50');
|
||||||
const usersPerRoom = parseInt(process.env.USERS_PER_ROOM || '60');
|
const usersPerRoom = parseInt(process.env.USERS_PER_ROOM || '60');
|
||||||
const roomAssociations = {};
|
const roomAssociations = {};
|
||||||
const maxMessages = parseInt(process.env.MAX_MESSAGES || '20');
|
const maxMessages = parseInt(process.env.MAX_MESSAGES || '20');
|
||||||
const conversationInterval = parseInt(process.env.CONVERSATION_INTERVAL || '1000');
|
const conversationInterval = parseInt(process.env.CONVERSATION_INTERVAL || '1000');
|
||||||
const batchSize = 10; // Number of simultaneous connections
|
const batchSize = 5;
|
||||||
const batchDelay = 500;
|
const batchDelay = 500;
|
||||||
|
const roomDelay = 1000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a room and immediately connects a teacher to it.
|
* Creates a room and immediately connects a teacher to it.
|
||||||
|
|
@ -30,8 +31,6 @@ async function createRoomWithTeacher(token, index) {
|
||||||
throw new Error('Room creation failed');
|
throw new Error('Room creation failed');
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Room ${index + 1} created with ID: ${room.id}`);
|
|
||||||
|
|
||||||
// Initialize room associations
|
// Initialize room associations
|
||||||
roomAssociations[room.id] = { watcher: null, teacher: null, students: [] };
|
roomAssociations[room.id] = { watcher: null, teacher: null, students: [] };
|
||||||
|
|
||||||
|
|
@ -41,7 +40,6 @@ async function createRoomWithTeacher(token, index) {
|
||||||
|
|
||||||
// Connect teacher to room
|
// Connect teacher to room
|
||||||
await teacher.connectToRoom(BASE_URL);
|
await teacher.connectToRoom(BASE_URL);
|
||||||
console.log(`Teacher connected to room ${room.id}`);
|
|
||||||
|
|
||||||
return room.id;
|
return room.id;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
@ -79,7 +77,6 @@ function addRemainingUsers() {
|
||||||
const participants = roomAssociations[roomId];
|
const participants = roomAssociations[roomId];
|
||||||
|
|
||||||
// Add watcher
|
// Add watcher
|
||||||
console.log('Adding users to room ' + roomId);
|
|
||||||
participants.watcher = new Watcher(`watcher_${roomIndex}`, roomId);
|
participants.watcher = new Watcher(`watcher_${roomIndex}`, roomId);
|
||||||
|
|
||||||
// Add students
|
// Add students
|
||||||
|
|
@ -95,32 +92,49 @@ function addRemainingUsers() {
|
||||||
*/
|
*/
|
||||||
async function connectRemainingParticipants(baseUrl) {
|
async function connectRemainingParticipants(baseUrl) {
|
||||||
console.log('Connecting remaining participants in batches');
|
console.log('Connecting remaining participants in batches');
|
||||||
|
|
||||||
for (const [roomId, participants] of Object.entries(roomAssociations)) {
|
for (const [roomId, participants] of Object.entries(roomAssociations)) {
|
||||||
console.log(`Processing room ${roomId}`);
|
console.log(`Processing room ${roomId}`);
|
||||||
|
|
||||||
// Collect remaining participants for this room
|
|
||||||
const remainingParticipants = [
|
const remainingParticipants = [
|
||||||
participants.watcher,
|
participants.watcher,
|
||||||
...participants.students
|
...participants.students
|
||||||
].filter(Boolean);
|
].filter(Boolean);
|
||||||
|
|
||||||
// Process participants in batches
|
// Connect in smaller batches with longer delays
|
||||||
for (let i = 0; i < remainingParticipants.length; i += batchSize) {
|
for (let i = 0; i < remainingParticipants.length; i += batchSize) {
|
||||||
const batch = remainingParticipants.slice(i, i + batchSize);
|
const batch = remainingParticipants.slice(i, i + batchSize);
|
||||||
|
|
||||||
|
// Add connection timeout handling
|
||||||
const batchPromises = batch.map(participant =>
|
const batchPromises = batch.map(participant =>
|
||||||
participant.connectToRoom(baseUrl)
|
Promise.race([
|
||||||
.catch(err => {
|
participant.connectToRoom(baseUrl),
|
||||||
console.warn(
|
new Promise((_, reject) =>
|
||||||
`Failed to connect ${participant.username} in room ${roomId}:`,
|
setTimeout(() => reject(new Error('Connection timeout')), 10000)
|
||||||
err.message
|
)
|
||||||
);
|
]).catch(err => {
|
||||||
return null;
|
console.warn(
|
||||||
})
|
`Failed to connect ${participant.username} in room ${roomId}:`,
|
||||||
|
err.message
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
await Promise.all(batchPromises);
|
await Promise.all(batchPromises);
|
||||||
|
|
||||||
|
// Cleanup disconnected sockets
|
||||||
|
batch.forEach(participant => {
|
||||||
|
if (!participant.socket?.connected) {
|
||||||
|
participant.disconnect();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
await new Promise(resolve => setTimeout(resolve, batchDelay));
|
await new Promise(resolve => setTimeout(resolve, batchDelay));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add delay between rooms
|
||||||
|
await new Promise(resolve => setTimeout(resolve, roomDelay));
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Finished connecting remaining participants');
|
console.log('Finished connecting remaining participants');
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue