-
Notifications
You must be signed in to change notification settings - Fork 49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support array result include sequence action #170
Support array result include sequence action #170
Conversation
ningyougang
commented
Jul 25, 2022
•
edited
Loading
edited
- Support array result
- make go runtime to support array result for common action
- make go runtime to support array result for sequence action (support array as input param)
The steps of test
[root@nccddev130026 ~]# cat ~/split.go
package main
import (
"strings"
)
// Main is the function implementing the action
func Main(obj map[string]interface{}) []interface{} {
payload, ok := obj["payload"].(string)
if !ok {
payload = "aaaa\nbbbb\ncccc"
}
separator, ok := obj["separator"].(string)
if !ok {
separator = "\n"
}
stringSlice := strings.Split(payload, separator)
output := make([]interface{}, len(stringSlice))
for i, v := range stringSlice {
output[i] = v
}
return output
}
[root@nccddev130026 ~]# cat ~/sort.go
package main
import (
"fmt"
"sort"
)
// Main is the function implementing the action
func Main(event []interface{}) []interface{} {
input := make([]string, len(event))
for i, v := range event {
input[i] = fmt.Sprint(v)
}
sort.Strings(input)
output := make([]interface{}, len(event))
for i, v := range input {
output[i] = v
}
return output
}
wsk -i action create /whisk.system/utils/split-go --kind go:1.17 ~/split.go
wsk -i action create /whisk.system/utils/sort-go --kind go:1.17 ~/sort.go
wsk -i action create mySequence-go --sequence /whisk.system/utils/split-go,/whisk.system/utils/sort-go
wsk -i action invoke --result mySequence-go --param payload "dddd\nbbbb\ncccc" -r -v |
7b7f3e8
to
a54a9ba
Compare
c.init(initPayload(src))._1 shouldBe (200) | ||
val result = c.runForJsArray(JsObject()) | ||
result._1 shouldBe (200) | ||
result._2 shouldBe Some(JsArray(JsString("a"), JsString("b"))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Compare the result
a54a9ba
to
2243586
Compare
err = json.Unmarshal(response, &objmap) | ||
if err != nil { | ||
sendError(w, http.StatusBadGateway, "The action did not return a dictionary or array.") | ||
return | ||
err = json.Unmarshal(response, &objarray) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First, parse the result as json, if failed, parse the result as array.
var payload map[string]interface{} | ||
isJsonObjectParam := true | ||
var payloadForJsonObject map[string]interface{} | ||
var payloadForJsonArray []interface{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Support jsonArray as input param as well. this is for sequence action
var payload map[string]interface{} | ||
isJsonObjectParam := true | ||
var payloadForJsonObject map[string]interface{} | ||
var payloadForJsonArray []interface{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Support json array as input param, this is for sequence action
s""" | ||
|package main | ||
| | ||
|func Main(obj map[string]interface{}) []interface{} { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So if we want to use the JSON array params, do we have to use this signature for the main function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for JSON array params, can use like blow
// Main is the function implementing the action
func Main(event []interface{}) []interface{} {
input := make([]string, len(event))
for i, v := range event {
input[i] = fmt.Sprint(v)
}
sort.Strings(input)
output := make([]interface{}, len(event))
for i, v := range input {
output[i] = v
}
return output
}
hm..it is better to add a test case for json array params as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok now I get it.
So originally the signature of the Main
method is
func Main(obj map[string]interface{}) map[string]interface{} {
...
}
And now we add support for JSON array params.
} | ||
// process the request | ||
result := action(payload) | ||
var result interface{} | ||
funcMain := reflect.ValueOf(Main) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not that familiar with the runtime-go code.
Where this Main
comes from?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is the user's action's Main. i debugged the /init(or /run) before, when execute /init
, it will inject user action codes to action container's suitable directory, the common/gobuild.py.launcher.go can recognize this Main method.
funcMain := reflect.ValueOf(Main) | ||
if isJsonObjectParam { | ||
param := []reflect.Value{reflect.ValueOf(payloadForJsonObject)} | ||
reflectResult := funcMain.Call(param) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If invokes Main directly, compile would be failed.
So i used go reflect
to invoke Main
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am ok with this change as long as we add this test case.
https://github.com/apache/openwhisk-runtime-go/pull/170/files#r937249726
s""" | ||
|package main | ||
| | ||
|func Main(obj map[string]interface{}) []interface{} { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok now I get it.
So originally the signature of the Main
method is
func Main(obj map[string]interface{}) map[string]interface{} {
...
}
And now we add support for JSON array params.
} | ||
} | ||
|
||
it should "support array as input param" in { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add another test case for support array as input param
s""" | ||
|package main | ||
| | ||
|func Main(obj []interface{}) []interface{} { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder what happens when the argument of the main function is an array and an object parameter is passed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@upgle
Use reflect to invoke the Main, e.g.
-
pass
object parameter
-
pass
array parameter
Can't invoke the Main directly due to compile error, should use reflect to invoke.
Btw, why can invoke Main direclty before? because the input param's data type is explicit.
But in this pr, the data type supports 2 data types, so should use reflect to invoke it.
I will merge due to |