fix(POSTV1-02): 补齐便携包Worker运行依赖
Dada P0-A isolated Windows CI / validate-and-package (push) Waiting to run
Dada P0-A isolated Windows CI / validate-and-package (push) Waiting to run
This commit is contained in:
@@ -336,7 +336,7 @@ export async function buildAndValidatePortablePackage({ evidenceDirectory, outpu
|
|||||||
debug("copy API application");
|
debug("copy API application");
|
||||||
const apiDependencies = copyApplication(join(repositoryRoot, "apps", "api"), join(serverRoot, "api"), ["@fastify/multipart", "@fastify/swagger", "@sinclair/typebox", "better-sqlite3", "fastify", "sharp"]);
|
const apiDependencies = copyApplication(join(repositoryRoot, "apps", "api"), join(serverRoot, "api"), ["@fastify/multipart", "@fastify/swagger", "@sinclair/typebox", "better-sqlite3", "fastify", "sharp"]);
|
||||||
debug("copy Worker application");
|
debug("copy Worker application");
|
||||||
const workerDependencies = copyApplication(join(repositoryRoot, "apps", "worker"), join(serverRoot, "worker"), ["better-sqlite3"]);
|
const workerDependencies = copyApplication(join(repositoryRoot, "apps", "worker"), join(serverRoot, "worker"), ["better-sqlite3", "sharp"]);
|
||||||
const sharedDestination = join(serverRoot, "api", "node_modules", "@dada", "shared-contracts");
|
const sharedDestination = join(serverRoot, "api", "node_modules", "@dada", "shared-contracts");
|
||||||
mkdirSync(sharedDestination, { recursive: true });
|
mkdirSync(sharedDestination, { recursive: true });
|
||||||
copyTree(join(repositoryRoot, "packages", "shared-contracts", "dist"), join(sharedDestination, "dist"));
|
copyTree(join(repositoryRoot, "packages", "shared-contracts", "dist"), join(sharedDestination, "dist"));
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { existsSync } from "node:fs";
|
|||||||
import { join, resolve } from "node:path";
|
import { join, resolve } from "node:path";
|
||||||
import { tmpdir } from "node:os";
|
import { tmpdir } from "node:os";
|
||||||
import { spawn } from "node:child_process";
|
import { spawn } from "node:child_process";
|
||||||
|
import { createServer } from "node:net";
|
||||||
|
|
||||||
const packageRoot = resolve(process.env.DADA_POSTV1_PACKAGE_ROOT ?? ".build/portable-release/Dada-P0A-0.0.0-win-x64");
|
const packageRoot = resolve(process.env.DADA_POSTV1_PACKAGE_ROOT ?? ".build/portable-release/Dada-P0A-0.0.0-win-x64");
|
||||||
const port = 43121;
|
const port = 43121;
|
||||||
@@ -43,6 +44,71 @@ async function stop(child) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function verifyWorkerStartup(configPath) {
|
||||||
|
const pipeName = `Dada.P0A.PostV1.${process.pid}.${Date.now()}`;
|
||||||
|
const pipePath = `\\\\.\\pipe\\${pipeName}`;
|
||||||
|
const server = createServer();
|
||||||
|
await new Promise((resolveListen, rejectListen) => {
|
||||||
|
server.once("error", rejectListen);
|
||||||
|
server.listen(pipePath, resolveListen);
|
||||||
|
});
|
||||||
|
const child = spawn(join(packageRoot, "runtime", "node.exe"), [
|
||||||
|
join(packageRoot, "server", "worker.mjs"),
|
||||||
|
"--dada-control-pipe", pipeName,
|
||||||
|
"--dada-credential-stdin",
|
||||||
|
], {
|
||||||
|
cwd: packageRoot,
|
||||||
|
env: {
|
||||||
|
...process.env,
|
||||||
|
DADA_INSTANCE_CONFIG_PATH: configPath,
|
||||||
|
DADA_SQLITE_NATIVE_BINDING: join(packageRoot, "server", "native", "better_sqlite3.node"),
|
||||||
|
},
|
||||||
|
stdio: ["pipe", "ignore", "ignore"],
|
||||||
|
windowsHide: true,
|
||||||
|
});
|
||||||
|
child.stdin.end(JSON.stringify({ "Dada/P0A/worker/ai-gateway": "synthetic-runtime-token" }));
|
||||||
|
try {
|
||||||
|
await new Promise((resolveReady, rejectReady) => {
|
||||||
|
let settled = false;
|
||||||
|
const finish = (error) => {
|
||||||
|
if (settled) return;
|
||||||
|
settled = true;
|
||||||
|
clearTimeout(deadline);
|
||||||
|
child.off("exit", onExit);
|
||||||
|
if (error) rejectReady(error); else resolveReady();
|
||||||
|
};
|
||||||
|
const deadline = setTimeout(() => finish(new Error("packaged worker ready timeout")), 15_000);
|
||||||
|
const onExit = (code) => finish(new Error(`packaged worker exited before ready: ${code}`));
|
||||||
|
child.once("exit", onExit);
|
||||||
|
server.once("connection", (connection) => {
|
||||||
|
connection.setEncoding("utf8");
|
||||||
|
let pending = "";
|
||||||
|
connection.on("data", (chunk) => {
|
||||||
|
pending += chunk;
|
||||||
|
while (pending.includes("\n")) {
|
||||||
|
const newline = pending.indexOf("\n");
|
||||||
|
const status = pending.slice(0, newline).trim();
|
||||||
|
pending = pending.slice(newline + 1);
|
||||||
|
if (status === "storage_unavailable") finish(new Error("packaged worker reported storage_unavailable"));
|
||||||
|
if (status === "ready") {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (settled) return;
|
||||||
|
connection.write("shutdown\n");
|
||||||
|
finish();
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
const exitCode = await new Promise((resolveExit) => child.once("exit", resolveExit));
|
||||||
|
assert.equal(exitCode, 0);
|
||||||
|
} finally {
|
||||||
|
if (child.exitCode === null) child.kill();
|
||||||
|
await new Promise((resolveClose) => server.close(resolveClose));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
test("portable package serves the product and keeps SQLite data across API restart", async () => {
|
test("portable package serves the product and keeps SQLite data across API restart", async () => {
|
||||||
assert.ok(existsSync(join(packageRoot, "Dada.exe")));
|
assert.ok(existsSync(join(packageRoot, "Dada.exe")));
|
||||||
assert.ok(existsSync(join(packageRoot, "web", "index.html")));
|
assert.ok(existsSync(join(packageRoot, "web", "index.html")));
|
||||||
@@ -72,6 +138,7 @@ test("portable package serves the product and keeps SQLite data across API resta
|
|||||||
assert.match(await page.text(), /<div id="root"><\/div>/);
|
assert.match(await page.text(), /<div id="root"><\/div>/);
|
||||||
}
|
}
|
||||||
assert.ok(existsSync(join(dataRoot, "db", "dada.sqlite3")));
|
assert.ok(existsSync(join(dataRoot, "db", "dada.sqlite3")));
|
||||||
|
await verifyWorkerStartup(configPath);
|
||||||
} finally {
|
} finally {
|
||||||
await stop(api);
|
await stop(api);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user