Add ping pong health, remove a timeout interval, fix up network events (#1555)

* Add ping pong health, fix up network events

* Change the default connection state for test

---------

Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>
This commit is contained in:
49fl
2024-03-14 12:18:06 -04:00
committed by GitHub
parent 0579ccd53b
commit 61d7950ca3
4 changed files with 296 additions and 188 deletions

View File

@ -6,7 +6,8 @@ import {
ConnectingTypeGroup,
DisconnectingType,
engineCommandManager,
EngineConnectionState,
EngineCommandManagerEvents,
EngineConnectionEvents,
EngineConnectionStateType,
ErrorType,
initialConnectingTypeGroupState,
@ -81,37 +82,35 @@ const overallConnectionStateIcon: Record<
}
export function useNetworkStatus() {
const [steps, setSteps] = useState(initialConnectingTypeGroupState)
const [steps, setSteps] = useState(
structuredClone(initialConnectingTypeGroupState)
)
const [internetConnected, setInternetConnected] = useState<boolean>(true)
const [overallState, setOverallState] = useState<NetworkHealthState>(
NetworkHealthState.Ok
NetworkHealthState.Disconnected
)
const [pingPongHealth, setPingPongHealth] = useState<'OK' | 'BAD'>('BAD')
const [hasCopied, setHasCopied] = useState<boolean>(false)
const [error, setError] = useState<ErrorType | undefined>(undefined)
const issues: Record<ConnectingTypeGroup, boolean> = {
[ConnectingTypeGroup.WebSocket]: steps[ConnectingTypeGroup.WebSocket].some(
(a: [ConnectingType, boolean | undefined]) => a[1] === false
),
[ConnectingTypeGroup.ICE]: steps[ConnectingTypeGroup.ICE].some(
(a: [ConnectingType, boolean | undefined]) => a[1] === false
),
[ConnectingTypeGroup.WebRTC]: steps[ConnectingTypeGroup.WebRTC].some(
(a: [ConnectingType, boolean | undefined]) => a[1] === false
),
}
const hasIssue = (i: [ConnectingType, boolean | undefined]) =>
i[1] === undefined ? i[1] : !i[1]
const hasIssues: boolean =
issues[ConnectingTypeGroup.WebSocket] ||
issues[ConnectingTypeGroup.ICE] ||
issues[ConnectingTypeGroup.WebRTC]
const [issues, setIssues] = useState<
Record<ConnectingTypeGroup, boolean | undefined>
>({
[ConnectingTypeGroup.WebSocket]: undefined,
[ConnectingTypeGroup.ICE]: undefined,
[ConnectingTypeGroup.WebRTC]: undefined,
})
const [hasIssues, setHasIssues] = useState<boolean | undefined>(undefined)
useEffect(() => {
setOverallState(
!internetConnected
? NetworkHealthState.Disconnected
: hasIssues
: hasIssues || hasIssues === undefined
? NetworkHealthState.Issue
: NetworkHealthState.Ok
)
@ -134,19 +133,59 @@ export function useNetworkStatus() {
}, [])
useEffect(() => {
engineCommandManager.onConnectionStateChange(
(engineConnectionState: EngineConnectionState) => {
let hasSetAStep = false
console.log(pingPongHealth)
}, [pingPongHealth])
useEffect(() => {
const issues = {
[ConnectingTypeGroup.WebSocket]: steps[
ConnectingTypeGroup.WebSocket
].reduce(
(acc: boolean | undefined, a) =>
acc === true || acc === undefined ? acc : hasIssue(a),
false
),
[ConnectingTypeGroup.ICE]: steps[ConnectingTypeGroup.ICE].reduce(
(acc: boolean | undefined, a) =>
acc === true || acc === undefined ? acc : hasIssue(a),
false
),
[ConnectingTypeGroup.WebRTC]: steps[ConnectingTypeGroup.WebRTC].reduce(
(acc: boolean | undefined, a) =>
acc === true || acc === undefined ? acc : hasIssue(a),
false
),
}
setIssues(issues)
}, [steps])
useEffect(() => {
setHasIssues(
issues[ConnectingTypeGroup.WebSocket] ||
issues[ConnectingTypeGroup.ICE] ||
issues[ConnectingTypeGroup.WebRTC]
)
}, [issues])
useEffect(() => {
const onPingPongChange = ({ detail: state }: CustomEvent) => {
setPingPongHealth(state)
}
const onConnectionStateChange = ({
detail: engineConnectionState,
}: CustomEvent) => {
setSteps((steps) => {
let nextSteps = structuredClone(steps)
if (
engineConnectionState.type === EngineConnectionStateType.Connecting
) {
const groups = Object.values(steps)
const groups = Object.values(nextSteps)
for (let group of groups) {
for (let step of group) {
if (step[0] !== engineConnectionState.value.type) continue
step[1] = true
hasSetAStep = true
}
}
}
@ -154,7 +193,7 @@ export function useNetworkStatus() {
if (
engineConnectionState.type === EngineConnectionStateType.Disconnecting
) {
const groups = Object.values(steps)
const groups = Object.values(nextSteps)
for (let group of groups) {
for (let step of group) {
if (
@ -165,7 +204,6 @@ export function useNetworkStatus() {
?.type === step[0]
) {
step[1] = false
hasSetAStep = true
}
}
}
@ -176,11 +214,50 @@ export function useNetworkStatus() {
}
}
if (hasSetAStep) {
setSteps(steps)
// Reset the state of all steps if we have disconnected.
if (
engineConnectionState.type === EngineConnectionStateType.Disconnected
) {
return structuredClone(initialConnectingTypeGroupState)
}
}
return nextSteps
})
}
const onEngineAvailable = ({ detail: engineConnection }: CustomEvent) => {
engineConnection.addEventListener(
EngineConnectionEvents.PingPongChanged,
onPingPongChange as EventListener
)
engineConnection.addEventListener(
EngineConnectionEvents.ConnectionStateChanged,
onConnectionStateChange as EventListener
)
}
engineCommandManager.addEventListener(
EngineCommandManagerEvents.EngineAvailable,
onEngineAvailable as EventListener
)
return () => {
engineCommandManager.removeEventListener(
EngineCommandManagerEvents.EngineAvailable,
onEngineAvailable as EventListener
)
// When the component is unmounted these should be assigned, but it's possible
// the component mounts and unmounts before engine is available.
engineCommandManager.engineConnection?.addEventListener(
EngineConnectionEvents.PingPongChanged,
onPingPongChange as EventListener
)
engineCommandManager.engineConnection?.addEventListener(
EngineConnectionEvents.ConnectionStateChanged,
onConnectionStateChange as EventListener
)
}
}, [])
return {
@ -192,6 +269,7 @@ export function useNetworkStatus() {
error,
setHasCopied,
hasCopied,
pingPongHealth,
}
}
@ -256,18 +334,18 @@ export const NetworkHealthIndicator = () => {
size="lg"
icon={
hasIssueToIcon[
issues[name as ConnectingTypeGroup].toString()
String(issues[name as ConnectingTypeGroup])
]
}
iconClassName={
hasIssueToIconColors[
issues[name as ConnectingTypeGroup].toString()
String(issues[name as ConnectingTypeGroup])
].icon
}
bgClassName={
'rounded-sm ' +
hasIssueToIconColors[
issues[name as ConnectingTypeGroup].toString()
String(issues[name as ConnectingTypeGroup])
].bg
}
/>