connect-fox

This commit is contained in:
Untone 2024-05-18 20:43:20 +03:00
parent c8517c85c6
commit 95c4d777b2

View File

@ -30,19 +30,19 @@ const ConnectContext = createContext<ConnectContextType>()
export const ConnectProvider = (props: { children: JSX.Element }) => { export const ConnectProvider = (props: { children: JSX.Element }) => {
const [messageHandlers, setHandlers] = createSignal<MessageHandler[]>([]) const [messageHandlers, setHandlers] = createSignal<MessageHandler[]>([])
// const [messages, setMessages] = createSignal<Array<SSEMessage>>([]);
const [connected, setConnected] = createSignal(false) const [connected, setConnected] = createSignal(false)
const { session } = useSession() const { session } = useSession()
const [retried, setRetried] = createSignal<number>(0)
const addHandler = (handler: MessageHandler) => { const addHandler = (handler: MessageHandler) => {
setHandlers((hhh) => [...hhh, handler]) setHandlers((hhh) => [...hhh, handler])
} }
const [retried, setRetried] = createSignal<number>(0)
createEffect(async () => { createEffect(async () => {
const token = session()?.access_token const token = session()?.access_token
if (token && !connected()) { if (token && !connected() && retried() <= RECONNECT_TIMES) {
console.info('[context.connect] init SSE connection') console.info('[context.connect] init SSE connection')
try {
await fetchEventSource('https://connect.discours.io', { await fetchEventSource('https://connect.discours.io', {
method: 'GET', method: 'GET',
headers: { headers: {
@ -52,31 +52,35 @@ export const ConnectProvider = (props: { children: JSX.Element }) => {
onmessage(event) { onmessage(event) {
const m: SSEMessage = JSON.parse(event.data || '{}') const m: SSEMessage = JSON.parse(event.data || '{}')
console.log('[context.connect] Received message:', m) console.log('[context.connect] Received message:', m)
// Iterate over all registered handlers and call them
messageHandlers().forEach((handler) => handler(m)) messageHandlers().forEach((handler) => handler(m))
}, },
async onopen(response) { onopen: (response) => {
console.log('[context.connect] SSE connection opened', response) console.log('[context.connect] SSE connection opened', response)
if (response.ok && response.headers.get('content-type') === EventStreamContentType) { if (response.ok && response.headers.get('content-type') === EventStreamContentType) {
setConnected(true) setConnected(true)
} else if (response.status === 401) { setRetried(0)
throw new Error('SSE: cannot connect to real-time updates') return Promise.resolve()
} else {
setRetried((r) => r + 1)
throw new Error(`SSE: failed to connect ${retried()} times`)
} }
return Promise.reject(`SSE: cannot connect to real-time updates, status: ${response.status}`)
}, },
onclose() { onclose() {
console.log('[context.connect] SSE connection closed by server') console.log('[context.connect] SSE connection closed by server')
setConnected(false) setConnected(false)
}, if (retried() < RECONNECT_TIMES) {
onerror(err) { setRetried((r) => r + 1)
if (err.message === 'unauthorized' || retried() > RECONNECT_TIMES) {
throw err // rethrow to stop the operation
} }
}, },
onerror(err) {
console.error('[context.connect] SSE connection error:', err)
setConnected(false)
if (retried() < RECONNECT_TIMES) {
setRetried((r) => r + 1)
} else throw Error(err)
},
}) })
} catch (error) {
console.error('[context.connect] SSE connection failed:', error)
}
} }
}) })