1
0
mirror of https://github.com/sasjs/adapter.git synced 2026-01-05 03:30:05 +00:00

Compare commits

...

9 Commits

Author SHA1 Message Date
Yury Shkoda
33a202fa1c Merge pull request #189 from sasjs/job-pid
feat(job-pid): added print PID of the executed job
2020-12-23 12:06:24 +03:00
Yury Shkoda
ff5463a84c chore(example): fixed example 2020-12-23 09:24:15 +03:00
Yury Shkoda
aa7c3ae4a9 docs(pid): updated docs 2020-12-23 09:18:49 +03:00
Yury Shkoda
2e66bfde4b chore(pid): made printing PID optional 2020-12-23 09:17:40 +03:00
Yury Shkoda
16e21adb20 chore: updated docs 2020-12-22 16:58:14 +03:00
Yury Shkoda
01c5682c3d Merge branch 'job-pid' of https://github.com/sasjs/adapter into job-pid 2020-12-22 16:46:48 +03:00
Yury Shkoda
cfc8ff2837 chore: added 'Assign Reviewer' CI step 2020-12-22 16:46:16 +03:00
Yury Shkoda
edf25b471a chore: added 'Assign Reviewer' CI step 2020-12-22 16:41:22 +03:00
Yury Shkoda
bb894e6107 feat(job-pid): added print PID of the executed job 2020-12-22 16:21:24 +03:00
40 changed files with 6264 additions and 2984 deletions

2
.env.example Normal file
View File

@@ -0,0 +1,2 @@
SERVER_URL=https://server.com
DEFAULT_COMPUTE_CONTEXT=SAS Job Execution compute context

9
.github/reviewer-lottery.yml vendored Normal file
View File

@@ -0,0 +1,9 @@
groups:
- name: SASjs Devs # name of the group
reviewers: 1 # how many reviewers do you want to assign?
usernames: # github usernames of the reviewers
- krishna-acondy
- YuryShkoda
- saadjutt01
- medjedovicm
- allanbowe

13
.github/workflows/assign-reviewer.yml vendored Normal file
View File

@@ -0,0 +1,13 @@
name: 'Assign Reviewer'
on:
pull_request:
types: [opened]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: uesteibar/reviewer-lottery@v1
with:
repo-token: ${{ secrets.GH_TOKEN }}

4
.gitignore vendored
View File

@@ -1,2 +1,4 @@
node_modules node_modules
build build
.env

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1673
docs/classes/root.sasjs.html Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

125
docs/modules/root.html Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4610
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -39,6 +39,7 @@
"@types/isomorphic-fetch": "0.0.35", "@types/isomorphic-fetch": "0.0.35",
"@types/jest": "^26.0.15", "@types/jest": "^26.0.15",
"cp": "^0.2.0", "cp": "^0.2.0",
"dotenv": "^8.2.0",
"jest": "^25.5.4", "jest": "^25.5.4",
"path": "^0.12.7", "path": "^0.12.7",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
@@ -57,6 +58,7 @@
}, },
"main": "index.js", "main": "index.js",
"dependencies": { "dependencies": {
"@sasjs/utils": "^1.5.0",
"es6-promise": "^4.2.8", "es6-promise": "^4.2.8",
"form-data": "^3.0.0", "form-data": "^3.0.0",
"isomorphic-fetch": "^2.2.1" "isomorphic-fetch": "^2.2.1"

View File

@@ -16,12 +16,13 @@ import {
Folder, Folder,
CsrfToken, CsrfToken,
EditContextInput, EditContextInput,
ErrorResponse,
JobDefinition, JobDefinition,
PollOptions PollOptions
} from './types' } from './types'
import { formatDataForRequest } from './utils/formatDataForRequest' import { formatDataForRequest } from './utils/formatDataForRequest'
import { SessionManager } from './SessionManager' 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. * 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 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 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 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( public async executeScript(
jobPath: string, jobPath: string,
@@ -440,7 +442,8 @@ export class SASViyaApiClient {
debug: boolean = false, debug: boolean = false,
expectWebout = false, expectWebout = false,
waitForResult = true, waitForResult = true,
pollOptions?: PollOptions pollOptions?: PollOptions,
printPid = false
): Promise<any> { ): Promise<any> {
try { try {
const headers: any = { const headers: any = {
@@ -460,6 +463,28 @@ export class SASViyaApiClient {
executionSessionId = session!.id 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 } = { const jobArguments: { [key: string]: any } = {
_contextName: contextName, _contextName: contextName,
_OMITJSONLISTING: true, _OMITJSONLISTING: true,
@@ -958,6 +983,7 @@ export class SASViyaApiClient {
* @param waitForResult - a boolean indicating if the function should wait for a result. * @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 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 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( public async executeComputeJob(
sasJob: string, sasJob: string,
@@ -967,7 +993,8 @@ export class SASViyaApiClient {
accessToken?: string, accessToken?: string,
waitForResult = true, waitForResult = true,
expectWebout = false, expectWebout = false,
pollOptions?: PollOptions pollOptions?: PollOptions,
printPid = false
) { ) {
if (isRelativePath(sasJob) && !this.rootFolderName) { if (isRelativePath(sasJob) && !this.rootFolderName) {
throw new Error( throw new Error(
@@ -1053,7 +1080,8 @@ export class SASViyaApiClient {
debug, debug,
expectWebout, expectWebout,
waitForResult, waitForResult,
pollOptions pollOptions,
printPid
) )
} }

View File

@@ -723,6 +723,7 @@ export default class SASjs {
* The access token is not required when the user is authenticated via the browser. * 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 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 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( public async startComputeJob(
sasJob: string, sasJob: string,
@@ -730,7 +731,8 @@ export default class SASjs {
config: any = {}, config: any = {},
accessToken?: string, accessToken?: string,
waitForResult?: boolean, waitForResult?: boolean,
pollOptions?: PollOptions pollOptions?: PollOptions,
printPid = false
) { ) {
config = { config = {
...this.sasjsConfig, ...this.sasjsConfig,
@@ -752,7 +754,8 @@ export default class SASjs {
accessToken, accessToken,
!!waitForResult, !!waitForResult,
false, 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 { asyncForEach, makeRequest, isUrl } from './utils'
import { prefixMessage } from '@sasjs/utils/error'
const MAX_SESSION_COUNT = 1 const MAX_SESSION_COUNT = 1
const RETRY_LIMIT: number = 3 const RETRY_LIMIT: number = 3
@@ -265,4 +266,21 @@ export class SessionManager {
throw err 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 creationTimeStamp: string
} }
export interface SessionVariable {
value: string
}