feat: implement ws
This commit is contained in:
parent
a83088387b
commit
b78b3f005b
@ -45,6 +45,9 @@ siren-api.key=siren-ap
|
||||
quarkus.rest-client."fr.titionfire.ffsaf.rest.client.SirenService".url=https://data.siren-api.fr/
|
||||
quarkus.rest-client."fr.titionfire.ffsaf.rest.client.StateIdService".url=https://www.data-asso.fr/api/
|
||||
|
||||
quarkus.websockets-next.server.auto-ping-interval=PT10s
|
||||
quarkus.websockets-next.client.connection-idle-timeout=PT30s
|
||||
|
||||
#Login
|
||||
quarkus.oidc.token-state-manager.split-tokens=true
|
||||
quarkus.oidc.token.refresh-expired=true
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import {createContext, useContext, useEffect, useReducer, useRef, useState} from "react";
|
||||
import {createContext, useContext, useEffect, useId, useReducer, useRef, useState} from "react";
|
||||
|
||||
function uuidv4() {
|
||||
return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, c =>
|
||||
@ -36,8 +36,10 @@ function reducer(state, action) {
|
||||
}
|
||||
}
|
||||
|
||||
const mountCounter = {};
|
||||
|
||||
export function WSProvider({url, onmessage, children}) {
|
||||
const id = useId();
|
||||
const [isReady, setIsReady] = useState(false)
|
||||
const [state, dispatch] = useReducer(reducer, {listener: []})
|
||||
const ws = useRef(null)
|
||||
@ -49,57 +51,104 @@ export function WSProvider({url, onmessage, children}) {
|
||||
}, [state.listener])
|
||||
|
||||
useEffect(() => {
|
||||
console.log("WSProvider: connecting to", url);
|
||||
const socket = new WebSocket(url)
|
||||
if (!mountCounter[id])
|
||||
mountCounter[id] = 0
|
||||
mountCounter[id] += 1
|
||||
console.log(`WSProvider ${id} mounted ${mountCounter[id]} time(s)`);
|
||||
|
||||
socket.onopen = () => setIsReady(true)
|
||||
socket.onclose = () => setIsReady(false)
|
||||
socket.onmessage = (event) => {
|
||||
const msg = JSON.parse(event.data)
|
||||
if (mountCounter[id] === 1 && (ws.current === null || ws.current.readyState >= WebSocket.CLOSING)){
|
||||
console.log("WSProvider: connecting to", url);
|
||||
const socket = new WebSocket(url)
|
||||
|
||||
if (msg.type === "REPLY" || msg.type === "ERROR") {
|
||||
const cb = callbackRef.current[msg.uuid];
|
||||
if (cb) {
|
||||
if (msg.type === "REPLY")
|
||||
cb.onReply(msg.data);
|
||||
else
|
||||
cb.onError(msg.data);
|
||||
delete callbackRef.current[msg.uuid]
|
||||
socket.onopen = () => setIsReady(true)
|
||||
socket.onclose = () => {
|
||||
setIsReady(false)
|
||||
if (mountCounter[id] > 0) {
|
||||
console.log("WSProvider: reconnecting to", url);
|
||||
setTimeout(() => {
|
||||
try {
|
||||
const newSocket = new WebSocket(url)
|
||||
ws.current = newSocket
|
||||
newSocket.onopen = socket.onopen
|
||||
newSocket.onclose = socket.onclose
|
||||
newSocket.onmessage = socket.onmessage
|
||||
}catch (e) {
|
||||
|
||||
}
|
||||
}, 5000)
|
||||
}
|
||||
return;
|
||||
}
|
||||
socket.onmessage = (event) => {
|
||||
const msg = JSON.parse(event.data)
|
||||
|
||||
if (msg.type === "REPLY" || msg.type === "ERROR") {
|
||||
const cb = callbackRef.current[msg.uuid];
|
||||
if (cb) {
|
||||
if (msg.type === "REPLY")
|
||||
cb.onReply(msg.data);
|
||||
else
|
||||
cb.onError(msg.data);
|
||||
delete callbackRef.current[msg.uuid]
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let isHandled = false;
|
||||
|
||||
listenersRef.current
|
||||
.filter(l => l.code === msg.code)
|
||||
.forEach(l => {
|
||||
try {
|
||||
l.callback({...msg})
|
||||
isHandled = true;
|
||||
} catch (err) {
|
||||
console.error("Listener callback error:", err)
|
||||
}
|
||||
});
|
||||
if (!isHandled && onmessage)
|
||||
onmessage(JSON.parse(event.data))
|
||||
}
|
||||
|
||||
let isHandled = false;
|
||||
|
||||
listenersRef.current
|
||||
.filter(l => l.code === msg.code)
|
||||
.forEach(l => {
|
||||
try {
|
||||
l.callback({...msg})
|
||||
isHandled = true;
|
||||
} catch (err) {
|
||||
console.error("Listener callback error:", err)
|
||||
}
|
||||
});
|
||||
if (!isHandled && onmessage)
|
||||
onmessage(JSON.parse(event.data))
|
||||
ws.current = socket
|
||||
}
|
||||
|
||||
ws.current = socket
|
||||
return () => {
|
||||
socket.close()
|
||||
mountCounter[id] -= 1
|
||||
console.log(`WSProvider ${id} unmounted, ${mountCounter[id]} instance(s) remain`);
|
||||
|
||||
setTimeout(() => {
|
||||
console.log(`WSProvider ${id} checking for close, ${mountCounter[id]} instance(s) remain`);
|
||||
if (mountCounter[id] === 0) {
|
||||
console.log("WSProvider: closing connection to", url);
|
||||
ws.current.close()
|
||||
}
|
||||
}, 250)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const send = (uuid, code, type, data, onReply = () => {
|
||||
}, onError = () => {
|
||||
const send = (uuid, code, type, data, resolve = () => {
|
||||
}, reject = () => {
|
||||
}) => {
|
||||
if (!isReady) {
|
||||
onError("WebSocket is not connected");
|
||||
reject("WebSocket is not connected");
|
||||
return;
|
||||
}
|
||||
if (type === "REQUEST") {
|
||||
callbackRef.current[uuid] = {onReply: onReply, onError: onError}
|
||||
const timeout = setTimeout(() => {
|
||||
reject("timeout");
|
||||
delete callbackRef.current[uuid];
|
||||
}, 30000);
|
||||
callbackRef.current[uuid] = {
|
||||
onReply: (data) => {
|
||||
clearTimeout(timeout);
|
||||
resolve(data);
|
||||
},
|
||||
onError: (data) => {
|
||||
clearTimeout(timeout);
|
||||
reject(data);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
ws.current?.send(JSON.stringify({
|
||||
uuid: uuid,
|
||||
@ -124,17 +173,7 @@ export function useWS() {
|
||||
wait_length,
|
||||
sendRequest: (code, data) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const timeout = setTimeout(() => {
|
||||
reject("timeout");
|
||||
}, 1000);
|
||||
|
||||
send(uuidv4(), code, "REQUEST", data, (data) => {
|
||||
clearTimeout(timeout);
|
||||
resolve(data);
|
||||
}, (data) => {
|
||||
clearTimeout(timeout);
|
||||
reject(data);
|
||||
});
|
||||
send(uuidv4(), code, "REQUEST", data, resolve, reject);
|
||||
})
|
||||
},
|
||||
sendNotify: (code, data) => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user