🐛 fix(vscode): webhook 窗口登记先写临时文件再改名,避免被占端口的窗口当成陈旧条目删掉

This commit is contained in:
cruldra committed 2026-10-19 08:38:54 +11:00
1 parent 2dabbf1200
commit 3e3de0ae07
2 files changed
+27 -2

No files matched your search

+5 -1
View File
@@ -36,9 +36,13 @@ function processAlive(pid: number): boolean {
export class PeerRegistry {
constructor(private readonly dir: string) {}
/** 先写进临时文件再改名成端口号,别的窗口列登记时就不会读到还没写进 pid 的空文件、把它当成已退出的窗口删掉。 */
async add(port: number): Promise<void> {
await fsp.mkdir(this.dir, { recursive: true })
await fsp.writeFile(path.join(this.dir, String(port)), String(process.pid))
const file = path.join(this.dir, String(port))
const temp = `${file}.${process.pid}.tmp`
await fsp.writeFile(temp, String(process.pid))
await fsp.rename(temp, file)
}
async remove(port: number): Promise<void> {
+22 -1
View File
@@ -2,10 +2,11 @@ import type { IncomingHttpHeaders } from 'node:http'
import type { WebhookEvent } from './eventParser'
import { Buffer } from 'node:buffer'
import { createHmac } from 'node:crypto'
import { mkdirSync, mkdtempSync, readdirSync, rmSync, writeFileSync } from 'node:fs'
import { promises as fsp, mkdirSync, mkdtempSync, readdirSync, rmSync, writeFileSync } from 'node:fs'
import { tmpdir } from 'node:os'
import path from 'node:path'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { PeerRegistry } from './relay'
import { handleWebhookRequest, WebhookServer } from './server'
const mocks = vi.hoisted(() => ({ log: vi.fn() }))
@@ -206,6 +207,26 @@ describe('同一台机器多个窗口共用端口', () => {
await vi.waitFor(() => expect(readdirSync(dir)).toEqual([]))
})
it('登记文件写到一半时别的窗口来列登记,不会把它当成陈旧条目删掉', async () => {
const registry = new PeerRegistry(path.join(peerRoot, '17421'))
const remove = vi.spyOn(registry, 'remove')
const realWriteFile = fsp.writeFile.bind(fsp)
const write = vi.spyOn(fsp, 'writeFile').mockImplementation(async (file, data) => {
// 文件已经建好、pid 还没写进去的那一刻,占着端口的窗口正好来列登记。
await realWriteFile(file, '')
await registry.ports()
await realWriteFile(file, data)
})
try {
await registry.add(50000)
}
finally {
write.mockRestore()
}
expect(remove).not.toHaveBeenCalled()
expect(await registry.ports()).toEqual([50000])
})
it('同一端口重复 start 不会自己挤掉自己', async () => {
const hub = open()
await hub.server.start(0)