From 03670cf0d69dfeed189a32239ae19ede3928f749 Mon Sep 17 00:00:00 2001 From: Yury Date: Wed, 30 Oct 2024 15:25:03 +0300 Subject: [PATCH 1/9] chore(swagger): fixed code/stp trigger examples --- api/src/controllers/code.ts | 2 +- api/src/controllers/stp.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/api/src/controllers/code.ts b/api/src/controllers/code.ts index 039ce3c..3719cce 100644 --- a/api/src/controllers/code.ts +++ b/api/src/controllers/code.ts @@ -45,7 +45,7 @@ interface TriggerCodeResponse { * The SessionId is the name of the temporary folder used to store the outputs. * For SAS, this would be the SASWORK folder. Can be used to poll job status. * This session ID should be used to poll job status. - * @example "{ sessionId: '20241028074744-54132-1730101664824' }" + * @example "20241028074744-54132-1730101664824" */ sessionId: string } diff --git a/api/src/controllers/stp.ts b/api/src/controllers/stp.ts index 3e66e88..ad3b5bd 100644 --- a/api/src/controllers/stp.ts +++ b/api/src/controllers/stp.ts @@ -43,7 +43,7 @@ interface TriggerProgramResponse { * The SessionId is the name of the temporary folder used to store the outputs. * For SAS, this would be the SASWORK folder. Can be used to poll program status. * This session ID should be used to poll program status. - * @example "{ sessionId: '20241028074744-54132-1730101664824' }" + * @example "20241028074744-54132-1730101664824" */ sessionId: string } From f94ddc0352973e208b2398bdd400832b8eab50ee Mon Sep 17 00:00:00 2001 From: Yury Date: Wed, 30 Oct 2024 15:33:06 +0300 Subject: [PATCH 2/9] refactor(session): implemented session state --- .vscode/settings.json | 4 +- api/src/controllers/internal/Execution.ts | 11 ++- .../internal/FileUploadController.ts | 12 +-- api/src/controllers/internal/Session.ts | 93 ++++++++++--------- .../controllers/internal/processProgram.ts | 19 ++-- api/src/routes/api/spec/stp.spec.ts | 7 +- api/src/types/Session.ts | 14 ++- 7 files changed, 84 insertions(+), 76 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 9a770f0..c15453a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,3 @@ { - "cSpell.words": [ - "autoexec" - ] + "cSpell.words": ["autoexec", "initialising"] } diff --git a/api/src/controllers/internal/Execution.ts b/api/src/controllers/internal/Execution.ts index 3004f56..c1ff197 100644 --- a/api/src/controllers/internal/Execution.ts +++ b/api/src/controllers/internal/Execution.ts @@ -2,7 +2,7 @@ import path from 'path' import fs from 'fs' import { getSessionController, processProgram } from './' import { readFile, fileExists, createFile, readFileBinary } from '@sasjs/utils' -import { PreProgramVars, Session, TreeNode } from '../../types' +import { PreProgramVars, Session, TreeNode, SessionState } from '../../types' import { extractHeaders, getFilesFolder, @@ -75,8 +75,7 @@ export class ExecutionController { const session = sessionByFileUpload ?? (await sessionController.getSession()) - session.inUse = true - session.consumed = true + session.state = SessionState.running const logPath = path.join(session.path, 'log.log') const headersPath = path.join(session.path, 'stpsrv_header.txt') @@ -121,7 +120,7 @@ export class ExecutionController { : '' // it should be deleted by scheduleSessionDestroy - session.inUse = false + session.state = SessionState.completed const resultParts = [] @@ -145,7 +144,9 @@ export class ExecutionController { return { httpHeaders, result: - isDebugOn(vars) || session.crashed ? resultParts.join(`\n`) : webout + isDebugOn(vars) || session.failureReason + ? resultParts.join(`\n`) + : webout } } diff --git a/api/src/controllers/internal/FileUploadController.ts b/api/src/controllers/internal/FileUploadController.ts index a06f512..f234772 100644 --- a/api/src/controllers/internal/FileUploadController.ts +++ b/api/src/controllers/internal/FileUploadController.ts @@ -2,11 +2,8 @@ import { Request, RequestHandler } from 'express' import multer from 'multer' import { uuidv4 } from '@sasjs/utils' import { getSessionController } from '.' -import { - executeProgramRawValidation, - getRunTimeAndFilePath, - RunTimeType -} from '../../utils' +import { executeProgramRawValidation, getRunTimeAndFilePath } from '../../utils' +import { SessionState } from '../../types' export class FileUploadController { private storage = multer.diskStorage({ @@ -56,9 +53,8 @@ export class FileUploadController { } const session = await sessionController.getSession() - // marking consumed true, so that it's not available - // as readySession for any other request - session.consumed = true + // change session state to 'running', so that it's not available for any other request + session.state = SessionState.running req.sasjsSession = session diff --git a/api/src/controllers/internal/Session.ts b/api/src/controllers/internal/Session.ts index 3000c07..c14310e 100644 --- a/api/src/controllers/internal/Session.ts +++ b/api/src/controllers/internal/Session.ts @@ -1,5 +1,5 @@ import path from 'path' -import { Session } from '../../types' +import { Session, SessionState } from '../../types' import { promisify } from 'util' import { execFile } from 'child_process' import { @@ -23,7 +23,9 @@ export class SessionController { protected sessions: Session[] = [] protected getReadySessions = (): Session[] => - this.sessions.filter((sess: Session) => sess.ready && !sess.consumed) + this.sessions.filter( + (session: Session) => session.state === SessionState.pending + ) protected async createSession(): Promise { const sessionId = generateUniqueFileName(generateTimestamp()) @@ -39,19 +41,18 @@ export class SessionController { const session: Session = { id: sessionId, - ready: true, - inUse: true, - consumed: false, - completed: false, + state: SessionState.pending, creationTimeStamp, deathTimeStamp, path: sessionFolder } const headersPath = path.join(session.path, 'stpsrv_header.txt') + await createFile(headersPath, 'content-type: text/html; charset=utf-8') this.sessions.push(session) + return session } @@ -83,10 +84,7 @@ export class SASSessionController extends SessionController { const session: Session = { id: sessionId, - ready: false, - inUse: false, - consumed: false, - completed: false, + state: SessionState.initialising, creationTimeStamp, deathTimeStamp, path: sessionFolder @@ -144,13 +142,20 @@ ${autoExecContent}` process.sasLoc!.endsWith('sas.exe') ? session.path : '' ]) .then(() => { - session.completed = true + session.state = SessionState.completed + process.logger.info('session completed', session) }) .catch((err) => { - session.completed = true - session.crashed = err.toString() - process.logger.error('session crashed', session.id, session.crashed) + session.state = SessionState.failed + + session.failureReason = err.toString() + + process.logger.error( + 'session crashed', + session.id, + session.failureReason + ) }) // we have a triggered session - add to array @@ -167,15 +172,19 @@ ${autoExecContent}` const codeFilePath = path.join(session.path, 'code.sas') // TODO: don't wait forever - while ((await fileExists(codeFilePath)) && !session.crashed) {} + while ( + (await fileExists(codeFilePath)) && + session.state !== SessionState.failed + ) {} - if (session.crashed) + if (session.state === SessionState.failed) { process.logger.error( 'session crashed! while waiting to be ready', - session.crashed + session.failureReason ) - - session.ready = true + } else { + session.state = SessionState.pending + } } private async deleteSession(session: Session) { @@ -189,37 +198,33 @@ ${autoExecContent}` } private scheduleSessionDestroy(session: Session) { - setTimeout( - async () => { - if (session.inUse) { - // adding 10 more minutes + setTimeout(async () => { + if (session.state === SessionState.running) { + // adding 10 more minutes + const newDeathTimeStamp = + parseInt(session.deathTimeStamp) + 10 * 60 * 1000 + session.deathTimeStamp = newDeathTimeStamp.toString() + + this.scheduleSessionDestroy(session) + } else { + const { expiresAfterMins } = session + + // delay session destroy if expiresAfterMins present + if (expiresAfterMins && session.state !== SessionState.completed) { + // calculate session death time using expiresAfterMins const newDeathTimeStamp = - parseInt(session.deathTimeStamp) + 10 * 60 * 1000 + parseInt(session.deathTimeStamp) + expiresAfterMins.mins * 60 * 1000 session.deathTimeStamp = newDeathTimeStamp.toString() + // set expiresAfterMins to true to avoid using it again + session.expiresAfterMins!.used = true + this.scheduleSessionDestroy(session) } else { - const { expiresAfterMins } = session - - // delay session destroy if expiresAfterMins present - if (expiresAfterMins && !expiresAfterMins.used) { - // calculate session death time using expiresAfterMins - const newDeathTimeStamp = - parseInt(session.deathTimeStamp) + - expiresAfterMins.mins * 60 * 1000 - session.deathTimeStamp = newDeathTimeStamp.toString() - - // set expiresAfterMins to true to avoid using it again - session.expiresAfterMins!.used = true - - this.scheduleSessionDestroy(session) - } else { - await this.deleteSession(session) - } + await this.deleteSession(session) } - }, - parseInt(session.deathTimeStamp) - new Date().getTime() - 100 - ) + } + }, parseInt(session.deathTimeStamp) - new Date().getTime() - 100) } } diff --git a/api/src/controllers/internal/processProgram.ts b/api/src/controllers/internal/processProgram.ts index 206f429..791a3a9 100644 --- a/api/src/controllers/internal/processProgram.ts +++ b/api/src/controllers/internal/processProgram.ts @@ -3,7 +3,7 @@ import { WriteStream, createWriteStream } from 'fs' import { execFile } from 'child_process' import { once } from 'stream' import { createFile, moveFile } from '@sasjs/utils' -import { PreProgramVars, Session } from '../../types' +import { PreProgramVars, Session, SessionState } from '../../types' import { RunTimeType } from '../../utils' import { ExecutionVars, @@ -49,7 +49,7 @@ export const processProgram = async ( await moveFile(codePath + '.bkp', codePath) // we now need to poll the session status - while (!session.completed) { + while (session.state === SessionState.completed) { await delay(50) } } else { @@ -114,13 +114,20 @@ export const processProgram = async ( await execFilePromise(executablePath, [codePath], writeStream) .then(() => { - session.completed = true + session.state = SessionState.completed + process.logger.info('session completed', session) }) .catch((err) => { - session.completed = true - session.crashed = err.toString() - process.logger.error('session crashed', session.id, session.crashed) + session.state = SessionState.failed + + session.failureReason = err.toString() + + process.logger.error( + 'session crashed', + session.id, + session.failureReason + ) }) // copy the code file to log and end write stream diff --git a/api/src/routes/api/spec/stp.spec.ts b/api/src/routes/api/spec/stp.spec.ts index 1512378..1bfd79b 100644 --- a/api/src/routes/api/spec/stp.spec.ts +++ b/api/src/routes/api/spec/stp.spec.ts @@ -25,7 +25,7 @@ import { SASSessionController } from '../../../controllers/internal' import * as ProcessProgramModule from '../../../controllers/internal/processProgram' -import { Session } from '../../../types' +import { Session, SessionState } from '../../../types' const clientId = 'someclientID' @@ -493,10 +493,7 @@ const mockedGetSession = async () => { const session: Session = { id: sessionId, - ready: true, - inUse: true, - consumed: false, - completed: false, + state: SessionState.pending, creationTimeStamp, deathTimeStamp, path: sessionFolder diff --git a/api/src/types/Session.ts b/api/src/types/Session.ts index 4fa1cfb..1015e1e 100644 --- a/api/src/types/Session.ts +++ b/api/src/types/Session.ts @@ -1,12 +1,16 @@ +export enum SessionState { + initialising = 'initialising', // session is initialising and nor ready to be used yet + pending = 'pending', // session is ready to be used + running = 'running', // session is in use + completed = 'completed', // session is completed and can be destroyed + failed = 'failed' // session failed +} export interface Session { id: string - ready: boolean + state: SessionState creationTimeStamp: string deathTimeStamp: string path: string - inUse: boolean - consumed: boolean - completed: boolean - crashed?: string expiresAfterMins?: { mins: number; used: boolean } + failureReason?: string } From 6b6546c7ad0833347f8dc4cdba6ad19132f7aaef Mon Sep 17 00:00:00 2001 From: Yury Date: Wed, 30 Oct 2024 17:42:50 +0300 Subject: [PATCH 3/9] feat(api): added session state endpoint --- api/public/swagger.yaml | 35 +++++++++++++++++++++++-- api/src/controllers/internal/Session.ts | 4 +++ api/src/controllers/session.ts | 31 ++++++++++++++++++++++ api/src/routes/api/session.ts | 23 +++++++++++++++- api/src/utils/validation.ts | 5 ++++ 5 files changed, 95 insertions(+), 3 deletions(-) diff --git a/api/public/swagger.yaml b/api/public/swagger.yaml index c9b00c6..947aa3f 100644 --- a/api/public/swagger.yaml +++ b/api/public/swagger.yaml @@ -114,7 +114,7 @@ components: sessionId: type: string description: "The SessionId is the name of the temporary folder used to store the outputs.\nFor SAS, this would be the SASWORK folder. Can be used to poll job status.\nThis session ID should be used to poll job status." - example: '{ sessionId: ''20241028074744-54132-1730101664824'' }' + example: 20241028074744-54132-1730101664824 required: - sessionId type: object @@ -585,6 +585,14 @@ components: - needsToUpdatePassword type: object additionalProperties: false + SessionState: + enum: + - initialising + - pending + - running + - completed + - failed + type: string ExecutePostRequestPayload: properties: _program: @@ -598,7 +606,7 @@ components: sessionId: type: string description: "The SessionId is the name of the temporary folder used to store the outputs.\nFor SAS, this would be the SASWORK folder. Can be used to poll program status.\nThis session ID should be used to poll program status." - example: '{ sessionId: ''20241028074744-54132-1730101664824'' }' + example: 20241028074744-54132-1730101664824 required: - sessionId type: object @@ -1841,6 +1849,29 @@ paths: - bearerAuth: [] parameters: [] + '/SASjsApi/session/{sessionId}/state': + get: + operationId: SessionState + responses: + '200': + description: Ok + content: + application/json: + schema: + $ref: '#/components/schemas/SessionState' + summary: 'Get session state (initialising, pending, running, completed, failed).' + tags: + - Session + security: + - + bearerAuth: [] + parameters: + - + in: path + name: sessionId + required: true + schema: + type: string /SASjsApi/stp/execute: get: operationId: ExecuteGetRequest diff --git a/api/src/controllers/internal/Session.ts b/api/src/controllers/internal/Session.ts index c14310e..616c3c7 100644 --- a/api/src/controllers/internal/Session.ts +++ b/api/src/controllers/internal/Session.ts @@ -67,6 +67,10 @@ export class SessionController { return session } + + public getSessionById(id: string) { + return this.sessions.find((session) => session.id === id) + } } export class SASSessionController extends SessionController { diff --git a/api/src/controllers/session.ts b/api/src/controllers/session.ts index f0cd049..0f5cfef 100644 --- a/api/src/controllers/session.ts +++ b/api/src/controllers/session.ts @@ -1,6 +1,8 @@ import express from 'express' import { Request, Security, Route, Tags, Example, Get } from 'tsoa' import { UserResponse } from './user' +import { getSessionController } from './internal' +import { SessionState } from '../types' interface SessionResponse extends UserResponse { needsToUpdatePassword: boolean @@ -26,6 +28,15 @@ export class SessionController { ): Promise { return session(request) } + + /** + * @summary Get session state (initialising, pending, running, completed, failed). + * @example completed + */ + @Get('/:sessionId/state') + public async sessionState(sessionId: string): Promise { + return sessionState(sessionId) + } } const session = (req: express.Request) => ({ @@ -35,3 +46,23 @@ const session = (req: express.Request) => ({ isAdmin: req.user!.isAdmin, needsToUpdatePassword: req.user!.needsToUpdatePassword }) + +const sessionState = (sessionId: string): SessionState => { + for (let runTime of process.runTimes) { + // get session controller for each available runTime + const sessionController = getSessionController(runTime) + + // get session by sessionId + const session = sessionController.getSessionById(sessionId) + + // return session state if session was found + if (session) { + return session.state + } + } + + throw { + code: 404, + message: `Session with ID '${sessionId}' was not found.` + } +} diff --git a/api/src/routes/api/session.ts b/api/src/routes/api/session.ts index 09d0d87..e866832 100644 --- a/api/src/routes/api/session.ts +++ b/api/src/routes/api/session.ts @@ -1,16 +1,37 @@ import express from 'express' import { SessionController } from '../../controllers' +import { sessionIdValidation } from '../../utils' const sessionRouter = express.Router() +const controller = new SessionController() + sessionRouter.get('/', async (req, res) => { - const controller = new SessionController() try { const response = await controller.session(req) + res.send(response) } catch (err: any) { res.status(403).send(err.toString()) } }) +sessionRouter.get('/:sessionId/state', async (req, res) => { + const { error, value: params } = sessionIdValidation(req.params) + if (error) return res.status(400).send(error.details[0].message) + + try { + const response = await controller.sessionState(params.sessionId) + + res.status(200) + res.send(response) + } catch (err: any) { + const statusCode = err.code + + delete err.code + + res.status(statusCode).send(err) + } +}) + export default sessionRouter diff --git a/api/src/utils/validation.ts b/api/src/utils/validation.ts index a4fe696..4ba5dab 100644 --- a/api/src/utils/validation.ts +++ b/api/src/utils/validation.ts @@ -201,3 +201,8 @@ export const triggerProgramValidation = (data: any): Joi.ValidationResult => }) .pattern(/^/, Joi.alternatives(Joi.string(), Joi.number())) .validate(data) + +export const sessionIdValidation = (data: any): Joi.ValidationResult => + Joi.object({ + sessionId: Joi.string().required() + }).validate(data) From 4f6f735f5ba86aa0059db89163ec37c48c3ebfbc Mon Sep 17 00:00:00 2001 From: Yury Date: Thu, 31 Oct 2024 10:08:34 +0300 Subject: [PATCH 4/9] chore(lint): fixed code style issue --- api/src/controllers/internal/Session.ts | 46 ++++++++++++++----------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/api/src/controllers/internal/Session.ts b/api/src/controllers/internal/Session.ts index 616c3c7..751d306 100644 --- a/api/src/controllers/internal/Session.ts +++ b/api/src/controllers/internal/Session.ts @@ -202,33 +202,37 @@ ${autoExecContent}` } private scheduleSessionDestroy(session: Session) { - setTimeout(async () => { - if (session.state === SessionState.running) { - // adding 10 more minutes - const newDeathTimeStamp = - parseInt(session.deathTimeStamp) + 10 * 60 * 1000 - session.deathTimeStamp = newDeathTimeStamp.toString() - - this.scheduleSessionDestroy(session) - } else { - const { expiresAfterMins } = session - - // delay session destroy if expiresAfterMins present - if (expiresAfterMins && session.state !== SessionState.completed) { - // calculate session death time using expiresAfterMins + setTimeout( + async () => { + if (session.state === SessionState.running) { + // adding 10 more minutes const newDeathTimeStamp = - parseInt(session.deathTimeStamp) + expiresAfterMins.mins * 60 * 1000 + parseInt(session.deathTimeStamp) + 10 * 60 * 1000 session.deathTimeStamp = newDeathTimeStamp.toString() - // set expiresAfterMins to true to avoid using it again - session.expiresAfterMins!.used = true - this.scheduleSessionDestroy(session) } else { - await this.deleteSession(session) + const { expiresAfterMins } = session + + // delay session destroy if expiresAfterMins present + if (expiresAfterMins && session.state !== SessionState.completed) { + // calculate session death time using expiresAfterMins + const newDeathTimeStamp = + parseInt(session.deathTimeStamp) + + expiresAfterMins.mins * 60 * 1000 + session.deathTimeStamp = newDeathTimeStamp.toString() + + // set expiresAfterMins to true to avoid using it again + session.expiresAfterMins!.used = true + + this.scheduleSessionDestroy(session) + } else { + await this.deleteSession(session) + } } - } - }, parseInt(session.deathTimeStamp) - new Date().getTime() - 100) + }, + parseInt(session.deathTimeStamp) - new Date().getTime() - 100 + ) } } From 48a9a4dd0e31f84209635382be4ec4bb2c3a9c0c Mon Sep 17 00:00:00 2001 From: Yury Date: Thu, 31 Oct 2024 11:17:20 +0300 Subject: [PATCH 5/9] fix(api): fixed condition in processProgram --- api/src/controllers/internal/processProgram.ts | 2 +- api/src/types/Session.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/api/src/controllers/internal/processProgram.ts b/api/src/controllers/internal/processProgram.ts index 791a3a9..0557c0f 100644 --- a/api/src/controllers/internal/processProgram.ts +++ b/api/src/controllers/internal/processProgram.ts @@ -49,7 +49,7 @@ export const processProgram = async ( await moveFile(codePath + '.bkp', codePath) // we now need to poll the session status - while (session.state === SessionState.completed) { + while (session.state !== SessionState.completed) { await delay(50) } } else { diff --git a/api/src/types/Session.ts b/api/src/types/Session.ts index 1015e1e..31399e4 100644 --- a/api/src/types/Session.ts +++ b/api/src/types/Session.ts @@ -1,5 +1,5 @@ export enum SessionState { - initialising = 'initialising', // session is initialising and nor ready to be used yet + initialising = 'initialising', // session is initialising and not ready to be used yet pending = 'pending', // session is ready to be used running = 'running', // session is in use completed = 'completed', // session is completed and can be destroyed From 73df1024224c254a014f6aab524d5b55e5ae283a Mon Sep 17 00:00:00 2001 From: Yury Date: Thu, 31 Oct 2024 12:27:56 +0300 Subject: [PATCH 6/9] chore(api): updated endpoint description --- api/public/swagger.yaml | 2 +- api/src/controllers/session.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/api/public/swagger.yaml b/api/public/swagger.yaml index 947aa3f..c006b26 100644 --- a/api/public/swagger.yaml +++ b/api/public/swagger.yaml @@ -1859,7 +1859,7 @@ paths: application/json: schema: $ref: '#/components/schemas/SessionState' - summary: 'Get session state (initialising, pending, running, completed, failed).' + summary: "Get session state (initialising, pending, running, completed, failed).\nPolling session state won't work in a load-balanced situation." tags: - Session security: diff --git a/api/src/controllers/session.ts b/api/src/controllers/session.ts index 0f5cfef..c2acea4 100644 --- a/api/src/controllers/session.ts +++ b/api/src/controllers/session.ts @@ -31,6 +31,7 @@ export class SessionController { /** * @summary Get session state (initialising, pending, running, completed, failed). + * Polling session state won't work in a load-balanced situation. * @example completed */ @Get('/:sessionId/state') From ca17e7c1921ebd8879c80ed9a7873e2560a5b39d Mon Sep 17 00:00:00 2001 From: Yury Date: Thu, 31 Oct 2024 14:08:56 +0300 Subject: [PATCH 7/9] chore(api): updated endpoint description --- api/public/swagger.yaml | 3 ++- api/src/controllers/session.ts | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/api/public/swagger.yaml b/api/public/swagger.yaml index c006b26..243f5a0 100644 --- a/api/public/swagger.yaml +++ b/api/public/swagger.yaml @@ -1859,7 +1859,8 @@ paths: application/json: schema: $ref: '#/components/schemas/SessionState' - summary: "Get session state (initialising, pending, running, completed, failed).\nPolling session state won't work in a load-balanced situation." + description: "The polling endpoint is currently implemented for single-server deployments only.
\nLoad balanced / grid topologies will be supported in a future release.
\nIf your site requires this, please reach out to SASjs Support." + summary: 'Get session state (initialising, pending, running, completed, failed).' tags: - Session security: diff --git a/api/src/controllers/session.ts b/api/src/controllers/session.ts index c2acea4..e4cfdf5 100644 --- a/api/src/controllers/session.ts +++ b/api/src/controllers/session.ts @@ -30,8 +30,10 @@ export class SessionController { } /** + * The polling endpoint is currently implemented for single-server deployments only.
+ * Load balanced / grid topologies will be supported in a future release.
+ * If your site requires this, please reach out to SASjs Support. * @summary Get session state (initialising, pending, running, completed, failed). - * Polling session state won't work in a load-balanced situation. * @example completed */ @Get('/:sessionId/state') From 66aa9b589131f17d14e255250c79628186f95967 Mon Sep 17 00:00:00 2001 From: Yury Date: Thu, 31 Oct 2024 15:20:35 +0300 Subject: [PATCH 8/9] chore(api): updated trigger endpoints description --- api/public/swagger.yaml | 4 ++-- api/src/controllers/code.ts | 8 +++++--- api/src/controllers/stp.ts | 8 +++++--- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/api/public/swagger.yaml b/api/public/swagger.yaml index 243f5a0..4e8469e 100644 --- a/api/public/swagger.yaml +++ b/api/public/swagger.yaml @@ -113,7 +113,7 @@ components: properties: sessionId: type: string - description: "The SessionId is the name of the temporary folder used to store the outputs.\nFor SAS, this would be the SASWORK folder. Can be used to poll job status.\nThis session ID should be used to poll job status." + description: "sessionId is the ID of the session and the name of the temporary folder\nused to store code outputs.
\nFor SAS, this would be the SASWORK folder.
\nsessionId can be used to poll session state using\nGET /SASjsApi/session/{sessionId}/state endpoint." example: 20241028074744-54132-1730101664824 required: - sessionId @@ -605,7 +605,7 @@ components: properties: sessionId: type: string - description: "The SessionId is the name of the temporary folder used to store the outputs.\nFor SAS, this would be the SASWORK folder. Can be used to poll program status.\nThis session ID should be used to poll program status." + description: "sessionId is the ID of the session and the name of the temporary folder\nused to store program outputs.
\nFor SAS, this would be the SASWORK folder.
\nsessionId can be used to poll session state using\nGET /SASjsApi/session/{sessionId}/state endpoint." example: 20241028074744-54132-1730101664824 required: - sessionId diff --git a/api/src/controllers/code.ts b/api/src/controllers/code.ts index 3719cce..f57b184 100644 --- a/api/src/controllers/code.ts +++ b/api/src/controllers/code.ts @@ -42,9 +42,11 @@ interface TriggerCodePayload { interface TriggerCodeResponse { /** - * The SessionId is the name of the temporary folder used to store the outputs. - * For SAS, this would be the SASWORK folder. Can be used to poll job status. - * This session ID should be used to poll job status. + * sessionId is the ID of the session and the name of the temporary folder + * used to store code outputs.
+ * For SAS, this would be the SASWORK folder.
+ * sessionId can be used to poll session state using + * GET /SASjsApi/session/{sessionId}/state endpoint. * @example "20241028074744-54132-1730101664824" */ sessionId: string diff --git a/api/src/controllers/stp.ts b/api/src/controllers/stp.ts index ad3b5bd..0bc432b 100644 --- a/api/src/controllers/stp.ts +++ b/api/src/controllers/stp.ts @@ -40,9 +40,11 @@ interface TriggerProgramPayload { interface TriggerProgramResponse { /** - * The SessionId is the name of the temporary folder used to store the outputs. - * For SAS, this would be the SASWORK folder. Can be used to poll program status. - * This session ID should be used to poll program status. + * sessionId is the ID of the session and the name of the temporary folder + * used to store program outputs.
+ * For SAS, this would be the SASWORK folder.
+ * sessionId can be used to poll session state using + * GET /SASjsApi/session/{sessionId}/state endpoint. * @example "20241028074744-54132-1730101664824" */ sessionId: string From bc2cff1d0d68715702db0209c9fc1bc66112ce6f Mon Sep 17 00:00:00 2001 From: Yury Date: Thu, 31 Oct 2024 15:30:32 +0300 Subject: [PATCH 9/9] chore(api): updated trigger endpoints description --- api/public/swagger.yaml | 4 ++-- api/src/controllers/code.ts | 8 ++++---- api/src/controllers/stp.ts | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/api/public/swagger.yaml b/api/public/swagger.yaml index 4e8469e..f7929f0 100644 --- a/api/public/swagger.yaml +++ b/api/public/swagger.yaml @@ -113,7 +113,7 @@ components: properties: sessionId: type: string - description: "sessionId is the ID of the session and the name of the temporary folder\nused to store code outputs.
\nFor SAS, this would be the SASWORK folder.
\nsessionId can be used to poll session state using\nGET /SASjsApi/session/{sessionId}/state endpoint." + description: "`sessionId` is the ID of the session and the name of the temporary folder\nused to store code outputs.

\nFor SAS, this would be the location of the SASWORK folder.

\n`sessionId` can be used to poll session state using the\nGET /SASjsApi/session/{sessionId}/state endpoint." example: 20241028074744-54132-1730101664824 required: - sessionId @@ -605,7 +605,7 @@ components: properties: sessionId: type: string - description: "sessionId is the ID of the session and the name of the temporary folder\nused to store program outputs.
\nFor SAS, this would be the SASWORK folder.
\nsessionId can be used to poll session state using\nGET /SASjsApi/session/{sessionId}/state endpoint." + description: "`sessionId` is the ID of the session and the name of the temporary folder\nused to store program outputs.

\nFor SAS, this would be the location of the SASWORK folder.

\n`sessionId` can be used to poll session state using the\nGET /SASjsApi/session/{sessionId}/state endpoint." example: 20241028074744-54132-1730101664824 required: - sessionId diff --git a/api/src/controllers/code.ts b/api/src/controllers/code.ts index f57b184..f6aaa30 100644 --- a/api/src/controllers/code.ts +++ b/api/src/controllers/code.ts @@ -42,10 +42,10 @@ interface TriggerCodePayload { interface TriggerCodeResponse { /** - * sessionId is the ID of the session and the name of the temporary folder - * used to store code outputs.
- * For SAS, this would be the SASWORK folder.
- * sessionId can be used to poll session state using + * `sessionId` is the ID of the session and the name of the temporary folder + * used to store code outputs.

+ * For SAS, this would be the location of the SASWORK folder.

+ * `sessionId` can be used to poll session state using the * GET /SASjsApi/session/{sessionId}/state endpoint. * @example "20241028074744-54132-1730101664824" */ diff --git a/api/src/controllers/stp.ts b/api/src/controllers/stp.ts index 0bc432b..d1797ec 100644 --- a/api/src/controllers/stp.ts +++ b/api/src/controllers/stp.ts @@ -40,10 +40,10 @@ interface TriggerProgramPayload { interface TriggerProgramResponse { /** - * sessionId is the ID of the session and the name of the temporary folder - * used to store program outputs.
- * For SAS, this would be the SASWORK folder.
- * sessionId can be used to poll session state using + * `sessionId` is the ID of the session and the name of the temporary folder + * used to store program outputs.

+ * For SAS, this would be the location of the SASWORK folder.

+ * `sessionId` can be used to poll session state using the * GET /SASjsApi/session/{sessionId}/state endpoint. * @example "20241028074744-54132-1730101664824" */