-
Notifications
You must be signed in to change notification settings - Fork 13.8k
Expand file tree
/
Copy pathAppRuntimeManager.ts
More file actions
84 lines (64 loc) · 2.56 KB
/
Copy pathAppRuntimeManager.ts
File metadata and controls
84 lines (64 loc) · 2.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import type { AppManager } from '../AppManager';
import type { IParseAppPackageResult } from '../compiler';
import type { IRuntimeController } from '../runtime/IRuntimeController';
import { DenoRuntimeSubprocessController } from '../runtime/deno/AppsEngineDenoRuntime';
import { NodeRuntimeSubprocessController } from '../runtime/node/AppsEngineNodeRuntime';
import type { IAppStorageItem } from '../storage';
export type AppRuntimeParams = {
appId: string;
appSource: string;
};
export type ExecRequestContext = {
method: string;
params: unknown[];
};
export type ExecRequestOptions = {
timeout?: number;
};
const { APPS_ENGINE_RUNTIME_BACKEND = 'deno' } = process.env;
export const nodeRuntimeFactory = (manager: AppManager, appPackage: IParseAppPackageResult, storageItem: IAppStorageItem) =>
new NodeRuntimeSubprocessController(manager, appPackage, storageItem);
export const denoRuntimeFactory = (manager: AppManager, appPackage: IParseAppPackageResult, storageItem: IAppStorageItem) =>
new DenoRuntimeSubprocessController(manager, appPackage, storageItem);
const defaultRuntimeFactory = APPS_ENGINE_RUNTIME_BACKEND === 'node' ? nodeRuntimeFactory : denoRuntimeFactory;
export class AppRuntimeManager {
private readonly subprocesses: Record<string, IRuntimeController> = {};
constructor(
private readonly manager: AppManager,
private readonly runtimeFactory = defaultRuntimeFactory,
) {}
public async startRuntimeForApp(
appPackage: IParseAppPackageResult,
storageItem: IAppStorageItem,
options = { force: false },
): Promise<IRuntimeController> {
const { id: appId } = appPackage.info;
if (appId in this.subprocesses && !options.force) {
throw new Error('App already has an associated runtime');
}
this.subprocesses[appId] = this.runtimeFactory(this.manager, appPackage, storageItem);
try {
await this.subprocesses[appId].setupApp();
} catch (error) {
const subprocess = this.subprocesses[appId];
delete this.subprocesses[appId];
await subprocess.stopApp();
throw error;
}
return this.subprocesses[appId];
}
public async runInSandbox(appId: string, execRequest: ExecRequestContext, options?: ExecRequestOptions): Promise<unknown> {
const subprocess = this.subprocesses[appId];
if (!subprocess) {
throw new Error('App does not have an associated runtime');
}
return subprocess.sendRequest(execRequest);
}
public async stopRuntime(controller: IRuntimeController): Promise<void> {
await controller.stopApp();
const appId = controller.getAppId();
if (appId in this.subprocesses) {
delete this.subprocesses[appId];
}
}
}