From 2d0488b3a8c29455228c7d9ec7945817a7149b3a Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Tue, 8 Oct 2024 23:53:57 +0530 Subject: [PATCH 01/65] wip: runs api --- server/src/api/run.ts | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 server/src/api/run.ts diff --git a/server/src/api/run.ts b/server/src/api/run.ts new file mode 100644 index 00000000..ea419e49 --- /dev/null +++ b/server/src/api/run.ts @@ -0,0 +1,4 @@ +import { readFile, readFiles } from "../workflow-management/storage"; +import { Router, Request, Response } from 'express'; +import { requireAPIKey } from "../middlewares/api"; +const router = Router(); \ No newline at end of file From 113a55a6b0c5af35fab2f79c180ae1a5044373c2 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 03:10:22 +0530 Subject: [PATCH 02/65] refactor: robot storage path --- server/src/routes/storage.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/src/routes/storage.ts b/server/src/routes/storage.ts index d24c0131..74faa504 100644 --- a/server/src/routes/storage.ts +++ b/server/src/routes/storage.ts @@ -16,7 +16,7 @@ import { requireSignIn } from '../middlewares/auth'; // todo: move from here export const getRecordingByFileName = async (fileName: string): Promise => { try { - const recording = await readFile(`./../storage/recordings/${fileName}.waw.json`) + const recording = await readFile(`./../storage/recordings/${fileName}.json`) const parsedRecording = JSON.parse(recording); return parsedRecording; } catch (error: any) { @@ -53,11 +53,11 @@ router.get('/recordings', requireSignIn, async (req, res) => { */ router.delete('/recordings/:fileName', requireSignIn, async (req, res) => { try { - await deleteFile(`./../storage/recordings/${req.params.fileName}.waw.json`); + await deleteFile(`./../storage/recordings/${req.params.fileName}.json`); return res.send(true); } catch (e) { const { message } = e as Error; - logger.log('info', `Error while deleting a recording with name: ${req.params.fileName}.waw.json`); + logger.log('info', `Error while deleting a recording with name: ${req.params.fileName}.json`); return res.send(false); } }); @@ -176,7 +176,7 @@ router.get('/runs/run/:fileName/:runId', requireSignIn, async (req, res) => { */ router.post('/runs/run/:fileName/:runId', requireSignIn, async (req, res) => { try { - const recording = await readFile(`./../storage/recordings/${req.params.fileName}.waw.json`) + const recording = await readFile(`./../storage/recordings/${req.params.fileName}.json`) const parsedRecording = JSON.parse(recording); const run = await readFile(`./../storage/runs/${req.params.fileName}_${req.params.runId}.json`) From ff096f6b3c5d0daa0a966a9a2a6726a8673d693d Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 03:11:27 +0530 Subject: [PATCH 03/65] refactor: robot workflow storage path --- server/src/routes/workflow.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/routes/workflow.ts b/server/src/routes/workflow.ts index e5c03a33..ffbfb39e 100644 --- a/server/src/routes/workflow.ts +++ b/server/src/routes/workflow.ts @@ -107,7 +107,7 @@ router.put('/:browserId/:fileName', requireSignIn, async (req, res) => { const browser = browserPool.getRemoteBrowser(req.params.browserId); logger.log('debug', `Updating workflow file`); if (browser && browser.generator) { - const recording = await readFile(`./../storage/recordings/${req.params.fileName}.waw.json`) + const recording = await readFile(`./../storage/recordings/${req.params.fileName}.json`) const parsedRecording = JSON.parse(recording); if (parsedRecording.recording) { browser.generator?.updateWorkflowFile(parsedRecording.recording, parsedRecording.recording_meta); @@ -118,7 +118,7 @@ router.put('/:browserId/:fileName', requireSignIn, async (req, res) => { return res.send(null); } catch (e) { const { message } = e as Error; - logger.log('info', `Error while reading a recording with name: ${req.params.fileName}.waw.json`); + logger.log('info', `Error while reading a recording with name: ${req.params.fileName}.json`); return res.send(null); } }); From fb2ca29fa839613c6aca2561e62a8ff71cfc865b Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 03:11:53 +0530 Subject: [PATCH 04/65] refactor: scheduled robot storage path --- server/src/workflow-management/scheduler/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/workflow-management/scheduler/index.ts b/server/src/workflow-management/scheduler/index.ts index fe014f81..bf7a0ce6 100644 --- a/server/src/workflow-management/scheduler/index.ts +++ b/server/src/workflow-management/scheduler/index.ts @@ -67,7 +67,7 @@ async function runWorkflow(fileName: string, runId: string) { async function executeRun(fileName: string, runId: string) { try { - const recording = await readFile(`./../storage/recordings/${fileName}.waw.json`); + const recording = await readFile(`./../storage/recordings/${fileName}.json`); const parsedRecording = JSON.parse(recording); const run = await readFile(`./../storage/runs/${fileName}_${runId}.json`); From cb470371f5e61f0aa1aec18f2c2548f7ce864242 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 03:12:26 +0530 Subject: [PATCH 05/65] refactor: generator robot storage path --- server/src/workflow-management/classes/Generator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/workflow-management/classes/Generator.ts b/server/src/workflow-management/classes/Generator.ts index b0a95873..95a86016 100644 --- a/server/src/workflow-management/classes/Generator.ts +++ b/server/src/workflow-management/classes/Generator.ts @@ -488,7 +488,7 @@ export class WorkflowGenerator { } fs.mkdirSync('../storage/recordings', { recursive: true }) await saveFile( - `../storage/recordings/${fileName}.waw.json`, + `../storage/recordings/${fileName}.json`, JSON.stringify({ recording_meta: this.recordingMeta, recording }, null, 2) ); } From 7074e5f18359e0f71767d8a7cb2027ea899ef80f Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 03:22:36 +0530 Subject: [PATCH 06/65] feat: robot model --- server/src/models/Robot.ts | 67 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 server/src/models/Robot.ts diff --git a/server/src/models/Robot.ts b/server/src/models/Robot.ts new file mode 100644 index 00000000..c5887447 --- /dev/null +++ b/server/src/models/Robot.ts @@ -0,0 +1,67 @@ +import { Model, DataTypes, Optional } from 'sequelize'; +import sequelize from '../db/config'; + +interface RobotAttributes { + id: string; + name: string; + createdAt: Date; + updatedAt: Date; + pairs: number; + params: object; + workflow: object; // Store workflow details as JSONB +} + +interface RobotCreationAttributes extends Optional {} + +class Robot extends Model implements RobotAttributes { + public id!: string; + public name!: string; + public createdAt!: Date; + public updatedAt!: Date; + public pairs!: number; + public params!: object; + public workflow!: object; +} + +Robot.init( + { + id: { + type: DataTypes.UUID, + defaultValue: DataTypes.UUIDV4, + primaryKey: true, + }, + name: { + type: DataTypes.STRING(255), + allowNull: false, + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false, + defaultValue: DataTypes.NOW, + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false, + defaultValue: DataTypes.NOW, + }, + pairs: { + type: DataTypes.INTEGER, + allowNull: false, + }, + params: { + type: DataTypes.JSONB, + allowNull: true, + }, + workflow: { + type: DataTypes.JSONB, + allowNull: true, + }, + }, + { + sequelize, + tableName: 'robots', + timestamps: true, + } +); + +export default Robot; From 28e8dff21773fe09e8ba79175958e2025e4e9f35 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 03:24:54 +0530 Subject: [PATCH 07/65] feat: rename to robot --- server/src/models/Robot.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/models/Robot.ts b/server/src/models/Robot.ts index c5887447..2e1c5c4f 100644 --- a/server/src/models/Robot.ts +++ b/server/src/models/Robot.ts @@ -59,7 +59,7 @@ Robot.init( }, { sequelize, - tableName: 'robots', + tableName: 'robot', timestamps: true, } ); From 280c493ec264b600064175487bc2f5f129c2f279 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 03:27:04 +0530 Subject: [PATCH 08/65] feat: run model --- server/src/models/Run.ts | 94 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 server/src/models/Run.ts diff --git a/server/src/models/Run.ts b/server/src/models/Run.ts new file mode 100644 index 00000000..906ce3c3 --- /dev/null +++ b/server/src/models/Run.ts @@ -0,0 +1,94 @@ +import { Model, DataTypes, Optional } from 'sequelize'; +import sequelize from '../db/config'; +import Robot from './Robot'; + +interface RunAttributes { + id: string; + recordingId: string; + status: string; + name: string; + startedAt: Date; + finishedAt: Date; + browserId: string; + interpreterSettings: object; + log: string; + serializableRun: object; + binaryRunUrl: string; +} + +interface RunCreationAttributes extends Optional {} + +class Run extends Model implements RunAttributes { + public id!: string; + public recordingId!: string; + public status!: string; + public name!: string; + public startedAt!: Date; + public finishedAt!: Date; + public browserId!: string; + public interpreterSettings!: object; + public log!: string; + public serializableRun!: object; + public binaryRunUrl!: string; +} + +Run.init( + { + id: { + type: DataTypes.UUID, + defaultValue: DataTypes.UUIDV4, + primaryKey: true, + }, + recordingId: { + type: DataTypes.UUID, + allowNull: false, + references: { + model: Robot, + key: 'id', + }, + }, + status: { + type: DataTypes.STRING(50), + allowNull: false, + }, + name: { + type: DataTypes.STRING(255), + allowNull: false, + }, + startedAt: { + type: DataTypes.DATE, + allowNull: false, + }, + finishedAt: { + type: DataTypes.DATE, + allowNull: false, + }, + browserId: { + type: DataTypes.UUID, + allowNull: false, + }, + interpreterSettings: { + type: DataTypes.JSONB, + allowNull: true, + }, + log: { + type: DataTypes.TEXT, + allowNull: true, + }, + serializableRun: { + type: DataTypes.JSONB, + allowNull: true, + }, + binaryRunUrl: { + type: DataTypes.TEXT, + allowNull: true, + }, + }, + { + sequelize, + tableName: 'run', + timestamps: false, + } +); + +export default Run; From 9d268c3e7ff77cc1ca98f05f511fd57a5dc15de7 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 03:27:19 +0530 Subject: [PATCH 09/65] chore: lint --- server/src/models/Run.ts | 156 +++++++++++++++++++-------------------- 1 file changed, 78 insertions(+), 78 deletions(-) diff --git a/server/src/models/Run.ts b/server/src/models/Run.ts index 906ce3c3..05fc7f28 100644 --- a/server/src/models/Run.ts +++ b/server/src/models/Run.ts @@ -3,92 +3,92 @@ import sequelize from '../db/config'; import Robot from './Robot'; interface RunAttributes { - id: string; - recordingId: string; - status: string; - name: string; - startedAt: Date; - finishedAt: Date; - browserId: string; - interpreterSettings: object; - log: string; - serializableRun: object; - binaryRunUrl: string; + id: string; + recordingId: string; + status: string; + name: string; + startedAt: Date; + finishedAt: Date; + browserId: string; + interpreterSettings: object; + log: string; + serializableRun: object; + binaryRunUrl: string; } -interface RunCreationAttributes extends Optional {} +interface RunCreationAttributes extends Optional { } class Run extends Model implements RunAttributes { - public id!: string; - public recordingId!: string; - public status!: string; - public name!: string; - public startedAt!: Date; - public finishedAt!: Date; - public browserId!: string; - public interpreterSettings!: object; - public log!: string; - public serializableRun!: object; - public binaryRunUrl!: string; + public id!: string; + public recordingId!: string; + public status!: string; + public name!: string; + public startedAt!: Date; + public finishedAt!: Date; + public browserId!: string; + public interpreterSettings!: object; + public log!: string; + public serializableRun!: object; + public binaryRunUrl!: string; } Run.init( - { - id: { - type: DataTypes.UUID, - defaultValue: DataTypes.UUIDV4, - primaryKey: true, + { + id: { + type: DataTypes.UUID, + defaultValue: DataTypes.UUIDV4, + primaryKey: true, + }, + recordingId: { + type: DataTypes.UUID, + allowNull: false, + references: { + model: Robot, + key: 'id', + }, + }, + status: { + type: DataTypes.STRING(50), + allowNull: false, + }, + name: { + type: DataTypes.STRING(255), + allowNull: false, + }, + startedAt: { + type: DataTypes.DATE, + allowNull: false, + }, + finishedAt: { + type: DataTypes.DATE, + allowNull: false, + }, + browserId: { + type: DataTypes.UUID, + allowNull: false, + }, + interpreterSettings: { + type: DataTypes.JSONB, + allowNull: true, + }, + log: { + type: DataTypes.TEXT, + allowNull: true, + }, + serializableRun: { + type: DataTypes.JSONB, + allowNull: true, + }, + binaryRunUrl: { + type: DataTypes.TEXT, + allowNull: true, + }, }, - recordingId: { - type: DataTypes.UUID, - allowNull: false, - references: { - model: Robot, - key: 'id', - }, - }, - status: { - type: DataTypes.STRING(50), - allowNull: false, - }, - name: { - type: DataTypes.STRING(255), - allowNull: false, - }, - startedAt: { - type: DataTypes.DATE, - allowNull: false, - }, - finishedAt: { - type: DataTypes.DATE, - allowNull: false, - }, - browserId: { - type: DataTypes.UUID, - allowNull: false, - }, - interpreterSettings: { - type: DataTypes.JSONB, - allowNull: true, - }, - log: { - type: DataTypes.TEXT, - allowNull: true, - }, - serializableRun: { - type: DataTypes.JSONB, - allowNull: true, - }, - binaryRunUrl: { - type: DataTypes.TEXT, - allowNull: true, - }, - }, - { - sequelize, - tableName: 'run', - timestamps: false, - } + { + sequelize, + tableName: 'run', + timestamps: false, + } ); export default Run; From 49f6193b37fdf529fc09ec8ddab1daff18d28f8b Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 03:27:28 +0530 Subject: [PATCH 10/65] chore: lint --- server/src/models/Robot.ts | 104 ++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/server/src/models/Robot.ts b/server/src/models/Robot.ts index 2e1c5c4f..8f37eb19 100644 --- a/server/src/models/Robot.ts +++ b/server/src/models/Robot.ts @@ -2,66 +2,66 @@ import { Model, DataTypes, Optional } from 'sequelize'; import sequelize from '../db/config'; interface RobotAttributes { - id: string; - name: string; - createdAt: Date; - updatedAt: Date; - pairs: number; - params: object; - workflow: object; // Store workflow details as JSONB + id: string; + name: string; + createdAt: Date; + updatedAt: Date; + pairs: number; + params: object; + workflow: object; // Store workflow details as JSONB } -interface RobotCreationAttributes extends Optional {} +interface RobotCreationAttributes extends Optional { } class Robot extends Model implements RobotAttributes { - public id!: string; - public name!: string; - public createdAt!: Date; - public updatedAt!: Date; - public pairs!: number; - public params!: object; - public workflow!: object; + public id!: string; + public name!: string; + public createdAt!: Date; + public updatedAt!: Date; + public pairs!: number; + public params!: object; + public workflow!: object; } Robot.init( - { - id: { - type: DataTypes.UUID, - defaultValue: DataTypes.UUIDV4, - primaryKey: true, + { + id: { + type: DataTypes.UUID, + defaultValue: DataTypes.UUIDV4, + primaryKey: true, + }, + name: { + type: DataTypes.STRING(255), + allowNull: false, + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false, + defaultValue: DataTypes.NOW, + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false, + defaultValue: DataTypes.NOW, + }, + pairs: { + type: DataTypes.INTEGER, + allowNull: false, + }, + params: { + type: DataTypes.JSONB, + allowNull: true, + }, + workflow: { + type: DataTypes.JSONB, + allowNull: true, + }, }, - name: { - type: DataTypes.STRING(255), - allowNull: false, - }, - createdAt: { - type: DataTypes.DATE, - allowNull: false, - defaultValue: DataTypes.NOW, - }, - updatedAt: { - type: DataTypes.DATE, - allowNull: false, - defaultValue: DataTypes.NOW, - }, - pairs: { - type: DataTypes.INTEGER, - allowNull: false, - }, - params: { - type: DataTypes.JSONB, - allowNull: true, - }, - workflow: { - type: DataTypes.JSONB, - allowNull: true, - }, - }, - { - sequelize, - tableName: 'robot', - timestamps: true, - } + { + sequelize, + tableName: 'robot', + timestamps: true, + } ); export default Robot; From 646626469f6bc9a6a6ae3396cb71b84255b56dc0 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 03:31:31 +0530 Subject: [PATCH 11/65] feat: robot has many association w run --- server/src/models/Robot.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/src/models/Robot.ts b/server/src/models/Robot.ts index 8f37eb19..c348a27a 100644 --- a/server/src/models/Robot.ts +++ b/server/src/models/Robot.ts @@ -1,5 +1,6 @@ import { Model, DataTypes, Optional } from 'sequelize'; import sequelize from '../db/config'; +import Run from './Run'; interface RobotAttributes { id: string; @@ -64,4 +65,6 @@ Robot.init( } ); +Robot.hasMany(Run, { foreignKey: 'robotId' }); + export default Robot; From 4827a232abbb0d04cdc1e4f41bafc8af17461f96 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 03:31:51 +0530 Subject: [PATCH 12/65] feat: robotId --- server/src/models/Run.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/src/models/Run.ts b/server/src/models/Run.ts index 05fc7f28..ac3b91b7 100644 --- a/server/src/models/Run.ts +++ b/server/src/models/Run.ts @@ -4,7 +4,7 @@ import Robot from './Robot'; interface RunAttributes { id: string; - recordingId: string; + robotId: string; status: string; name: string; startedAt: Date; @@ -20,7 +20,7 @@ interface RunCreationAttributes extends Optional { } class Run extends Model implements RunAttributes { public id!: string; - public recordingId!: string; + public robotId!: string; public status!: string; public name!: string; public startedAt!: Date; @@ -39,7 +39,7 @@ Run.init( defaultValue: DataTypes.UUIDV4, primaryKey: true, }, - recordingId: { + robotId: { type: DataTypes.UUID, allowNull: false, references: { From 14d5de80841b68a655accae08bac837523f46ef9 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 03:32:45 +0530 Subject: [PATCH 13/65] feat: run belongs to association w robot --- server/src/models/Run.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/src/models/Run.ts b/server/src/models/Run.ts index ac3b91b7..ab514c2a 100644 --- a/server/src/models/Run.ts +++ b/server/src/models/Run.ts @@ -91,4 +91,6 @@ Run.init( } ); +Run.belongsTo(Robot, { foreignKey: 'robotId' }); + export default Run; From 6acde9d958f6be976884f785dcc8487f7cee3294 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 03:50:53 +0530 Subject: [PATCH 14/65] feat: match exact format of file system robot --- server/src/models/Robot.ts | 125 ++++++++++++++++++++++--------------- 1 file changed, 74 insertions(+), 51 deletions(-) diff --git a/server/src/models/Robot.ts b/server/src/models/Robot.ts index c348a27a..534b1953 100644 --- a/server/src/models/Robot.ts +++ b/server/src/models/Robot.ts @@ -2,67 +2,90 @@ import { Model, DataTypes, Optional } from 'sequelize'; import sequelize from '../db/config'; import Run from './Run'; +interface RecordingMeta { + name: string; + id: string; + createdAt: Date; + pairs: number; + updatedAt: Date; + params: object[]; +} + +interface Recording { + workflow: Array<{ + where: { + url: string; + }; + what: Array<{ + action: string; + args: any[]; + }>; + }>; +} + interface RobotAttributes { - id: string; - name: string; - createdAt: Date; - updatedAt: Date; - pairs: number; - params: object; - workflow: object; // Store workflow details as JSONB + id: string; + name: string; + createdAt: Date; + updatedAt: Date; + pairs: number; + recording_meta: RecordingMeta; + recording: Recording; } interface RobotCreationAttributes extends Optional { } class Robot extends Model implements RobotAttributes { - public id!: string; - public name!: string; - public createdAt!: Date; - public updatedAt!: Date; - public pairs!: number; - public params!: object; - public workflow!: object; + public id!: string; + public name!: string; + public createdAt!: Date; + public updatedAt!: Date; + public pairs!: number; + public recording_meta!: RecordingMeta; + public recording!: Recording; } Robot.init( - { - id: { - type: DataTypes.UUID, - defaultValue: DataTypes.UUIDV4, - primaryKey: true, - }, - name: { - type: DataTypes.STRING(255), - allowNull: false, - }, - createdAt: { - type: DataTypes.DATE, - allowNull: false, - defaultValue: DataTypes.NOW, - }, - updatedAt: { - type: DataTypes.DATE, - allowNull: false, - defaultValue: DataTypes.NOW, - }, - pairs: { - type: DataTypes.INTEGER, - allowNull: false, - }, - params: { - type: DataTypes.JSONB, - allowNull: true, - }, - workflow: { - type: DataTypes.JSONB, - allowNull: true, - }, + { + id: { + type: DataTypes.UUID, + defaultValue: DataTypes.UUIDV4, + primaryKey: true, }, - { - sequelize, - tableName: 'robot', - timestamps: true, - } + name: { + type: DataTypes.STRING(255), + allowNull: false, + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false, + defaultValue: DataTypes.NOW, + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false, + defaultValue: DataTypes.NOW, + }, + pairs: { + type: DataTypes.INTEGER, + allowNull: false, + }, + // JSONB field for recording_meta (storing as a structured object) + recording_meta: { + type: DataTypes.JSONB, + allowNull: false, + }, + // JSONB field for recording (storing as a structured object) + recording: { + type: DataTypes.JSONB, + allowNull: false, + }, + }, + { + sequelize, + tableName: 'robot', + timestamps: true, + } ); Robot.hasMany(Run, { foreignKey: 'robotId' }); From 3baeb09d6040c26de384bc1a42bca73fcef5492e Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 03:59:31 +0530 Subject: [PATCH 15/65] feat: rename to Robot --- server/src/models/Robot.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/server/src/models/Robot.ts b/server/src/models/Robot.ts index 534b1953..68424f08 100644 --- a/server/src/models/Robot.ts +++ b/server/src/models/Robot.ts @@ -2,7 +2,7 @@ import { Model, DataTypes, Optional } from 'sequelize'; import sequelize from '../db/config'; import Run from './Run'; -interface RecordingMeta { +interface RobotMeta { name: string; id: string; createdAt: Date; @@ -11,7 +11,7 @@ interface RecordingMeta { params: object[]; } -interface Recording { +interface Robot { workflow: Array<{ where: { url: string; @@ -29,8 +29,8 @@ interface RobotAttributes { createdAt: Date; updatedAt: Date; pairs: number; - recording_meta: RecordingMeta; - recording: Recording; + recording_meta: RobotMeta; + recording: Robot; } interface RobotCreationAttributes extends Optional { } @@ -41,8 +41,8 @@ class Robot extends Model implements R public createdAt!: Date; public updatedAt!: Date; public pairs!: number; - public recording_meta!: RecordingMeta; - public recording!: Recording; + public recording_meta!: RobotMeta; + public recording!: Robot; } Robot.init( From d303afc2af372b882874b72c4d8682f992f89955 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 04:03:45 +0530 Subject: [PATCH 16/65] feat: match exact format of file system robot --- server/src/models/Robot.ts | 58 +++++++++++--------------------------- 1 file changed, 16 insertions(+), 42 deletions(-) diff --git a/server/src/models/Robot.ts b/server/src/models/Robot.ts index 68424f08..cdc67bdc 100644 --- a/server/src/models/Robot.ts +++ b/server/src/models/Robot.ts @@ -5,42 +5,36 @@ import Run from './Run'; interface RobotMeta { name: string; id: string; - createdAt: Date; + createdAt: string; pairs: number; - updatedAt: Date; - params: object[]; + updatedAt: string; + params: any[]; +} + +interface Workflow { + where: { + url: string; + }; + what: Array<{ + action: string; + args: any[]; + }>; } interface Robot { - workflow: Array<{ - where: { - url: string; - }; - what: Array<{ - action: string; - args: any[]; - }>; - }>; + workflow: Workflow[]; } interface RobotAttributes { id: string; - name: string; - createdAt: Date; - updatedAt: Date; - pairs: number; recording_meta: RobotMeta; recording: Robot; } -interface RobotCreationAttributes extends Optional { } +interface RobotCreationAttributes extends Optional {} class Robot extends Model implements RobotAttributes { public id!: string; - public name!: string; - public createdAt!: Date; - public updatedAt!: Date; - public pairs!: number; public recording_meta!: RobotMeta; public recording!: Robot; } @@ -52,30 +46,10 @@ Robot.init( defaultValue: DataTypes.UUIDV4, primaryKey: true, }, - name: { - type: DataTypes.STRING(255), - allowNull: false, - }, - createdAt: { - type: DataTypes.DATE, - allowNull: false, - defaultValue: DataTypes.NOW, - }, - updatedAt: { - type: DataTypes.DATE, - allowNull: false, - defaultValue: DataTypes.NOW, - }, - pairs: { - type: DataTypes.INTEGER, - allowNull: false, - }, - // JSONB field for recording_meta (storing as a structured object) recording_meta: { type: DataTypes.JSONB, allowNull: false, }, - // JSONB field for recording (storing as a structured object) recording: { type: DataTypes.JSONB, allowNull: false, @@ -84,7 +58,7 @@ Robot.init( { sequelize, tableName: 'robot', - timestamps: true, + timestamps: false, // We'll manage timestamps manually in recording_meta } ); From db13b9afaa37f7d9fa5c21f4be90ab5418470e85 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 14:34:43 +0530 Subject: [PATCH 17/65] feat: match types from maxun-core --- server/src/models/Robot.ts | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/server/src/models/Robot.ts b/server/src/models/Robot.ts index cdc67bdc..444dcf2d 100644 --- a/server/src/models/Robot.ts +++ b/server/src/models/Robot.ts @@ -1,6 +1,7 @@ import { Model, DataTypes, Optional } from 'sequelize'; import sequelize from '../db/config'; import Run from './Run'; +import { WorkflowFile, Where, What, WhereWhatPair } from 'maxun-core'; interface RobotMeta { name: string; @@ -11,18 +12,8 @@ interface RobotMeta { params: any[]; } -interface Workflow { - where: { - url: string; - }; - what: Array<{ - action: string; - args: any[]; - }>; -} - interface Robot { - workflow: Workflow[]; + workflow: WhereWhatPair[]; } interface RobotAttributes { @@ -58,10 +49,10 @@ Robot.init( { sequelize, tableName: 'robot', - timestamps: false, // We'll manage timestamps manually in recording_meta + timestamps: false, } ); Robot.hasMany(Run, { foreignKey: 'robotId' }); -export default Robot; +export default Robot; \ No newline at end of file From dae74286f9a4eb998d61b94c1a9cbcf944869baf Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 14:34:58 +0530 Subject: [PATCH 18/65] chore: lint --- server/src/models/Robot.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/models/Robot.ts b/server/src/models/Robot.ts index 444dcf2d..a255c453 100644 --- a/server/src/models/Robot.ts +++ b/server/src/models/Robot.ts @@ -22,7 +22,7 @@ interface RobotAttributes { recording: Robot; } -interface RobotCreationAttributes extends Optional {} +interface RobotCreationAttributes extends Optional { } class Robot extends Model implements RobotAttributes { public id!: string; @@ -49,7 +49,7 @@ Robot.init( { sequelize, tableName: 'robot', - timestamps: false, + timestamps: false, } ); From 6e2529bb49cffc4130458f12631da6ae6f3e77ef Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 14:36:19 +0530 Subject: [PATCH 19/65] feat: use robot model & robotId instead of fileName --- server/src/routes/workflow.ts | 38 +++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/server/src/routes/workflow.ts b/server/src/routes/workflow.ts index ffbfb39e..c2e0be6b 100644 --- a/server/src/routes/workflow.ts +++ b/server/src/routes/workflow.ts @@ -7,6 +7,7 @@ import logger from "../logger"; import { browserPool } from "../server"; import { readFile } from "../workflow-management/storage"; import { requireSignIn } from '../middlewares/auth'; +import Robot from '../models/Robot'; export const router = Router(); @@ -122,3 +123,40 @@ router.put('/:browserId/:fileName', requireSignIn, async (req, res) => { return res.send(null); } }); + + +router.put('/:browserId/:robotId', requireSignIn, async (req, res) => { + try { + const browser = browserPool.getRemoteBrowser(req.params.browserId); + logger.log('debug', `Updating workflow for Robot ID: ${req.params.robotId}`); + + if (browser && browser.generator) { + const robot = await Robot.findByPk(req.params.robotId); + + if (!robot) { + logger.log('info', `Robot not found with ID: ${req.params.robotId}`); + return res.status(404).send({ error: 'Robot not found' }); + } + + const { recording, recording_meta } = robot; + + if (recording && recording.workflow) { + browser.generator.updateWorkflowFile(recording, recording_meta); + const workflowFile = browser.generator.getWorkflowFile(); + return res.send(workflowFile); + } else { + logger.log('info', `Invalid recording data for Robot ID: ${req.params.robotId}`); + return res.status(400).send({ error: 'Invalid recording data' }); + } + } + + logger.log('info', `Browser or generator not available for ID: ${req.params.browserId}`); + return res.status(400).send({ error: 'Browser or generator not available' }); + } catch (e) { + const { message } = e as Error; + logger.log('error', `Error while updating workflow for Robot ID: ${req.params.robotId}. Error: ${message}`); + return res.status(500).send({ error: 'Internal server error' }); + } +}); + +export default router; \ No newline at end of file From 29d90ec5821d316a75a1a3aaafe76e2afe48f6ab Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 14:43:48 +0530 Subject: [PATCH 20/65] feat: match run model to run format --- server/src/models/Run.ts | 168 +++++++++++++++++++++------------------ 1 file changed, 90 insertions(+), 78 deletions(-) diff --git a/server/src/models/Run.ts b/server/src/models/Run.ts index ab514c2a..3b181114 100644 --- a/server/src/models/Run.ts +++ b/server/src/models/Run.ts @@ -2,95 +2,107 @@ import { Model, DataTypes, Optional } from 'sequelize'; import sequelize from '../db/config'; import Robot from './Robot'; +interface InterpreterSettings { + maxConcurrency: number; + maxRepeats: number; + debug: boolean; +} + interface RunAttributes { - id: string; - robotId: string; - status: string; - name: string; - startedAt: Date; - finishedAt: Date; - browserId: string; - interpreterSettings: object; - log: string; - serializableRun: object; - binaryRunUrl: string; + id: string; + status: string; + name: string; + robotId: string; + startedAt: string; + finishedAt: string; + browserId: string; + interpreterSettings: InterpreterSettings; + log: string; + runId: string; + serializableOutput: Record; + binaryOutput: Record; } interface RunCreationAttributes extends Optional { } class Run extends Model implements RunAttributes { - public id!: string; - public robotId!: string; - public status!: string; - public name!: string; - public startedAt!: Date; - public finishedAt!: Date; - public browserId!: string; - public interpreterSettings!: object; - public log!: string; - public serializableRun!: object; - public binaryRunUrl!: string; + public id!: string; + public status!: string; + public name!: string; + public robotId!: string; + public startedAt!: string; + public finishedAt!: string; + public browserId!: string; + public interpreterSettings!: InterpreterSettings; + public log!: string; + public runId!: string; + public serializableOutput!: Record; + public binaryOutput!: Record; } Run.init( - { - id: { - type: DataTypes.UUID, - defaultValue: DataTypes.UUIDV4, - primaryKey: true, - }, - robotId: { - type: DataTypes.UUID, - allowNull: false, - references: { - model: Robot, - key: 'id', - }, - }, - status: { - type: DataTypes.STRING(50), - allowNull: false, - }, - name: { - type: DataTypes.STRING(255), - allowNull: false, - }, - startedAt: { - type: DataTypes.DATE, - allowNull: false, - }, - finishedAt: { - type: DataTypes.DATE, - allowNull: false, - }, - browserId: { - type: DataTypes.UUID, - allowNull: false, - }, - interpreterSettings: { - type: DataTypes.JSONB, - allowNull: true, - }, - log: { - type: DataTypes.TEXT, - allowNull: true, - }, - serializableRun: { - type: DataTypes.JSONB, - allowNull: true, - }, - binaryRunUrl: { - type: DataTypes.TEXT, - allowNull: true, - }, + { + id: { + type: DataTypes.UUID, + defaultValue: DataTypes.UUIDV4, + primaryKey: true, }, - { - sequelize, - tableName: 'run', - timestamps: false, - } + status: { + type: DataTypes.STRING(50), + allowNull: false, + }, + name: { + type: DataTypes.STRING(255), + allowNull: false, + }, + robotId: { + type: DataTypes.UUID, + allowNull: false, + references: { + model: Robot, + key: 'id', + }, + }, + startedAt: { + type: DataTypes.STRING(255), + allowNull: false, + }, + finishedAt: { + type: DataTypes.STRING(255), + allowNull: false, + }, + browserId: { + type: DataTypes.UUID, + allowNull: false, + }, + interpreterSettings: { + type: DataTypes.JSONB, + allowNull: false, + }, + log: { + type: DataTypes.TEXT, + allowNull: true, + }, + runId: { + type: DataTypes.UUID, + allowNull: false, + }, + serializableOutput: { + type: DataTypes.JSONB, + allowNull: true, + }, + binaryOutput: { + type: DataTypes.JSONB, + allowNull: true, + }, + }, + { + sequelize, + tableName: 'run', + timestamps: false, + } ); Run.belongsTo(Robot, { foreignKey: 'robotId' }); -export default Run; +export default Run; \ No newline at end of file From 40cebea20fdce8d620da1a784cf504e8a1422e38 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 15:45:22 +0530 Subject: [PATCH 21/65] chore: todo --- server/src/models/Run.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server/src/models/Run.ts b/server/src/models/Run.ts index 3b181114..1446fec3 100644 --- a/server/src/models/Run.ts +++ b/server/src/models/Run.ts @@ -2,6 +2,10 @@ import { Model, DataTypes, Optional } from 'sequelize'; import sequelize from '../db/config'; import Robot from './Robot'; +// TODO: +// 1. rename variables +// 2. we might not need interpreter settings? +// 3. store binaryOutput in MinIO interface InterpreterSettings { maxConcurrency: number; maxRepeats: number; From 28e2a89548d76550c80daae6abd6a297d4c81e34 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 20:42:10 +0530 Subject: [PATCH 22/65] feat: no associations in model files --- server/src/models/Robot.ts | 3 --- server/src/models/Run.ts | 2 -- 2 files changed, 5 deletions(-) diff --git a/server/src/models/Robot.ts b/server/src/models/Robot.ts index a255c453..4a193477 100644 --- a/server/src/models/Robot.ts +++ b/server/src/models/Robot.ts @@ -1,6 +1,5 @@ import { Model, DataTypes, Optional } from 'sequelize'; import sequelize from '../db/config'; -import Run from './Run'; import { WorkflowFile, Where, What, WhereWhatPair } from 'maxun-core'; interface RobotMeta { @@ -53,6 +52,4 @@ Robot.init( } ); -Robot.hasMany(Run, { foreignKey: 'robotId' }); - export default Robot; \ No newline at end of file diff --git a/server/src/models/Run.ts b/server/src/models/Run.ts index 1446fec3..020bb863 100644 --- a/server/src/models/Run.ts +++ b/server/src/models/Run.ts @@ -107,6 +107,4 @@ Run.init( } ); -Run.belongsTo(Robot, { foreignKey: 'robotId' }); - export default Run; \ No newline at end of file From d096cf54ddb5deeba9d0caa185033db97d9adea8 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 20:43:15 +0530 Subject: [PATCH 23/65] feat: rename interface to RobotWorkflow --- server/src/models/Robot.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/src/models/Robot.ts b/server/src/models/Robot.ts index 4a193477..2400a917 100644 --- a/server/src/models/Robot.ts +++ b/server/src/models/Robot.ts @@ -11,14 +11,14 @@ interface RobotMeta { params: any[]; } -interface Robot { +interface RobotWorkflow { workflow: WhereWhatPair[]; } interface RobotAttributes { id: string; recording_meta: RobotMeta; - recording: Robot; + recording: RobotWorkflow; } interface RobotCreationAttributes extends Optional { } @@ -26,7 +26,7 @@ interface RobotCreationAttributes extends Optional { } class Robot extends Model implements RobotAttributes { public id!: string; public recording_meta!: RobotMeta; - public recording!: Robot; + public recording!: RobotWorkflow; } Robot.init( From bb80d561ab75be0effb000fee27d58f715d886d2 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 22:30:13 +0530 Subject: [PATCH 24/65] feat: pass row.id --- src/components/molecules/RecordingsTable.tsx | 23 ++++++++++---------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/components/molecules/RecordingsTable.tsx b/src/components/molecules/RecordingsTable.tsx index 251356bd..ac185322 100644 --- a/src/components/molecules/RecordingsTable.tsx +++ b/src/components/molecules/RecordingsTable.tsx @@ -16,7 +16,7 @@ import { useGlobalInfoStore } from "../../context/globalInfo"; import { deleteRecordingFromStorage, getStoredRecordings } from "../../api/storage"; interface Column { - id: 'interpret' | 'name' | 'createdAt' | 'edit' | 'updatedAt' | 'delete' | 'schedule' | 'integrate'; + id: 'id' | 'interpret' | 'name' | 'createdAt' | 'edit' | 'updatedAt' | 'delete' | 'schedule' | 'integrate'; label: string; minWidth?: number; align?: 'right'; @@ -24,6 +24,7 @@ interface Column { } const columns: readonly Column[] = [ + { id: 'id', label: 'ID', minWidth: 80 }, { id: 'interpret', label: 'Run', minWidth: 80 }, { id: 'name', label: 'Name', minWidth: 80 }, { @@ -61,7 +62,7 @@ const columns: readonly Column[] = [ ]; interface Data { - id: number; + id: string; name: string; createdAt: string; updatedAt: string; @@ -70,10 +71,10 @@ interface Data { } interface RecordingsTableProps { - handleEditRecording: (fileName: string) => void; - handleRunRecording: (fileName: string, params: string[]) => void; - handleScheduleRecording: (fileName: string, params: string[]) => void; - handleIntegrateRecording: (fileName: string, params: string[]) => void; + handleEditRecording: (id: string, fileName: string) => void; + handleRunRecording: (id: string,fileName: string, params: string[]) => void; + handleScheduleRecording: (id: string,fileName: string, params: string[]) => void; + handleIntegrateRecording: (id: string,fileName: string, params: string[]) => void; } export const RecordingsTable = ({ handleEditRecording, handleRunRecording, handleScheduleRecording, handleIntegrateRecording }: RecordingsTableProps) => { @@ -156,14 +157,14 @@ export const RecordingsTable = ({ handleEditRecording, handleRunRecording, handl case 'interpret': return ( - handleRunRecording(row.name, row.params || [])} /> + handleRunRecording(row.id, row.name, row.params || [])} /> ); case 'edit': return ( { - handleEditRecording(row.name); + handleEditRecording(row.id, row.name); }} sx={{ '&:hover': { color: '#1976d2', backgroundColor: 'transparent' } }}> @@ -172,20 +173,20 @@ export const RecordingsTable = ({ handleEditRecording, handleRunRecording, handl case 'schedule': return ( - handleScheduleRecording(row.name, row.params || [])} /> + handleScheduleRecording(row.id, row.name, row.params || [])} /> ); case 'integrate': return ( - handleIntegrateRecording(row.name, row.params || [])} /> + handleIntegrateRecording(row.id, row.name, row.params || [])} /> ); case 'delete': return ( { - deleteRecordingFromStorage(row.name).then((result: boolean) => { + deleteRecordingFromStorage(row.id).then((result: boolean) => { if (result) { setRows([]); notify('success', 'Recording deleted successfully'); From 7b61f8c750381d468d15b3966a9becda5ade6629 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 22:30:32 +0530 Subject: [PATCH 25/65] feat: !parse recording --- src/components/molecules/RecordingsTable.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/components/molecules/RecordingsTable.tsx b/src/components/molecules/RecordingsTable.tsx index ac185322..77cf7e8e 100644 --- a/src/components/molecules/RecordingsTable.tsx +++ b/src/components/molecules/RecordingsTable.tsx @@ -97,13 +97,12 @@ export const RecordingsTable = ({ handleEditRecording, handleRunRecording, handl const recordings = await getStoredRecordings(); if (recordings) { const parsedRows: Data[] = []; - recordings.map((recording, index) => { - const parsedRecording = JSON.parse(recording); - if (parsedRecording.recording_meta) { + recordings.map((recording: any, index: number) => { + if (recording && recording.recording_meta) { parsedRows.push({ id: index, - ...parsedRecording.recording_meta, - content: parsedRecording.recording + ...recording.recording_meta, + content: recording.recording }); } }); From 5316b915dd877383032239c7ccbb1ee7f8029c7e Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 22:31:11 +0530 Subject: [PATCH 26/65] feat: accept id for recording handlers --- src/components/organisms/Recordings.tsx | 42 +++++++++++++++---------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/src/components/organisms/Recordings.tsx b/src/components/organisms/Recordings.tsx index e7c65ce4..fbc52bea 100644 --- a/src/components/organisms/Recordings.tsx +++ b/src/components/organisms/Recordings.tsx @@ -6,68 +6,78 @@ import { ScheduleSettings, ScheduleSettingsModal } from "../molecules/ScheduleSe import { IntegrationSettings, IntegrationSettingsModal } from "../molecules/IntegrationSettings"; interface RecordingsProps { - handleEditRecording: (fileName: string) => void; + handleEditRecording: (id: string) => void; handleRunRecording: (settings: RunSettings) => void; handleScheduleRecording: (settings: ScheduleSettings) => void; handleIntegrateRecording: (settings: IntegrationSettings) => void; - setFileName: (fileName: string) => void; + setRecordingInfo: (id: string, name: string) => void; } -export const Recordings = ({ handleEditRecording, handleRunRecording, setFileName, handleScheduleRecording, handleIntegrateRecording }: RecordingsProps) => { +export const Recordings = ({ handleEditRecording, handleRunRecording, setRecordingInfo, handleScheduleRecording, handleIntegrateRecording }: RecordingsProps) => { const [runSettingsAreOpen, setRunSettingsAreOpen] = useState(false); const [scheduleSettingsAreOpen, setScheduleSettingsAreOpen] = useState(false); const [integrateSettingsAreOpen, setIntegrateSettingsAreOpen] = useState(false); const [params, setParams] = useState([]); + const [selectedRecordingId, setSelectedRecordingId] = useState(''); - const handleSettingsAndIntegrate = (fileName: string, params: string[]) => { + const handleSettingsAndIntegrate = (id: string, name: string, params: string[]) => { if (params.length === 0) { setIntegrateSettingsAreOpen(true); - setFileName(fileName); + setRecordingInfo(id, name); + setSelectedRecordingId(id); } else { setParams(params); setIntegrateSettingsAreOpen(true); - setFileName(fileName); + setRecordingInfo(id, name); + setSelectedRecordingId(id); } } - const handleSettingsAndRun = (fileName: string, params: string[]) => { + const handleSettingsAndRun = (id: string, name: string, params: string[]) => { if (params.length === 0) { setRunSettingsAreOpen(true); - setFileName(fileName); + setRecordingInfo(id, name); + setSelectedRecordingId(id); } else { setParams(params); setRunSettingsAreOpen(true); - setFileName(fileName); + setRecordingInfo(id, name); + setSelectedRecordingId(id); } } - const handleSettingsAndSchedule = (fileName: string, params: string[]) => { + const handleSettingsAndSchedule = (id: string, name: string, params: string[]) => { if (params.length === 0) { setScheduleSettingsAreOpen(true); - setFileName(fileName); + setRecordingInfo(id, name); + setSelectedRecordingId(id); } else { setParams(params); setScheduleSettingsAreOpen(true); - setFileName(fileName); + setRecordingInfo(id, name); + setSelectedRecordingId(id); } } const handleClose = () => { setParams([]); setRunSettingsAreOpen(false); - setFileName(''); + setRecordingInfo('', ''); + setSelectedRecordingId(''); } const handleIntegrateClose = () => { setParams([]); setIntegrateSettingsAreOpen(false); - setFileName(''); + setRecordingInfo('', ''); + setSelectedRecordingId(''); } const handleScheduleClose = () => { setParams([]); setScheduleSettingsAreOpen(false); - setFileName(''); + setRecordingInfo('', ''); + setSelectedRecordingId(''); } return ( @@ -98,4 +108,4 @@ export const Recordings = ({ handleEditRecording, handleRunRecording, setFileNam ); -} +} \ No newline at end of file From 981f75c9c6023a23f0c91a3c1ef43962064da4f0 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 23:07:09 +0530 Subject: [PATCH 27/65] feat: call setupAssociations() before sync --- server/src/db/config.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/src/db/config.ts b/server/src/db/config.ts index be1ee123..56c68d8b 100644 --- a/server/src/db/config.ts +++ b/server/src/db/config.ts @@ -1,5 +1,6 @@ import { Sequelize } from 'sequelize'; import dotenv from 'dotenv'; +import setupAssociations from '../models/associations'; dotenv.config(); const sequelize = new Sequelize( @@ -22,6 +23,7 @@ export const connectDB = async () => { export const syncDB = async () => { try { + //setupAssociations(); await sequelize.sync({ force: false }); // force: true will drop and recreate tables on every run console.log('Database synced successfully!'); } catch (error) { From a174e2281c0d10eba1f2843300b83576575227d6 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 23:07:28 +0530 Subject: [PATCH 28/65] feat: robot & run association --- server/src/models/associations.ts | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 server/src/models/associations.ts diff --git a/server/src/models/associations.ts b/server/src/models/associations.ts new file mode 100644 index 00000000..50c22834 --- /dev/null +++ b/server/src/models/associations.ts @@ -0,0 +1,7 @@ +import Robot from './Robot'; +import Run from './Run'; + +export default function setupAssociations() { + Run.belongsTo(Robot, { foreignKey: 'robotId' }); + Robot.hasMany(Run, { foreignKey: 'robotId' }); +} From 565d86ec549f54db8d0110737d516f4588ed5c5d Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 23:08:13 +0530 Subject: [PATCH 29/65] wip: use db model instead of file system --- server/src/routes/workflow.ts | 40 +++++++++++++++++------------------ 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/server/src/routes/workflow.ts b/server/src/routes/workflow.ts index c2e0be6b..c1bbc00d 100644 --- a/server/src/routes/workflow.ts +++ b/server/src/routes/workflow.ts @@ -103,26 +103,26 @@ router.put('/pair/:index', requireSignIn, (req, res) => { /** * PUT endpoint for updating the currently generated workflow file from the one in the storage. */ -router.put('/:browserId/:fileName', requireSignIn, async (req, res) => { - try { - const browser = browserPool.getRemoteBrowser(req.params.browserId); - logger.log('debug', `Updating workflow file`); - if (browser && browser.generator) { - const recording = await readFile(`./../storage/recordings/${req.params.fileName}.json`) - const parsedRecording = JSON.parse(recording); - if (parsedRecording.recording) { - browser.generator?.updateWorkflowFile(parsedRecording.recording, parsedRecording.recording_meta); - const workflowFile = browser.generator?.getWorkflowFile(); - return res.send(workflowFile); - } - } - return res.send(null); - } catch (e) { - const { message } = e as Error; - logger.log('info', `Error while reading a recording with name: ${req.params.fileName}.json`); - return res.send(null); - } -}); +// router.put('/:browserId/:fileName', requireSignIn, async (req, res) => { +// try { +// const browser = browserPool.getRemoteBrowser(req.params.browserId); +// logger.log('debug', `Updating workflow file`); +// if (browser && browser.generator) { +// const recording = await readFile(`./../storage/recordings/${req.params.fileName}.json`) +// const parsedRecording = JSON.parse(recording); +// if (parsedRecording.recording) { +// browser.generator?.updateWorkflowFile(parsedRecording.recording, parsedRecording.recording_meta); +// const workflowFile = browser.generator?.getWorkflowFile(); +// return res.send(workflowFile); +// } +// } +// return res.send(null); +// } catch (e) { +// const { message } = e as Error; +// logger.log('info', `Error while reading a recording with name: ${req.params.fileName}.json`); +// return res.send(null); +// } +// }); router.put('/:browserId/:robotId', requireSignIn, async (req, res) => { From 7e22582997165bf6b127d2d963bf36896d5014ba Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 23:08:30 +0530 Subject: [PATCH 30/65] wip: use db model instead of file system --- server/src/routes/storage.ts | 139 +++++++++++++++++++++-------------- 1 file changed, 83 insertions(+), 56 deletions(-) diff --git a/server/src/routes/storage.ts b/server/src/routes/storage.ts index 74faa504..6e74a287 100644 --- a/server/src/routes/storage.ts +++ b/server/src/routes/storage.ts @@ -11,6 +11,8 @@ import cron from 'node-cron'; import { googleSheetUpdateTasks, processGoogleSheetUpdates } from '../workflow-management/integrations/gsheet'; import { getDecryptedProxyConfig } from './proxy'; import { requireSignIn } from '../middlewares/auth'; +import Robot from '../models/Robot'; +import Run from '../models/Run'; // import { workflowQueue } from '../worker'; // todo: move from here @@ -40,7 +42,7 @@ router.all('/', requireSignIn, (req, res, next) => { */ router.get('/recordings', requireSignIn, async (req, res) => { try { - const data = await readFiles('./../storage/recordings/'); + const data = await Robot.findAll(); return res.send(data); } catch (e) { logger.log('info', 'Error while reading recordings'); @@ -51,9 +53,9 @@ router.get('/recordings', requireSignIn, async (req, res) => { /** * DELETE endpoint for deleting a recording from the storage. */ -router.delete('/recordings/:fileName', requireSignIn, async (req, res) => { +router.delete('/recordings/:id', requireSignIn, async (req, res) => { try { - await deleteFile(`./../storage/recordings/${req.params.fileName}.json`); + await Robot.destroy({ where: { id: req.params.id } }); return res.send(true); } catch (e) { const { message } = e as Error; @@ -67,7 +69,7 @@ router.delete('/recordings/:fileName', requireSignIn, async (req, res) => { */ router.get('/runs', requireSignIn, async (req, res) => { try { - const data = await readFiles('./../storage/runs/'); + const data = await Run.findAll(); return res.send(data); } catch (e) { logger.log('info', 'Error while reading runs'); @@ -78,9 +80,9 @@ router.get('/runs', requireSignIn, async (req, res) => { /** * DELETE endpoint for deleting a run from the storage. */ -router.delete('/runs/:fileName', requireSignIn, async (req, res) => { +router.delete('/runs/:id', requireSignIn, async (req, res) => { try { - await deleteFile(`./../storage/runs/${req.params.fileName}.json`); + await Run.destroy({ where: { id: req.params.id } }); return res.send(true); } catch (e) { const { message } = e as Error; @@ -93,9 +95,14 @@ router.delete('/runs/:fileName', requireSignIn, async (req, res) => { * PUT endpoint for starting a remote browser instance and saving run metadata to the storage. * Making it ready for interpretation and returning a runId. */ -router.put('/runs/:fileName', requireSignIn, async (req, res) => { +router.put('/runs/:id', requireSignIn, async (req, res) => { try { - const recording = await getRecordingByFileName(req.params.fileName); + console.log(`Params recieved:`,req.params ) + const recording = await Robot.findOne({ + where: { + 'recording_meta.id': req.params.id + } + }); if (!recording || !recording.recording_meta || !recording.recording_meta.id) { return res.status(404).send({ error: 'Recording not found' }); @@ -124,29 +131,35 @@ router.put('/runs/:fileName', requireSignIn, async (req, res) => { const runId = uuid(); - const run_meta = { + const run = await Run.create({ status: 'RUNNING', name: req.params.fileName, - recordingId: recording.recording_meta.id, + robotId: recording.recording_meta.id, startedAt: new Date().toLocaleString(), finishedAt: '', browserId: id, interpreterSettings: req.body, log: '', runId, - }; - fs.mkdirSync('../storage/runs', { recursive: true }) - await saveFile( - `../storage/runs/${req.params.fileName}_${runId}.json`, - JSON.stringify({ ...run_meta }, null, 2) - ); - logger.log('debug', `Created run with name: ${req.params.fileName}.json`); + serializableOutput: {}, + binaryOutput: {}, + }); - console.log('Run meta:', run_meta); + // // we need to handle this via DB + // fs.mkdirSync('../storage/runs', { recursive: true }) + // await saveFile( + // `../storage/runs/${req.params.fileName}_${runId}.json`, + // JSON.stringify({ ...run_meta }, null, 2) + // ); + // logger.log('debug', `Created run with name: ${req.params.fileName}.json`); + + // console.log('Run meta:', run_meta); + + logger.log('debug', `Created run with id: ${run.id}`); return res.send({ browserId: id, - runId: runId, + runId: run.id, }); } catch (e) { const { message } = e as Error; @@ -158,12 +171,16 @@ router.put('/runs/:fileName', requireSignIn, async (req, res) => { /** * GET endpoint for getting a run from the storage. */ -router.get('/runs/run/:fileName/:runId', requireSignIn, async (req, res) => { +router.get('/runs/run/:id', requireSignIn, async (req, res) => { try { + console.log(`Params for GET /runs/run/:id`, req.params.id) // read the run from storage - const run = await readFile(`./../storage/runs/${req.params.fileName}_${req.params.runId}.json`) - const parsedRun = JSON.parse(run); - return res.send(parsedRun); + const run = await Run.findByPk(req.params.id); + //const parsedRun = JSON.parse(run); + if (!run) { + return res.status(404).send(null); + } + return res.send(run); } catch (e) { const { message } = e as Error; logger.log('error', `Error ${message} while reading a run with name: ${req.params.fileName}_${req.params.runId}.json`); @@ -174,38 +191,44 @@ router.get('/runs/run/:fileName/:runId', requireSignIn, async (req, res) => { /** * PUT endpoint for finishing a run and saving it to the storage. */ -router.post('/runs/run/:fileName/:runId', requireSignIn, async (req, res) => { +router.post('/runs/run/:id', requireSignIn, async (req, res) => { try { - const recording = await readFile(`./../storage/recordings/${req.params.fileName}.json`) - const parsedRecording = JSON.parse(recording); + // const recording = await readFile(`./../storage/recordings/${req.params.fileName}.json`) + // const parsedRecording = JSON.parse(recording); - const run = await readFile(`./../storage/runs/${req.params.fileName}_${req.params.runId}.json`) - const parsedRun = JSON.parse(run); + // const run = await readFile(`./../storage/runs/${req.params.fileName}_${req.params.runId}.json`) + // const parsedRun = JSON.parse(run); + console.log(`Params for POST /runs/run/:id`, req.params.id) + + const run = await Run.findByPk(req.params.id); + if (!run) { + return res.status(404).send(false); + } + + const recording = await Robot.findByPk(run.robotId); + if (!recording) { + return res.status(404).send(false); + } // interpret the run in active browser - const browser = browserPool.getRemoteBrowser(parsedRun.browserId); + const browser = browserPool.getRemoteBrowser(run.browserId); const currentPage = browser?.getCurrentPage(); if (browser && currentPage) { const interpretationInfo = await browser.interpreter.InterpretRecording( - parsedRecording.recording, currentPage, parsedRun.interpreterSettings); - await destroyRemoteBrowser(parsedRun.browserId); - const run_meta = { - ...parsedRun, + recording.recording, currentPage, run.interpreterSettings); + await destroyRemoteBrowser(run.browserId); + await run.update({ + ...run, status: 'success', finishedAt: new Date().toLocaleString(), - browserId: parsedRun.browserId, + browserId: run.browserId, log: interpretationInfo.log.join('\n'), serializableOutput: interpretationInfo.serializableOutput, binaryOutput: interpretationInfo.binaryOutput, - }; - fs.mkdirSync('../storage/runs', { recursive: true }) - await saveFile( - `../storage/runs/${parsedRun.name}_${req.params.runId}.json`, - JSON.stringify(run_meta, null, 2) - ); + }); googleSheetUpdateTasks[req.params.runId] = { - name: parsedRun.name, - runId: req.params.runId, + name: run.name, + runId: run.id, status: 'pending', retries: 5, }; @@ -316,12 +339,16 @@ router.put('/schedule/:fileName/', requireSignIn, async (req, res) => { /** * POST endpoint for aborting a current interpretation of the run. */ -router.post('/runs/abort/:fileName/:runId', requireSignIn, async (req, res) => { +router.post('/runs/abort/:id', requireSignIn, async (req, res) => { try { - const run = await readFile(`./../storage/runs/${req.params.fileName}_${req.params.runId}.json`) - const parsedRun = JSON.parse(run); + console.log(`Params for POST /runs/abort/:id`, req.params.id) + const run = await Run.findByPk(req.params.id); + if (!run) { + return res.status(404).send(false); + } + //const parsedRun = JSON.parse(run); - const browser = browserPool.getRemoteBrowser(parsedRun.browserId); + const browser = browserPool.getRemoteBrowser(run.browserId); const currentLog = browser?.interpreter.debugMessages.join('/n'); const serializableOutput = browser?.interpreter.serializableData.reduce((reducedObject, item, index) => { return { @@ -335,19 +362,19 @@ router.post('/runs/abort/:fileName/:runId', requireSignIn, async (req, res) => { ...reducedObject, } }, {}); - const run_meta = { - ...parsedRun, + await run.update({ + ...run, status: 'aborted', - finishedAt: null, - browserId: null, + finishedAt: new Date().toLocaleString(), + browserId: run.browserId, log: currentLog, - }; + }); - fs.mkdirSync('../storage/runs', { recursive: true }) - await saveFile( - `../storage/runs/${parsedRun.name}_${req.params.runId}.json`, - JSON.stringify({ ...run_meta, serializableOutput, binaryOutput }, null, 2) - ); + // fs.mkdirSync('../storage/runs', { recursive: true }) + // await saveFile( + // `../storage/runs/${run.name}_${req.params.runId}.json`, + // JSON.stringify({ ...run_meta, serializableOutput, binaryOutput }, null, 2) + // ); return res.send(true); } catch (e) { const { message } = e as Error; From 70c7938fad5537a0f678b7dd2396d0aa1d417566 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 23:09:04 +0530 Subject: [PATCH 31/65] feat: use robot model to save new workflow --- server/src/workflow-management/classes/Generator.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/server/src/workflow-management/classes/Generator.ts b/server/src/workflow-management/classes/Generator.ts index 95a86016..0516703b 100644 --- a/server/src/workflow-management/classes/Generator.ts +++ b/server/src/workflow-management/classes/Generator.ts @@ -14,6 +14,8 @@ import { } from "../selector"; import { CustomActions } from "../../../../src/shared/types"; import { workflow } from "../../routes"; +import Robot from "../../models/Robot"; +import Run from "../../models/Run"; import { saveFile } from "../storage"; import fs from "fs"; import { getBestSelectorForAction } from "../utils"; @@ -486,11 +488,12 @@ export class WorkflowGenerator { updatedAt: new Date().toLocaleString(), params: this.getParams() || [], } - fs.mkdirSync('../storage/recordings', { recursive: true }) - await saveFile( - `../storage/recordings/${fileName}.json`, - JSON.stringify({ recording_meta: this.recordingMeta, recording }, null, 2) - ); + const robot = await Robot.create({ + recording_meta: this.recordingMeta, + recording: recording, + }); + + logger.log('info', `Robot saved with id: ${robot.id}`); } catch (e) { const { message } = e as Error; From 01e33120d62f498b3158e90989cdb64fabc7b11f Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 23:09:42 +0530 Subject: [PATCH 32/65] feat: use id instead of file name (wip) --- src/api/storage.ts | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/api/storage.ts b/src/api/storage.ts index 913c7d85..e72d400d 100644 --- a/src/api/storage.ts +++ b/src/api/storage.ts @@ -32,13 +32,13 @@ export const getStoredRuns = async (): Promise => { } }; -export const deleteRecordingFromStorage = async (fileName: string): Promise => { +export const deleteRecordingFromStorage = async (id: string): Promise => { try { - const response = await axios.delete(`http://localhost:8080/storage/recordings/${fileName}`); + const response = await axios.delete(`http://localhost:8080/storage/recordings/${id}`); if (response.status === 200) { return response.data; } else { - throw new Error(`Couldn't delete stored recording ${fileName}`); + throw new Error(`Couldn't delete stored recording ${id}`); } } catch(error: any) { console.log(error); @@ -46,13 +46,13 @@ export const deleteRecordingFromStorage = async (fileName: string): Promise => { +export const deleteRunFromStorage = async (id: string): Promise => { try { - const response = await axios.delete(`http://localhost:8080/storage/runs/${fileName}`); + const response = await axios.delete(`http://localhost:8080/storage/runs/${id}`); if (response.status === 200) { return response.data; } else { - throw new Error(`Couldn't delete stored recording ${fileName}`); + throw new Error(`Couldn't delete stored recording ${id}`); } } catch(error: any) { console.log(error); @@ -60,13 +60,13 @@ export const deleteRunFromStorage = async (fileName: string): Promise = } }; -export const editRecordingFromStorage = async (browserId: string, fileName: string): Promise => { +export const editRecordingFromStorage = async (browserId: string, robotId: string): Promise => { try { - const response = await axios.put(`http://localhost:8080/workflow/${browserId}/${fileName}`); + const response = await axios.put(`http://localhost:8080/workflow/${browserId}/${robotId}`); if (response.status === 200) { return response.data; } else { - throw new Error(`Couldn't edit stored recording ${fileName}`); + throw new Error(`Couldn't edit stored recording ${robotId}`); } } catch(error: any) { console.log(error); @@ -74,15 +74,15 @@ export const editRecordingFromStorage = async (browserId: string, fileName: stri } }; -export const createRunForStoredRecording = async (fileName: string, settings: RunSettings): Promise => { +export const createRunForStoredRecording = async (id: string, settings: RunSettings): Promise => { try { const response = await axios.put( - `http://localhost:8080/storage/runs/${fileName}`, + `http://localhost:8080/storage/runs/${id}`, {...settings}); if (response.status === 200) { return response.data; } else { - throw new Error(`Couldn't create a run for a recording ${fileName}`); + throw new Error(`Couldn't create a run for a recording ${id}`); } } catch(error: any) { console.log(error); @@ -90,13 +90,13 @@ export const createRunForStoredRecording = async (fileName: string, settings: Ru } } -export const interpretStoredRecording = async (fileName: string, runId: string): Promise => { +export const interpretStoredRecording = async (runId: string): Promise => { try { - const response = await axios.post(`http://localhost:8080/storage/runs/run/${fileName}/${runId}`); + const response = await axios.post(`http://localhost:8080/storage/runs/run/${runId}`); if (response.status === 200) { return response.data; } else { - throw new Error(`Couldn't run a recording ${fileName}`); + throw new Error(`Couldn't run a recording ${runId}`); } } catch(error: any) { console.log(error); @@ -104,13 +104,13 @@ export const interpretStoredRecording = async (fileName: string, runId: string): } } -export const notifyAboutAbort = async (fileName: string, runId:string): Promise => { +export const notifyAboutAbort = async (runId:string): Promise => { try { - const response = await axios.post(`http://localhost:8080/storage/runs/abort/${fileName}/${runId}`); + const response = await axios.post(`http://localhost:8080/storage/runs/abort/${runId}`); if (response.status === 200) { return response.data; } else { - throw new Error(`Couldn't abort a running recording ${fileName} with id ${runId}`); + throw new Error(`Couldn't abort a running recording with id ${runId}`); } } catch(error: any) { console.log(error); From e03bd5c8caf1bfa122015f48b0426fb7de7588b2 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 23:10:06 +0530 Subject: [PATCH 33/65] feat: include recordingId --- src/context/globalInfo.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/context/globalInfo.tsx b/src/context/globalInfo.tsx index e0efb678..7e7a3826 100644 --- a/src/context/globalInfo.tsx +++ b/src/context/globalInfo.tsx @@ -16,6 +16,8 @@ interface GlobalInfo { setRerenderRuns: (rerenderRuns: boolean) => void; recordingLength: number; setRecordingLength: (recordingLength: number) => void; + recordingId: string | null; + setRecordingId: (newId: string | null) => void; recordingName: string; setRecordingName: (recordingName: string) => void; }; @@ -29,6 +31,7 @@ class GlobalInfoStore implements Partial { message: '', isOpen: false, }; + recordingId = null; recordings: string[] = []; rerenderRuns = false; recordingName = ''; @@ -46,6 +49,7 @@ export const GlobalInfoProvider = ({ children }: { children: JSX.Element }) => { const [recordings, setRecordings] = useState(globalInfoStore.recordings); const [rerenderRuns, setRerenderRuns] = useState(globalInfoStore.rerenderRuns); const [recordingLength, setRecordingLength] = useState(globalInfoStore.recordingLength); + const [recordingId, setRecordingId] = useState(globalInfoStore.recordingId); const [recordingName, setRecordingName] = useState(globalInfoStore.recordingName); const notify = (severity: 'error' | 'warning' | 'info' | 'success', message: string) => { @@ -79,6 +83,8 @@ export const GlobalInfoProvider = ({ children }: { children: JSX.Element }) => { setRerenderRuns, recordingLength, setRecordingLength, + recordingId, + setRecordingId, recordingName, setRecordingName }} From 6b4eb8daf09c5653fe80795020f30e1bfa4f1f4b Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 9 Oct 2024 23:22:38 +0530 Subject: [PATCH 34/65] feat: delete recording based on meta id --- server/src/routes/storage.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/src/routes/storage.ts b/server/src/routes/storage.ts index 6e74a287..4dbc71b4 100644 --- a/server/src/routes/storage.ts +++ b/server/src/routes/storage.ts @@ -55,7 +55,9 @@ router.get('/recordings', requireSignIn, async (req, res) => { */ router.delete('/recordings/:id', requireSignIn, async (req, res) => { try { - await Robot.destroy({ where: { id: req.params.id } }); + await Robot.destroy({ + where: { 'recording_meta.id': req.params.id } + }); return res.send(true); } catch (e) { const { message } = e as Error; From b83dc9d75551bc8594f9c89abbe9adeb754da614 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 01:19:03 +0530 Subject: [PATCH 35/65] feat: start recording run --- server/src/routes/storage.ts | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/server/src/routes/storage.ts b/server/src/routes/storage.ts index 4dbc71b4..73252446 100644 --- a/server/src/routes/storage.ts +++ b/server/src/routes/storage.ts @@ -103,9 +103,12 @@ router.put('/runs/:id', requireSignIn, async (req, res) => { const recording = await Robot.findOne({ where: { 'recording_meta.id': req.params.id - } + }, + raw: true }); + console.log(`Recording found:`, recording) + if (!recording || !recording.recording_meta || !recording.recording_meta.id) { return res.status(404).send({ error: 'Recording not found' }); } @@ -135,8 +138,9 @@ router.put('/runs/:id', requireSignIn, async (req, res) => { const run = await Run.create({ status: 'RUNNING', - name: req.params.fileName, - robotId: recording.recording_meta.id, + name: recording.recording_meta.name, + robotId: recording.id, + robotMetaId: recording.recording_meta.id, startedAt: new Date().toLocaleString(), finishedAt: '', browserId: id, @@ -157,15 +161,15 @@ router.put('/runs/:id', requireSignIn, async (req, res) => { // console.log('Run meta:', run_meta); - logger.log('debug', `Created run with id: ${run.id}`); + logger.log('debug', `Created run with id: ${run.runId}`); return res.send({ browserId: id, - runId: run.id, + runId: run.runId, }); } catch (e) { const { message } = e as Error; - logger.log('info', `Error while creating a run with name: ${req.params.fileName}.json`); + logger.log('info', `Error while creating a run with recording id: ${req.params.id} - ${message}`); return res.send(''); } }); @@ -177,7 +181,7 @@ router.get('/runs/run/:id', requireSignIn, async (req, res) => { try { console.log(`Params for GET /runs/run/:id`, req.params.id) // read the run from storage - const run = await Run.findByPk(req.params.id); + const run = await Run.findOne({ where: { runId: req.params.runId }, raw: true }); //const parsedRun = JSON.parse(run); if (!run) { return res.status(404).send(null); @@ -202,12 +206,12 @@ router.post('/runs/run/:id', requireSignIn, async (req, res) => { // const parsedRun = JSON.parse(run); console.log(`Params for POST /runs/run/:id`, req.params.id) - const run = await Run.findByPk(req.params.id); + const run = await Run.findOne({ where: { runId: req.params.runId }, raw: true }); if (!run) { return res.status(404).send(false); } - const recording = await Robot.findByPk(run.robotId); + const recording = await Robot.findOne({ where: { 'recording_meta.id': run.robotMetaId }, raw: true }); if (!recording) { return res.status(404).send(false); } @@ -230,7 +234,7 @@ router.post('/runs/run/:id', requireSignIn, async (req, res) => { }); googleSheetUpdateTasks[req.params.runId] = { name: run.name, - runId: run.id, + runId: run.runId, status: 'pending', retries: 5, }; @@ -344,7 +348,7 @@ router.put('/schedule/:fileName/', requireSignIn, async (req, res) => { router.post('/runs/abort/:id', requireSignIn, async (req, res) => { try { console.log(`Params for POST /runs/abort/:id`, req.params.id) - const run = await Run.findByPk(req.params.id); + const run = await Run.findOne({ where: { runId: req.params.runId }, raw: true }); if (!run) { return res.status(404).send(false); } @@ -370,6 +374,8 @@ router.post('/runs/abort/:id', requireSignIn, async (req, res) => { finishedAt: new Date().toLocaleString(), browserId: run.browserId, log: currentLog, + serializableOutput, + binaryOutput, }); // fs.mkdirSync('../storage/runs', { recursive: true }) From 6dcc927d6a65b03709d14c543308c5eaa9364217 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 01:19:31 +0530 Subject: [PATCH 36/65] chore: lint --- server/src/routes/storage.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/server/src/routes/storage.ts b/server/src/routes/storage.ts index 73252446..d6462e10 100644 --- a/server/src/routes/storage.ts +++ b/server/src/routes/storage.ts @@ -99,10 +99,10 @@ router.delete('/runs/:id', requireSignIn, async (req, res) => { */ router.put('/runs/:id', requireSignIn, async (req, res) => { try { - console.log(`Params recieved:`,req.params ) + console.log(`Params recieved:`, req.params) const recording = await Robot.findOne({ - where: { - 'recording_meta.id': req.params.id + where: { + 'recording_meta.id': req.params.id }, raw: true }); @@ -206,12 +206,12 @@ router.post('/runs/run/:id', requireSignIn, async (req, res) => { // const parsedRun = JSON.parse(run); console.log(`Params for POST /runs/run/:id`, req.params.id) - const run = await Run.findOne({ where: { runId: req.params.runId }, raw: true }); + const run = await Run.findOne({ where: { runId: req.params.runId }, raw: true }); if (!run) { return res.status(404).send(false); } - const recording = await Robot.findOne({ where: { 'recording_meta.id': run.robotMetaId }, raw: true }); + const recording = await Robot.findOne({ where: { 'recording_meta.id': run.robotMetaId }, raw: true }); if (!recording) { return res.status(404).send(false); } @@ -348,7 +348,7 @@ router.put('/schedule/:fileName/', requireSignIn, async (req, res) => { router.post('/runs/abort/:id', requireSignIn, async (req, res) => { try { console.log(`Params for POST /runs/abort/:id`, req.params.id) - const run = await Run.findOne({ where: { runId: req.params.runId }, raw: true }); + const run = await Run.findOne({ where: { runId: req.params.runId }, raw: true }); if (!run) { return res.status(404).send(false); } From f4665d197e0569ed3d5ac5c1245387c6aec05645 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 01:21:49 +0530 Subject: [PATCH 37/65] feat: add robotMetaId --- server/src/models/Run.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/server/src/models/Run.ts b/server/src/models/Run.ts index 020bb863..5c14dfd9 100644 --- a/server/src/models/Run.ts +++ b/server/src/models/Run.ts @@ -17,6 +17,7 @@ interface RunAttributes { status: string; name: string; robotId: string; + robotMetaId: string; startedAt: string; finishedAt: string; browserId: string; @@ -34,6 +35,7 @@ class Run extends Model implements RunAttr public status!: string; public name!: string; public robotId!: string; + public robotMetaId!: string; public startedAt!: string; public finishedAt!: string; public browserId!: string; @@ -67,6 +69,10 @@ Run.init( key: 'id', }, }, + robotMetaId: { + type: DataTypes.UUID, + allowNull: false, + }, startedAt: { type: DataTypes.STRING(255), allowNull: false, From b90a1d5375b4cb08f1df5b8bf7cc920bc1cc0903 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 01:55:23 +0530 Subject: [PATCH 38/65] feat: start interpretation --- server/src/routes/storage.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/server/src/routes/storage.ts b/server/src/routes/storage.ts index d6462e10..3116176d 100644 --- a/server/src/routes/storage.ts +++ b/server/src/routes/storage.ts @@ -151,6 +151,10 @@ router.put('/runs/:id', requireSignIn, async (req, res) => { binaryOutput: {}, }); + const plainRun = run.toJSON(); + +console.log(`Created run (plain object):`, plainRun); + // // we need to handle this via DB // fs.mkdirSync('../storage/runs', { recursive: true }) // await saveFile( @@ -160,12 +164,9 @@ router.put('/runs/:id', requireSignIn, async (req, res) => { // logger.log('debug', `Created run with name: ${req.params.fileName}.json`); // console.log('Run meta:', run_meta); - - logger.log('debug', `Created run with id: ${run.runId}`); - return res.send({ browserId: id, - runId: run.runId, + runId: plainRun.runId, }); } catch (e) { const { message } = e as Error; @@ -189,7 +190,7 @@ router.get('/runs/run/:id', requireSignIn, async (req, res) => { return res.send(run); } catch (e) { const { message } = e as Error; - logger.log('error', `Error ${message} while reading a run with name: ${req.params.fileName}_${req.params.runId}.json`); + logger.log('error', `Error ${message} while reading a run with id: ${req.params.id}.json`); return res.send(null); } }); @@ -206,7 +207,7 @@ router.post('/runs/run/:id', requireSignIn, async (req, res) => { // const parsedRun = JSON.parse(run); console.log(`Params for POST /runs/run/:id`, req.params.id) - const run = await Run.findOne({ where: { runId: req.params.runId }, raw: true }); + const run = await Run.findOne({ where: { runId: req.params.id }, raw: true }); if (!run) { return res.status(404).send(false); } @@ -348,7 +349,7 @@ router.put('/schedule/:fileName/', requireSignIn, async (req, res) => { router.post('/runs/abort/:id', requireSignIn, async (req, res) => { try { console.log(`Params for POST /runs/abort/:id`, req.params.id) - const run = await Run.findOne({ where: { runId: req.params.runId }, raw: true }); + const run = await Run.findOne({ where: { runId: req.params.id }, raw: true }); if (!run) { return res.status(404).send(false); } From a30c08b819b3d2a3307b7325f31a548a071c670b Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 02:02:43 +0530 Subject: [PATCH 39/65] feat: delete run based on runId --- server/src/routes/storage.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/server/src/routes/storage.ts b/server/src/routes/storage.ts index 3116176d..766daae8 100644 --- a/server/src/routes/storage.ts +++ b/server/src/routes/storage.ts @@ -84,7 +84,7 @@ router.get('/runs', requireSignIn, async (req, res) => { */ router.delete('/runs/:id', requireSignIn, async (req, res) => { try { - await Run.destroy({ where: { id: req.params.id } }); + await Run.destroy({ where: { runId: req.params.id } }); return res.send(true); } catch (e) { const { message } = e as Error; @@ -212,6 +212,8 @@ router.post('/runs/run/:id', requireSignIn, async (req, res) => { return res.status(404).send(false); } + console.log(`found run: ${run}`) + const recording = await Robot.findOne({ where: { 'recording_meta.id': run.robotMetaId }, raw: true }); if (!recording) { return res.status(404).send(false); @@ -233,7 +235,7 @@ router.post('/runs/run/:id', requireSignIn, async (req, res) => { serializableOutput: interpretationInfo.serializableOutput, binaryOutput: interpretationInfo.binaryOutput, }); - googleSheetUpdateTasks[req.params.runId] = { + googleSheetUpdateTasks[req.params.id] = { name: run.name, runId: run.runId, status: 'pending', @@ -246,7 +248,7 @@ router.post('/runs/run/:id', requireSignIn, async (req, res) => { } } catch (e) { const { message } = e as Error; - logger.log('info', `Error while running a recording with name: ${req.params.fileName}_${req.params.runId}.json`); + logger.log('info', `Error while running a recording with id: ${req.params.id} - ${message}`); return res.send(false); } }); From 590e7e9d9f0d641b4cb1c7ffb7c97f8d84499332 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 02:23:33 +0530 Subject: [PATCH 40/65] feat: successful run + interpretation of robots --- server/src/routes/storage.ts | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/server/src/routes/storage.ts b/server/src/routes/storage.ts index 766daae8..eb5185f1 100644 --- a/server/src/routes/storage.ts +++ b/server/src/routes/storage.ts @@ -207,37 +207,39 @@ router.post('/runs/run/:id', requireSignIn, async (req, res) => { // const parsedRun = JSON.parse(run); console.log(`Params for POST /runs/run/:id`, req.params.id) - const run = await Run.findOne({ where: { runId: req.params.id }, raw: true }); + const run = await Run.findOne({ where: { runId: req.params.id } }); if (!run) { return res.status(404).send(false); } console.log(`found run: ${run}`) - const recording = await Robot.findOne({ where: { 'recording_meta.id': run.robotMetaId }, raw: true }); + const plainRun = run.toJSON(); + + const recording = await Robot.findOne({ where: { 'recording_meta.id': plainRun.robotMetaId }, raw: true }); if (!recording) { return res.status(404).send(false); } // interpret the run in active browser - const browser = browserPool.getRemoteBrowser(run.browserId); + const browser = browserPool.getRemoteBrowser(plainRun.browserId); const currentPage = browser?.getCurrentPage(); if (browser && currentPage) { const interpretationInfo = await browser.interpreter.InterpretRecording( - recording.recording, currentPage, run.interpreterSettings); - await destroyRemoteBrowser(run.browserId); + recording.recording, currentPage, plainRun.interpreterSettings); + await destroyRemoteBrowser(plainRun.browserId); await run.update({ ...run, status: 'success', finishedAt: new Date().toLocaleString(), - browserId: run.browserId, + browserId: plainRun.browserId, log: interpretationInfo.log.join('\n'), serializableOutput: interpretationInfo.serializableOutput, binaryOutput: interpretationInfo.binaryOutput, }); googleSheetUpdateTasks[req.params.id] = { - name: run.name, - runId: run.runId, + name: plainRun.name, + runId: plainRun.runId, status: 'pending', retries: 5, }; @@ -351,7 +353,7 @@ router.put('/schedule/:fileName/', requireSignIn, async (req, res) => { router.post('/runs/abort/:id', requireSignIn, async (req, res) => { try { console.log(`Params for POST /runs/abort/:id`, req.params.id) - const run = await Run.findOne({ where: { runId: req.params.id }, raw: true }); + const run = await Run.findOne({ where: { runId: req.params.id }}); if (!run) { return res.status(404).send(false); } From 64e313de015ee50c59e80f7c4d7c212bda30714b Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 02:24:23 +0530 Subject: [PATCH 41/65] feat: use id instead of runId --- src/api/storage.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/api/storage.ts b/src/api/storage.ts index e72d400d..47946717 100644 --- a/src/api/storage.ts +++ b/src/api/storage.ts @@ -90,13 +90,13 @@ export const createRunForStoredRecording = async (id: string, settings: RunSetti } } -export const interpretStoredRecording = async (runId: string): Promise => { +export const interpretStoredRecording = async (id: string): Promise => { try { - const response = await axios.post(`http://localhost:8080/storage/runs/run/${runId}`); + const response = await axios.post(`http://localhost:8080/storage/runs/run/${id}`); if (response.status === 200) { return response.data; } else { - throw new Error(`Couldn't run a recording ${runId}`); + throw new Error(`Couldn't run a recording ${id}`); } } catch(error: any) { console.log(error); @@ -104,13 +104,13 @@ export const interpretStoredRecording = async (runId: string): Promise } } -export const notifyAboutAbort = async (runId:string): Promise => { +export const notifyAboutAbort = async (id:string): Promise => { try { - const response = await axios.post(`http://localhost:8080/storage/runs/abort/${runId}`); + const response = await axios.post(`http://localhost:8080/storage/runs/abort/${id}`); if (response.status === 200) { return response.data; } else { - throw new Error(`Couldn't abort a running recording with id ${runId}`); + throw new Error(`Couldn't abort a running recording with id ${id}`); } } catch(error: any) { console.log(error); From d9d563b0ef5ff275496de13dfaa6f362218b909e Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 02:25:48 +0530 Subject: [PATCH 42/65] feat (temp) : show robot it --- src/components/molecules/ColapsibleRow.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/molecules/ColapsibleRow.tsx b/src/components/molecules/ColapsibleRow.tsx index bec7c0cf..ca56bf4c 100644 --- a/src/components/molecules/ColapsibleRow.tsx +++ b/src/components/molecules/ColapsibleRow.tsx @@ -65,7 +65,7 @@ export const CollapsibleRow = ({ row, handleDelete, isOpen, currentLog, abortRun return ( { - deleteRunFromStorage(`${row.name}_${row.runId}`).then((result: boolean) => { + deleteRunFromStorage(`${row.runId}`).then((result: boolean) => { if (result) { handleDelete(); } From 8b9381e5e17656a17df58c35a7fc09a1889a98d1 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 02:26:05 +0530 Subject: [PATCH 43/65] feat: remove run parsing --- src/components/molecules/RunsTable.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/molecules/RunsTable.tsx b/src/components/molecules/RunsTable.tsx index 578f8140..7f414c58 100644 --- a/src/components/molecules/RunsTable.tsx +++ b/src/components/molecules/RunsTable.tsx @@ -77,11 +77,11 @@ export const RunsTable = ( const runs = await getStoredRuns(); if (runs) { const parsedRows: Data[] = []; - runs.map((run, index) => { - const parsedRun = JSON.parse(run); + runs.map((run: any, index) => { + // const run = JSON.parse(run); parsedRows.push({ id: index, - ...parsedRun, + ...run, }); }); setRows(parsedRows); From b29e37b94febc53d17e7aa10a673f888bb324948 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 02:29:12 +0530 Subject: [PATCH 44/65] feat: include id for recording edit and info --- src/components/organisms/Recordings.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/organisms/Recordings.tsx b/src/components/organisms/Recordings.tsx index fbc52bea..06af02fd 100644 --- a/src/components/organisms/Recordings.tsx +++ b/src/components/organisms/Recordings.tsx @@ -6,7 +6,7 @@ import { ScheduleSettings, ScheduleSettingsModal } from "../molecules/ScheduleSe import { IntegrationSettings, IntegrationSettingsModal } from "../molecules/IntegrationSettings"; interface RecordingsProps { - handleEditRecording: (id: string) => void; + handleEditRecording: (id: string, fileName: string) => void; handleRunRecording: (settings: RunSettings) => void; handleScheduleRecording: (settings: ScheduleSettings) => void; handleIntegrateRecording: (settings: IntegrationSettings) => void; From ff741b5cc62bc96928f786ab8b91533f9110e089 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 02:30:59 +0530 Subject: [PATCH 45/65] feat: include recording id --- src/pages/PageWrappper.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/pages/PageWrappper.tsx b/src/pages/PageWrappper.tsx index 975db578..cd0de1a4 100644 --- a/src/pages/PageWrappper.tsx +++ b/src/pages/PageWrappper.tsx @@ -18,17 +18,19 @@ export const PageWrapper = () => { const navigate = useNavigate(); - const { browserId, setBrowserId, notification, recordingName, setRecordingName } = useGlobalInfoStore(); + const { browserId, setBrowserId, notification, recordingName, setRecordingName, recordingId, setRecordingId } = useGlobalInfoStore(); const handleNewRecording = () => { setBrowserId('new-recording'); setRecordingName(''); + setRecordingId(''); navigate('/recording'); } - const handleEditRecording = (fileName: string) => { + const handleEditRecording = (recordingId: string, fileName: string) => { setRecordingName(fileName); + setRecordingId(recordingId); setBrowserId('new-recording'); navigate('/recording'); From 7557721a226fda05d5bfa0bf9a95b947564f86e3 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 02:31:25 +0530 Subject: [PATCH 46/65] chore: lint --- src/pages/PageWrappper.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/pages/PageWrappper.tsx b/src/pages/PageWrappper.tsx index cd0de1a4..c9731645 100644 --- a/src/pages/PageWrappper.tsx +++ b/src/pages/PageWrappper.tsx @@ -25,7 +25,6 @@ export const PageWrapper = () => { setRecordingName(''); setRecordingId(''); navigate('/recording'); - } const handleEditRecording = (recordingId: string, fileName: string) => { @@ -33,7 +32,6 @@ export const PageWrapper = () => { setRecordingId(recordingId); setBrowserId('new-recording'); navigate('/recording'); - } const isNotification = (): boolean => { From 9d9643c40966cca4155d86fac70a089c18f8c62a Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 02:31:54 +0530 Subject: [PATCH 47/65] feat: pass id everywhereeeeeeee --- src/pages/MainPage.tsx | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/pages/MainPage.tsx b/src/pages/MainPage.tsx index e5d04b54..f2f3e664 100644 --- a/src/pages/MainPage.tsx +++ b/src/pages/MainPage.tsx @@ -15,7 +15,7 @@ import { ScheduleSettings } from "../components/molecules/ScheduleSettings"; import { IntegrationSettings } from "../components/molecules/IntegrationSettings"; interface MainPageProps { - handleEditRecording: (fileName: string) => void; + handleEditRecording: (id: string, fileName: string) => void; } export interface CreateRunResponse { @@ -32,6 +32,7 @@ export const MainPage = ({ handleEditRecording }: MainPageProps) => { const [content, setContent] = React.useState('recordings'); const [sockets, setSockets] = React.useState([]); + const [runningRecordingId, setRunningRecordingId] = React.useState(''); const [runningRecordingName, setRunningRecordingName] = React.useState(''); const [currentInterpretationLog, setCurrentInterpretationLog] = React.useState(''); const [ids, setIds] = React.useState({ @@ -45,7 +46,7 @@ export const MainPage = ({ handleEditRecording }: MainPageProps) => { const abortRunHandler = (runId: string) => { aborted = true; - notifyAboutAbort(runningRecordingName, runId).then(async (response) => { + notifyAboutAbort(runId).then(async (response) => { if (response) { notify('success', `Interpretation of ${runningRecordingName} aborted successfully`); await stopRecording(ids.browserId); @@ -55,12 +56,13 @@ export const MainPage = ({ handleEditRecording }: MainPageProps) => { }) } - const setFileName = (fileName: string) => { - setRunningRecordingName(fileName); + const setRecordingInfo = (id: string, name: string) => { + setRunningRecordingId(id); + setRunningRecordingName(name); } const readyForRunHandler = useCallback((browserId: string, runId: string) => { - interpretStoredRecording(runningRecordingName, runId).then(async (interpretation: boolean) => { + interpretStoredRecording(runId).then(async (interpretation: boolean) => { if (!aborted) { if (interpretation) { notify('success', `Interpretation of ${runningRecordingName} succeeded`); @@ -82,7 +84,7 @@ export const MainPage = ({ handleEditRecording }: MainPageProps) => { }, [currentInterpretationLog]) const handleRunRecording = useCallback((settings: RunSettings) => { - createRunForStoredRecording(runningRecordingName, settings).then(({ browserId, runId }: CreateRunResponse) => { + createRunForStoredRecording(runningRecordingId, settings).then(({ browserId, runId }: CreateRunResponse) => { setIds({ browserId, runId }); const socket = io(`http://localhost:8080/${browserId}`, { @@ -98,7 +100,7 @@ export const MainPage = ({ handleEditRecording }: MainPageProps) => { } else { notify('error', `Failed to run recording: ${runningRecordingName}`); } - }); + }) return (socket: Socket, browserId: string, runId: string) => { socket.off('ready-for-run', () => readyForRunHandler(browserId, runId)); socket.off('debugMessage', debugMessageHandler); @@ -133,7 +135,7 @@ export const MainPage = ({ handleEditRecording }: MainPageProps) => { return ; From 8b820dd121b39e338f170a9d8e71a1131c785a89 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 02:32:46 +0530 Subject: [PATCH 48/65] fix: format --- server/src/routes/storage.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/routes/storage.ts b/server/src/routes/storage.ts index eb5185f1..ab2af9ec 100644 --- a/server/src/routes/storage.ts +++ b/server/src/routes/storage.ts @@ -153,7 +153,7 @@ router.put('/runs/:id', requireSignIn, async (req, res) => { const plainRun = run.toJSON(); -console.log(`Created run (plain object):`, plainRun); + console.log(`Created run (plain object):`, plainRun); // // we need to handle this via DB // fs.mkdirSync('../storage/runs', { recursive: true }) @@ -353,7 +353,7 @@ router.put('/schedule/:fileName/', requireSignIn, async (req, res) => { router.post('/runs/abort/:id', requireSignIn, async (req, res) => { try { console.log(`Params for POST /runs/abort/:id`, req.params.id) - const run = await Run.findOne({ where: { runId: req.params.id }}); + const run = await Run.findOne({ where: { runId: req.params.id } }); if (!run) { return res.status(404).send(false); } From 079110edca0efc26ad179121812e4a1306fb0378 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 02:39:45 +0530 Subject: [PATCH 49/65] feat: use id for schedule --- server/src/routes/storage.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/src/routes/storage.ts b/server/src/routes/storage.ts index ab2af9ec..7dcb2373 100644 --- a/server/src/routes/storage.ts +++ b/server/src/routes/storage.ts @@ -255,10 +255,10 @@ router.post('/runs/run/:id', requireSignIn, async (req, res) => { } }); -router.put('/schedule/:fileName/', requireSignIn, async (req, res) => { +router.put('/schedule/:id/', requireSignIn, async (req, res) => { console.log(req.body); try { - const { fileName } = req.params; + const { id } = req.params; const { runEvery, runEveryUnit, @@ -267,7 +267,7 @@ router.put('/schedule/:fileName/', requireSignIn, async (req, res) => { timezone } = req.body; - if (!fileName || !runEvery || !runEveryUnit || !startFrom || !atTime || !timezone) { + if (!id || !runEvery || !runEveryUnit || !startFrom || !atTime || !timezone) { return res.status(400).json({ error: 'Missing required parameters' }); } @@ -318,7 +318,7 @@ router.put('/schedule/:fileName/', requireSignIn, async (req, res) => { // await workflowQueue.add( // 'run workflow', - // { fileName, runId }, + // { id, runId }, // { // repeat: { // pattern: cronExpression, From de200220d3e4273aa1d4eaa27c812120b655eb2b Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 02:40:52 +0530 Subject: [PATCH 50/65] feat: use plainRun to abort run --- server/src/routes/storage.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/src/routes/storage.ts b/server/src/routes/storage.ts index 7dcb2373..e11854ee 100644 --- a/server/src/routes/storage.ts +++ b/server/src/routes/storage.ts @@ -357,9 +357,9 @@ router.post('/runs/abort/:id', requireSignIn, async (req, res) => { if (!run) { return res.status(404).send(false); } - //const parsedRun = JSON.parse(run); + const plainRun = run.toJSON(); - const browser = browserPool.getRemoteBrowser(run.browserId); + const browser = browserPool.getRemoteBrowser(plainRun.browserId); const currentLog = browser?.interpreter.debugMessages.join('/n'); const serializableOutput = browser?.interpreter.serializableData.reduce((reducedObject, item, index) => { return { @@ -377,7 +377,7 @@ router.post('/runs/abort/:id', requireSignIn, async (req, res) => { ...run, status: 'aborted', finishedAt: new Date().toLocaleString(), - browserId: run.browserId, + browserId: plainRun.browserId, log: currentLog, serializableOutput, binaryOutput, From 5d43444cd3a78ebf174ebb4e42925e8ecf06139c Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 02:54:27 +0530 Subject: [PATCH 51/65] feat: use robot & run model in runWorkflow --- .../workflow-management/scheduler/index.ts | 67 ++++++++++++------- 1 file changed, 43 insertions(+), 24 deletions(-) diff --git a/server/src/workflow-management/scheduler/index.ts b/server/src/workflow-management/scheduler/index.ts index bf7a0ce6..1bc7cecf 100644 --- a/server/src/workflow-management/scheduler/index.ts +++ b/server/src/workflow-management/scheduler/index.ts @@ -8,19 +8,40 @@ import logger from '../../logger'; import { browserPool } from "../../server"; import { googleSheetUpdateTasks, processGoogleSheetUpdates } from "../integrations/gsheet"; import { getRecordingByFileName } from "../../routes/storage"; +import Robot from "../../models/Robot"; +import Run from "../../models/Run"; +import { getDecryptedProxyConfig } from "../../routes/proxy"; -async function runWorkflow(fileName: string, runId: string) { - if (!runId) { - runId = uuid(); +async function runWorkflow(id: string) { + if (!id) { + id = uuid(); } - const recording = await getRecordingByFileName(fileName); + const recording = await Robot.findOne({ + where: { + 'recording_meta.id': id + }, + raw: true + }); - if (!recording || !recording.recording_meta || !recording.recording_meta.id) { - logger.log('info', `Recording with name: ${fileName} not found`); - return { - success: false, - error: `Recording with name: ${fileName} not found`, + if (!recording || !recording.recording_meta || !recording.recording_meta.id) { + return { + success: false, + error: 'Recording not found' + }; + } + + // req.user.id will not be available here :) + const proxyConfig = await getDecryptedProxyConfig(req.user.id); + let proxyOptions: any = {}; + + if (proxyConfig.proxy_url) { + proxyOptions = { + server: proxyConfig.proxy_url, + ...(proxyConfig.proxy_username && proxyConfig.proxy_password && { + username: proxyConfig.proxy_username, + password: proxyConfig.proxy_password, + }), }; } @@ -29,34 +50,32 @@ async function runWorkflow(fileName: string, runId: string) { browser: chromium, launchOptions: { headless: true } }); - const run_meta = { + + const run = await Run.create({ status: 'Scheduled', - name: fileName, - recordingId: recording.recording_meta.id, + name: recording.recording_meta.name, + robotId: recording.id, + robotMetaId: recording.recording_meta.id, startedAt: new Date().toLocaleString(), finishedAt: '', - browserId: browserId, + browserId: id, interpreterSettings: { maxConcurrency: 1, maxRepeats: 1, debug: true }, log: '', - runId: runId, - }; + runId: id, + serializableOutput: {}, + binaryOutput: {}, + }); - fs.mkdirSync('../storage/runs', { recursive: true }); - await saveFile( - `../storage/runs/${fileName}_${runId}.json`, - JSON.stringify(run_meta, null, 2) - ); - - logger.log('debug', `Scheduled run with name: ${fileName}_${runId}.json`); + const plainRun = run.toJSON(); return { browserId, - runId + runId: plainRun.runId, } } catch (e) { const { message } = e as Error; - logger.log('info', `Error while scheduling a run with name: ${fileName}_${runId}.json`); + logger.log('info', `Error while scheduling a run with id: ${id}`); console.log(message); return { success: false, From 95a40cd287d2eadb643bb5722cc270c38943a02a Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 02:54:53 +0530 Subject: [PATCH 52/65] chore: lint --- .../src/workflow-management/scheduler/index.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/server/src/workflow-management/scheduler/index.ts b/server/src/workflow-management/scheduler/index.ts index 1bc7cecf..45bd98ad 100644 --- a/server/src/workflow-management/scheduler/index.ts +++ b/server/src/workflow-management/scheduler/index.ts @@ -35,15 +35,15 @@ async function runWorkflow(id: string) { const proxyConfig = await getDecryptedProxyConfig(req.user.id); let proxyOptions: any = {}; - if (proxyConfig.proxy_url) { - proxyOptions = { - server: proxyConfig.proxy_url, - ...(proxyConfig.proxy_username && proxyConfig.proxy_password && { - username: proxyConfig.proxy_username, - password: proxyConfig.proxy_password, - }), - }; - } + if (proxyConfig.proxy_url) { + proxyOptions = { + server: proxyConfig.proxy_url, + ...(proxyConfig.proxy_username && proxyConfig.proxy_password && { + username: proxyConfig.proxy_username, + password: proxyConfig.proxy_password, + }), + }; + } try { const browserId = createRemoteBrowserForRun({ From 9d9db067a9d1d9f71e16d20055be65b66a28fc26 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 03:01:13 +0530 Subject: [PATCH 53/65] feat: use robot & run model in executeWorkflow --- .../workflow-management/scheduler/index.ts | 64 +++++++++---------- 1 file changed, 29 insertions(+), 35 deletions(-) diff --git a/server/src/workflow-management/scheduler/index.ts b/server/src/workflow-management/scheduler/index.ts index 45bd98ad..42555f1b 100644 --- a/server/src/workflow-management/scheduler/index.ts +++ b/server/src/workflow-management/scheduler/index.ts @@ -84,21 +84,29 @@ async function runWorkflow(id: string) { } } -async function executeRun(fileName: string, runId: string) { +async function executeRun(id: string) { try { - const recording = await readFile(`./../storage/recordings/${fileName}.json`); - const parsedRecording = JSON.parse(recording); + const run = await Run.findOne({ where: { runId: id } }); + if (!run) { + return { + success: false, + error: 'Run not found' + } + } - const run = await readFile(`./../storage/runs/${fileName}_${runId}.json`); - const parsedRun = JSON.parse(run); + const plainRun = run.toJSON(); - parsedRun.status = 'running'; - await saveFile( - `../storage/runs/${fileName}_${runId}.json`, - JSON.stringify(parsedRun, null, 2) - ); + const recording = await Robot.findOne({ where: { 'recording_meta.id': plainRun.robotMetaId }, raw: true }); + if (!recording) { + return { + success: false, + error: 'Recording not found' + } + } - const browser = browserPool.getRemoteBrowser(parsedRun.browserId); + plainRun.status = 'running'; + + const browser = browserPool.getRemoteBrowser(plainRun.browserId); if (!browser) { throw new Error('Could not access browser'); } @@ -109,45 +117,31 @@ async function executeRun(fileName: string, runId: string) { } const interpretationInfo = await browser.interpreter.InterpretRecording( - parsedRecording.recording, currentPage, parsedRun.interpreterSettings); + recording.recording, currentPage, plainRun.interpreterSettings); - await destroyRemoteBrowser(parsedRun.browserId); + await destroyRemoteBrowser(plainRun.browserId); - const updated_run_meta = { - ...parsedRun, + await run.update({ + ...run, status: 'success', finishedAt: new Date().toLocaleString(), - browserId: parsedRun.browserId, + browserId: plainRun.browserId, log: interpretationInfo.log.join('\n'), serializableOutput: interpretationInfo.serializableOutput, binaryOutput: interpretationInfo.binaryOutput, - }; + }); - await saveFile( - `../storage/runs/${fileName}_${runId}.json`, - JSON.stringify(updated_run_meta, null, 2) - ); - googleSheetUpdateTasks[runId] = { - name: parsedRun.name, - runId: runId, + googleSheetUpdateTasks[id] = { + name: plainRun.name, + runId: id, status: 'pending', retries: 5, }; processGoogleSheetUpdates(); return true; } catch (error: any) { - logger.log('info', `Error while running a recording with name: ${fileName}_${runId}.json`); + logger.log('info', `Error while running a recording with id: ${id} - ${error.message}`); console.log(error.message); - - const errorRun = await readFile(`./../storage/runs/${fileName}_${runId}.json`); - const parsedErrorRun = JSON.parse(errorRun); - parsedErrorRun.status = 'ERROR'; - parsedErrorRun.log += `\nError: ${error.message}`; - await saveFile( - `../storage/runs/${fileName}_${runId}.json`, - JSON.stringify(parsedErrorRun, null, 2) - ); - return false; } } From 2cc07d545ceece6acb9612ef4ddba2934314c6d7 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 03:03:14 +0530 Subject: [PATCH 54/65] feat: use id in readyForRunHandler --- .../src/workflow-management/scheduler/index.ts | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/server/src/workflow-management/scheduler/index.ts b/server/src/workflow-management/scheduler/index.ts index 42555f1b..f8bb4951 100644 --- a/server/src/workflow-management/scheduler/index.ts +++ b/server/src/workflow-management/scheduler/index.ts @@ -146,18 +146,18 @@ async function executeRun(id: string) { } } -async function readyForRunHandler(browserId: string, fileName: string, runId: string) { +async function readyForRunHandler(browserId: string, id: string) { try { - const interpretation = await executeRun(fileName, runId); + const interpretation = await executeRun(id); if (interpretation) { - logger.log('info', `Interpretation of ${fileName} succeeded`); + logger.log('info', `Interpretation of ${id} succeeded`); } else { - logger.log('error', `Interpretation of ${fileName} failed`); + logger.log('error', `Interpretation of ${id} failed`); await destroyRemoteBrowser(browserId); } - resetRecordingState(browserId, fileName, runId); + resetRecordingState(browserId, id); } catch (error: any) { logger.error(`Error during readyForRunHandler: ${error.message}`); @@ -165,11 +165,9 @@ async function readyForRunHandler(browserId: string, fileName: string, runId: st } } -function resetRecordingState(browserId: string, fileName: string, runId: string) { +function resetRecordingState(browserId: string, id: string) { browserId = ''; - fileName = ''; - runId = ''; - logger.log(`info`, `reset values for ${browserId}, ${fileName}, and ${runId}`); + id = ''; } export async function handleRunRecording(fileName: string, runId: string) { From b087688e821ea20fe36cf9dc6749cc10f110efbf Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 03:05:39 +0530 Subject: [PATCH 55/65] feat: use id --- server/src/workflow-management/scheduler/index.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/server/src/workflow-management/scheduler/index.ts b/server/src/workflow-management/scheduler/index.ts index f8bb4951..2916fb9b 100644 --- a/server/src/workflow-management/scheduler/index.ts +++ b/server/src/workflow-management/scheduler/index.ts @@ -170,9 +170,9 @@ function resetRecordingState(browserId: string, id: string) { id = ''; } -export async function handleRunRecording(fileName: string, runId: string) { +export async function handleRunRecording(id: string) { try { - const result = await runWorkflow(fileName, runId); + const result = await runWorkflow(id); const { browserId, runId: newRunId } = result; if (!browserId || !newRunId) { @@ -184,9 +184,9 @@ export async function handleRunRecording(fileName: string, runId: string) { rejectUnauthorized: false }); - socket.on('ready-for-run', () => readyForRunHandler(browserId, fileName, newRunId)); + socket.on('ready-for-run', () => readyForRunHandler(browserId, newRunId)); - logger.log('info', `Running recording: ${fileName}`); + logger.log('info', `Running recording: ${id}`); socket.on('disconnect', () => { cleanupSocketListeners(socket, browserId, newRunId); @@ -197,9 +197,9 @@ export async function handleRunRecording(fileName: string, runId: string) { } } -function cleanupSocketListeners(socket: Socket, browserId: string, runId: string) { - socket.off('ready-for-run', () => readyForRunHandler(browserId, '', runId)); - logger.log('info', `Cleaned up listeners for browserId: ${browserId}, runId: ${runId}`); +function cleanupSocketListeners(socket: Socket, browserId: string, id: string) { + socket.off('ready-for-run', () => readyForRunHandler(browserId, id)); + logger.log('info', `Cleaned up listeners for browserId: ${browserId}, runId: ${id}`); } export { runWorkflow }; \ No newline at end of file From 4d7679d5a9126cfbf6e6d3981347b4284df4b92d Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 03:19:03 +0530 Subject: [PATCH 56/65] feat: pass req.user.id to add workflow --- server/src/routes/storage.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/routes/storage.ts b/server/src/routes/storage.ts index e11854ee..66ffbdbc 100644 --- a/server/src/routes/storage.ts +++ b/server/src/routes/storage.ts @@ -318,7 +318,7 @@ router.put('/schedule/:id/', requireSignIn, async (req, res) => { // await workflowQueue.add( // 'run workflow', - // { id, runId }, + // { id, runId, req.user.id }, // { // repeat: { // pattern: cronExpression, From 33a01f500f86a7dac80ab15546dbbb7f32671984 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 03:21:32 +0530 Subject: [PATCH 57/65] feat: remove fileName references --- server/src/worker.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/src/worker.ts b/server/src/worker.ts index 3afb39c5..2d4c404e 100644 --- a/server/src/worker.ts +++ b/server/src/worker.ts @@ -20,9 +20,9 @@ connection.on('error', (err) => { const workflowQueue = new Queue('workflow', { connection }); const worker = new Worker('workflow', async job => { - const { fileName, runId } = job.data; + const { runId } = job.data; try { - const result = await handleRunRecording(fileName, runId); + const result = await handleRunRecording(runId); return result; } catch (error) { logger.error('Error running workflow:', error); @@ -31,11 +31,11 @@ const worker = new Worker('workflow', async job => { }, { connection }); worker.on('completed', async (job: any) => { - logger.log(`info`, `Job ${job.id} completed for ${job.data.fileName}_${job.data.runId}`); + logger.log(`info`, `Job ${job.id} completed for ${job.data.runId}`); }); worker.on('failed', async (job: any, err) => { - logger.log(`error`, `Job ${job.id} failed for ${job.data.fileName}_${job.data.runId}:`, err); + logger.log(`error`, `Job ${job.id} failed for ${job.data.runId}:`, err); }); console.log('Worker is running...'); From 4355f5bebcf426e60560ab65199287ff83652a46 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 03:22:04 +0530 Subject: [PATCH 58/65] feat: accept userId --- server/src/workflow-management/scheduler/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/workflow-management/scheduler/index.ts b/server/src/workflow-management/scheduler/index.ts index 2916fb9b..cc22f712 100644 --- a/server/src/workflow-management/scheduler/index.ts +++ b/server/src/workflow-management/scheduler/index.ts @@ -170,7 +170,7 @@ function resetRecordingState(browserId: string, id: string) { id = ''; } -export async function handleRunRecording(id: string) { +export async function handleRunRecording(id: string, userId: string) { try { const result = await runWorkflow(id); const { browserId, runId: newRunId } = result; From d2782503eb07c1b5621f8f7c398a6ffc965cb125 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 03:23:29 +0530 Subject: [PATCH 59/65] feat: accept userId --- server/src/routes/storage.ts | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/server/src/routes/storage.ts b/server/src/routes/storage.ts index 66ffbdbc..fa21a1b3 100644 --- a/server/src/routes/storage.ts +++ b/server/src/routes/storage.ts @@ -13,7 +13,7 @@ import { getDecryptedProxyConfig } from './proxy'; import { requireSignIn } from '../middlewares/auth'; import Robot from '../models/Robot'; import Run from '../models/Run'; -// import { workflowQueue } from '../worker'; +import { workflowQueue } from '../worker'; // todo: move from here export const getRecordingByFileName = async (fileName: string): Promise => { @@ -315,17 +315,18 @@ router.put('/schedule/:id/', requireSignIn, async (req, res) => { } const runId = uuid(); + const userId = req.user.id; - // await workflowQueue.add( - // 'run workflow', - // { id, runId, req.user.id }, - // { - // repeat: { - // pattern: cronExpression, - // tz: timezone - // } - // } - // ); + await workflowQueue.add( + 'run workflow', + { id, runId, userId }, + { + repeat: { + pattern: cronExpression, + tz: timezone + } + } + ); res.status(200).json({ message: 'success', From 258d0aa9a243af1b3f3d3ca6ea85f462fddc711e Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 03:24:04 +0530 Subject: [PATCH 60/65] feat: get userId from workflow queue --- server/src/worker.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/worker.ts b/server/src/worker.ts index 2d4c404e..d50e6220 100644 --- a/server/src/worker.ts +++ b/server/src/worker.ts @@ -20,9 +20,9 @@ connection.on('error', (err) => { const workflowQueue = new Queue('workflow', { connection }); const worker = new Worker('workflow', async job => { - const { runId } = job.data; + const { runId, userId } = job.data; try { - const result = await handleRunRecording(runId); + const result = await handleRunRecording(runId, userId); return result; } catch (error) { logger.error('Error running workflow:', error); From 3c648fc5f4ce74de826213fd364df1cd13437edd Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 03:24:19 +0530 Subject: [PATCH 61/65] chore: lint --- server/src/worker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/worker.ts b/server/src/worker.ts index d50e6220..baef2387 100644 --- a/server/src/worker.ts +++ b/server/src/worker.ts @@ -20,7 +20,7 @@ connection.on('error', (err) => { const workflowQueue = new Queue('workflow', { connection }); const worker = new Worker('workflow', async job => { - const { runId, userId } = job.data; + const { runId, userId } = job.data; try { const result = await handleRunRecording(runId, userId); return result; From 321ae008d45659f50235eaaec6fc079f519b4bff Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 03:26:12 +0530 Subject: [PATCH 62/65] feat: use userId for getDecryptedProxyConfig --- server/src/workflow-management/scheduler/index.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/src/workflow-management/scheduler/index.ts b/server/src/workflow-management/scheduler/index.ts index cc22f712..48948c65 100644 --- a/server/src/workflow-management/scheduler/index.ts +++ b/server/src/workflow-management/scheduler/index.ts @@ -12,7 +12,7 @@ import Robot from "../../models/Robot"; import Run from "../../models/Run"; import { getDecryptedProxyConfig } from "../../routes/proxy"; -async function runWorkflow(id: string) { +async function runWorkflow(id: string, userId: string) { if (!id) { id = uuid(); } @@ -32,7 +32,7 @@ async function runWorkflow(id: string) { } // req.user.id will not be available here :) - const proxyConfig = await getDecryptedProxyConfig(req.user.id); + const proxyConfig = await getDecryptedProxyConfig(userId); let proxyOptions: any = {}; if (proxyConfig.proxy_url) { @@ -175,8 +175,8 @@ export async function handleRunRecording(id: string, userId: string) { const result = await runWorkflow(id); const { browserId, runId: newRunId } = result; - if (!browserId || !newRunId) { - throw new Error('browserId or runId is undefined'); + if (!browserId || !newRunId || !userId) { + throw new Error('browserId or runId or userId is undefined'); } const socket = io(`http://localhost:8080/${browserId}`, { From fbc67af7bc00d44b51edad967f7b8225550f833c Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 03:26:41 +0530 Subject: [PATCH 63/65] fix: pass userId --- server/src/workflow-management/scheduler/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/workflow-management/scheduler/index.ts b/server/src/workflow-management/scheduler/index.ts index 48948c65..98b3f524 100644 --- a/server/src/workflow-management/scheduler/index.ts +++ b/server/src/workflow-management/scheduler/index.ts @@ -172,7 +172,7 @@ function resetRecordingState(browserId: string, id: string) { export async function handleRunRecording(id: string, userId: string) { try { - const result = await runWorkflow(id); + const result = await runWorkflow(id, userId); const { browserId, runId: newRunId } = result; if (!browserId || !newRunId || !userId) { From a3d5cff89dc44eed5d172cee0d9199ba3161b19b Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 03:29:25 +0530 Subject: [PATCH 64/65] feat: use proxy options for launchOPtions --- server/src/workflow-management/scheduler/index.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/server/src/workflow-management/scheduler/index.ts b/server/src/workflow-management/scheduler/index.ts index 98b3f524..1991cce7 100644 --- a/server/src/workflow-management/scheduler/index.ts +++ b/server/src/workflow-management/scheduler/index.ts @@ -48,7 +48,10 @@ async function runWorkflow(id: string, userId: string) { try { const browserId = createRemoteBrowserForRun({ browser: chromium, - launchOptions: { headless: true } + launchOptions: { + headless: true, + proxy: proxyOptions.server ? proxyOptions : undefined, + } }); const run = await Run.create({ From 6d38e3f234aa874855a3712e1709d68c9648c3f1 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Thu, 10 Oct 2024 03:29:48 +0530 Subject: [PATCH 65/65] chore: remove todo --- server/src/workflow-management/scheduler/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/server/src/workflow-management/scheduler/index.ts b/server/src/workflow-management/scheduler/index.ts index 1991cce7..d7a481bf 100644 --- a/server/src/workflow-management/scheduler/index.ts +++ b/server/src/workflow-management/scheduler/index.ts @@ -31,7 +31,6 @@ async function runWorkflow(id: string, userId: string) { }; } - // req.user.id will not be available here :) const proxyConfig = await getDecryptedProxyConfig(userId); let proxyOptions: any = {};