refactor: replace Bun.sleep with node timers (#15013)

This commit is contained in:
Dax 2026-03-05 21:54:06 -05:00 committed by GitHub
parent cf425d114e
commit 3ebba02d04
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 29 additions and 18 deletions

View File

@ -8,6 +8,7 @@ import type { Context as GitHubContext } from "@actions/github/lib/context"
import type { IssueCommentEvent, PullRequestReviewCommentEvent } from "@octokit/webhooks-types" import type { IssueCommentEvent, PullRequestReviewCommentEvent } from "@octokit/webhooks-types"
import { createOpencodeClient } from "@opencode-ai/sdk" import { createOpencodeClient } from "@opencode-ai/sdk"
import { spawn } from "node:child_process" import { spawn } from "node:child_process"
import { setTimeout as sleep } from "node:timers/promises"
type GitHubAuthor = { type GitHubAuthor = {
login: string login: string
@ -281,7 +282,7 @@ async function assertOpencodeConnected() {
connected = true connected = true
break break
} catch (e) {} } catch (e) {}
await Bun.sleep(300) await sleep(300)
} while (retry++ < 30) } while (retry++ < 30)
if (!connected) { if (!connected) {

View File

@ -13,6 +13,7 @@ import { Instance } from "../../project/instance"
import type { Hooks } from "@opencode-ai/plugin" import type { Hooks } from "@opencode-ai/plugin"
import { Process } from "../../util/process" import { Process } from "../../util/process"
import { text } from "node:stream/consumers" import { text } from "node:stream/consumers"
import { setTimeout as sleep } from "node:timers/promises"
type PluginAuth = NonNullable<Hooks["auth"]> type PluginAuth = NonNullable<Hooks["auth"]>
@ -47,7 +48,7 @@ async function handlePluginAuth(plugin: { auth: PluginAuth }, provider: string,
const method = plugin.auth.methods[index] const method = plugin.auth.methods[index]
// Handle prompts for all auth types // Handle prompts for all auth types
await Bun.sleep(10) await sleep(10)
const inputs: Record<string, string> = {} const inputs: Record<string, string> = {}
if (method.prompts) { if (method.prompts) {
for (const prompt of method.prompts) { for (const prompt of method.prompts) {

View File

@ -3,6 +3,7 @@ import { bootstrap } from "../../bootstrap"
import { cmd } from "../cmd" import { cmd } from "../cmd"
import { Log } from "../../../util/log" import { Log } from "../../../util/log"
import { EOL } from "os" import { EOL } from "os"
import { setTimeout as sleep } from "node:timers/promises"
export const LSPCommand = cmd({ export const LSPCommand = cmd({
command: "lsp", command: "lsp",
@ -19,7 +20,7 @@ const DiagnosticsCommand = cmd({
async handler(args) { async handler(args) {
await bootstrap(process.cwd(), async () => { await bootstrap(process.cwd(), async () => {
await LSP.touchFile(args.file, true) await LSP.touchFile(args.file, true)
await Bun.sleep(1000) await sleep(1000)
process.stdout.write(JSON.stringify(await LSP.diagnostics(), null, 2) + EOL) process.stdout.write(JSON.stringify(await LSP.diagnostics(), null, 2) + EOL)
}) })
}, },

View File

@ -28,6 +28,7 @@ import { Bus } from "../../bus"
import { MessageV2 } from "../../session/message-v2" import { MessageV2 } from "../../session/message-v2"
import { SessionPrompt } from "@/session/prompt" import { SessionPrompt } from "@/session/prompt"
import { $ } from "bun" import { $ } from "bun"
import { setTimeout as sleep } from "node:timers/promises"
type GitHubAuthor = { type GitHubAuthor = {
login: string login: string
@ -353,7 +354,7 @@ export const GithubInstallCommand = cmd({
} }
retries++ retries++
await Bun.sleep(1000) await sleep(1000)
} while (true) } while (true)
s.stop("Installed GitHub app") s.stop("Installed GitHub app")
@ -1372,7 +1373,7 @@ Co-authored-by: ${actor} <${actor}@users.noreply.github.com>"`
} catch (e) { } catch (e) {
if (retries > 0) { if (retries > 0) {
console.log(`Retrying after ${delayMs}ms...`) console.log(`Retrying after ${delayMs}ms...`)
await Bun.sleep(delayMs) await sleep(delayMs)
return withRetry(fn, retries - 1, delayMs) return withRetry(fn, retries - 1, delayMs)
} }
throw e throw e

View File

@ -10,6 +10,7 @@ import { GlobalBus } from "@/bus/global"
import { createOpencodeClient, type Event } from "@opencode-ai/sdk/v2" import { createOpencodeClient, type Event } from "@opencode-ai/sdk/v2"
import type { BunWebSocketData } from "hono/bun" import type { BunWebSocketData } from "hono/bun"
import { Flag } from "@/flag/flag" import { Flag } from "@/flag/flag"
import { setTimeout as sleep } from "node:timers/promises"
await Log.init({ await Log.init({
print: process.argv.includes("--print-logs"), print: process.argv.includes("--print-logs"),
@ -75,7 +76,7 @@ const startEventStream = (directory: string) => {
).catch(() => undefined) ).catch(() => undefined)
if (!events) { if (!events) {
await Bun.sleep(250) await sleep(250)
continue continue
} }
@ -84,7 +85,7 @@ const startEventStream = (directory: string) => {
} }
if (!signal.aborted) { if (!signal.aborted) {
await Bun.sleep(250) await sleep(250)
} }
} }
})().catch((error) => { })().catch((error) => {

View File

@ -4,6 +4,7 @@ import { Installation } from "../installation"
import { Auth, OAUTH_DUMMY_KEY } from "../auth" import { Auth, OAUTH_DUMMY_KEY } from "../auth"
import os from "os" import os from "os"
import { ProviderTransform } from "@/provider/transform" import { ProviderTransform } from "@/provider/transform"
import { setTimeout as sleep } from "node:timers/promises"
const log = Log.create({ service: "plugin.codex" }) const log = Log.create({ service: "plugin.codex" })
@ -602,7 +603,7 @@ export async function CodexAuthPlugin(input: PluginInput): Promise<Hooks> {
return { type: "failed" as const } return { type: "failed" as const }
} }
await Bun.sleep(interval + OAUTH_POLLING_SAFETY_MARGIN_MS) await sleep(interval + OAUTH_POLLING_SAFETY_MARGIN_MS)
} }
}, },
} }

View File

@ -1,6 +1,7 @@
import type { Hooks, PluginInput } from "@opencode-ai/plugin" import type { Hooks, PluginInput } from "@opencode-ai/plugin"
import { Installation } from "@/installation" import { Installation } from "@/installation"
import { iife } from "@/util/iife" import { iife } from "@/util/iife"
import { setTimeout as sleep } from "node:timers/promises"
const CLIENT_ID = "Ov23li8tweQw6odWQebz" const CLIENT_ID = "Ov23li8tweQw6odWQebz"
// Add a small safety buffer when polling to avoid hitting the server // Add a small safety buffer when polling to avoid hitting the server
@ -270,7 +271,7 @@ export async function CopilotAuthPlugin(input: PluginInput): Promise<Hooks> {
} }
if (data.error === "authorization_pending") { if (data.error === "authorization_pending") {
await Bun.sleep(deviceData.interval * 1000 + OAUTH_POLLING_SAFETY_MARGIN_MS) await sleep(deviceData.interval * 1000 + OAUTH_POLLING_SAFETY_MARGIN_MS)
continue continue
} }
@ -286,13 +287,13 @@ export async function CopilotAuthPlugin(input: PluginInput): Promise<Hooks> {
newInterval = serverInterval * 1000 newInterval = serverInterval * 1000
} }
await Bun.sleep(newInterval + OAUTH_POLLING_SAFETY_MARGIN_MS) await sleep(newInterval + OAUTH_POLLING_SAFETY_MARGIN_MS)
continue continue
} }
if (data.error) return { type: "failed" as const } if (data.error) return { type: "failed" as const }
await Bun.sleep(deviceData.interval * 1000 + OAUTH_POLLING_SAFETY_MARGIN_MS) await sleep(deviceData.interval * 1000 + OAUTH_POLLING_SAFETY_MARGIN_MS)
continue continue
} }
}, },

