refactor: connections and types

This commit is contained in:
Zephyruso 2023-09-08 13:39:51 +08:00
parent 9fb91e764b
commit 700302fd78
4 changed files with 77 additions and 84 deletions

View File

@ -42,11 +42,6 @@ import {
} from '~/signals' } from '~/signals'
import type { Connection } from '~/types' import type { Connection } from '~/types'
type ConnectionWithSpeed = Connection & {
downloadSpeed: number
uploadSpeed: number
}
type ColumnVisibility = Partial<Record<CONNECTIONS_TABLE_ACCESSOR_KEY, boolean>> type ColumnVisibility = Partial<Record<CONNECTIONS_TABLE_ACCESSOR_KEY, boolean>>
type ColumnOrder = CONNECTIONS_TABLE_ACCESSOR_KEY[] type ColumnOrder = CONNECTIONS_TABLE_ACCESSOR_KEY[]
@ -61,12 +56,8 @@ export default () => {
const [search, setSearch] = createSignal('') const [search, setSearch] = createSignal('')
const [activeTab, setActiveTab] = createSignal(ActiveTab.activeConnections) const [activeTab, setActiveTab] = createSignal(ActiveTab.activeConnections)
const { const { activeConnections, closedConnections, paused, setPaused } =
activeConnectionsWithSpeed, useConnections()
closedConnectionsWithSpeed,
paused,
setPaused,
} = useConnections()
const onCloseConnection = (id: string) => request.delete(`connections/${id}`) const onCloseConnection = (id: string) => request.delete(`connections/${id}`)
const [columnVisibility, setColumnVisibility] = makePersisted( const [columnVisibility, setColumnVisibility] = makePersisted(
@ -84,7 +75,7 @@ export default () => {
}, },
) )
const columns = createMemo<ColumnDef<ConnectionWithSpeed>[]>(() => [ const columns = createMemo<ColumnDef<Connection>[]>(() => [
{ {
header: () => t('close'), header: () => t('close'),
enableGrouping: false, enableGrouping: false,
@ -229,8 +220,8 @@ export default () => {
}, },
get data() { get data() {
return activeTab() === ActiveTab.activeConnections return activeTab() === ActiveTab.activeConnections
? activeConnectionsWithSpeed() ? activeConnections()
: closedConnectionsWithSpeed() : closedConnections()
}, },
sortDescFirst: true, sortDescFirst: true,
enableHiding: true, enableHiding: true,
@ -249,12 +240,12 @@ export default () => {
{ {
type: ActiveTab.activeConnections, type: ActiveTab.activeConnections,
name: t('activeConnections'), name: t('activeConnections'),
count: activeConnectionsWithSpeed().length, count: activeConnections().length,
}, },
{ {
type: ActiveTab.closedConnections, type: ActiveTab.closedConnections,
name: t('closedConnections'), name: t('closedConnections'),
count: closedConnectionsWithSpeed().length, count: closedConnections().length,
}, },
]) ])

View File

@ -13,7 +13,7 @@ import {
createSignal, createSignal,
} from 'solid-js' } from 'solid-js'
import { CHART_MAX_XAXIS, DEFAULT_CHART_OPTIONS } from '~/constants' import { CHART_MAX_XAXIS, DEFAULT_CHART_OPTIONS } from '~/constants'
import { connections, useWsRequest } from '~/signals' import { latestConnectionMsg, useWsRequest } from '~/signals'
const TrafficWidget: ParentComponent<{ label: JSX.Element }> = (props) => ( const TrafficWidget: ParentComponent<{ label: JSX.Element }> = (props) => (
<div class="stat flex-1 place-items-center"> <div class="stat flex-1 place-items-center">
@ -95,15 +95,15 @@ export default () => {
</TrafficWidget> </TrafficWidget>
<TrafficWidget label={t('uploadTotal')}> <TrafficWidget label={t('uploadTotal')}>
{byteSize(connections()?.uploadTotal || 0).toString()} {byteSize(latestConnectionMsg()?.uploadTotal || 0).toString()}
</TrafficWidget> </TrafficWidget>
<TrafficWidget label={t('downloadTotal')}> <TrafficWidget label={t('downloadTotal')}>
{byteSize(connections()?.downloadTotal || 0).toString()} {byteSize(latestConnectionMsg()?.downloadTotal || 0).toString()}
</TrafficWidget> </TrafficWidget>
<TrafficWidget label={t('activeConnections')}> <TrafficWidget label={t('activeConnections')}>
{connections()?.connections.length || 0} {latestConnectionMsg()?.connections.length || 0}
</TrafficWidget> </TrafficWidget>
<TrafficWidget label={t('memoryUsage')}> <TrafficWidget label={t('memoryUsage')}>

View File

@ -1,10 +1,10 @@
import { differenceWith, unionWith } from 'lodash' import { differenceWith, isNumber, unionWith } from 'lodash'
import { Accessor, createEffect, createSignal, untrack } from 'solid-js' import { Accessor, createEffect, createSignal, untrack } from 'solid-js'
import { Connection, ConnectionWithSpeed } from '~/types' import { Connection, ConnectionRawMessage } from '~/types'
import { selectedEndpoint, useWsRequest } from './request' import { selectedEndpoint, useWsRequest } from './request'
type WsMsg = { type WsMsg = {
connections: Connection[] connections: ConnectionRawMessage[]
uploadTotal: number uploadTotal: number
downloadTotal: number downloadTotal: number
} | null } | null
@ -12,11 +12,9 @@ type WsMsg = {
// we make connections global, so we can keep track of connections when user in proxy page // we make connections global, so we can keep track of connections when user in proxy page
// when user selects proxy and close some connections they can back and check connections // when user selects proxy and close some connections they can back and check connections
// they closed // they closed
const [allConnectionsWithSpeed, setAllConnectionsWithSpeed] = createSignal< const [allConnections, setAllConnections] = createSignal<Connection[]>([])
ConnectionWithSpeed[]
>([])
export let connections: Accessor<WsMsg> = () => ({ export let latestConnectionMsg: Accessor<WsMsg> = () => ({
uploadTotal: 0, uploadTotal: 0,
downloadTotal: 0, downloadTotal: 0,
connections: [], connections: [],
@ -24,82 +22,86 @@ export let connections: Accessor<WsMsg> = () => ({
createEffect(() => { createEffect(() => {
if (selectedEndpoint()) { if (selectedEndpoint()) {
connections = useWsRequest<WsMsg>('connections') setAllConnections([])
latestConnectionMsg = useWsRequest<WsMsg>('connections')
} }
}) })
export const useConnections = () => { export const useConnections = () => {
const [closedConnectionsWithSpeed, setClosedConnectionsWithSpeed] = const [closedConnections, setClosedConnections] = createSignal<Connection[]>(
createSignal<ConnectionWithSpeed[]>([]) [],
const [activeConnectionsWithSpeed, setActiveConnectionsWithSpeed] = )
createSignal<ConnectionWithSpeed[]>([]) const [activeConnections, setActiveConnections] = createSignal<Connection[]>(
[],
)
const [paused, setPaused] = createSignal(false) const [paused, setPaused] = createSignal(false)
const updateConnectionsWithSpeed = (connections: Connection[]) => {
const prevActiveConnections = activeConnectionsWithSpeed()
const prevMap = new Map<string, Connection>()
prevActiveConnections.forEach((prev) => prevMap.set(prev.id, prev))
const activeConnections: ConnectionWithSpeed[] = connections.map(
(connection) => {
const prevConn = prevMap.get(connection.id)
if (!prevConn) {
return { ...connection, downloadSpeed: 0, uploadSpeed: 0 }
}
return {
...connection,
downloadSpeed:
connection.download - (prevConn.download ?? connection.download),
uploadSpeed:
connection.upload - (prevConn.upload ?? connection.upload),
}
},
)
const allConnections = unionWith(
allConnectionsWithSpeed(),
activeConnections,
(a, b) => a.id === b.id,
)
const closedConnections = differenceWith(
allConnections,
activeConnections,
(a, b) => a.id === b.id,
)
return {
activeConns: activeConnections.slice(-200),
closedConns: closedConnections.slice(-200),
allConns: allConnections.slice(-400),
}
}
createEffect(() => { createEffect(() => {
const connection = connections()?.connections const rawConns = latestConnectionMsg()?.connections
if (!connection) { if (!rawConns) {
return return
} }
untrack(() => { untrack(() => {
const { activeConns, closedConns, allConns } = const activeConns = restructRawMsgToConnection(
updateConnectionsWithSpeed(connection) rawConns,
activeConnections(),
)
const allConns = mergeAllConnections(activeConns)
if (!paused()) { if (!paused()) {
setActiveConnectionsWithSpeed(activeConns) const closedConns = diffClosedConnections(activeConns, allConns)
setClosedConnectionsWithSpeed(closedConns)
setActiveConnections(activeConns)
setClosedConnections(closedConns)
} }
setAllConnectionsWithSpeed(allConns) setAllConnections(allConns)
}) })
}) })
return { return {
closedConnectionsWithSpeed, closedConnections,
activeConnectionsWithSpeed, activeConnections,
paused, paused,
setPaused, setPaused,
} }
} }
function restructRawMsgToConnection(
connections: ConnectionRawMessage[],
prevActiveConnections: Connection[],
): Connection[] {
const prevMap = new Map<string, Connection>()
prevActiveConnections.forEach((prev) => prevMap.set(prev.id, prev))
return connections.map((connection) => {
const prevConn = prevMap.get(connection.id)
if (
!prevConn ||
!isNumber(prevConn.download) ||
!isNumber(prevConn.upload)
) {
return { ...connection, downloadSpeed: 0, uploadSpeed: 0 }
}
return {
...connection,
downloadSpeed: connection.download - prevConn.download,
uploadSpeed: connection.upload - prevConn.upload,
}
})
}
function mergeAllConnections(activeConns: Connection[]) {
return unionWith(allConnections(), activeConns, (a, b) => a.id === b.id)
}
function diffClosedConnections(
activeConns: Connection[],
allConns: Connection[],
) {
return differenceWith(allConns, activeConns, (a, b) => a.id === b.id)
}

View File

@ -69,7 +69,7 @@ export type RuleProvider = {
vehicleType: string vehicleType: string
} }
export type Connection = { export type ConnectionRawMessage = {
id: string id: string
download: number download: number
upload: number upload: number
@ -100,7 +100,7 @@ export type Connection = {
} }
} }
export type ConnectionWithSpeed = Connection & { export type Connection = ConnectionRawMessage & {
downloadSpeed: number downloadSpeed: number
uploadSpeed: number uploadSpeed: number
} }