Improved websocket to ensure the reconnection
This commit is contained in:
parent
8512b90d36
commit
225dd27c2c
@ -1,36 +1,53 @@
|
|||||||
import { AnkFlag } from 'pkg/sdk_client';
|
import { AnkFlag } from '../../pkg/sdk_client'; // Vérifie le chemin vers pkg
|
||||||
import Services from './service';
|
import Services from './service';
|
||||||
|
|
||||||
let ws: WebSocket;
|
let ws: WebSocket | null = null;
|
||||||
let messageQueue: string[] = [];
|
let messageQueue: string[] = [];
|
||||||
|
let reconnectInterval = 1000; // Délai initial de 1s avant reconnexion
|
||||||
|
const MAX_RECONNECT_INTERVAL = 30000; // Max 30s
|
||||||
|
let isConnecting = false;
|
||||||
|
let urlReference: string = '';
|
||||||
|
let pingIntervalId: any = null;
|
||||||
|
|
||||||
export async function initWebsocket(url: string) {
|
export async function initWebsocket(url: string) {
|
||||||
ws = new WebSocket(url);
|
urlReference = url;
|
||||||
|
connect();
|
||||||
|
}
|
||||||
|
|
||||||
if (ws !== null) {
|
function connect() {
|
||||||
ws.onopen = async (event) => {
|
if (isConnecting || (ws && ws.readyState === WebSocket.OPEN)) return;
|
||||||
console.log('WebSocket connection established');
|
isConnecting = true;
|
||||||
|
|
||||||
|
console.log(`[WS] 🔌 Tentative de connexion à ${urlReference}...`);
|
||||||
|
ws = new WebSocket(urlReference);
|
||||||
|
|
||||||
|
ws.onopen = async () => {
|
||||||
|
console.log('[WS] ✅ Connexion établie !');
|
||||||
|
isConnecting = false;
|
||||||
|
reconnectInterval = 1000; // Reset du délai
|
||||||
|
|
||||||
|
// Démarrer le Heartbeat (Ping pour garder la connexion vivante)
|
||||||
|
startHeartbeat();
|
||||||
|
|
||||||
|
// Vider la file d'attente (messages envoyés pendant la coupure)
|
||||||
while (messageQueue.length > 0) {
|
while (messageQueue.length > 0) {
|
||||||
const message = messageQueue.shift();
|
const message = messageQueue.shift();
|
||||||
if (message) {
|
if (message) ws?.send(message);
|
||||||
ws.send(message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Listen for messages
|
|
||||||
ws.onmessage = (event) => {
|
ws.onmessage = (event) => {
|
||||||
const msgData = event.data;
|
const msgData = event.data;
|
||||||
|
|
||||||
// console.log("Received text message: ", msgData);
|
|
||||||
(async () => {
|
|
||||||
if (typeof msgData === 'string') {
|
if (typeof msgData === 'string') {
|
||||||
|
(async () => {
|
||||||
try {
|
try {
|
||||||
const parsedMessage = JSON.parse(msgData);
|
const parsedMessage = JSON.parse(msgData);
|
||||||
const services = await Services.getInstance();
|
const services = await Services.getInstance();
|
||||||
|
|
||||||
|
// Gestion des messages
|
||||||
switch (parsedMessage.flag) {
|
switch (parsedMessage.flag) {
|
||||||
case 'Handshake':
|
case 'Handshake':
|
||||||
await services.handleHandshakeMsg(url, parsedMessage.content);
|
await services.handleHandshakeMsg(urlReference, parsedMessage.content);
|
||||||
break;
|
break;
|
||||||
case 'NewTx':
|
case 'NewTx':
|
||||||
await services.parseNewTx(parsedMessage.content);
|
await services.parseNewTx(parsedMessage.content);
|
||||||
@ -39,51 +56,80 @@ export async function initWebsocket(url: string) {
|
|||||||
await services.parseCipher(parsedMessage.content);
|
await services.parseCipher(parsedMessage.content);
|
||||||
break;
|
break;
|
||||||
case 'Commit':
|
case 'Commit':
|
||||||
// Basically if we see this it means we have an error
|
|
||||||
await services.handleCommitError(parsedMessage.content);
|
await services.handleCommitError(parsedMessage.content);
|
||||||
break;
|
break;
|
||||||
|
// Ajoute d'autres cas si nécessaire
|
||||||
|
default:
|
||||||
|
// console.log('[WS] Message reçu:', parsedMessage.flag);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Received an invalid message:', error);
|
console.error('[WS] Erreur traitement message:', error);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.error('Received a non-string message');
|
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
};
|
|
||||||
|
|
||||||
// Listen for possible errors
|
|
||||||
ws.onerror = (event) => {
|
|
||||||
console.error('WebSocket error:', event);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Listen for when the connection is closed
|
|
||||||
ws.onclose = (event) => {
|
|
||||||
console.log('WebSocket is closed now.');
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ws.onerror = (event) => {
|
||||||
|
console.error('[WS] 💥 Erreur:', event);
|
||||||
|
// Pas besoin de reconnecter ici, onclose sera appelé juste après
|
||||||
|
};
|
||||||
|
|
||||||
|
ws.onclose = (event) => {
|
||||||
|
isConnecting = false;
|
||||||
|
stopHeartbeat();
|
||||||
|
console.warn(`[WS] ⚠️ Déconnecté (Code: ${event.code}). Reconnexion dans ${reconnectInterval / 1000}s...`);
|
||||||
|
|
||||||
|
// Reconnexion exponentielle (1s, 1.5s, 2.25s...)
|
||||||
|
setTimeout(() => {
|
||||||
|
connect();
|
||||||
|
reconnectInterval = Math.min(reconnectInterval * 1.5, MAX_RECONNECT_INTERVAL);
|
||||||
|
}, reconnectInterval);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function startHeartbeat() {
|
||||||
|
stopHeartbeat();
|
||||||
|
// Envoie un ping toutes les 30 secondes pour éviter que le serveur ou le navigateur ne coupe la connexion
|
||||||
|
pingIntervalId = setInterval(() => {
|
||||||
|
if (ws && ws.readyState === WebSocket.OPEN) {
|
||||||
|
// Adapter selon ce que ton serveur attend comme Ping, ou envoyer un message vide
|
||||||
|
// ws.send(JSON.stringify({ flag: 'Ping', content: '' }));
|
||||||
|
}
|
||||||
|
}, 30000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopHeartbeat() {
|
||||||
|
if (pingIntervalId) clearInterval(pingIntervalId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method to send messages
|
|
||||||
export function sendMessage(flag: AnkFlag, message: string): void {
|
export function sendMessage(flag: AnkFlag, message: string): void {
|
||||||
if (ws.readyState === WebSocket.OPEN) {
|
if (ws && ws.readyState === WebSocket.OPEN) {
|
||||||
const networkMessage = {
|
const networkMessage = {
|
||||||
flag: flag,
|
flag: flag,
|
||||||
content: message,
|
content: message,
|
||||||
};
|
};
|
||||||
console.log('Sending message of type:', flag);
|
|
||||||
ws.send(JSON.stringify(networkMessage));
|
ws.send(JSON.stringify(networkMessage));
|
||||||
} else {
|
} else {
|
||||||
console.error('WebSocket is not open. ReadyState:', ws.readyState);
|
console.warn(`[WS] Pas connecté. Message '${flag}' mis en file d'attente.`);
|
||||||
messageQueue.push(message);
|
const networkMessage = {
|
||||||
|
flag: flag,
|
||||||
|
content: message,
|
||||||
|
};
|
||||||
|
messageQueue.push(JSON.stringify(networkMessage));
|
||||||
|
|
||||||
|
// Si on n'est pas déjà en train de se connecter, on force une tentative
|
||||||
|
if (!isConnecting) connect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUrl(): string {
|
export function getUrl(): string {
|
||||||
return ws.url;
|
return urlReference;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method to close the WebSocket connection
|
|
||||||
export function close(): void {
|
export function close(): void {
|
||||||
|
if (ws) {
|
||||||
|
ws.onclose = null; // On évite la reconnexion auto si fermeture volontaire
|
||||||
|
stopHeartbeat();
|
||||||
ws.close();
|
ws.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user