View File

@ -3,6 +3,7 @@ import { lazy } from "@/util/lazy"
import { Filesystem } from "@/util/filesystem" import { Filesystem } from "@/util/filesystem"
import path from "path" import path from "path"
import { spawn, type ChildProcess } from "child_process" import { spawn, type ChildProcess } from "child_process"
import { setTimeout as sleep } from "node:timers/promises"
const SIGKILL_TIMEOUT_MS = 200 const SIGKILL_TIMEOUT_MS = 200
@ -22,13 +23,13 @@ export namespace Shell {
try { try {
process.kill(-pid, "SIGTERM") process.kill(-pid, "SIGTERM")
await Bun.sleep(SIGKILL_TIMEOUT_MS) await sleep(SIGKILL_TIMEOUT_MS)
if (!opts?.exited?.()) { if (!opts?.exited?.()) {
process.kill(-pid, "SIGKILL") process.kill(-pid, "SIGKILL")
} }
} catch (_e) { } catch (_e) {
proc.kill("SIGTERM") proc.kill("SIGTERM")
await Bun.sleep(SIGKILL_TIMEOUT_MS) await sleep(SIGKILL_TIMEOUT_MS)
if (!opts?.exited?.()) { if (!opts?.exited?.()) {
proc.kill("SIGKILL") proc.kill("SIGKILL")
} }

View File

@ -3,6 +3,7 @@
import os from "os" import os from "os"
import path from "path" import path from "path"
import fs from "fs/promises" import fs from "fs/promises"
import { setTimeout as sleep } from "node:timers/promises"
import { afterAll } from "bun:test" import { afterAll } from "bun:test"
// Set XDG env vars FIRST, before any src/ imports // Set XDG env vars FIRST, before any src/ imports
@ -15,7 +16,7 @@ afterAll(async () => {
typeof error === "object" && error !== null && "code" in error && error.code === "EBUSY" typeof error === "object" && error !== null && "code" in error && error.code === "EBUSY"
const rm = async (left: number): Promise<void> => { const rm = async (left: number): Promise<void> => {
Bun.gc(true) Bun.gc(true)
await Bun.sleep(100) await sleep(100)
return fs.rm(dir, { recursive: true, force: true }).catch((error) => { return fs.rm(dir, { recursive: true, force: true }).catch((error) => {
if (!busy(error)) throw error if (!busy(error)) throw error
if (left <= 1) throw error if (left <= 1) throw error

View File

@ -2,6 +2,7 @@ import { describe, expect, test } from "bun:test"
import { Instance } from "../../src/project/instance" import { Instance } from "../../src/project/instance"
import { Pty } from "../../src/pty" import { Pty } from "../../src/pty"
import { tmpdir } from "../fixture/fixture" import { tmpdir } from "../fixture/fixture"
import { setTimeout as sleep } from "node:timers/promises"
describe("pty", () => { describe("pty", () => {
test("does not leak output when websocket objects are reused", async () => { test("does not leak output when websocket objects are reused", async () => {
@ -43,7 +44,7 @@ describe("pty", () => {
// Output from a must never show up in b. // Output from a must never show up in b.
Pty.write(a.id, "AAA\n") Pty.write(a.id, "AAA\n")
await Bun.sleep(100) await sleep(100)
expect(outB.join("")).not.toContain("AAA") expect(outB.join("")).not.toContain("AAA")
} finally { } finally {
@ -88,7 +89,7 @@ describe("pty", () => {
} }
Pty.write(a.id, "AAA\n") Pty.write(a.id, "AAA\n")
await Bun.sleep(100) await sleep(100)
expect(outB.join("")).not.toContain("AAA") expect(outB.join("")).not.toContain("AAA")
} finally { } finally {
@ -128,7 +129,7 @@ describe("pty", () => {
ctx.connId = 2 ctx.connId = 2
Pty.write(a.id, "AAA\n") Pty.write(a.id, "AAA\n")
await Bun.sleep(100) await sleep(100)
expect(out.join("")).toContain("AAA") expect(out.join("")).toContain("AAA")
} finally { } finally {

View File

@ -1,6 +1,7 @@
import { describe, expect, test } from "bun:test" import { describe, expect, test } from "bun:test"
import type { NamedError } from "@opencode-ai/util/error" import type { NamedError } from "@opencode-ai/util/error"
import { APICallError } from "ai" import { APICallError } from "ai"
import { setTimeout as sleep } from "node:timers/promises"
import { SessionRetry } from "../../src/session/retry" import { SessionRetry } from "../../src/session/retry"
import { MessageV2 } from "../../src/session/message-v2" import { MessageV2 } from "../../src/session/message-v2"
@ -135,7 +136,7 @@ describe("session.message-v2.fromError", () => {
new ReadableStream({ new ReadableStream({
async pull(controller) { async pull(controller) {
controller.enqueue("Hello,") controller.enqueue("Hello,")
await Bun.sleep(10000) await sleep(10000)
controller.enqueue(" World!") controller.enqueue(" World!")
controller.close() controller.close()
}, },