fix(review round 1, own slice): plugin welcome-gap counting + null-id guard; bridge setup group-kill; Makefile staticcheck gate + worker-image rsync; deploy excludes
This commit is contained in:
@@ -20,14 +20,12 @@ web:
|
|||||||
cd web && bun install && bun run build
|
cd web && bun install && bun run build
|
||||||
|
|
||||||
worker-image:
|
worker-image:
|
||||||
docker build -f docker/worker.Dockerfile \
|
bash deploy/rsync-pi-agent.sh
|
||||||
--build-arg LVMH_PLUGIN=build-plugin/lvmh-agent.ts \
|
docker build -f docker/worker.Dockerfile -t lvmh-worker:latest .
|
||||||
-t lvmh-worker:latest .
|
|
||||||
@# build-plugin/ is prepared by deploy/prep-worker.sh
|
|
||||||
|
|
||||||
verify: daemon
|
verify: daemon
|
||||||
cd daemon && go vet ./...
|
cd daemon && go vet ./...
|
||||||
cd daemon && staticcheck ./... || true
|
cd daemon && staticcheck ./...
|
||||||
cd daemon && go test ./... -count=1
|
cd daemon && go test ./... -count=1
|
||||||
cd web && bun run build
|
cd web && bun run build
|
||||||
cd plugin && bunx tsc@5.9 --noEmit -p tsconfig.json
|
cd plugin && bunx tsc@5.9 --noEmit -p tsconfig.json
|
||||||
@@ -35,7 +33,7 @@ verify: daemon
|
|||||||
test:
|
test:
|
||||||
cd daemon && go test ./... -count=1
|
cd daemon && go test ./... -count=1
|
||||||
|
|
||||||
deploy: verify worker-image
|
deploy: verify
|
||||||
bash deploy/deploy.sh $(REMOTE) $(REMOTE_DIR)
|
bash deploy/deploy.sh $(REMOTE) $(REMOTE_DIR)
|
||||||
|
|
||||||
e2e:
|
e2e:
|
||||||
|
|||||||
+10
-2
@@ -17,15 +17,23 @@ async function runRepoSetup() {
|
|||||||
if (!existsSync(SETUP_PATH)) return;
|
if (!existsSync(SETUP_PATH)) return;
|
||||||
console.error(`[lvmh-bridge] running repo setup: ${SETUP_PATH}`);
|
console.error(`[lvmh-bridge] running repo setup: ${SETUP_PATH}`);
|
||||||
const code = await new Promise((resolve) => {
|
const code = await new Promise((resolve) => {
|
||||||
|
// detached + negative-pid kill: take down the whole process group so
|
||||||
|
// setup grandchildren cannot outlive the timeout (node-as-PID1 never
|
||||||
|
// reaps adopted orphans).
|
||||||
const child = spawn("bash", [SETUP_PATH], {
|
const child = spawn("bash", [SETUP_PATH], {
|
||||||
cwd: "/workspace",
|
cwd: "/workspace",
|
||||||
|
detached: true,
|
||||||
stdio: ["ignore", "inherit", "inherit"],
|
stdio: ["ignore", "inherit", "inherit"],
|
||||||
});
|
});
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
console.error(
|
console.error(
|
||||||
`[lvmh-bridge] setup timed out after ${SETUP_TIMEOUT_MS}ms, killing`,
|
`[lvmh-bridge] setup timed out after ${SETUP_TIMEOUT_MS}ms, killing process group`,
|
||||||
);
|
);
|
||||||
child.kill("SIGKILL");
|
try {
|
||||||
|
process.kill(-child.pid, "SIGKILL");
|
||||||
|
} catch {
|
||||||
|
child.kill("SIGKILL");
|
||||||
|
}
|
||||||
resolve(124);
|
resolve(124);
|
||||||
}, SETUP_TIMEOUT_MS);
|
}, SETUP_TIMEOUT_MS);
|
||||||
timer.unref?.();
|
timer.unref?.();
|
||||||
|
|||||||
@@ -487,6 +487,20 @@ export default function (pi: ExtensionAPI): void {
|
|||||||
const counter: number = seqCounters.get(currentSessionId) ?? 0;
|
const counter: number = seqCounters.get(currentSessionId) ?? 0;
|
||||||
if (counter <= lastSeq) seqCounters.set(currentSessionId, lastSeq);
|
if (counter <= lastSeq) seqCounters.set(currentSessionId, lastSeq);
|
||||||
}
|
}
|
||||||
|
// Events already covered by the daemon's lastSeq are silently absent
|
||||||
|
// from both replay and queue below — count them so the buffer_overflow
|
||||||
|
// notice reflects every gap, not just cap drops.
|
||||||
|
const covered: number =
|
||||||
|
replayBuf.filter((f) => f.seq <= lastSeq).length +
|
||||||
|
sendQueue.filter(
|
||||||
|
(f) => !TRANSIENT_TYPES.has(f.type) && f.seq <= lastSeq,
|
||||||
|
).length;
|
||||||
|
if (covered > 0) {
|
||||||
|
droppedEvents += covered;
|
||||||
|
log(
|
||||||
|
`welcome lastSeq=${lastSeq} covers ${covered} in-flight events; flagging`,
|
||||||
|
);
|
||||||
|
}
|
||||||
// Replay persisted events the daemon is missing, before queued live
|
// Replay persisted events the daemon is missing, before queued live
|
||||||
// frames. Persisted-kind frames still sitting in the queue are dropped
|
// frames. Persisted-kind frames still sitting in the queue are dropped
|
||||||
// here: they are already in replayBuf, so sending both would duplicate
|
// here: they are already in replayBuf, so sending both would duplicate
|
||||||
@@ -620,6 +634,10 @@ export default function (pi: ExtensionAPI): void {
|
|||||||
}
|
}
|
||||||
if (sessionId === null) {
|
if (sessionId === null) {
|
||||||
log("no session id; lvmh mirroring disabled for this session");
|
log("no session id; lvmh mirroring disabled for this session");
|
||||||
|
// Enforce the logged contract: stop mirroring rather than
|
||||||
|
// attributing this session's events to the previous session id.
|
||||||
|
currentSessionId = null;
|
||||||
|
handleDisconnect();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const assignedId = process.env[ENV_SESSION_ID];
|
const assignedId = process.env[ENV_SESSION_ID];
|
||||||
|
|||||||
Reference in New Issue
Block a user