mirror of
https://github.com/stablyai/orca.git
synced 2026-11-13 17:37:40 +00:00
refactor(mobile): move the bridge connection snapshot into its own module (#36818)
The connection snapshot schema, the shell's snapshot builder and the page's not-ready guard move to bridge-connection-snapshot.ts and BridgeConnectionCache.require(). No behavior change: the envelope re-exports the schema, so every frame parses and serializes as before. Prepares the next change, which adds connection path fields to the snapshot, without pushing the bridge modules over the size cap.
This commit is contained in:
@@ -9,8 +9,7 @@ import {
|
||||
BRIDGE_PROTOCOL_VERSION,
|
||||
BRIDGE_RPC_ENVELOPE_GRANT,
|
||||
readBridgeClientMessage,
|
||||
type BridgeClientMessage,
|
||||
type BridgeConnectionSnapshot
|
||||
type BridgeClientMessage
|
||||
} from './bridge/bridge-envelope'
|
||||
import { BridgePageRouteGrantsSchema } from './bridge/bridge-page-route-grants'
|
||||
import { createBridgeInitFrame } from './bridge/bridge-init-frame'
|
||||
@@ -21,6 +20,7 @@ import { createBridgeNotifyForwarder } from './bridge-host-notify'
|
||||
import { createBridgeHostRoute } from './bridge-host-route'
|
||||
import { pageStorageForReader } from './page-storage-keys'
|
||||
import { BRIDGE_TERMINAL_KEY_FRAME } from './bridge/bridge-terminal-key'
|
||||
import { readBridgeConnectionSnapshot } from './bridge/bridge-connection-snapshot'
|
||||
import type { BridgeHost, BridgeHostOptions } from './bridge-host-contract'
|
||||
|
||||
export type { BridgeHost, BridgeHostDiagnostic, BridgeHostOptions } from './bridge-host-contract'
|
||||
@@ -87,15 +87,7 @@ export function createBridgeHost(options: BridgeHostOptions): BridgeHost {
|
||||
})
|
||||
|
||||
// Use the event’s state; listeners can run before the mirrored getter updates.
|
||||
function snapshot(state?: ConnectionState): BridgeConnectionSnapshot {
|
||||
return {
|
||||
state: state ?? client.getState(),
|
||||
reconnectAttempt: client.getReconnectAttempt(),
|
||||
lastConnectedAt: client.getLastConnectedAt(),
|
||||
lastInboundAt: client.getLastInboundAt?.() ?? null,
|
||||
generation: client.getGeneration?.() ?? null
|
||||
}
|
||||
}
|
||||
const snapshot = (state?: ConnectionState) => readBridgeConnectionSnapshot(client, state)
|
||||
|
||||
/**
|
||||
* Posts `init`, and answers nothing (ruling 34).
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { ConnectionState } from '../../transport/types'
|
||||
import type { BridgeConnectionSnapshot } from './bridge-envelope'
|
||||
import { BridgeClientNotReadyError } from './bridge-client-errors'
|
||||
import type { BridgeConnectionSnapshot } from './bridge-connection-snapshot'
|
||||
|
||||
export type BridgeSnapshotOutcome = 'applied' | 'stale' | 'unprimed'
|
||||
|
||||
@@ -12,6 +13,14 @@ export class BridgeConnectionCache {
|
||||
return this.held
|
||||
}
|
||||
|
||||
// Getters run only after init primed the cache; reading earlier is a page bug, not a disconnect.
|
||||
require(): BridgeConnectionSnapshot {
|
||||
if (this.held === null) {
|
||||
throw new BridgeClientNotReadyError()
|
||||
}
|
||||
return this.held
|
||||
}
|
||||
|
||||
// Repriming identical state is not a transition and must notify nobody.
|
||||
prime(snapshot: BridgeConnectionSnapshot): void {
|
||||
const changed = this.held?.state !== snapshot.state
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import { z } from 'zod'
|
||||
import type { RpcClient } from '../../transport/rpc-client'
|
||||
import type { ConnectionState } from '../../transport/types'
|
||||
|
||||
export const BRIDGE_CONNECTION_STATES = [
|
||||
'connecting',
|
||||
'handshaking',
|
||||
'connected',
|
||||
'disconnected',
|
||||
'reconnecting',
|
||||
'auth-failed'
|
||||
] as const
|
||||
|
||||
// Send whole connection snapshots so lost frames cannot leave partial state; generation detects snapshots that need repair.
|
||||
export const BridgeConnectionSnapshotSchema = z.object({
|
||||
state: z.enum(BRIDGE_CONNECTION_STATES),
|
||||
reconnectAttempt: z.number().int().nonnegative(),
|
||||
lastConnectedAt: z.number().nullable(),
|
||||
lastInboundAt: z.number().nullable(),
|
||||
generation: z.number().int().nonnegative().nullable()
|
||||
})
|
||||
|
||||
export type BridgeConnectionSnapshot = z.infer<typeof BridgeConnectionSnapshotSchema>
|
||||
|
||||
/** The shell's whole view of its client; `state` is the event's, which a getter can outrun. */
|
||||
export function readBridgeConnectionSnapshot(
|
||||
client: RpcClient,
|
||||
state?: ConnectionState
|
||||
): BridgeConnectionSnapshot {
|
||||
return {
|
||||
state: state ?? client.getState(),
|
||||
reconnectAttempt: client.getReconnectAttempt(),
|
||||
lastConnectedAt: client.getLastConnectedAt(),
|
||||
lastInboundAt: client.getLastInboundAt?.() ?? null,
|
||||
generation: client.getGeneration?.() ?? null
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import { NODE_PLATFORM_NAMES } from '../../transport/mobile-runtime-host-platfor
|
||||
import { RpcEnvelopeFieldsSchema } from '../../transport/rpc-envelope-fields'
|
||||
import { isRpcResponse } from '../../transport/rpc-response-shape'
|
||||
import type { RpcResponse } from '../../transport/types'
|
||||
import { BridgeConnectionSnapshotSchema } from './bridge-connection-snapshot'
|
||||
import { BridgeErrorCaptureSchema } from './bridge-error-capture'
|
||||
import { BridgeInitRouteSchema, type BridgeInitRoute } from './bridge-init-route'
|
||||
import { BridgePageRouteGrantsSchema } from './bridge-page-route-grants'
|
||||
@@ -21,6 +22,11 @@ import {
|
||||
} from './bridge-terminal-key'
|
||||
import { BRIDGE_ID_PATTERN, idSchema, methodSchema, versionSchema } from './bridge-frame-fields'
|
||||
|
||||
export {
|
||||
BRIDGE_CONNECTION_STATES,
|
||||
BridgeConnectionSnapshotSchema,
|
||||
type BridgeConnectionSnapshot
|
||||
} from './bridge-connection-snapshot'
|
||||
export {
|
||||
BRIDGE_EXTERNAL_LINK_GRANT,
|
||||
BRIDGE_FAULT_GRANT,
|
||||
@@ -46,28 +52,8 @@ import {
|
||||
type BridgeRead
|
||||
} from './bridge-caps'
|
||||
|
||||
export const BRIDGE_CONNECTION_STATES = [
|
||||
'connecting',
|
||||
'handshaking',
|
||||
'connected',
|
||||
'disconnected',
|
||||
'reconnecting',
|
||||
'auth-failed'
|
||||
] as const
|
||||
|
||||
export const BRIDGE_BINARY_FORMATS = ['jpeg', 'png'] as const
|
||||
|
||||
// Send whole connection snapshots so lost frames cannot leave partial state; generation detects snapshots that need repair.
|
||||
export const BridgeConnectionSnapshotSchema = z.object({
|
||||
state: z.enum(BRIDGE_CONNECTION_STATES),
|
||||
reconnectAttempt: z.number().int().nonnegative(),
|
||||
lastConnectedAt: z.number().nullable(),
|
||||
lastInboundAt: z.number().nullable(),
|
||||
generation: z.number().int().nonnegative().nullable()
|
||||
})
|
||||
|
||||
export type BridgeConnectionSnapshot = z.infer<typeof BridgeConnectionSnapshotSchema>
|
||||
|
||||
export const BridgeGrantsSchema = z.object({
|
||||
rpc: z.object({
|
||||
maxPendingRequests: z.number().int().positive(),
|
||||
|
||||
@@ -149,13 +149,7 @@ export function createBridgeRpcClient(options: BridgeRpcClientOptions): BridgeRp
|
||||
}
|
||||
}
|
||||
|
||||
function snapshot(): BridgeConnectionSnapshot {
|
||||
const held = cache.read()
|
||||
if (held === null) {
|
||||
throw new BridgeClientNotReadyError()
|
||||
}
|
||||
return held
|
||||
}
|
||||
const snapshot = () => cache.require()
|
||||
|
||||
// Repeated init for the same session updates route/insets/cache while preserving exchanges and the original storage snapshot. A different session id invalidates prior work.
|
||||
const shellSession = createBridgeClientShellSession({
|
||||
|
||||
Reference in New Issue
Block a user