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

Merge pull request #445 from sasjs/handle-304-status

fix(session): fixed polling session state, refresh token before server calls
This commit is contained in:
Krishna Acondy
2021-06-30 18:07:44 +01:00
committed by GitHub
4 changed files with 52 additions and 60 deletions

View File

@@ -13,7 +13,7 @@
"postpublish": "git clean -fd",
"semantic-release": "semantic-release",
"typedoc": "typedoc",
"postinstall": "[ -d .git ] && git config core.hooksPath ./.git-hooks || true"
"prepare": "[ -d .git ] && git config core.hooksPath ./.git-hooks || true"
},
"publishConfig": {
"access": "public"

View File

@@ -290,16 +290,14 @@ export class SASViyaApiClient {
printPid = false,
variables?: MacroVar
): Promise<any> {
const { access_token } = authConfig || {}
let access_token = (authConfig || {}).access_token
if (authConfig) {
;({ access_token } = await this.getTokens(authConfig))
}
const logger = process.logger || console
try {
const headers: any = {
'Content-Type': 'application/json'
}
if (access_token) headers.Authorization = `Bearer ${access_token}`
let executionSessionId: string
const session = await this.sessionManager
@@ -443,6 +441,10 @@ export class SASViyaApiClient {
throw prefixMessage(err, 'Error while polling job status. ')
})
if (authConfig) {
;({ access_token } = await this.getTokens(authConfig))
}
const { result: currentJob } = await this.requestClient
.get<Job>(
`/compute/sessions/${executionSessionId}/jobs/${postedJob.id}`,
@@ -886,7 +888,10 @@ export class SASViyaApiClient {
printPid = false,
variables?: MacroVar
) {
let { access_token } = authConfig || {}
let access_token = (authConfig || {}).access_token
if (authConfig) {
;({ access_token } = await this.getTokens(authConfig))
}
if (isRelativePath(sasJob) && !this.rootFolderName) {
throw new Error(
@@ -913,12 +918,6 @@ export class SASViyaApiClient {
)
}
const headers: any = { 'Content-Type': 'application/json' }
if (!!access_token) {
headers.Authorization = `Bearer ${access_token}`
}
const jobToExecute = jobFolder?.find((item) => item.name === jobName)
if (!jobToExecute) {
@@ -985,7 +984,10 @@ export class SASViyaApiClient {
data?: any,
authConfig?: AuthConfig
) {
let { access_token } = authConfig || {}
let access_token = (authConfig || {}).access_token
if (authConfig) {
;({ access_token } = await this.getTokens(authConfig))
}
if (isRelativePath(sasJob) && !this.rootFolderName) {
throw new Error(
'Relative paths cannot be used without specifying a root folder name.'
@@ -1145,21 +1147,9 @@ export class SASViyaApiClient {
let POLL_INTERVAL = 300
let MAX_POLL_COUNT = 1000
let MAX_ERROR_COUNT = 5
let { access_token, refresh_token, client, secret } = authConfig || {}
if (access_token && refresh_token) {
if (
client &&
secret &&
refresh_token &&
(isAccessTokenExpiring(access_token) ||
isRefreshTokenExpiring(refresh_token))
) {
;({ access_token, refresh_token } = await this.refreshTokens(
client,
secret,
refresh_token
))
}
let access_token = (authConfig || {}).access_token
if (authConfig) {
;({ access_token } = await this.getTokens(authConfig))
}
if (pollOptions) {
@@ -1213,20 +1203,8 @@ export class SASViyaApiClient {
postedJobState === 'pending' ||
postedJobState === 'unavailable'
) {
if (access_token && refresh_token) {
if (
client &&
secret &&
refresh_token &&
(isAccessTokenExpiring(access_token) ||
isRefreshTokenExpiring(refresh_token))
) {
;({ access_token, refresh_token } = await this.refreshTokens(
client,
secret,
refresh_token
))
}
if (authConfig) {
;({ access_token } = await this.getTokens(authConfig))
}
if (stateLink) {
@@ -1510,4 +1488,21 @@ export class SASViyaApiClient {
return movedFolder
}
private async getTokens(authConfig: AuthConfig): Promise<AuthConfig> {
const logger = process.logger || console
let { access_token, refresh_token, client, secret } = authConfig
if (
isAccessTokenExpiring(access_token) ||
isRefreshTokenExpiring(refresh_token)
) {
logger.info('Refreshing access and refresh tokens.')
;({ access_token, refresh_token } = await this.refreshTokens(
client,
secret,
refresh_token
))
}
return { access_token, refresh_token, client, secret }
}
}

View File

@@ -6,10 +6,6 @@ import { RequestClient } from './request/RequestClient'
const MAX_SESSION_COUNT = 1
const RETRY_LIMIT: number = 3
let RETRY_COUNT: number = 0
const INTERNAL_SAS_ERROR = {
status: 304,
message: 'Not Modified'
}
export class SessionManager {
constructor(
@@ -164,7 +160,7 @@ export class SessionManager {
const stateLink = session.links.find((l: any) => l.rel === 'state')
return new Promise(async (resolve, _) => {
return new Promise(async (resolve, reject) => {
if (
sessionState === 'pending' ||
sessionState === 'running' ||
@@ -182,7 +178,7 @@ export class SessionManager {
etag!,
accessToken
).catch((err) => {
throw err
throw prefixMessage(err, 'Error while getting session state.')
})
sessionState = state.trim()
@@ -196,13 +192,14 @@ export class SessionManager {
// There is an internal error present in SAS Viya 3.5
// Retry to wait for a session status in such case of SAS internal error
if (
sessionState === INTERNAL_SAS_ERROR.message &&
RETRY_COUNT < RETRY_LIMIT
) {
RETRY_COUNT++
if (!sessionState) {
if (RETRY_COUNT < RETRY_LIMIT) {
RETRY_COUNT++
resolve(this.waitForSession(session, etag, accessToken))
resolve(this.waitForSession(session, etag, accessToken))
} else {
reject('Could not get session state.')
}
}
resolve(sessionState)
@@ -222,9 +219,6 @@ export class SessionManager {
.get(url, accessToken, 'text/plain', { 'If-None-Match': etag })
.then((res) => res.result as string)
.catch((err) => {
if (err.status === INTERNAL_SAS_ERROR.status)
return INTERNAL_SAS_ERROR.message
throw err
})
}

View File

@@ -63,6 +63,9 @@ export class RequestClient implements HttpClient {
baseURL: baseUrl
})
}
this.httpClient.defaults.validateStatus = (status) =>
status >= 200 && status < 305
}
public getCsrfToken(type: 'general' | 'file' = 'general') {