Skip to content

Commit f6605e3

Browse files
wan9chiclaude
andcommitted
fix(server): drain backlog-queued accepts before shutting down listener
The accept loop's `tokio::select!` could exit via the shutdown branch before ever observing a connection that had already been established at the kernel level, so fire-and-forget clients that connect, write, and exit right before the runner signals stop_accepting would silently lose their requests. After the main loop exits we now do one non-blocking `poll!` of `listener.accept()` per iteration until it returns Pending, ensuring every backlog-queued connection gets its handle_client future pushed and drained. Also: - drop the now-redundant `crates/vite_task_client_napi/tests/e2e.rs`; the IPC path is covered end-to-end by the `ipc_client_test` fixture plus `vite_build_cache` - oxfmt the fixture scripts and the JS wrapper Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 41fe1c0 commit f6605e3

12 files changed

Lines changed: 224 additions & 158 deletions

File tree

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { disableCache } from "@voidzero-dev/vite-task-client";
2-
import { writeFileSync, mkdirSync } from "node:fs";
1+
import { disableCache } from '@voidzero-dev/vite-task-client';
2+
import { writeFileSync, mkdirSync } from 'node:fs';
33

44
// Produce an output, then ask the runner not to cache this execution — the
55
// next `vt run` should re-execute the task.
6-
mkdirSync("dist", { recursive: true });
7-
writeFileSync("dist/out.txt", "ok\n");
6+
mkdirSync('dist', { recursive: true });
7+
writeFileSync('dist/out.txt', 'ok\n');
88
disableCache();
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { fetchEnv } from "@voidzero-dev/vite-task-client";
2-
import { writeFileSync, mkdirSync } from "node:fs";
1+
import { fetchEnv } from '@voidzero-dev/vite-task-client';
2+
import { writeFileSync, mkdirSync } from 'node:fs';
33

44
// fetchEnv populates process.env from the runner and — with tracked: true —
55
// adds the env to the post-run fingerprint, so a change between runs
66
// invalidates the cache.
7-
fetchEnv("PROBE_ENV", { tracked: true });
8-
const value = process.env.PROBE_ENV ?? "(unset)";
7+
fetchEnv('PROBE_ENV', { tracked: true });
8+
const value = process.env.PROBE_ENV ?? '(unset)';
99

10-
mkdirSync("dist", { recursive: true });
11-
writeFileSync("dist/out.txt", "PROBE_ENV=" + value + "\n");
10+
mkdirSync('dist', { recursive: true });
11+
writeFileSync('dist/out.txt', 'PROBE_ENV=' + value + '\n');
Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
import { ignoreInput } from "@voidzero-dev/vite-task-client";
2-
import { writeFileSync, readFileSync } from "node:fs";
3-
import { mkdirSync } from "node:fs";
1+
import { ignoreInput } from '@voidzero-dev/vite-task-client';
2+
import { writeFileSync, readFileSync } from 'node:fs';
3+
import { mkdirSync } from 'node:fs';
44

55
// The task reads from `cache_like/` (which we want the runner to IGNORE as
66
// an input), and writes to `dist/`. Without the ignore, the auto-input
77
// fingerprint would fluctuate with cache_like/ contents even though they're
88
// not semantic inputs.
9-
mkdirSync("cache_like", { recursive: true });
10-
writeFileSync("cache_like/stale.txt", "stale-" + Date.now() + "\n");
11-
ignoreInput("cache_like");
12-
readFileSync("cache_like/stale.txt", "utf8");
9+
mkdirSync('cache_like', { recursive: true });
10+
writeFileSync('cache_like/stale.txt', 'stale-' + Date.now() + '\n');
11+
ignoreInput('cache_like');
12+
readFileSync('cache_like/stale.txt', 'utf8');
1313

14-
mkdirSync("dist", { recursive: true });
15-
writeFileSync("dist/out.txt", "ok\n");
14+
mkdirSync('dist', { recursive: true });
15+
writeFileSync('dist/out.txt', 'ok\n');
Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
import { ignoreOutput } from "@voidzero-dev/vite-task-client";
2-
import { writeFileSync, readFileSync, mkdirSync } from "node:fs";
1+
import { ignoreOutput } from '@voidzero-dev/vite-task-client';
2+
import { writeFileSync, readFileSync, mkdirSync } from 'node:fs';
33

