When the startupservice fails, the modal is a dead end: the adapter returned no log, so there is nothing to act on. The modal now offers a button that runs the same service through the JES / STP web app in a new browser window, where the SAS log is returned as the page body. `_debug=131` is always added (the log is the point), and `_executionTasks` is never included, so on Viya the run is not submitted as a Compute task and cannot hit the execution-task timeout. The URL is built by `buildServiceUrl`, which works for SAS 9, Viya and SASjs Server, and is the same shape the deploy configurator already uses to open makedata. The startup failure modals now carry the service name, which is what shows the button: all three failure branches (malformed response, missing properties, request rejected) pass `public/startupservice`.
47 lines
1.7 KiB
TypeScript
47 lines
1.7 KiB
TypeScript
/**
|
|
* Builds the URL that runs a SAS service directly in a browser window.
|
|
*
|
|
* The adapter submits requests from JavaScript, and on Viya that can route the
|
|
* run through the Compute service (`_executionTasks=true`), where the SAS log
|
|
* is not returned to the caller and the request can time out before the
|
|
* service finishes. A browser request to the JES / STP web app runs the same
|
|
* `_program` without any task involved, and `_debug=131` returns the SAS log
|
|
* as the page body - which is what makes it useful when a service fails.
|
|
*
|
|
* `serverUrl` is left empty on SAS 9 when the app is served from the SAS
|
|
* server itself; the browser then resolves the path against the current
|
|
* origin.
|
|
*/
|
|
export interface ServiceUrlOptions {
|
|
serverUrl: string
|
|
appLoc: string
|
|
executionPath: string
|
|
service: string
|
|
params?: { [name: string]: string | number | null | undefined }
|
|
debug?: boolean
|
|
}
|
|
|
|
export const buildServiceUrl = ({
|
|
serverUrl,
|
|
appLoc,
|
|
executionPath,
|
|
service,
|
|
params = {},
|
|
debug = true
|
|
}: ServiceUrlOptions): string => {
|
|
// Callers pass the service as the app knows it: `public/getdata` in the
|
|
// request path, but the request wrapper reports `services/public/getdata`
|
|
// on a failed request. Both resolve to the same program.
|
|
const servicePath = service.replace(/^\/+/, '').replace(/^services\//, '')
|
|
const paramString = Object.entries(params)
|
|
.filter(([, value]) => value !== null && value !== undefined)
|
|
.map(
|
|
([name, value]) =>
|
|
`&${encodeURIComponent(name)}=${encodeURIComponent(String(value))}`
|
|
)
|
|
.join('')
|
|
const debugParam = debug ? '&_debug=131' : ''
|
|
|
|
return `${serverUrl}${executionPath}/?_program=${appLoc}/services/${servicePath}${paramString}${debugParam}`
|
|
}
|