perf(mobile): project home host connection maps once (#17459)

This commit is contained in:
Neil
2026-08-30 23:04:42 -07:00
committed by GitHub
parent fb271f2f3b
commit 7e5cc79e93
3 changed files with 122 additions and 11 deletions
@@ -0,0 +1,78 @@
import { describe, expect, it } from 'vitest'
import type { MobileConnectionPath } from '../transport/stable-logical-rpc-client'
import {
projectHomeHostConnections,
type HomeHostConnectionProjectionEntry
} from './home-host-connection-projection'
describe('projectHomeHostConnections', () => {
it('reads each connection once while preserving all lookup values', () => {
const entryCount = 1_000
const reads = {
hostId: 0,
path: 0,
pendingPath: 0,
pairingRejected: 0
}
const entries = Array.from({ length: entryCount }, (_, index) => {
const hostId = index === entryCount - 1 ? '__proto__' : `host-${index}`
const path: MobileConnectionPath = index % 2 === 0 ? 'lan' : 'relay'
const pendingPath = index === 1 ? undefined : index % 2 === 0 ? null : 'tailscale'
const pairingRejected = index % 3 === 0
const entry = {} as HomeHostConnectionProjectionEntry
Object.defineProperties(entry, {
hostId: {
enumerable: true,
get: () => {
reads.hostId += 1
return hostId
}
},
path: {
enumerable: true,
get: () => {
reads.path += 1
return path
}
},
pendingPath: {
enumerable: true,
get: () => {
reads.pendingPath += 1
return pendingPath
}
},
pairingRejected: {
enumerable: true,
get: () => {
reads.pairingRejected += 1
return pairingRejected
}
}
})
return entry
})
const projection = projectHomeHostConnections(entries)
expect(reads).toEqual({
hostId: entryCount,
path: entryCount,
pendingPath: entryCount,
pairingRejected: entryCount
})
expect(Object.keys(projection.hostPaths)).toHaveLength(entryCount)
expect(Object.keys(projection.hostPendingPaths)).toHaveLength(entryCount)
expect(Object.keys(projection.hostPairingRejected)).toHaveLength(entryCount)
expect(projection.hostPaths['host-0']).toBe('lan')
expect(projection.hostPaths['host-1']).toBe('relay')
expect(projection.hostPendingPaths['host-0']).toBeNull()
expect(projection.hostPendingPaths['host-1']).toBeUndefined()
expect(projection.hostPendingPaths['host-3']).toBe('tailscale')
expect(projection.hostPairingRejected['host-0']).toBe(true)
expect(projection.hostPairingRejected['host-1']).toBe(false)
expect(Object.hasOwn(projection.hostPaths, '__proto__')).toBe(true)
expect(projection.hostPaths['__proto__']).toBe('relay')
expect(Object.getPrototypeOf(projection.hostPaths)).toBe(Object.prototype)
})
})
@@ -0,0 +1,37 @@
import type { MobileConnectionPath } from '../transport/stable-logical-rpc-client'
export type HomeHostConnectionProjectionEntry = {
hostId: string
path: MobileConnectionPath
pendingPath: MobileConnectionPath | null
pairingRejected: boolean
}
export type HomeHostConnectionProjection = {
hostPaths: Record<string, MobileConnectionPath>
hostPendingPaths: Record<string, MobileConnectionPath | null>
hostPairingRejected: Record<string, boolean>
}
/** Build all host lookup maps while reading each connection entry once. */
export function projectHomeHostConnections(
entries: readonly HomeHostConnectionProjectionEntry[]
): HomeHostConnectionProjection {
// Null-prototype records avoid the __proto__ setter; restore the usual prototype for parity
// with Object.fromEntries once the projection is complete.
const hostPaths = Object.create(null) as Record<string, MobileConnectionPath>
const hostPendingPaths = Object.create(null) as Record<string, MobileConnectionPath | null>
const hostPairingRejected = Object.create(null) as Record<string, boolean>
for (const { hostId, path, pendingPath, pairingRejected } of entries) {
hostPaths[hostId] = path
hostPendingPaths[hostId] = pendingPath
hostPairingRejected[hostId] = pairingRejected
}
Object.setPrototypeOf(hostPaths, Object.prototype)
Object.setPrototypeOf(hostPendingPaths, Object.prototype)
Object.setPrototypeOf(hostPairingRejected, Object.prototype)
return { hostPaths, hostPendingPaths, hostPairingRejected }
}
+7 -11
View File
@@ -29,6 +29,7 @@ import {
fetchMobileHomeStats,
fetchMobileHomeTaskProviders
} from './mobile-home-host-requests'
import { projectHomeHostConnections } from './home-host-connection-projection'
import { useMobileHomeHostConnections } from './use-mobile-home-host-connections'
export function useMobileHomeData() {
@@ -167,14 +168,9 @@ export function useMobileHomeData() {
const primaryTaskProviders = primaryHost
? (taskProvidersByHost[primaryHost.id] ?? ['github'])
: []
const hostPaths = Object.fromEntries(
connections.allClients.map(({ hostId, path }) => [hostId, path])
)
const hostPendingPaths = Object.fromEntries(
connections.allClients.map(({ hostId, pendingPath }) => [hostId, pendingPath])
)
const hostPairingRejected = Object.fromEntries(
connections.allClients.map(({ hostId, pairingRejected }) => [hostId, pairingRejected])
const hostConnectionProjection = useMemo(
() => projectHomeHostConnections(connections.allClients),
[connections.allClients]
)
return {
@@ -182,9 +178,9 @@ export function useMobileHomeData() {
accountsHosts,
connectedHosts,
hostCatalog,
hostPairingRejected,
hostPaths,
hostPendingPaths,
hostPairingRejected: hostConnectionProjection.hostPairingRejected,
hostPaths: hostConnectionProjection.hostPaths,
hostPendingPaths: hostConnectionProjection.hostPendingPaths,
primaryHost,
primaryTaskProviders,
resumeCard,