44
// The task both reads and writes `sidecar/tmp.txt`. If the runner didn't
55
// treat `sidecar/` as an ignored output, the read-write overlap check would
66
// refuse to cache the task. `dist/out.txt` is the real output.
7-
mkdirSync("sidecar", { recursive: true });
8-
writeFileSync("sidecar/tmp.txt", "initial\n");
9-
readFileSync("sidecar/tmp.txt", "utf8");
10-
writeFileSync("sidecar/tmp.txt", "final\n");
11-
ignoreOutput("sidecar");
7+
mkdirSync('sidecar', { recursive: true });
8+
writeFileSync('sidecar/tmp.txt', 'initial\n');
9+
readFileSync('sidecar/tmp.txt', 'utf8');
10+
writeFileSync('sidecar/tmp.txt', 'final\n');
11+
ignoreOutput('sidecar');
1212

13-
mkdirSync("dist", { recursive: true });
14-
writeFileSync("dist/out.txt", "ok\n");
13+
mkdirSync('dist', { recursive: true });
14+
writeFileSync('dist/out.txt', 'ok\n');

crates/vite_task_bin/tests/e2e_snapshots/fixtures/ipc_client_test/snapshots.toml

Lines changed: 76 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,22 @@ runs do not invalidate the cache.
77
"""
88
ignore = true
99
steps = [
10-
{ argv = ["vt", "run", "ignore-input"], comment = "populate the cache" },
11-
{ argv = ["vtt", "write-file", "cache_like/other.txt", "after"], comment = "mutate the ignored directory — would invalidate if tracked" },
12-
{ argv = ["vt", "run", "ignore-input"], comment = "cache hit: cache_like/ was ignored via ignoreInput" },
10+
{ argv = [
11+
"vt",
12+
"run",
13+
"ignore-input",
14+
], comment = "populate the cache" },
15+
{ argv = [
16+
"vtt",
17+
"write-file",
18+
"cache_like/other.txt",
19+
"after",
20+
], comment = "mutate the ignored directory — would invalidate if tracked" },
21+
{ argv = [
22+
"vt",
23+
"run",
24+
"ignore-input",
25+
], comment = "cache hit: cache_like/ was ignored via ignoreInput" },
1326
]
1427

1528
[[e2e]]
@@ -21,10 +34,26 @@ cache the run ("read and wrote 'sidecar/tmp.txt'").
2134
"""
2235
ignore = true
2336
steps = [
24-
{ argv = ["vt", "run", "ignore-output"], comment = "first run populates the cache" },
25-
{ argv = ["vtt", "rm", "dist/out.txt"], comment = "remove the real output so the cache-hit restore is observable" },
26-
{ argv = ["vt", "run", "ignore-output"], comment = "cache hit: sidecar/ writes were ignored" },
27-
{ argv = ["vtt", "print-file", "dist/out.txt"], comment = "restored from the cache archive" },
37+
{ argv = [
38+
"vt",
39+
"run",
40+
"ignore-output",
41+
], comment = "first run populates the cache" },
42+
{ argv = [
43+
"vtt",
44+
"rm",
45+
"dist/out.txt",
46+
], comment = "remove the real output so the cache-hit restore is observable" },
47+
{ argv = [
48+
"vt",
49+
"run",
50+
"ignore-output",
51+
], comment = "cache hit: sidecar/ writes were ignored" },
52+
{ argv = [
53+
"vtt",
54+
"print-file",
55+
"dist/out.txt",
56+
], comment = "restored from the cache archive" },
2857
]
2958

