Skip to content

Disheartening API:--watch --hot #25373

@vamsaya

Description

@vamsaya

What version of Bun is running?

1.3.4

What platform is your computer?

Ubuntu 22

What steps can reproduce the bug?

中文 English
由于 Bun 没有实现原生的 FileWatcher,Node 的 fs.watch 又过于简单,因此不得不使用子进程方案。但新的问题层出不穷,让人为之抓狂。 Due to Bun's lack of a native FileWatcher and Node's fs.watch being too simplistic, I had to resort to subprocess-based solutions. However, this has introduced a cascade of new issues that are incredibly frustrating.
fs.watch API 在 --watch 模式下表现正常,但在 --hot 模式下,随着重载次数的增多,会触发大量的回调。 The fs.watch API works correctly in --watch mode, but in --hot mode, it triggers an excessive number of callbacks with each reload.
inotifywait 子进程无论在 --watch 还是 --hot 模式下运行,随着脚本更新,系统进程列表中会残留并堆积大量僵尸进程,持续消耗系统资源。 The inotifywait subprocess leaves behind a growing number of orphaned processes in the system process list as scripts are updated, consuming resources continuously in both --watch and --hot modes.
只有按下 Ctrl+C 结束 Bun 进程后,这些子进程才会被关闭。 These subprocesses only terminate when the Bun process itself is killed with Ctrl+C.
我记得 --hot 最初设计的初衷是保证 Bun.serve 不中断服务,以及通过 global.varName ??= "value" 声明的变量不受重载影响。 I recall that --hot was originally designed to keep Bun.serve running without interruption and to preserve variables declared via global.varName ??= "value" across reloads.
此外,在 --hot 模式下,Bun.build 首次构建正常,但一旦主脚本发生变化导致进程重载,就会报错(error: Unexpected reading file:)。 Additionally, under --hot mode, Bun.build succeeds on the first build but throws errors (error: Unexpected reading file:) after the main script changes and triggers a reload.
现在,为什么变得这么难用? Why has it become so unreliable and difficult to use?
async function Watcher(dirname, callback) {
    console.log("watch", dirname);
    const proc = Bun.spawn([
        "inotifywait",
        "--format", "%e\t%w%f",
        "-mrq",
        "-e", "create,modify,delete,moved_from,moved_to",
        dirname
    ]);
    const decoder = new TextDecoder();
    for await (let line of proc.stdout) {
        line = decoder.decode(line).trimEnd();
        for (const row of line.split("\n")) {
            const [event, filename] = row.split("\t");
            callback(event, filename);
        }
    }
}
Watcher("./foo", function () {
    console.log(...arguments);
});
Image

What is the expected behavior?

No response

What do you see instead?

No response

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions