Production Ready Macros for SAS Application Developers
https://github.com/sasjs/core
mv_getjobresult.sas
Go to the documentation of this file.
1/**
2 @file
3 @brief Extract the result from a completed SAS Viya Job
4 @details Extracts result from a Viya job and writes it out to a fileref
5 and/or a JSON-engine library.
6
7 To query the job, you need the URI. Sample code for achieving this
8 is provided below.
9
10 ## Example
11
12 First, compile the macros:
13
14 filename mc url
15 "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
16 %inc mc;
17
18 Next, create a job (in this case, a web service):
19
20 filename ft15f001 temp;
21 parmcards4;
22 data test;
23 rand=ranuni(0)*1000;
24 do x=1 to rand;
25 y=rand*4;
26 output;
27 end;
28 run;
29 proc sort data=&syslast
30 by descending y;
31 run;
32 %webout(OPEN)
33 %webout(OBJ, test)
34 %webout(CLOSE)
35 ;;;;
36 %mv_createwebservice(path=/Public/temp,name=demo)
37
38 Execute it:
39
40 %mv_jobexecute(path=/Public/temp
41 ,name=demo
42 ,outds=work.info
43 )
44
45 Wait for it to finish, and grab the uri:
46
47 data _null_;
48 set work.info;
49 if method='GET' and rel='self';
50 call symputx('uri',uri);
51 run;
52
53 Finally, fetch the result (In this case, WEBOUT):
54
55 %mv_getjobresult(uri=&uri,result=WEBOUT_JSON,outref=myweb,outlib=myweblib)
56
57
58 @param [in] access_token_var= The global macro variable containing the access
59 token
60 @param [in] mdebug= set to 1 to enable DEBUG messages
61 @param [in] grant_type= valid values:
62 @li password
63 @li authorization_code
64 @li detect - will check if access_token exists, if not will use sas_services
65 if a SASStudioV session else authorization_code. Default option.
66 @li sas_services - will use oauth_bearer=sas_services.
67 @param [in] uri= The uri of the running job for which to fetch the status,
68 in the format `/jobExecution/jobs/$UUID` (unquoted).
69
70 @param [out] result= (WEBOUT_JSON) The result type to capture. Resolves
71 to "_[column name]" from the results table when parsed with the JSON libname
72 engine. Example values:
73 @li WEBOUT_JSON
74 @li WEBOUT_TXT
75
76 @param [out] outref= (0) The output fileref to which to write the results
77 @param [out] outlib= (0) The output library to which to assign the results
78 (assumes the data is in JSON format)
79
80
81 @version VIYA V.03.05
82 @author Allan Bowe, source: https://github.com/sasjs/core
83
84 <h4> SAS Macros </h4>
85 @li mp_abort.sas
86 @li mp_binarycopy.sas
87 @li mf_getplatform.sas
88 @li mf_existfileref.sas
89
90**/
91
92%macro mv_getjobresult(uri=0
93 ,access_token_var=ACCESS_TOKEN
94 ,grant_type=sas_services
95 ,mdebug=0
96 ,result=WEBOUT_JSON
97 ,outref=0
98 ,outlib=0
99 );
100%local dbg;
101%if &mdebug=1 %then %do;
102 %put &sysmacroname entry vars:;
103 %put _local_;
104%end;
105%else %let dbg=*;
106
107%local oauth_bearer;
108%if &grant_type=detect %then %do;
109 %if %symexist(&access_token_var) %then %let grant_type=authorization_code;
110 %else %let grant_type=sas_services;
111%end;
112%if &grant_type=sas_services %then %do;
113 %let oauth_bearer=oauth_bearer=sas_services;
114 %let &access_token_var=;
115%end;
116
117%mp_abort(iftrue=(&grant_type ne authorization_code and &grant_type ne password
118 and &grant_type ne sas_services
119 )
120 ,mac=&sysmacroname
121 ,msg=%str(Invalid value for grant_type: &grant_type)
122)
123
124
125/* validation in datastep for better character safety */
126%local errmsg errflg;
127data _null_;
128 uri=symget('uri');
129 if length(uri)<12 then do;
130 call symputx('errflg',1);
131 call symputx('errmsg',"URI is invalid (too short) - '&uri'",'l');
132 end;
133 if scan(uri,-1)='state' or scan(uri,1) ne 'jobExecution' then do;
134 call symputx('errflg',1);
135 call symputx('errmsg',
136 "URI should be in format /jobExecution/jobs/$$$$UUID$$$$"
137 !!" but is actually like: &uri",'l');
138 end;
139run;
140
141%mp_abort(iftrue=(&errflg=1)
142 ,mac=&sysmacroname
143 ,msg=%str(&errmsg)
144)
145
146%if &outref ne 0 and %mf_existfileref(&outref) ne 1 %then %do;
147 filename &outref temp;
148%end;
149
150options noquotelenmax;
151%local base_uri; /* location of rest apis */
152%let base_uri=%mf_getplatform(VIYARESTAPI);
153
154/* fetch job info */
155%local fname1;
156%let fname1=%mf_getuniquefileref();
157proc http method='GET' out=&fname1 &oauth_bearer
158 url="&base_uri&uri";
159 headers "Accept"="application/json"
160 %if &grant_type=authorization_code %then %do;
161 "Authorization"="Bearer &&&access_token_var"
162 %end;
163 ;
164run;
165%if &SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201 %then
166%do;
167 data _null_;infile &fname1;input;putlog _infile_;run;
168 %mp_abort(mac=&sysmacroname
169 ,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
170 )
171%end;
172%if &mdebug=1 %then %do;
173 data _null_;
174 infile &fname1 lrecl=32767;
175 input;
176 putlog _infile_;
177 run;
178%end;
179
180/* extract results link */
181%local lib1 resuri;
182%let lib1=%mf_getuniquelibref();
183libname &lib1 JSON fileref=&fname1;
184data _null_;
185 set &lib1..results;
186 call symputx('resuri',_&result,'l');
187 &dbg putlog "&sysmacroname results: " (_all_)(=);
188run;
189%mp_abort(iftrue=("&resuri"=".")
190 ,mac=&sysmacroname
191 ,msg=%str(Variable _&result did not exist in the response json)
192)
193
194/* extract results */
195%local fname2;
196%let fname2=%mf_getuniquefileref();
197proc http method='GET' out=&fname2 &oauth_bearer
198 url="&base_uri&resuri/content?limit=10000";
199 headers "Accept"="application/json"
200 %if &grant_type=authorization_code %then %do;
201 "Authorization"="Bearer &&&access_token_var"
202 %end;
203 ;
204run;
205%if &mdebug=1 %then %do;
206 /* send one char at a time as the json can be very wide */
207 data _null_;
208 infile &fname2 recfm=n;
209 input char $char1. ;
210 putlog char $char1. @;
211 run;
212%end;
213
214%if &outref ne 0 %then %do;
215 filename &outref temp;
216 %mp_binarycopy(inref=&fname2,outref=&outref)
217%end;
218%if &outlib ne 0 %then %do;
219 libname &outlib JSON fileref=&fname2;
220%end;
221
222%if &mdebug=0 %then %do;
223 filename &fname1 clear;
224 filename &fname2 clear;
225 libname &lib1 clear;
226%end;
227%else %do;
228 %put &sysmacroname exit vars:;
229 %put _local_;
230%end;
231
232%mend mv_getjobresult;