Skip to content

Commit da5e7d8

Browse files
committed
api/v2/exec: refactor process stats monitor and reuse a part of it
1 parent 667cab3 commit da5e7d8

File tree

21 files changed

+459
-225
lines changed

21 files changed

+459
-225
lines changed

src/packages/backend/execute-code.test.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
process.env.COCALC_PROJECT_MONITOR_INTERVAL_S = "1";
2+
13
import { executeCode } from "./execute-code";
24

35
describe("hello world", () => {
@@ -90,6 +92,27 @@ describe("test timeout", () => {
9092
});
9193
});
9294

95+
describe("test longer execution", () => {
96+
it(
97+
"runs 5 seconds",
98+
async () => {
99+
const t0 = Date.now();
100+
const { stdout, stderr, exit_code } = await executeCode({
101+
command: "sh",
102+
args: ["-c", "echo foo; sleep 5; echo bar"],
103+
err_on_exit: false,
104+
bash: false,
105+
});
106+
expect(stdout).toBe("foo\nbar\n");
107+
expect(stderr).toBe("");
108+
expect(exit_code).toBe(0);
109+
const t1 = Date.now();
110+
expect((t1 - t0) / 1000).toBeGreaterThan(4.9);
111+
},
112+
10 * 1000,
113+
);
114+
});
115+
93116
describe("test env", () => {
94117
it("allows to specify environment variables", async () => {
95118
const { stdout, stderr, type } = await executeCode({
@@ -211,6 +234,7 @@ describe("async", () => {
211234
expect(typeof job_id).toEqual("string");
212235
if (typeof job_id !== "string") return;
213236
await new Promise((done) => setTimeout(done, 250));
237+
// now we check up on the job
214238
const s = await executeCode({ async_get: job_id });
215239
expect(s.type).toEqual("async");
216240
if (s.type !== "async") return;
@@ -224,4 +248,47 @@ describe("async", () => {
224248
);
225249
expect(s.exit_code).toEqual(1);
226250
});
251+
252+
it(
253+
"long running async job",
254+
async () => {
255+
const c = await executeCode({
256+
command: "sh",
257+
args: ["-c", `echo foo; python3 -c '${CPU_PY}'; echo bar;`],
258+
bash: false,
259+
err_on_exit: false,
260+
async_call: true,
261+
});
262+
expect(c.type).toEqual("async");
263+
if (c.type !== "async") return;
264+
const { status, job_id } = c;
265+
expect(status).toEqual("running");
266+
expect(typeof job_id).toEqual("string");
267+
if (typeof job_id !== "string") return;
268+
await new Promise((done) => setTimeout(done, 5500));
269+
// now we check up on the job
270+
const s = await executeCode({ async_get: job_id });
271+
expect(s.type).toEqual("async");
272+
if (s.type !== "async") return;
273+
expect(s.elapsed_s).toBeGreaterThan(5);
274+
expect(s.exit_code).toBe(0);
275+
expect(s.pid).toBeGreaterThan(1);
276+
expect(s.stats).toBeDefined();
277+
if (!Array.isArray(s.stats)) return;
278+
const last_stat = s.stats[s.stats.length - 2];
279+
expect(last_stat.cpu_pct).toBeGreaterThan(10);
280+
expect(last_stat.cpu_secs).toBeGreaterThan(1);
281+
expect(last_stat.mem_rss).toBeGreaterThan(1);
282+
expect(s.stdout).toEqual("foo\nbar\n");
283+
},
284+
10 * 1000,
285+
);
227286
});
287+
288+
// we burn a bit of CPU to get the cpu_pct and cpu_secs up
289+
const CPU_PY = `
290+
from time import time
291+
t0=time()
292+
while t0+5>time():
293+
sum([_ for _ in range(10**6)])
294+
`;

0 commit comments

Comments
 (0)