3059
[[e2e]]
@@ -35,8 +64,16 @@ so the next invocation re-executes instead of hitting a prior entry.
3564
"""
3665
ignore = true
3766
steps = [
38-
{ argv = ["vt", "run", "disable-cache"], comment = "first run — tool calls disableCache" },
39-
{ argv = ["vt", "run", "disable-cache"], comment = "cache miss (NotFound) because nothing was cached" },
67+
{ argv = [
68+
"vt",
69+
"run",
70+
"disable-cache",
71+
], comment = "first run — tool calls disableCache" },
72+
{ argv = [
73+
"vt",
74+
"run",
75+
"disable-cache",
76+
], comment = "cache miss (NotFound) because nothing was cached" },
4077
]
4178

4279
[[e2e]]
@@ -48,7 +85,34 @@ misses with `tracked env 'PROBE_ENV' changed`.
4885
"""
4986
ignore = true
5087
steps = [
51-
{ argv = ["vt", "run", "fetch-env"], envs = [["PROBE_ENV", "first"]], comment = "first run captures PROBE_ENV=first in the fingerprint" },
52-
{ argv = ["vt", "run", "fetch-env"], envs = [["PROBE_ENV", "first"]], comment = "cache hit: PROBE_ENV unchanged" },
53-
{ argv = ["vt", "run", "fetch-env"], envs = [["PROBE_ENV", "second"]], comment = "cache miss: tracked env changed" },
88+
{ argv = [
89+
"vt",
90+
"run",
91+
"fetch-env",
92+
], envs = [
93+
[
94+
"PROBE_ENV",
95+
"first",
96+
],
97+
], comment = "first run captures PROBE_ENV=first in the fingerprint" },
98+
{ argv = [
99+
"vt",
100+
"run",
101+
"fetch-env",
102+
], envs = [
103+
[
104+
"PROBE_ENV",
105+
"first",
106+
],
107+
], comment = "cache hit: PROBE_ENV unchanged" },
108+
{ argv = [
109+
"vt",
110+
"run",
111+
"fetch-env",
112+
], envs = [
113+
[
114+
"PROBE_ENV",
115+
"second",
116+
],
117+
], comment = "cache miss: tracked env changed" },
54118
]

crates/vite_task_bin/tests/e2e_snapshots/fixtures/vite_build_cache/index.html

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
<!DOCTYPE html>
1+
<!doctype html>
22
<html>
3-
<head><title>vp-run-vite-cache</title></head>
3+
<head>
4+
<title>vp-run-vite-cache</title>
5+
</head>
46
<body>
57
<script type="module" src="/src/main.js"></script>
68
</body>

crates/vite_task_bin/tests/e2e_snapshots/fixtures/vite_build_cache/snapshots.toml

