Skip to content

Commit

Permalink
fix(#252): Fix websocket retry logic
Browse files Browse the repository at this point in the history
  • Loading branch information
jugglingcats committed Oct 11, 2024
1 parent b30ee6b commit 8a8d72e
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 17 deletions.
54 changes: 37 additions & 17 deletions libs/controls/src/app/ConnectionProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ type ConnectionProviderPrivateState = {
connection: WebSocket
connectionState: ConnectionState
autoConnect: boolean
retryCount: number
}

const DISCONNECTED_STATE: ConnectionProviderPrivateState = {
connection: null,
connectionState: ConnectionState.DISCONNECTED,
autoConnect: false
autoConnect: false,
retryCount: 0
}

export const ConnectionProvider = ({ autoConnect: defaultAutoConnect, children }) => {
Expand All @@ -33,9 +35,11 @@ export const ConnectionProvider = ({ autoConnect: defaultAutoConnect, children }

const [state, setState] = useState<ConnectionProviderPrivateState>({
...DISCONNECTED_STATE,
autoConnect: defaultAutoConnect
autoConnect: defaultAutoConnect,
retryCount: 0
})
const { connectionState, connection, autoConnect } = state

const { connectionState, connection, autoConnect, retryCount } = state
const [lastStatus, setLastStatus] = useState<GlowbuzzerStatus["status"]>(null)

const process_status = useStatusProcessor(connection)
Expand All @@ -45,8 +49,6 @@ export const ConnectionProvider = ({ autoConnect: defaultAutoConnect, children }
const urlRef = useRef("")

function init_connection(websocket: WebSocket) {
// console.log("✅ connection open", "reconnect enabled=", autoConnectRef.current)

websocket.onmessage = msg => {
const message: GlowbuzzerStatus = JSON.parse(msg.data)
// TODO: H: this is only used to pass current status to external flowmaker endpoint
Expand Down Expand Up @@ -82,12 +84,23 @@ export const ConnectionProvider = ({ autoConnect: defaultAutoConnect, children }
setState({
connection: websocket,
connectionState: ConnectionState.CONNECTED,
autoConnect: true
autoConnect: true,
retryCount: 0
})
init_connection(websocket)
}
}, [])

useEffect(() => {
if (retryCount) {
const timer = setTimeout(() => {
connect(urlRef.current)
}, 1000)

return () => clearTimeout(timer)
}
}, [retryCount])

function connect(url: string, autoConnect = true) {
urlRef.current = url

Expand All @@ -97,31 +110,37 @@ export const ConnectionProvider = ({ autoConnect: defaultAutoConnect, children }
setState({
connection: null,
connectionState: ConnectionState.CONNECTING,
autoConnect
autoConnect,
retryCount: retryCount
})

connection.onopen = () => {
init_connection(connection)
setState({
connection,
connectionState: ConnectionState.CONNECTED,
autoConnect: autoConnectRef.current
autoConnect: autoConnectRef.current,
retryCount: 0
})
}

connection.onclose = () => {
console.log("❌ connection closed", "reconnect enabled=", autoConnectRef.current)
function handle_close() {
console.log(
"Connection closed",
"reconnect enabled=",
autoConnectRef.current,
"retry count=",
retryCount
)
handler.clear()
setState({ ...DISCONNECTED_STATE, autoConnect: autoConnectRef.current })
}

connection.onerror = () => {
setState({
connection: null,
connectionState: ConnectionState.DISCONNECTED,
autoConnect: autoConnectRef.current
...DISCONNECTED_STATE,
autoConnect: autoConnectRef.current,
retryCount: autoConnectRef.current ? retryCount + 1 : 0
})
}

connection.onclose = handle_close
}

function send(msg: string) {
Expand All @@ -139,6 +158,7 @@ export const ConnectionProvider = ({ autoConnect: defaultAutoConnect, children }
const context: GlowbuzzerConnectionContextType = useMemo(
() => ({
autoConnect,
retryCount,
state: connectionState,
statusReceived: true,
lastStatus,
Expand Down
1 change: 1 addition & 0 deletions libs/controls/src/app/lifecycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const GlowbuzzerAppLifecycle = new (class {
persistenceConfiguration: GbdbConfiguration = { facets: {} }
) {
if (typeof import.meta !== "undefined" && import.meta?.hot?.data.store) {
// console.log("GlowbuzzerAppLifecycle: reusing existing store (hot reload)")
return import.meta.hot.data.store
}

Expand Down
2 changes: 2 additions & 0 deletions libs/store/src/connect/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ export type GlowbuzzerConnectionContextType = {
statusReceived: boolean
/** Whether the connection should be reestablished automatically if it drops */
autoConnect: boolean
/** Retry attempts */
retryCount: number
/** The last status message received */
lastStatus: GlowbuzzerStatus["status"]
}
Expand Down

0 comments on commit 8a8d72e

Please sign in to comment.