From cd838915fdb216ee364ea677747409311b1214fb Mon Sep 17 00:00:00 2001 From: Saad Jutt Date: Thu, 6 Jan 2022 18:40:23 +0500 Subject: [PATCH 1/5] fix: added sas9 server address --- api/src/app.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/api/src/app.ts b/api/src/app.ts index 6879eff..634ed5a 100644 --- a/api/src/app.ts +++ b/api/src/app.ts @@ -13,11 +13,14 @@ dotenv.config() const app = express() const { MODE, CORS, PORT_WEB } = process.env +const whiteList = [ + `http://localhost:${PORT_WEB ?? 3000}`, + 'https://sas.analytium.co.uk:8343/' +] + if (MODE?.trim() !== 'server' || CORS?.trim() === 'enable') { console.log('All CORS Requests are enabled') - app.use( - cors({ credentials: true, origin: `http://localhost:${PORT_WEB ?? 3000}` }) - ) + app.use(cors({ credentials: true, origin: whiteList })) } app.use(express.json({ limit: '50mb' })) From 6cbc657da3eb7fa821a678443a3ae4079c2a1f09 Mon Sep 17 00:00:00 2001 From: Saad Jutt Date: Thu, 6 Jan 2022 23:12:44 +0500 Subject: [PATCH 2/5] fix: recreate crashed session --- api/src/app.ts | 2 +- api/src/controllers/internal/Session.ts | 24 ++++++++++++++++++------ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/api/src/app.ts b/api/src/app.ts index 634ed5a..27aff05 100644 --- a/api/src/app.ts +++ b/api/src/app.ts @@ -15,7 +15,7 @@ const app = express() const { MODE, CORS, PORT_WEB } = process.env const whiteList = [ `http://localhost:${PORT_WEB ?? 3000}`, - 'https://sas.analytium.co.uk:8343/' + 'https://sas.analytium.co.uk:8343' ] if (MODE?.trim() !== 'server' || CORS?.trim() === 'enable') { diff --git a/api/src/controllers/internal/Session.ts b/api/src/controllers/internal/Session.ts index e9bf581..f3baf6c 100644 --- a/api/src/controllers/internal/Session.ts +++ b/api/src/controllers/internal/Session.ts @@ -12,7 +12,8 @@ import { createFile, fileExists, generateTimestamp, - readFile + readFile, + moveFile } from '@sasjs/utils' const execFilePromise = promisify(execFile) @@ -32,8 +33,9 @@ export class SessionController { return session } - private async createSession() { + private async createSession(): Promise { const sessionId = generateUniqueFileName(generateTimestamp()) + console.log('creating session', sessionId) const sessionFolder = path.join(getTmpSessionsFolderPath(), sessionId) const creationTimeStamp = sessionId.split('-').pop() as string @@ -100,25 +102,35 @@ export class SessionController { // SAS has been triggered but we can't use it until // the autoexec deletes the code.sas file - await this.waitForSession(session) + if (!(await this.waitForSession(session))) { + console.log('session is crashed', sessionId) + return this.createSession() + } + + console.log('session is ready', sessionId) return session } - public async waitForSession(session: Session) { + private async waitForSession(session: Session) { const codeFilePath = path.join(session.path, 'code.sas') // TODO: don't wait forever while ((await fileExists(codeFilePath)) && !session.crashed) {} console.log('session crashed?', !!session.crashed, session.crashed || '') + if (session.crashed) { + await this.deleteSession(session) + return false + } session.ready = true - return Promise.resolve(session) + return true } public async deleteSession(session: Session) { // remove the temporary files, to avoid buildup - await deleteFolder(session.path) + if (session.crashed) await moveFile(session.path, `${session.path}-crashed`) + else await deleteFolder(session.path) // remove the session from the session array if (session.ready) { From 0a6ebe6e62af71dffccc2d6b15e71b346787917a Mon Sep 17 00:00:00 2001 From: Saad Jutt Date: Fri, 7 Jan 2022 15:38:11 +0500 Subject: [PATCH 3/5] chore: debugging --- api/src/controllers/internal/Execution.ts | 7 +++-- api/src/controllers/internal/Session.ts | 32 +++++++++-------------- 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/api/src/controllers/internal/Execution.ts b/api/src/controllers/internal/Execution.ts index 5abb742..d97d1be 100644 --- a/api/src/controllers/internal/Execution.ts +++ b/api/src/controllers/internal/Execution.ts @@ -36,6 +36,7 @@ export class ExecutionController { const sessionController = getSessionController() const session = await sessionController.getSession() + console.log('using session', session.id) session.inUse = true const logPath = path.join(session.path, 'log.log') @@ -97,13 +98,15 @@ ${program}` // (which can mean SAS trying to run a partial program, or // failing due to file lock) we first create the file THEN // we rename it. + console.log('executing session', session.id) await createFile(codePath + '.bkp', program) await moveFile(codePath + '.bkp', codePath) - // we now need to poll the session array + // we now need to poll the session status while (!session.completed) { await delay(50) } + console.log('completed session', session.id) const log = ((await fileExists(logPath)) ? await readFile(logPath) : '') + @@ -115,8 +118,8 @@ ${program}` const debugValue = typeof vars._debug === 'string' ? parseInt(vars._debug) : vars._debug + // it should be deleted by scheduleSessionDestroy session.inUse = false - sessionController.deleteSession(session) if (returnJson) { return { diff --git a/api/src/controllers/internal/Session.ts b/api/src/controllers/internal/Session.ts index f3baf6c..21ca22c 100644 --- a/api/src/controllers/internal/Session.ts +++ b/api/src/controllers/internal/Session.ts @@ -22,7 +22,7 @@ export class SessionController { private sessions: Session[] = [] public async getSession() { - const readySessions = this.sessions.filter((sess: Session) => sess.ready) + const readySessions = this.getReadySessions() const session = readySessions.length ? readySessions[0] @@ -33,6 +33,9 @@ export class SessionController { return session } + private getReadySessions = (): Session[] => + this.sessions.filter((sess: Session) => sess.ready) + private async createSession(): Promise { const sessionId = generateUniqueFileName(generateTimestamp()) console.log('creating session', sessionId) @@ -102,13 +105,10 @@ export class SessionController { // SAS has been triggered but we can't use it until // the autoexec deletes the code.sas file - if (!(await this.waitForSession(session))) { - console.log('session is crashed', sessionId) - - return this.createSession() - } + await this.waitForSession(session) console.log('session is ready', sessionId) + return session } @@ -117,27 +117,21 @@ export class SessionController { // TODO: don't wait forever while ((await fileExists(codeFilePath)) && !session.crashed) {} - console.log('session crashed?', !!session.crashed, session.crashed || '') - if (session.crashed) { - await this.deleteSession(session) - return false - } + + if (session.crashed) + console.log('session crashed! while waiting to be ready', session.crashed) session.ready = true - return true } public async deleteSession(session: Session) { // remove the temporary files, to avoid buildup - if (session.crashed) await moveFile(session.path, `${session.path}-crashed`) - else await deleteFolder(session.path) + await deleteFolder(session.path) // remove the session from the session array - if (session.ready) { - this.sessions = this.sessions.filter( - (sess: Session) => sess.id !== session.id - ) - } + this.sessions = this.sessions.filter( + (sess: Session) => sess.id !== session.id + ) } private scheduleSessionDestroy(session: Session) { From 7a3d710153f37d12160ff45f8f97fb4fcc75d684 Mon Sep 17 00:00:00 2001 From: Saad Jutt Date: Fri, 7 Jan 2022 16:34:46 +0500 Subject: [PATCH 4/5] fix: session should be marked as consumed --- api/src/controllers/internal/Execution.ts | 1 + api/src/controllers/internal/Session.ts | 3 ++- api/src/types/Session.ts | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/api/src/controllers/internal/Execution.ts b/api/src/controllers/internal/Execution.ts index d97d1be..c488d95 100644 --- a/api/src/controllers/internal/Execution.ts +++ b/api/src/controllers/internal/Execution.ts @@ -38,6 +38,7 @@ export class ExecutionController { const session = await sessionController.getSession() console.log('using session', session.id) session.inUse = true + session.consumed = true const logPath = path.join(session.path, 'log.log') diff --git a/api/src/controllers/internal/Session.ts b/api/src/controllers/internal/Session.ts index 21ca22c..525a072 100644 --- a/api/src/controllers/internal/Session.ts +++ b/api/src/controllers/internal/Session.ts @@ -34,7 +34,7 @@ export class SessionController { } private getReadySessions = (): Session[] => - this.sessions.filter((sess: Session) => sess.ready) + this.sessions.filter((sess: Session) => sess.ready && !sess.consumed) private async createSession(): Promise { const sessionId = generateUniqueFileName(generateTimestamp()) @@ -52,6 +52,7 @@ export class SessionController { id: sessionId, ready: false, inUse: false, + consumed: false, completed: false, creationTimeStamp, deathTimeStamp, diff --git a/api/src/types/Session.ts b/api/src/types/Session.ts index cf3e490..0507a6d 100644 --- a/api/src/types/Session.ts +++ b/api/src/types/Session.ts @@ -5,6 +5,7 @@ export interface Session { deathTimeStamp: string path: string inUse: boolean + consumed: boolean completed: boolean crashed?: string } From 9c5772a30310fea1dc970db4f1484af7087fed0b Mon Sep 17 00:00:00 2001 From: Saad Jutt Date: Fri, 7 Jan 2022 16:42:38 +0500 Subject: [PATCH 5/5] chore: clean up --- api/src/controllers/internal/Execution.ts | 3 --- api/src/controllers/internal/Session.ts | 8 +++----- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/api/src/controllers/internal/Execution.ts b/api/src/controllers/internal/Execution.ts index c488d95..38cb88d 100644 --- a/api/src/controllers/internal/Execution.ts +++ b/api/src/controllers/internal/Execution.ts @@ -36,7 +36,6 @@ export class ExecutionController { const sessionController = getSessionController() const session = await sessionController.getSession() - console.log('using session', session.id) session.inUse = true session.consumed = true @@ -99,7 +98,6 @@ ${program}` // (which can mean SAS trying to run a partial program, or // failing due to file lock) we first create the file THEN // we rename it. - console.log('executing session', session.id) await createFile(codePath + '.bkp', program) await moveFile(codePath + '.bkp', codePath) @@ -107,7 +105,6 @@ ${program}` while (!session.completed) { await delay(50) } - console.log('completed session', session.id) const log = ((await fileExists(logPath)) ? await readFile(logPath) : '') + diff --git a/api/src/controllers/internal/Session.ts b/api/src/controllers/internal/Session.ts index 525a072..8e5ef75 100644 --- a/api/src/controllers/internal/Session.ts +++ b/api/src/controllers/internal/Session.ts @@ -21,6 +21,9 @@ const execFilePromise = promisify(execFile) export class SessionController { private sessions: Session[] = [] + private getReadySessions = (): Session[] => + this.sessions.filter((sess: Session) => sess.ready && !sess.consumed) + public async getSession() { const readySessions = this.getReadySessions() @@ -33,9 +36,6 @@ export class SessionController { return session } - private getReadySessions = (): Session[] => - this.sessions.filter((sess: Session) => sess.ready && !sess.consumed) - private async createSession(): Promise { const sessionId = generateUniqueFileName(generateTimestamp()) console.log('creating session', sessionId) @@ -108,8 +108,6 @@ export class SessionController { // the autoexec deletes the code.sas file await this.waitForSession(session) - console.log('session is ready', sessionId) - return session }