Files
deepseek-harness/apps/desktop/src/update-http-executor.ts
T

54 lines
2.3 KiB
TypeScript

/** Electron-native inactivity deadlines for updater checks, full downloads, and blockmap requests. */
import { ElectronHttpExecutor } from 'electron-updater/out/electronHttpExecutor.js'
import type { ClientRequest, IncomingMessage } from 'electron'
/** Retains electron-updater transport and proxy handling while bounding silent connections. */
export class DesktopUpdateHttpExecutor extends ElectronHttpExecutor {
/**
* @param idleTimeoutMs - Maximum silence before headers or between response chunks, not a total download deadline.
* @param proxyLogin - Existing updater login event forwarding.
*/
constructor(private readonly idleTimeoutMs: number, proxyLogin?: ConstructorParameters<typeof ElectronHttpExecutor>[0]) {
super(proxyLogin)
if (!Number.isSafeInteger(idleTimeoutMs) || idleTimeoutMs < 1000 || idleTimeoutMs > 2_147_483_647) {
throw new Error('desktop update: HTTP idle timeout must be an integer from 1000 through 2147483647')
}
}
override addErrorAndTimeoutHandlers(request: ClientRequest, reject: (error: Error) => void): void {
// The upstream socket timer is for Node HTTP; Electron ClientRequest has response/close events instead.
super.addErrorAndTimeoutHandlers(request, reject, this.idleTimeoutMs)
let response: IncomingMessage | undefined
let timer: ReturnType<typeof setTimeout>
const stop = (): void => {
clearTimeout(timer)
request.off('response', onResponse)
request.off('abort', stop)
request.off('error', stop)
response?.off('data', refresh)
response?.off('end', stop)
response?.off('error', stop)
}
const refresh = (): void => {
clearTimeout(timer)
timer = setTimeout(() => {
stop()
reject(Object.assign(new Error('Desktop update connection timed out'), { code: 'ETIMEDOUT' }))
request.abort()
}, this.idleTimeoutMs)
}
const onResponse = (incoming: IncomingMessage): void => {
response = incoming
response.on('data', refresh)
response.once('end', stop)
response.once('error', stop)
refresh()
}
request.once('response', onResponse)
// Electron 44 can emit writable close after finish, before response headers arrive.
request.once('abort', stop)
request.once('error', stop)
refresh()
}
}