Skip to content
This repository was archived by the owner on Dec 17, 2024. It is now read-only.

Commit 8fa893f

Browse files
committed
activation get for sessions should show same mode tabs as session get
Fixes #593
1 parent 415325a commit 8fa893f

File tree

2 files changed

+67
-82
lines changed

2 files changed

+67
-82
lines changed

app/content/js/ui.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1153,7 +1153,6 @@ const ui = (function() {
11531153
*/
11541154
self.showEntity = (entity, options={}, block, nextBlock) => {
11551155
debug('showEntity', entity, options)
1156-
console.trace()
11571156

11581157
const sidecar = document.querySelector('#sidecar'),
11591158
header = sidecar.querySelector('.sidecar-header')

app/plugins/modules/composer/lib/await-app.js

Lines changed: 67 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,45 @@
1717
const debug = require('debug')('composer:session_get')
1818
debug('loading')
1919

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')
2422

2523
debug('finished loading modules')
2624

2725
const viewName = 'session', // for back button and sidecar header labels
2826
viewNameLong = 'App Visualization',// ... long form
2927
defaultMode = 'visualization' // on open, which view mode should be selected?
3028

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+
3154
/**
3255
* This is the command handler for await-app
3356
*
3457
*/
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) => {
3659
let sessionId = argvNoOptions[argvNoOptions.indexOf(cmd) + 1]
3760

3861
if (typeof sessionId === 'number') {
@@ -49,73 +72,6 @@ const await = (wsk, cmd, projection) => (_a, _b, argv_full, modules, _1, _2, arg
4972
}
5073
debug('session get', sessionId)
5174

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-
11975
if (commandLineOptions.last || commandLineOptions['last-failed']) {
12076
//
12177
// 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
159115
if (!sessionId) {
160116
reject(new modules.errors.usage(usage(cmd)))
161117
} 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)
163126
}
164127
}
165-
}))
128+
})
166129

167130
/**
168131
* Here is the await-app module entry point. Here we register command
169132
* handlers.
170133
*
171134
*/
172135
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').$
174138

175139
// this one is mostly session get, but designed for internal consumption as an internal repl API
176140
commandTree.listen(`/wsk/app/await-app`, await(wsk, 'await-app'), { hide: true })
177141

178142
// 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+
})
185171

186172
// project out just the session result
187173
commandTree.listen(`/wsk/session/result`, await(wsk, 'result', _ => _.response.result), { usage: usage('result') })

0 commit comments

Comments
 (0)