mirror of
https://github.com/sasjs/server.git
synced 2026-01-08 07:00:04 +00:00
refactor: specs + cleanup
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import path from 'path'
|
||||
import { Session } from '../../types'
|
||||
import { configuration } from '../../../package.json'
|
||||
import { promisify } from 'util'
|
||||
@@ -7,22 +8,13 @@ import {
|
||||
deleteFolder,
|
||||
createFile,
|
||||
fileExists,
|
||||
deleteFile,
|
||||
generateTimestamp
|
||||
} from '@sasjs/utils'
|
||||
import path from 'path'
|
||||
import { ExecutionController } from './Execution'
|
||||
import { date } from 'joi'
|
||||
|
||||
const execFilePromise = promisify(execFile)
|
||||
|
||||
export class SessionController {
|
||||
private sessions: Session[] = []
|
||||
private executionController: ExecutionController
|
||||
|
||||
constructor() {
|
||||
this.executionController = new ExecutionController()
|
||||
}
|
||||
|
||||
public async getSession() {
|
||||
const readySessions = this.sessions.filter((sess: Session) => sess.ready)
|
||||
@@ -40,59 +32,36 @@ export class SessionController {
|
||||
const sessionId = generateUniqueFileName(generateTimestamp())
|
||||
const sessionFolder = path.join(getTmpSessionsFolderPath(), sessionId)
|
||||
|
||||
const autoExecContent = `
|
||||
data _null_;
|
||||
/* remove the dummy SYSIN */
|
||||
length fname $8;
|
||||
rc=filename(fname,getoption('SYSIN') );
|
||||
if rc = 0 and fexist(fname) then rc=fdelete(fname);
|
||||
rc=filename(fname);
|
||||
/* now wait for the real SYSIN */
|
||||
slept=0;
|
||||
do until ( fileexist(getoption('SYSIN')) or slept>(60*15) );
|
||||
slept=slept+sleep(0.01,1);
|
||||
end;
|
||||
stop;
|
||||
run;
|
||||
`
|
||||
// the autoexec file is executed on SAS startup
|
||||
const autoExec = path.join(sessionFolder, 'autoexec.sas')
|
||||
await createFile(autoExec, autoExecContent)
|
||||
|
||||
// a dummy SYSIN code.sas file is necessary to start SAS
|
||||
await createFile(path.join(sessionFolder, 'code.sas'), '')
|
||||
|
||||
const creationTimeStamp = sessionId.split('-').pop() as string
|
||||
const deathTimeStamp = (
|
||||
parseInt(creationTimeStamp) +
|
||||
15 * 60 * 1000 -
|
||||
1000
|
||||
).toString()
|
||||
|
||||
const session: Session = {
|
||||
id: sessionId,
|
||||
ready: false,
|
||||
creationTimeStamp: creationTimeStamp,
|
||||
deathTimeStamp: (
|
||||
parseInt(creationTimeStamp) +
|
||||
15 * 60 * 1000 -
|
||||
1000
|
||||
).toString(),
|
||||
path: sessionFolder,
|
||||
inUse: false,
|
||||
completed: false
|
||||
completed: false,
|
||||
creationTimeStamp,
|
||||
deathTimeStamp,
|
||||
path: sessionFolder
|
||||
}
|
||||
|
||||
// we do not want to leave sessions running forever
|
||||
// we do not want to leave sessions running forever
|
||||
// we clean them up after a predefined period, if unused
|
||||
this.scheduleSessionDestroy(session)
|
||||
|
||||
// the autoexec file is executed on SAS startup
|
||||
const autoExecPath = path.join(sessionFolder, 'autoexec.sas')
|
||||
await createFile(autoExecPath, autoExecContent)
|
||||
|
||||
// create empty code.sas as SAS will not start without a SYSIN
|
||||
const codePath = path.join(session.path, 'code.sas')
|
||||
await createFile(codePath, '')
|
||||
|
||||
|
||||
// this.executionController
|
||||
// .execute('', undefined, autoExec, session)
|
||||
// .catch((err) => {console.log(err)})
|
||||
|
||||
|
||||
// trigger SAS but don't wait for completion - we need to
|
||||
// trigger SAS but don't wait for completion - we need to
|
||||
// update the session array to say that it is currently running
|
||||
// however we also need a promise so that we can update the
|
||||
// session array to say that it has (eventually) finished.
|
||||
@@ -104,18 +73,24 @@ export class SessionController {
|
||||
path.join(session.path, 'log.log'),
|
||||
'-WORK',
|
||||
session.path,
|
||||
'-AUTOEXEC',
|
||||
path.join(session.path, 'autoexec.sas'),
|
||||
'-AUTOEXEC',
|
||||
autoExecPath,
|
||||
process.platform === 'win32' ? '-nosplash' : ''
|
||||
]).then(() => {
|
||||
session.completed=true
|
||||
console.log('session completed', session)
|
||||
}).catch((err) => {})
|
||||
])
|
||||
.then(() => {
|
||||
session.completed = true
|
||||
console.log('session completed', session)
|
||||
})
|
||||
.catch((err) => {
|
||||
session.completed = true
|
||||
session.crashed = true
|
||||
console.log('session crashed', session.id, err)
|
||||
})
|
||||
|
||||
// we have a triggered session - add to array
|
||||
this.sessions.push(session)
|
||||
|
||||
// SAS has been triggered but we can't use it until
|
||||
// SAS has been triggered but we can't use it until
|
||||
// the autoexec deletes the code.sas file
|
||||
await this.waitForSession(session)
|
||||
|
||||
@@ -123,17 +98,12 @@ export class SessionController {
|
||||
}
|
||||
|
||||
public async waitForSession(session: Session) {
|
||||
if (await fileExists(path.join(session.path, 'code.sas'))) {
|
||||
while (await fileExists(path.join(session.path, 'code.sas'))) {}
|
||||
const codeFilePath = path.join(session.path, 'code.sas')
|
||||
|
||||
session.ready = true
|
||||
while (await fileExists(codeFilePath)) {}
|
||||
|
||||
return Promise.resolve(session)
|
||||
} else {
|
||||
session.ready = true
|
||||
|
||||
return Promise.resolve(session)
|
||||
}
|
||||
session.ready = true
|
||||
return Promise.resolve(session)
|
||||
}
|
||||
|
||||
public async deleteSession(session: Session) {
|
||||
@@ -168,3 +138,19 @@ export const getSessionController = (): SessionController => {
|
||||
|
||||
return process.sessionController
|
||||
}
|
||||
|
||||
const autoExecContent = `
|
||||
data _null_;
|
||||
/* remove the dummy SYSIN */
|
||||
length fname $8;
|
||||
rc=filename(fname,getoption('SYSIN') );
|
||||
if rc = 0 and fexist(fname) then rc=fdelete(fname);
|
||||
rc=filename(fname);
|
||||
/* now wait for the real SYSIN */
|
||||
slept=0;
|
||||
do until ( fileexist(getoption('SYSIN')) or slept>(60*15) );
|
||||
slept=slept+sleep(0.01,1);
|
||||
end;
|
||||
stop;
|
||||
run;
|
||||
`
|
||||
|
||||
Reference in New Issue
Block a user