17
17
const debug = require ( 'debug' ) ( 'composer:session_get' )
18
18
debug ( 'loading' )
19
19
20
- const { init, decorateAsApp } = require ( './composer' ) ,
21
- { session_get :usage } = require ( './usage' ) ,
22
- messages = require ( './messages.json' ) ,
23
- parseDuration = require ( 'parse-duration' )
20
+ const { session_get :usage } = require ( './usage' ) ,
21
+ messages = require ( './messages.json' )
24
22
25
23
debug ( 'finished loading modules' )
26
24
27
25
const viewName = 'session' , // for back button and sidecar header labels
28
26
viewNameLong = 'App Visualization' , // ... long form
29
27
defaultMode = 'visualization' // on open, which view mode should be selected?
30
28
29
+ /**
30
+ * Format the given activation record for display as a session
31
+ *
32
+ */
33
+ const formatSessionResponse = projection => activation => {
34
+ activation . prettyType = 'sessions'
35
+
36
+ // entity onclick handler
37
+ activation . onclick = ( ) => repl . pexec ( `app get "/${ path } "` )
38
+
39
+ // add our visualization view mode
40
+ if ( ! activation . modes ) activation . modes = [ ]
41
+ activation . modes . find ( ( { mode} ) => mode === 'logs' ) . label = 'trace'
42
+
43
+ const path = activation . annotations . find ( ( { key} ) => key === 'path' ) . value
44
+
45
+ activation . modes . push ( {
46
+ mode : defaultMode ,
47
+ label : 'Session Flow' ,
48
+ direct : entity => repl . pexec ( `session flow ${ activation . activationId } ` )
49
+ } )
50
+
51
+ return activation
52
+ }
53
+
31
54
/**
32
55
* This is the command handler for await-app
33
56
*
34
57
*/
35
- const await = ( wsk , cmd , projection ) => ( _a , _b , argv_full , modules , _1 , _2 , argvNoOptions , commandLineOptions ) => new Promise ( ( resolve , reject ) => init ( wsk , { noping : true } ) . then ( ( { manager } ) => {
58
+ const await = ( wsk , cmd , projection ) => ( _a , _b , argv_full , modules , _1 , _2 , argvNoOptions , commandLineOptions ) => new Promise ( ( resolve , reject ) => {
36
59
let sessionId = argvNoOptions [ argvNoOptions . indexOf ( cmd ) + 1 ]
37
60
38
61
if ( typeof sessionId === 'number' ) {
@@ -49,73 +72,6 @@ const await = (wsk, cmd, projection) => (_a, _b, argv_full, modules, _1, _2, arg
49
72
}
50
73
debug ( 'session get' , sessionId )
51
74
52
- // parseDuration expects a string, and returns millis; we must be
53
- // aware that manager.get expects a value unit of seconds; the default is 30 seconds
54
- const defaultTimeout = 30
55
- const timeout = commandLineOptions . timeout ? parseDuration ( commandLineOptions . timeout . toString ( ) ) / 1000 : defaultTimeout
56
-
57
- /** poll once for completion */
58
- const poll = iter => {
59
- if ( iter > 100 ) {
60
- reject ( 'Timeout waiting for composer application to finish' )
61
- } else {
62
- manager . get ( sessionId , timeout , true )
63
- . then ( activation => {
64
- if ( projection ) {
65
- return resolve ( projection ( activation ) )
66
- }
67
-
68
- activation . prettyType = 'sessions'
69
-
70
- // entity onclick handler
71
- activation . onclick = ( ) => repl . pexec ( `app get "/${ path } "` )
72
-
73
- // add our visualization view mode
74
- if ( ! activation . modes ) activation . modes = [ ]
75
- activation . modes . find ( ( { mode} ) => mode === 'logs' ) . label = 'trace'
76
-
77
- const path = activation . annotations . find ( ( { key} ) => key === 'path' ) . value
78
-
79
- activation . modes . push ( {
80
- mode : defaultMode ,
81
- label : 'Session Flow' ,
82
- direct : entity => repl . pexec ( `session flow ${ activation . activationId } ` )
83
- } )
84
-
85
- resolve ( activation )
86
- } )
87
- . catch ( err => {
88
- //
89
- // hmm... maybe the user is confused and this is a plain activation?
90
- //
91
- return repl . qexec ( `activation get ${ sessionId } ` )
92
- . then ( resolve )
93
- . catch ( err2 => {
94
- //
95
- // nope, there is truly nothing to be found here
96
- //
97
- console . error ( err )
98
- if ( typeof err === 'string' && err . endsWith ( 'is still running' ) ) {
99
- setTimeout ( ( ) => poll ( iter + 1 ) , 300 )
100
- } else if ( typeof err == 'string' && err . startsWith ( 'Cannot find trace for session' ) ) {
101
- reject ( 'Trace data expired' )
102
- } else if ( err . message && err . message . indexOf ( 'ECONNREFUSED' ) >= 0 ) {
103
- reject ( messages . slowInit )
104
- } else {
105
- if ( typeof err === 'string' && err . indexOf ( 'Cannot find' ) >= 0 ) {
106
- // the composer's manager API does
107
- // not nicely wrap this error with
108
- // a status code :(
109
- reject ( { code : 404 , message : err } )
110
- } else {
111
- reject ( err )
112
- }
113
- }
114
- } )
115
- } )
116
- }
117
- }
118
-
119
75
if ( commandLineOptions . last || commandLineOptions [ 'last-failed' ] ) {
120
76
//
121
77
// then the user is asking for the last session; if last===true, this means the user didn't specify a name filter,
@@ -159,29 +115,59 @@ const await = (wsk, cmd, projection) => (_a, _b, argv_full, modules, _1, _2, arg
159
115
if ( ! sessionId ) {
160
116
reject ( new modules . errors . usage ( usage ( cmd ) ) )
161
117
} else {
162
- poll ( 0 )
118
+ repl . qexec ( `wsk activation get ${ sessionId } ` )
119
+ . then ( activation => {
120
+ if ( projection ) {
121
+ resolve ( projection ( activation ) )
122
+ } else {
123
+ resolve ( activation )
124
+ }
125
+ } ) . catch ( reject )
163
126
}
164
127
}
165
- } ) )
128
+ } )
166
129
167
130
/**
168
131
* Here is the await-app module entry point. Here we register command
169
132
* handlers.
170
133
*
171
134
*/
172
135
module . exports = ( commandTree , prequire ) => {
173
- const wsk = prequire ( '/ui/commands/openwhisk-core' )
136
+ const wsk = prequire ( '/ui/commands/openwhisk-core' ) ,
137
+ rawGet = commandTree . find ( '/wsk/activation/get' ) . $
174
138
175
139
// this one is mostly session get, but designed for internal consumption as an internal repl API
176
140
commandTree . listen ( `/wsk/app/await-app` , await ( wsk , 'await-app' ) , { hide : true } )
177
141
178
142
// session get
179
- commandTree . listen ( `/wsk/session/get` , await ( wsk , 'get' ) , { usage : usage ( 'get' ) ,
180
- needsUI : true ,
181
- viewName,
182
- fullscreen : true , width : 800 , height : 600 ,
183
- clearREPLOnLoad : true ,
184
- placeholder : 'Fetching session results...' } )
143
+ const sessionGet = await ( wsk , 'get' )
144
+ commandTree . listen ( `/wsk/session/get` , sessionGet , { usage : usage ( 'get' ) ,
145
+ needsUI : true ,
146
+ viewName,
147
+ fullscreen : true , width : 800 , height : 600 ,
148
+ clearREPLOnLoad : true ,
149
+ placeholder : 'Fetching session results...' } )
150
+
151
+ wsk . synonyms ( 'activations' ) . forEach ( syn => {
152
+ commandTree . listen ( `/wsk/${ syn } /get` , function ( ) {
153
+ if ( ! rawGet ) {
154
+ return Promise . reject ( )
155
+ }
156
+
157
+ return rawGet . apply ( undefined , arguments )
158
+ . then ( response => {
159
+ debug ( 'response' , response )
160
+
161
+ if ( response && response . annotations && response . annotations . find ( ( { key, value} ) => key === 'conductor' && value ) ) {
162
+ debug ( 'activation is session' )
163
+ return formatSessionResponse ( ) ( response )
164
+ } else {
165
+ debug ( 'activation is not session' )
166
+ return response
167
+ }
168
+ } )
169
+ } )
170
+ } )
185
171
186
172
// project out just the session result
187
173
commandTree . listen ( `/wsk/session/result` , await ( wsk , 'result' , _ => _ . response . result ) , { usage : usage ( 'result' ) } )
0 commit comments