Lines changed: 84 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,33 @@ writes to `node_modules/.vite/` don't poison the cache.
99
"""
1010
ignore = true
1111
steps = [
12-
{ argv = ["vt", "run", "--cache", "build"], comment = "first run: cache miss, emits dist/" },
13-
{ argv = ["vtt", "stat-file", "dist/assets/main.js"], comment = "existence check — content would drift across Vite versions" },
14-
{ argv = ["vtt", "rm", "dist/assets/main.js"], comment = "remove the artefact so the cache-hit restore is observable" },
15-
{ argv = ["vt", "run", "--cache", "build"], comment = "cache hit: outputs restored without manual config" },
16-
{ argv = ["vtt", "stat-file", "dist/assets/main.js"], comment = "restored from the cache archive" },
12+
{ argv = [
13+
"vt",
14+
"run",
15+
"--cache",
16+
"build",
17+
], comment = "first run: cache miss, emits dist/" },
18+
{ argv = [
19+
"vtt",
20+
"stat-file",
21+
"dist/assets/main.js",
22+
], comment = "existence check — content would drift across Vite versions" },
23+
{ argv = [
24+
"vtt",
25+
"rm",
26+
"dist/assets/main.js",
27+
], comment = "remove the artefact so the cache-hit restore is observable" },
28+
{ argv = [
29+
"vt",
30+
"run",
31+
"--cache",
32+
"build",
33+
], comment = "cache hit: outputs restored without manual config" },
34+
{ argv = [
35+
"vtt",
36+
"stat-file",
37+
"dist/assets/main.js",
38+
], comment = "restored from the cache archive" },
1739
]
1840

1941
[[e2e]]
@@ -27,11 +49,61 @@ the branch matching the current mode.
2749
"""
2850
ignore = true
2951
steps = [
30-
{ argv = ["vt", "run", "--cache", "build"], envs = [["NODE_ENV", "production"]], comment = "first run: production build" },
31-
{ argv = ["vtt", "grep-file", "dist/assets/main.js", "BUILD_MODE_PROD"], comment = "production build: PROD marker survived DCE" },
32-
{ argv = ["vtt", "grep-file", "dist/assets/main.js", "BUILD_MODE_DEV"], comment = "dev branch is gone" },
33-
{ argv = ["vt", "run", "--cache", "build"], envs = [["NODE_ENV", "production"]], comment = "cache hit: NODE_ENV unchanged" },
34-
{ argv = ["vt", "run", "--cache", "build"], envs = [["NODE_ENV", "development"]], comment = "cache miss: Vite's fetchEnv marked NODE_ENV as tracked" },
35-
{ argv = ["vtt", "grep-file", "dist/assets/main.js", "BUILD_MODE_PROD"], comment = "PROD marker gone after the dev rebuild" },
36-
{ argv = ["vtt", "grep-file", "dist/assets/main.js", "BUILD_MODE_DEV"], comment = "DEV marker now in the bundle" },
52+
{ argv = [
53+
"vt",
54+
"run",
55+
"--cache",
56+
"build",
57+
], envs = [
58+
[
59+
"NODE_ENV",
60+
"production",
61+
],
62+
], comment = "first run: production build" },
63+
{ argv = [
64+
"vtt",
65+
"grep-file",
66+
"dist/assets/main.js",
67+
"BUILD_MODE_PROD",
68+
], comment = "production build: PROD marker survived DCE" },
69+
{ argv = [
70+
"vtt",
71+
"grep-file",
72+
"dist/assets/main.js",
73+
"BUILD_MODE_DEV",
74+
], comment = "dev branch is gone" },
75+
{ argv = [
76+
"vt",
77+
"run",
78+
"--cache",
79+
"build",
80+
], envs = [
81+
[
82+
"NODE_ENV",
83+
"production",
84+
],
85+
], comment = "cache hit: NODE_ENV unchanged" },
86+
{ argv = [
87+
"vt",
88+
"run",
89+
"--cache",
90+
"build",
91+
], envs = [
92+
[
93+
"NODE_ENV",
94+
"development",
95+
],
96+
], comment = "cache miss: Vite's fetchEnv marked NODE_ENV as tracked" },
97+
{ argv = [
98+
"vtt",
99+
"grep-file",
100+
"dist/assets/main.js",
101+
"BUILD_MODE_PROD",
102+
], comment = "PROD marker gone after the dev rebuild" },
103+
{ argv = [
104+
"vtt",
105+
"grep-file",
106+
"dist/assets/main.js",
107+
"BUILD_MODE_DEV",
108+
], comment = "DEV marker now in the bundle" },
37109
]
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// Vite's `define` plugin replaces `process.env.NODE_ENV` at build time, so
22
// whichever branch runs becomes a static part of the bundle. The markers let
33
// the e2e test assert that flipping NODE_ENV actually changed what was built.
4-
if (process.env.NODE_ENV === "production") {
5-
document.body.append("BUILD_MODE_PROD");
4+
if (process.env.NODE_ENV === 'production') {
5+
document.body.append('BUILD_MODE_PROD');
66
} else {
7-
document.body.append("BUILD_MODE_DEV");
7+
document.body.append('BUILD_MODE_DEV');
88
}

crates/vite_task_bin/tests/e2e_snapshots/fixtures/vite_build_cache/vite.config.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
import { defineConfig } from "vite";
1+
import { defineConfig } from 'vite';
22

33
export default defineConfig({
4-
logLevel: "silent",
4+
logLevel: 'silent',
55
build: {
66
rollupOptions: {
77
output: {
88
// Stable filenames make cache behaviour deterministic across runs.
9-
entryFileNames: "assets/main.js",
10-
chunkFileNames: "assets/chunk.js",
11-
assetFileNames: "assets/[name][extname]",
9+
entryFileNames: 'assets/main.js',
10+
chunkFileNames: 'assets/chunk.js',
11+
assetFileNames: 'assets/[name][extname]',
1212
},
1313
},
1414
},

0 commit comments

Comments
 (0)