Skip to content

Commit ee24aec

Browse files
committed
frontend/project: if project does not support exec-stream service yet, a modal pops up to ask for a project restart (to get the newer project code)
1 parent ac3863e commit ee24aec

File tree

4 files changed

+62
-18
lines changed

4 files changed

+62
-18
lines changed

src/packages/conat/names.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ import generateVouchers from "@cocalc/util/vouchers";
1515
import type { Location } from "./types";
1616
import { encodeBase64 } from "@cocalc/conat/util";
1717

18+
// Service names for conat subjects
19+
export const EXEC_STREAM_SERVICE = "exec-stream";
20+
1821
// nice alphanumeric string that can be used as conat subject, and very
1922
// unlikely to randomly collide with another browser tab from this account.
2023
export function randomId() {

src/packages/frontend/client/project.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@
77
Functionality that mainly involves working with a specific project.
88
*/
99

10+
import { throttle } from "lodash";
11+
import { join } from "path";
12+
1013
import { readFile, type ReadFileOptions } from "@cocalc/conat/files/read";
1114
import { writeFile, type WriteFileOptions } from "@cocalc/conat/files/write";
12-
import { projectSubject } from "@cocalc/conat/names";
15+
import { projectSubject, EXEC_STREAM_SERVICE } from "@cocalc/conat/names";
1316
import { redux } from "@cocalc/frontend/app-framework";
1417
import { appBasePath } from "@cocalc/frontend/customize/app-base-path";
1518
import { dialogs } from "@cocalc/frontend/i18n";
@@ -40,8 +43,6 @@ import {
4043
} from "@cocalc/util/misc";
4144
import { reuseInFlight } from "@cocalc/util/reuse-in-flight";
4245
import { DirectoryListingEntry } from "@cocalc/util/types";
43-
import { throttle } from "lodash";
44-
import { join } from "path";
4546
import { WebappClient } from "./client";
4647
import { ExecStream } from "./types";
4748

@@ -214,13 +215,12 @@ export class ProjectClient {
214215
*/
215216
execStream = (
216217
opts: ExecOptsBlocking & {
217-
execStream?: ExecStream;
218218
startStreamExplicitly?: boolean;
219219
debug?: string;
220220
},
221221
startExplicitly = false,
222222
): ExecStream => {
223-
const execStream = opts.execStream ?? new ExecStream();
223+
const execStream = new ExecStream();
224224
(async () => {
225225
try {
226226
await this.execStreamAsync({ ...opts, execStream });
@@ -277,7 +277,7 @@ export class ProjectClient {
277277
const subject = projectSubject({
278278
project_id: opts.project_id,
279279
compute_server_id: opts.compute_server_id ?? 0,
280-
service: "exec-stream",
280+
service: EXEC_STREAM_SERVICE,
281281
});
282282

283283
let lastSeq = -1;

src/packages/frontend/frame-editors/latex-editor/util.ts

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,19 @@
55

66
// data and functions specific to the latex editor.
77

8+
import { Modal } from "antd";
9+
10+
import { redux } from "@cocalc/frontend/app-framework";
811
import { ExecOutput } from "@cocalc/frontend/frame-editors/generic/client";
912
import { webapp_client } from "@cocalc/frontend/webapp-client";
1013
import { ExecOptsBlocking } from "@cocalc/util/db-schema/projects";
1114
import { separate_file_extension } from "@cocalc/util/misc";
1215
import { ExecuteCodeOutputAsync } from "@cocalc/util/types/execute-code";
1316
import { TIMEOUT_LATEX_JOB_S } from "./constants";
1417

18+
// Track which projects have already shown the restart dialog
19+
const shownRestartDialogs = new Set<string>();
20+
1521
export function pdf_path(path: string): string {
1622
// if it is already a pdf, don't change the upper/lower casing -- #4562
1723
const { name, ext } = separate_file_extension(path);
@@ -167,12 +173,49 @@ export async function runJob(opts: RunJobOpts): Promise<ExecOutput> {
167173
resolve(result);
168174
});
169175

170-
stream.on("error", () => {
171-
reject(
172-
new Error(
173-
"Unable to run the compilation. Please check up on the project.",
174-
),
175-
);
176+
stream.on("error", (err) => {
177+
// Check if this is a 503 error (exec-stream service not available in old project)
178+
if (err?.code === 503) {
179+
showProjectRestartDialog(project_id);
180+
reject(err);
181+
} else {
182+
reject(
183+
new Error(
184+
"Unable to run the compilation. Please check up on the project.",
185+
),
186+
);
187+
}
176188
});
177189
});
178190
}
191+
192+
function showProjectRestartDialog(project_id: string): void {
193+
// Only show the dialog once per project
194+
if (shownRestartDialogs.has(project_id)) {
195+
return;
196+
}
197+
198+
shownRestartDialogs.add(project_id);
199+
200+
const actions = redux.getActions("projects");
201+
202+
Modal.confirm({
203+
title: "Project Needs Update",
204+
content: `This project needs to be restarted to support the new streaming compilation feature.
205+
Your work is automatically saved and will not be lost.`,
206+
okText: "Restart Project",
207+
cancelText: "Not Now",
208+
width: 500,
209+
onOk: () => {
210+
if (actions) {
211+
actions.restart_project(project_id);
212+
}
213+
// Clear the tracking when user clicks OK
214+
shownRestartDialogs.delete(project_id);
215+
},
216+
onCancel: () => {
217+
// Clear the tracking when user dismisses the dialog
218+
shownRestartDialogs.delete(project_id);
219+
},
220+
});
221+
}

src/packages/project/exec-stream.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,15 @@ Project-side exec-stream service that handles streaming execution requests.
33
Similar to how the project API service works, but specifically for streaming exec.
44
*/
55

6-
import { executeStream, StreamEvent } from "@cocalc/backend/exec-stream";
6+
import { executeStream, StreamEvent } from "@cocalc/backend/exec-stream";
77
import { Message, Subscription } from "@cocalc/conat/core/client";
8-
import { projectSubject } from "@cocalc/conat/names";
8+
import { projectSubject, EXEC_STREAM_SERVICE } from "@cocalc/conat/names";
99
import { connectToConat } from "@cocalc/project/conat/connection";
1010
import { project_id } from "@cocalc/project/data";
1111
import { getLogger } from "@cocalc/project/logger";
1212

1313
const logger = getLogger("project:exec-stream");
1414

15-
16-
1715
export function init() {
1816
serve();
1917
}
@@ -23,8 +21,8 @@ async function serve() {
2321
const cn = connectToConat();
2422
const subject = projectSubject({
2523
project_id,
26-
compute_server_id: 0, // This is the project service, always 0
27-
service: "exec-stream",
24+
compute_server_id: 0, // This is the project home base, always 0
25+
service: EXEC_STREAM_SERVICE,
2826
});
2927

3028
logger.debug(

0 commit comments

Comments
 (0)