Gomengine
This Go operator is an example on how to use message type with a golang script.
Configuration Parameters
Parameter |
Type |
Description |
---|---|---|
codelanguage |
string |
The programming language used in the code. Default: "go" |
script |
string |
Mandatory. The inline script to be executed. If the script starts with "file://", then the script file is executed. Default: "" |
Input
Input |
Type |
Description |
---|---|---|
input |
message |
Any message which body should be converted to an uppercase string. |
Output
Output |
Type |
Description |
---|---|---|
output |
message |
The message which body contains an uppercase string. |
Creating a GoExecutor Extension
- Create an extension of Go Executor operator and add the desired input and output ports.
- Add your Go code as an inline "script" parameter in the extension configuration or put the code into a separate file and use the prefix "file://" to specify the file name. The script must belong to package main.
- There are two reserved functions for initialization and cleanup (runs during shutdown of operator). The signature for the initialization function is func Setup(); this function may implement some setup code, it is called only once, when the operator starts. And the shutdown function should have the following signature: func Cleanup(); it is called only once before operator shuts down.
- All inputs are considered interface{} type, so for the one writing the
script is important to deal with correct type assertions. In order to use
message type, the value received through the input port should be converted
to type map[string]interface{}, then the values can be accessed as
"Attributes", "Encoding" and "Body" as in the following
example:
package main //here implement the function with the input port name, so data coming from this input will call this function func In(val interface{}){ message := val.(map[string]interface{}) body := message["Body"] attr := message["Attributes"].(map[string]interface{}) encoding := message["Encoding"] ... }
- In order to call a function based on an input incoming data, the function
name should be the same as the port name, and data from that port will be
sent through its parameter. And to output data, a function with the outport
name should be defined and called with data as parameter. As in the
following example:
package main var Out func(interface{}) //here implement the function with the input port name, so data coming from this input will call this function func In(val interface{}){ strValue := val.(string) strValue += "test" Out(strValue) ... }
Logging
package main var Log func(string) var Logf func(string, ...interface{}) func Setup() { Log("starting go operator") } func In(val interface{}){ strValue := val.(string) strValue += "test" Logf("input:%s", strValue) ... }
The error log is also available, it writes errors to operator's tracer and should be written with same formats of Log but called Error or Errorf. Note that the error does not stop the graph, only writes the error to the tracer.
Configuration
Configuration calls provide the ability to read the configuration provided via a graph description. The function parameter should be the property title.
package main var GetString func(string) string var GetInt func(string) int var GetBool func(string) bool var GetObject func(string) map[string]interface{} var AsObject func(string) map[string]interface{} func In(val interface{}){ strValue := GetString("str") intValue := GetInt("int") boolValue := GetBool("bool") objValue := GetObject("obj") entireConfig := AsObject() ... }
Message Response
SendResponse sends either a message response or error as the response to message request and can be called from golang script.
package main var SendResponse func(map[string]interface{}, map[string]interface{}, error) func Input(val interface{}){ message := val.(map[string]interface{}) body := message["Body"] attr := message["Attributes"].(map[string]interface{}) encoding := message["Encoding"] SendResponse(message, message, nil) ... }
Tick Timer
To create a tick function, where it will be called every x amount of ms, the script of the global variable Timer must be set, containing an integer value (time in ms). Then, the function named "Tick()" will be called after the time in a loop.
package main var Timer int64 = 500 func Tick() { //function to be called every 500 ms //changes here }