1
0
mirror of https://github.com/sasjs/adapter.git synced 2026-01-06 12:10:04 +00:00

Merge branch 'master' into issue-186

This commit is contained in:
Mihajlo Medjedovic
2020-12-23 14:23:26 +01:00
40 changed files with 6245 additions and 2983 deletions

View File

@@ -16,12 +16,13 @@ import {
Folder,
CsrfToken,
EditContextInput,
ErrorResponse,
JobDefinition,
PollOptions
} from './types'
import { formatDataForRequest } from './utils/formatDataForRequest'
import { SessionManager } from './SessionManager'
import { timestampToYYYYMMDDHHMMSS } from '@sasjs/utils/time'
import { Logger, LogLevel } from '@sasjs/utils/logger'
/**
* A client for interfacing with the SAS Viya REST API.
@@ -430,6 +431,7 @@ export class SASViyaApiClient {
* @param expectWebout - when set to true, the automatic _webout fileref will be checked for content, and that content returned. This fileref is used when the Job contains a SASjs web request (as opposed to executing arbitrary SAS code).
* @param waitForResult - when set to true, function will return the session
* @param pollOptions - an object that represents poll interval(milliseconds) and maximum amount of attempts. Object example: { MAX_POLL_COUNT: 24 * 60 * 60, POLL_INTERVAL: 1000 }.
* @param printPid - a boolean that indicates whether the function should print (PID) of the started job.
*/
public async executeScript(
jobPath: string,
@@ -440,7 +442,8 @@ export class SASViyaApiClient {
debug: boolean = false,
expectWebout = false,
waitForResult = true,
pollOptions?: PollOptions
pollOptions?: PollOptions,
printPid = false
): Promise<any> {
try {
const headers: any = {
@@ -460,6 +463,28 @@ export class SASViyaApiClient {
executionSessionId = session!.id
if (printPid) {
const { result: jobIdVariable } = await this.sessionManager.getVariable(
executionSessionId,
'SYSJOBID',
accessToken
)
if (jobIdVariable && jobIdVariable.value) {
const relativeJobPath = this.rootFolderName
? jobPath.split(this.rootFolderName).join('').replace(/^\//, '')
: jobPath
const logger = new Logger(debug ? LogLevel.Debug : LogLevel.Info)
logger.info(
`Triggered '${relativeJobPath}' with PID ${
jobIdVariable.value
} at ${timestampToYYYYMMDDHHMMSS()}`
)
}
}
const jobArguments: { [key: string]: any } = {
_contextName: contextName,
_OMITJSONLISTING: true,
@@ -958,6 +983,7 @@ export class SASViyaApiClient {
* @param waitForResult - a boolean indicating if the function should wait for a result.
* @param expectWebout - a boolean indicating whether to expect a _webout response.
* @param pollOptions - an object that represents poll interval(milliseconds) and maximum amount of attempts. Object example: { MAX_POLL_COUNT: 24 * 60 * 60, POLL_INTERVAL: 1000 }.
* @param printPid - a boolean that indicates whether the function should print (PID) of the started job.
*/
public async executeComputeJob(
sasJob: string,
@@ -967,7 +993,8 @@ export class SASViyaApiClient {
accessToken?: string,
waitForResult = true,
expectWebout = false,
pollOptions?: PollOptions
pollOptions?: PollOptions,
printPid = false
) {
if (isRelativePath(sasJob) && !this.rootFolderName) {
throw new Error(
@@ -1053,7 +1080,8 @@ export class SASViyaApiClient {
debug,
expectWebout,
waitForResult,
pollOptions
pollOptions,
printPid
)
}

View File

@@ -734,6 +734,7 @@ export default class SASjs {
* The access token is not required when the user is authenticated via the browser.
* @param waitForResult - a boolean that indicates whether the function needs to wait for execution to complete.
* @param pollOptions - an object that represents poll interval(milliseconds) and maximum amount of attempts. Object example: { MAX_POLL_COUNT: 24 * 60 * 60, POLL_INTERVAL: 1000 }.
* @param printPid - a boolean that indicates whether the function should print (PID) of the started job.
*/
public async startComputeJob(
sasJob: string,
@@ -741,7 +742,8 @@ export default class SASjs {
config: any = {},
accessToken?: string,
waitForResult?: boolean,
pollOptions?: PollOptions
pollOptions?: PollOptions,
printPid = false
) {
config = {
...this.sasjsConfig,
@@ -763,7 +765,8 @@ export default class SASjs {
accessToken,
!!waitForResult,
false,
pollOptions
pollOptions,
printPid
)
}

View File

@@ -1,5 +1,6 @@
import { Session, Context, CsrfToken } from './types'
import { Session, Context, CsrfToken, SessionVariable } from './types'
import { asyncForEach, makeRequest, isUrl } from './utils'
import { prefixMessage } from '@sasjs/utils/error'
const MAX_SESSION_COUNT = 1
const RETRY_LIMIT: number = 3
@@ -265,4 +266,21 @@ export class SessionManager {
throw err
})
}
async getVariable(sessionId: string, variable: string, accessToken?: string) {
const getSessionVariable = {
method: 'GET',
headers: this.getHeaders(accessToken)
}
return await this.request<SessionVariable>(
`${this.serverUrl}/compute/sessions/${sessionId}/variables/${variable}`,
getSessionVariable
).catch((err) => {
throw prefixMessage(
err,
`Error while fetching session variable '${variable}'.`
)
})
}
}

View File

@@ -0,0 +1,53 @@
import { SessionManager } from '../SessionManager'
import * as dotenv from 'dotenv'
describe('SessionManager', () => {
dotenv.config()
let originalFetch: any
const sessionManager = new SessionManager(
process.env.SERVER_URL as string,
process.env.DEFAULT_COMPUTE_CONTEXT as string,
() => {}
)
beforeAll(() => {
originalFetch = (global as any).fetch
})
afterEach(() => {
;(global as any).fetch = originalFetch
})
describe('getVariable', () => {
it('should fetch session variable', async () => {
const sampleResponse = {
ok: true,
links: [],
name: 'SYSJOBID',
scope: 'GLOBAL',
value: '25218',
version: 1
}
;(global as any).fetch = jest.fn().mockImplementation(() =>
Promise.resolve({
ok: true,
headers: { get: () => '' },
json: () => Promise.resolve(sampleResponse)
})
)
const expectedResponse = { etag: '', result: sampleResponse }
await expect(
sessionManager.getVariable(
'fakeSessionId',
'SYSJOBID',
'fakeAccessToken'
)
).resolves.toEqual(expectedResponse)
})
})
})

View File

@@ -9,3 +9,7 @@ export interface Session {
}
creationTimeStamp: string
}
export interface SessionVariable {
value: string
}