mirror of
https://git.hmsn.ink/kospo/helptalk/user.git
synced 2026-03-19 19:05:19 +09:00
203 lines
6.0 KiB
JavaScript
203 lines
6.0 KiB
JavaScript
// eslint-disable-next-line no-undef
|
|
importScripts(`/js/stomp.js`)
|
|
// eslint-disable-next-line no-undef
|
|
importScripts(`/js/sockjs.js`)
|
|
|
|
let sockJS;
|
|
let stompClient;
|
|
let reConnectAttempts = 0
|
|
let maxReconnectAttempts = 3
|
|
let messageList = []
|
|
let connectLock = false;
|
|
let lastHeartbeat = null;
|
|
/*재귀 함수 변수*/
|
|
let sendPing= null;
|
|
/*소켓 연결 변수*/
|
|
let subscribe = null;
|
|
// 클라이언트 에게 메시지 전달
|
|
async function hubToClients(message) {
|
|
const allClients = await clients.matchAll({
|
|
includeUncontrolled: true,
|
|
type: 'window',
|
|
});
|
|
|
|
allClients.forEach(client => {
|
|
client.postMessage(message);
|
|
});
|
|
}
|
|
|
|
// 브라우저 종료시 소켓 연결 해지
|
|
async function disConnectWebSocket(message) {
|
|
console.log('disConnect', message)
|
|
try {subscribe.unsubscribe()} catch (e) {}
|
|
try {stompClient.disconnect()} catch (e) {}
|
|
try {sockJS.close()} catch (e) {}
|
|
sockJS = null
|
|
stompClient = null
|
|
|
|
// 모든 클라이언트가 종료시 서비스워커 heartbeat 제거
|
|
const allClients = await clients.matchAll({
|
|
includeUncontrolled: true,
|
|
type: 'window',
|
|
});
|
|
|
|
if(allClients.length === 1) {
|
|
clearInterval(sendPing)
|
|
sendPing = null;
|
|
}
|
|
}
|
|
|
|
// 브라우저 종료시 소켓 연결 해지
|
|
async function kill() {
|
|
console.log('service worker stompClient', stompClient)
|
|
console.log('service worker sockJS', sockJS)
|
|
clearInterval(sendPing)
|
|
sendPing = null
|
|
try {subscribe.unsubscribe()} catch (e) {}
|
|
try {stompClient.disconnect()} catch (e) {}
|
|
try {sockJS.close()} catch (e) {}
|
|
stompClient = null;
|
|
sockJS = null;
|
|
}
|
|
|
|
// 웹소켓 연결 관리
|
|
function connectWebSocket(message) {
|
|
lastHeartbeat = Date.now();
|
|
console.log('sockJSConn',typeof (sockJS))
|
|
console.log('sockJSInfo',sockJS)
|
|
if (sockJS === null || sockJS === undefined) {
|
|
if(sockJS !== null && sockJS !== undefined) {
|
|
if(sockJS.readyState && sockJS.readyState === WebSocket.OPEN) {
|
|
try{subscribe.unsubscribe()} catch(e) {}
|
|
try{stompClient.disconnect();} catch(e) {}
|
|
try{sockJS.close();} catch(e) {}
|
|
stompClient = null;
|
|
sockJS = null;
|
|
}
|
|
}
|
|
|
|
sockJS = new WebSocket(`${message.url}/stomp/ws`);
|
|
if (sockJS !== WebSocket.CLOSED && sockJS !== WebSocket.CLOSING) {
|
|
stompClient = Stomp.over(sockJS);
|
|
stompClient.heartbeat.outgoing = 20000;
|
|
stompClient.heartbeat.incoming = 20000;
|
|
stompClient.debug = (e) => {
|
|
if (e.includes('ERROR') || e.includes('Exception') || e.includes('failed')) {
|
|
console.error('STOMP error:', e, new Date().toString());
|
|
}
|
|
};
|
|
|
|
stompClient.connect({location: 'SW'}, function (frame) {
|
|
console.log('message.sabun', message.sabun, stompClient)
|
|
subscribe = stompClient.subscribe(`/exchange/user.exchange/user.${message.sabun}`, async (content) => {
|
|
const payload = JSON.parse(content.body);
|
|
console.log('servicew-usersubcribe', payload)
|
|
|
|
})
|
|
console.log('hub connect()')
|
|
if (sendPing == null) {
|
|
sendPing = setInterval(() => {
|
|
hubToClients({type: "PING"})
|
|
}, 10000);
|
|
}
|
|
|
|
reConnectAttempts = 0;
|
|
})
|
|
}
|
|
|
|
const baseDelay = 500
|
|
sockJS.onclose = (e) => {
|
|
console.error('sockjs onclose', e);
|
|
if (e.code !== 1000) {
|
|
const delay = Math.min(baseDelay * Math.pow(2, reConnectAttempts), 5000)
|
|
setTimeout(() => {
|
|
hubReconnect()
|
|
if (reConnectAttempts < maxReconnectAttempts) {
|
|
reConnectAttempts++;
|
|
} else {
|
|
console.log('[Service Worker Hub] Max Reconnect attempts reached.')
|
|
}
|
|
}, delay)
|
|
}
|
|
|
|
}
|
|
} else {
|
|
console.log('socket is connected')
|
|
}
|
|
}
|
|
|
|
const hubReconnect = () => {
|
|
try {subscribe.unsubscribe()} catch (e) {}
|
|
try {stompClient.disconnect()} catch (e) {}
|
|
try {sockJS.close()} catch (e) {}
|
|
stompClient = null
|
|
sockJS = null
|
|
clearInterval(sendPing)
|
|
sendPing = null;
|
|
hubToClients({type:'RECONNECT'});
|
|
lastHeartbeat = Date.now();
|
|
}
|
|
|
|
// 서비스워커 설치
|
|
self.addEventListener('install', (event) => {
|
|
console.log('SW: Installing...');
|
|
event.waitUntil(
|
|
self.skipWaiting()
|
|
);
|
|
});
|
|
|
|
// 서비스워커 활성화
|
|
this.addEventListener('activate', function activator(event) {
|
|
console.log('activate!');
|
|
event.waitUntil(
|
|
self.clients.claim()
|
|
);
|
|
})
|
|
|
|
// 클라이언트로부터의 메시지 처리
|
|
self.addEventListener('message', async (event) => {
|
|
const message = event.data;
|
|
switch (message.type) {
|
|
case 'CONNECT':
|
|
connectWebSocket(message);
|
|
break;
|
|
case 'CLOSE':
|
|
disConnectWebSocket(message);
|
|
break;
|
|
case "KILL" :
|
|
kill();
|
|
break;
|
|
case 'PONG' :
|
|
if(typeof (stompClient) === "undefined") {
|
|
hubReconnect()
|
|
}
|
|
break;
|
|
case "WAKEUP" :
|
|
if(typeof (stompClient) === "undefined") {
|
|
if(!connectLock) {
|
|
connectLock = true;
|
|
hubReconnect()
|
|
}
|
|
} else {
|
|
if(!connectLock) {
|
|
hubToClients({type:"GETUP"})
|
|
}
|
|
}
|
|
break;
|
|
case 'RECONNECT_SUCCESS' :
|
|
let suc = true;
|
|
while (suc) {
|
|
if (stompClient.connected) {
|
|
connectLock = false;
|
|
suc = false;
|
|
}
|
|
await sleep(100)
|
|
}
|
|
break;
|
|
}
|
|
});
|
|
|
|
const sleep = (delay) => {
|
|
return new Promise(resolve => setTimeout(resolve, delay));
|
|
}
|