🐛 fix(vscode): webhook 窗口登记先写临时文件再改名,避免被占端口的窗口当成陈旧条目删掉
This commit is contained in:
1 parent
2dabbf1200
commit
3e3de0ae07
2 files changed
+27
-2
No files matched your search
@@ -36,9 +36,13 @@ function processAlive(pid: number): boolean {
|
|||||||
export class PeerRegistry {
|
export class PeerRegistry {
|
||||||
constructor(private readonly dir: string) {}
|
constructor(private readonly dir: string) {}
|
||||||
|
|
||||||
|
/** 先写进临时文件再改名成端口号,别的窗口列登记时就不会读到还没写进 pid 的空文件、把它当成已退出的窗口删掉。 */
|
||||||
async add(port: number): Promise<void> {
|
async add(port: number): Promise<void> {
|
||||||
await fsp.mkdir(this.dir, { recursive: true })
|
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> {
|
async remove(port: number): Promise<void> {
|
||||||
|
|||||||
@@ -2,10 +2,11 @@ import type { IncomingHttpHeaders } from 'node:http'
|
|||||||
import type { WebhookEvent } from './eventParser'
|
import type { WebhookEvent } from './eventParser'
|
||||||
import { Buffer } from 'node:buffer'
|
import { Buffer } from 'node:buffer'
|
||||||
import { createHmac } from 'node:crypto'
|
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 { tmpdir } from 'node:os'
|
||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||||
|
import { PeerRegistry } from './relay'
|
||||||
import { handleWebhookRequest, WebhookServer } from './server'
|
import { handleWebhookRequest, WebhookServer } from './server'
|
||||||
|
|
||||||
const mocks = vi.hoisted(() => ({ log: vi.fn() }))
|
const mocks = vi.hoisted(() => ({ log: vi.fn() }))
|
||||||
@@ -206,6 +207,26 @@ describe('同一台机器多个窗口共用端口', () => {
|
|||||||
await vi.waitFor(() => expect(readdirSync(dir)).toEqual([]))
|
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 () => {
|
it('同一端口重复 start 不会自己挤掉自己', async () => {
|
||||||
const hub = open()
|
const hub = open()
|
||||||
await hub.server.start(0)
|
await hub.server.start(0)
|
||||||
|
|||||||
Reference in new issue
Block a user