progress
This commit is contained in:
parent
3f951d1c09
commit
28c36ae710
31 changed files with 495 additions and 65 deletions
26
server/command.json
Normal file
26
server/command.json
Normal file
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"tensorBoard": {
|
||||
"execCommand": "nix run github:nixos/nixpkgs#python312Packages.tensorboard -- --logdir ${dir_path}",
|
||||
"date": null,
|
||||
"status": "Fail,Ok",
|
||||
"delay": 200,
|
||||
"checkCommand": null,
|
||||
"filter": null
|
||||
},
|
||||
"simulationProcess": {
|
||||
"execCommand": "nix run github:nixos/nixpkgs#python312Packages.tensorboard -- --logdir ${dir_path}",
|
||||
"date": null,
|
||||
"status": null,
|
||||
"delay": 0,
|
||||
"checkCommand": null,
|
||||
"filter": null
|
||||
},
|
||||
"btBuilderProcess": {
|
||||
"execCommand": "nix run github:nixos/nixpkgs#python312Packages.tensorboard -- --logdir ${dir_path}",
|
||||
"date": null,
|
||||
"status": null,
|
||||
"delay": 0,
|
||||
"checkCommand": null,
|
||||
"filter": null
|
||||
}
|
||||
}
|
|
@ -34,6 +34,33 @@ export abstract class CallbackStrategyWithFilesUploads {
|
|||
abstract call(files: File[]): ResponseBase;
|
||||
}
|
||||
|
||||
export class SubRouter<A> implements ISubSetFeatureRouter<A> {
|
||||
method: HttpMethodType;
|
||||
subUrl: string;
|
||||
fn:
|
||||
| CallbackStrategyWithValidationModel<A>
|
||||
| CallbackStrategyWithEmpty
|
||||
| CallbackStrategyWithIdQuery
|
||||
| CallBackStrategyWithQueryPage
|
||||
| CallbackStrategyWithFileUpload
|
||||
| CallbackStrategyWithFilesUploads;
|
||||
constructor(
|
||||
method: HttpMethodType,
|
||||
subUrl: string,
|
||||
fn:
|
||||
| CallbackStrategyWithValidationModel<A>
|
||||
| CallbackStrategyWithEmpty
|
||||
| CallbackStrategyWithIdQuery
|
||||
| CallBackStrategyWithQueryPage
|
||||
| CallbackStrategyWithFileUpload
|
||||
| CallbackStrategyWithFilesUploads
|
||||
) {
|
||||
this.fn = fn;
|
||||
this.subUrl = subUrl;
|
||||
this.method = method;
|
||||
}
|
||||
}
|
||||
|
||||
interface ISubSetFeatureRouter<A> {
|
||||
method: HttpMethodType;
|
||||
subUrl: string;
|
||||
|
@ -118,7 +145,7 @@ export class CoreHttpController<V> implements ICoreHttpController {
|
|||
await this.responseHelper(res, el.fn.call());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (el.fn instanceof CallbackStrategyWithFileUpload) {
|
||||
if (req["files"] === undefined) {
|
||||
res.status(400).json("need files to form-data request");
|
||||
|
|
|
@ -10,6 +10,7 @@ import { DigitalTwinsInstancePresentation } from "../../features/digital_twins_i
|
|||
import { DigitalTwinsTemplatePresentation } from "../../features/digital_twins_template/digital_twins_template_presentation";
|
||||
import { TopicsPresentation } from "../../features/topics/topics_presentation";
|
||||
import { SkillsPresentation } from "../../features/skills/skill_presentation";
|
||||
import { RunTimePresentation } from "../../features/runtime/runtime_presentation";
|
||||
|
||||
extensions();
|
||||
|
||||
|
@ -24,4 +25,5 @@ export const httpRoutes: Routes[] = [
|
|||
new DigitalTwinsInstancePresentation(),
|
||||
new TopicsPresentation(),
|
||||
new SkillsPresentation(),
|
||||
new RunTimePresentation(),
|
||||
].map((el) => el.call());
|
||||
|
|
|
@ -41,7 +41,7 @@ export class ExecutorProgramService
|
|||
await delay(300);
|
||||
|
||||
this.worker = worker;
|
||||
|
||||
|
||||
const workerDataExec: WorkerDataExec = {
|
||||
command: command,
|
||||
execPath: this.execPath,
|
||||
|
@ -50,6 +50,7 @@ export class ExecutorProgramService
|
|||
};
|
||||
worker.send(workerDataExec);
|
||||
worker.on("message", (e) => {
|
||||
console.log(JSON.stringify(e));
|
||||
const spawnError = SpawnError.isError(e);
|
||||
|
||||
if (spawnError instanceof SpawnError) {
|
||||
|
@ -60,7 +61,7 @@ export class ExecutorProgramService
|
|||
const execError = ExecError.isExecError(e);
|
||||
|
||||
if (execError instanceof ExecError) {
|
||||
execError.id = id
|
||||
execError.id = id;
|
||||
this.emit(Result.error(execError));
|
||||
this.worker = undefined;
|
||||
return;
|
||||
|
@ -68,7 +69,7 @@ export class ExecutorProgramService
|
|||
|
||||
const executorResult = ExecutorResult.isExecutorResult(e);
|
||||
if (executorResult instanceof ExecutorResult) {
|
||||
executorResult.id = id
|
||||
executorResult.id = id;
|
||||
this.emit(Result.ok(executorResult));
|
||||
this.worker = undefined;
|
||||
return;
|
||||
|
@ -103,7 +104,8 @@ export class ExecutorProgramService
|
|||
|
||||
return;
|
||||
}
|
||||
this.workerExecuted(command, WorkerType.SPAWN, args, id);
|
||||
const commands = command.split(" ");
|
||||
this.workerExecuted(commands.at(0), WorkerType.SPAWN, commands.slice(1, commands.length), id);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import * as cp from "child_process";
|
||||
import { CallbackStrategyWithEmpty } from "../controllers/http_controller";
|
||||
import { Result } from "../helpers/result";
|
||||
import { TypedEvent } from "../helpers/typed_event";
|
||||
import { EXEC_TYPE, ExecError, SpawnError } from "../models/exec_error_model";
|
||||
import { EXEC_EVENT, EXEC_TYPE, ExecError, SpawnError } from "../models/exec_error_model";
|
||||
import { ExecutorResult } from "../models/executor_result";
|
||||
import { ExecutorProgramService } from "../services/executor_program_service";
|
||||
|
||||
|
@ -26,7 +27,7 @@ export class ExecProcessUseCase {
|
|||
call = async (
|
||||
path: string,
|
||||
command: string,
|
||||
id:string,
|
||||
id: string,
|
||||
watcher?: TypedEvent<Result<ExecError | SpawnError, ExecutorResult>>
|
||||
): Promise<Result<Error, string>> => {
|
||||
try {
|
||||
|
@ -34,7 +35,7 @@ export class ExecProcessUseCase {
|
|||
executorProgramService.on((event) => {
|
||||
if (watcher) watcher.emit(event);
|
||||
});
|
||||
executorProgramService.call(EXEC_TYPE.EXEC, command, undefined ,id);
|
||||
executorProgramService.call(EXEC_TYPE.EXEC, command, undefined, id);
|
||||
|
||||
return Result.ok("ok");
|
||||
} catch (error) {
|
||||
|
@ -42,3 +43,38 @@ export class ExecProcessUseCase {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
export class SpawnProcessUseCase {
|
||||
call = async (
|
||||
path: string,
|
||||
command: string,
|
||||
id: string,
|
||||
watcher?: TypedEvent<Result<ExecError | SpawnError, ExecutorResult>>
|
||||
): Promise<Result<Error, string>> => {
|
||||
try {
|
||||
const commands = command.split(" ");
|
||||
|
||||
const subprocess = cp.spawn(commands.at(0), commands.slice(1, commands.length), {
|
||||
cwd: path,
|
||||
});
|
||||
const sendWatcher = (event: Buffer) => {
|
||||
if (watcher) {
|
||||
watcher.emit(Result.ok(new ExecutorResult(EXEC_TYPE.SPAWN, EXEC_EVENT.PROGRESS, event.toString())));
|
||||
}
|
||||
};
|
||||
subprocess.stdout.on("data", (data) => sendWatcher(data));
|
||||
|
||||
subprocess.stderr.on("data", (data) => sendWatcher(data));
|
||||
|
||||
subprocess.on("error", (error) => {
|
||||
console.error(`Ошибка: ${error.message}`);
|
||||
});
|
||||
|
||||
subprocess.on("close", (code) => {
|
||||
console.log(`Процесс завершился с кодом: ${code}`);
|
||||
});
|
||||
} catch (error) {
|
||||
return Result.error(error);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -15,8 +15,7 @@ export class ExecCalculationInstanceProcessScenario extends CallbackStrategyWith
|
|||
return (await new IsHaveActiveProcessUseCase().call()).map(async () => {
|
||||
const execCommand = `${model.script} --form '${JSON.stringify(
|
||||
model.formBuilder
|
||||
)}' --path ${model.instancePath.normalize()}`;
|
||||
console.log(execCommand);
|
||||
)}' --path ${model.instancePath.pathNormalize()}`;
|
||||
await CalculationInstanceDBModel.findById(id).updateOne({
|
||||
processStatus: "RUN",
|
||||
lastProcessExecCommand: execCommand,
|
||||
|
|
|
@ -21,10 +21,13 @@ export class ExecInstanceScenario extends CallbackStrategyWithIdQuery {
|
|||
await new ReadByIdDataBaseModelUseCase<IDigitalTwinsInstanceModel>(DigitalTwinsInstanceDatabaseModel).call(id)
|
||||
).map(
|
||||
(document) => (
|
||||
console.log(JSON.stringify(document)),
|
||||
console.log('DOCUMeNT PATH'),
|
||||
console.log(document.instancePath.pathNormalize()),
|
||||
new ExecProcessUseCase().call(
|
||||
document.instancePath,
|
||||
`python3 $GET_INTERFACES --path ${document.instancePath.pathNormalize()} --package '${JSON.stringify(document)}'`,
|
||||
`python3 $GET_INTERFACES --path ${document.instancePath.pathNormalize()} --package '${JSON.stringify(
|
||||
document
|
||||
)}'`,
|
||||
"",
|
||||
new ExecInstanceTwinsProcessService(document.instancePath, document)
|
||||
)
|
||||
|
|
|
@ -27,10 +27,11 @@ export class RobossemblerAssetsLocaleMapperScenario extends CallbackStrategyWith
|
|||
)
|
||||
).map(async (projectModel) => {
|
||||
const { rootDir } = projectModel[0];
|
||||
return (await new ReadFileAndParseJsonUseCase().call<Parts[]>(rootDir + StaticFilesProject.parts)).map(
|
||||
(model) => {
|
||||
return (await new ReadFileAndParseJsonUseCase().call<Parts[]>(rootDir + StaticFilesProject.parts)).map((model) =>
|
||||
Result.ok(
|
||||
model.map((el) => {
|
||||
const assetLibsAddress = rootDir + "/libs/objects/" + el.name;
|
||||
const assetLibsAddress = rootDir + "/assets/libs/objects/" + el.name;
|
||||
console.log(assetLibsAddress);
|
||||
el.fbx = `${assetLibsAddress}.fbx`;
|
||||
el.stlUrl = `${assetLibsAddress}${el.part_path}`;
|
||||
el.glUrl = `${assetLibsAddress}.glb`;
|
||||
|
@ -38,11 +39,11 @@ export class RobossemblerAssetsLocaleMapperScenario extends CallbackStrategyWith
|
|||
el.objUrl = `${assetLibsAddress}.obj`;
|
||||
el.image = `${assetLibsAddress}.png`;
|
||||
el.solidType = "active";
|
||||
|
||||
return el;
|
||||
});
|
||||
return Result.ok(model);
|
||||
}
|
||||
})
|
||||
)
|
||||
);
|
||||
// );
|
||||
|
||||
});
|
||||
}
|
||||
|
|
|
@ -34,8 +34,8 @@ export class RobossemblerAssetsNetworkMapperScenario extends CallbackStrategyWit
|
|||
rootDir.match(new RegExp(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gm))[0] +
|
||||
"/assets/";
|
||||
model.map((el) => {
|
||||
const assetLibsAddress = assetAddress + "libs/objects/" + el.name;
|
||||
|
||||
const assetLibsAddress = assetAddress + "/libs/objects/" + el.name;
|
||||
console.log(assetLibsAddress);
|
||||
el.stlUrl = `${assetAddress}${el.part_path}`;
|
||||
el.glUrl = `${assetLibsAddress}.glb`;
|
||||
el.daeUrl = `${assetLibsAddress}.dae`;
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
import { CallbackStrategyWithEmpty, ResponseBase } from "../../../core/controllers/http_controller";
|
||||
|
||||
export class ExecBtBuilderUseCase extends CallbackStrategyWithEmpty {
|
||||
call(): ResponseBase {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
import { App } from "../../../core/controllers/app";
|
||||
import { CallbackStrategyWithValidationModel, ResponseBase } from "../../../core/controllers/http_controller";
|
||||
import { Result } from "../../../core/helpers/result";
|
||||
import { SpawnProcessUseCase } from "../../../core/usecases/exec_process_usecase";
|
||||
import { ExecProcesssss } from "../model/exec_process";
|
||||
import { ProcessWatcher } from "../service/process_watcher";
|
||||
import { GetCommandScenario } from "./get_command_scenario";
|
||||
|
||||
export class ExecSimulationUseCase extends CallbackStrategyWithValidationModel<ExecProcesssss> {
|
||||
validationModel = new ExecProcesssss();
|
||||
call = async (): ResponseBase =>
|
||||
(await new GetCommandScenario().call("btBuilderProcess")).map((el) => {
|
||||
new SpawnProcessUseCase().call(
|
||||
App.staticFilesStoreDir(),
|
||||
el.execCommand.replace("${dir_path}", "/Users/idontsudo/train"),
|
||||
"btBuilder",
|
||||
new ProcessWatcher(2000, "localhost")
|
||||
);
|
||||
return Result.ok("200");
|
||||
});
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
import { CallbackStrategyWithEmpty, ResponseBase } from "../../../core/controllers/http_controller";
|
||||
|
||||
export class GetBtBuilderStateUseCase extends CallbackStrategyWithEmpty {
|
||||
call(): ResponseBase {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
}
|
14
server/src/features/runtime/domain/get_command_scenario.ts
Normal file
14
server/src/features/runtime/domain/get_command_scenario.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { ReadFileAndParseJsonUseCase } from "../../../core/usecases/read_file_and_parse_json";
|
||||
import { Result } from "../../../core/helpers/result";
|
||||
import { Command, ExecProcess } from "../model/command";
|
||||
|
||||
export class GetCommandScenario {
|
||||
call = async (command: string): Promise<Result<unknown, ExecProcess>> =>
|
||||
(
|
||||
await new ReadFileAndParseJsonUseCase().call<Command>(
|
||||
__filename.slice(0, __filename.lastIndexOf("/")).replace("/build/src/features/runtime/domain", "") +
|
||||
"/" +
|
||||
"command.json"
|
||||
)
|
||||
).map((el) => Result.ok(el[command]));
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
import { CallbackStrategyWithEmpty, ResponseBase } from "../../../core/controllers/http_controller";
|
||||
import { Result } from "../../../core/helpers/result";
|
||||
import { SpawnProcessUseCase } from "../../../core/usecases/exec_process_usecase";
|
||||
import { GetCommandScenario } from "./get_command_scenario";
|
||||
import { ProcessWatcher } from "../service/process_watcher";
|
||||
import { App } from "../../../core/controllers/app";
|
||||
|
||||
export class GetSimulationStateScenario extends CallbackStrategyWithEmpty {
|
||||
call = async (): ResponseBase => Result.ok("");
|
||||
}
|
14
server/src/features/runtime/model/command.ts
Normal file
14
server/src/features/runtime/model/command.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
export interface Command {
|
||||
tensorBoard: ExecProcess;
|
||||
simulationProcess: ExecProcess;
|
||||
btBuilderProcess: ExecProcess;
|
||||
}
|
||||
|
||||
export interface ExecProcess {
|
||||
execCommand: string;
|
||||
date: null;
|
||||
status: null | string;
|
||||
delay: number;
|
||||
checkCommand: null;
|
||||
filter: null;
|
||||
}
|
3
server/src/features/runtime/model/exec_process.ts
Normal file
3
server/src/features/runtime/model/exec_process.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
export class ExecProcesssss{
|
||||
|
||||
}
|
23
server/src/features/runtime/model/run_time_database_model.ts
Normal file
23
server/src/features/runtime/model/run_time_database_model.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
import { Schema, model } from "mongoose";
|
||||
import { ExecRunTimeCommandValidationModel as ExecRunTimeCommandValidationModel } from "./run_time_validation_model";
|
||||
|
||||
export interface IDigitalTwinsInstanceModel {
|
||||
instancePath: string;
|
||||
status?: string;
|
||||
}
|
||||
|
||||
export const ExecRunTimeDataBaseSchema = new Schema({
|
||||
execCommand: String,
|
||||
date: String,
|
||||
status: String,
|
||||
delay: Number,
|
||||
checkCommand: String,
|
||||
filter: Array,
|
||||
}).plugin(require("mongoose-autopopulate"));
|
||||
|
||||
export const ExecRuntimeSchema = "digital_twins_instance";
|
||||
|
||||
export const ExecRuntimeDatabaseModel = model<ExecRunTimeCommandValidationModel>(
|
||||
ExecRuntimeSchema,
|
||||
ExecRunTimeDataBaseSchema
|
||||
);
|
|
@ -0,0 +1,21 @@
|
|||
import { IsArray, IsEnum, IsNumber, IsString } from "class-validator";
|
||||
|
||||
export enum Status {
|
||||
OK = "Ok",
|
||||
ERROR = "Error",
|
||||
}
|
||||
|
||||
export class ExecRunTimeCommandValidationModel {
|
||||
@IsString()
|
||||
execCommand: string;
|
||||
@IsString()
|
||||
date: string = Date();
|
||||
@IsEnum(Status)
|
||||
status: Status;
|
||||
@IsNumber()
|
||||
delay: number;
|
||||
@IsString()
|
||||
checkCommand: string;
|
||||
@IsArray()
|
||||
filter: string[] = [];
|
||||
}
|
25
server/src/features/runtime/runtime_presentation.ts
Normal file
25
server/src/features/runtime/runtime_presentation.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
import { CrudController } from "../../core/controllers/crud_controller";
|
||||
import { ExecRunTimeCommandValidationModel } from "./model/run_time_validation_model";
|
||||
import { ExecRuntimeDatabaseModel } from "./model/run_time_database_model";
|
||||
import { CoreHttpController, SubRouter, HttpMethodType } from "../../core/controllers/http_controller";
|
||||
import { ExecBtBuilderUseCase } from "./domain/exec_bt_builder_usecase";
|
||||
import { ExecSimulationUseCase } from "./domain/exec_simulation_usecase";
|
||||
import { GetBtBuilderStateUseCase } from "./domain/get_bt_builder_status_usecase";
|
||||
import { GetSimulationStateScenario } from "./domain/get_simulation_state_usecase";
|
||||
|
||||
export class RunTimePresentation extends CoreHttpController<ExecRunTimeCommandValidationModel> {
|
||||
constructor() {
|
||||
super({
|
||||
url: "run_time",
|
||||
});
|
||||
|
||||
this.subRoutes.push(new SubRouter("POST", "/exec/bt/builder", new ExecBtBuilderUseCase()));
|
||||
this.subRoutes.push(new SubRouter("POST", "/get/bt/builder/state", new GetBtBuilderStateUseCase()));
|
||||
this.subRoutes.push(new SubRouter("POST", "/get/simulator/state", new GetSimulationStateScenario()));
|
||||
this.subRoutes.push({
|
||||
method: "POST",
|
||||
subUrl: "/exec/simulation/",
|
||||
fn: new ExecSimulationUseCase(),
|
||||
});
|
||||
}
|
||||
}
|
22
server/src/features/runtime/service/process_watcher.ts
Normal file
22
server/src/features/runtime/service/process_watcher.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import { Result } from "../../../core/helpers/result";
|
||||
import { TypedEvent } from "../../../core/helpers/typed_event";
|
||||
import { ExecError, SpawnError } from "../../../core/models/exec_error_model";
|
||||
import { ExecutorResult } from "../../../core/models/executor_result";
|
||||
|
||||
export class ProcessWatcher extends TypedEvent<Result<ExecError | SpawnError, ExecutorResult>> {
|
||||
logs = "";
|
||||
delay: number;
|
||||
constructor(delay: number, pattern: string) {
|
||||
super();
|
||||
this.on(this.lister);
|
||||
setTimeout(() => {
|
||||
console.log(this.logs);
|
||||
}, delay);
|
||||
}
|
||||
|
||||
lister = (event: Result<ExecError | SpawnError, ExecutorResult>) => {
|
||||
event.map(async (success) => {
|
||||
this.logs += success.data;
|
||||
});
|
||||
};
|
||||
}
|
10
server/src/p.json
Normal file
10
server/src/p.json
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"execCommand": "string",
|
||||
"date": "date",
|
||||
"status": "Fail,Ok",
|
||||
"delay": 1000,
|
||||
"checkCommand": "string",
|
||||
"filter": [
|
||||
"/assembly_config"
|
||||
]
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue