Around Advice
Node around advice (Around Advice): executes before and after the node OnMsg method. This type of advice can replace the original node logic. It can implement node failover, retry, caching and other functions.
Before, After, Around Advice execution order: Around->Before->Around
# Interface
// Order returns the execution order, the smaller the value, the higher the priority
Order() int
// New creates a new instance
New() Aspect
// PointCut declares a cut-in point, used to determine whether to execute the advice
//For example: specify some component types or relationType to execute the aspect logic;return ctx.Self().Type()=="mqttClient"
PointCut(ctx RuleContext, msg RuleMsg, relationType string) bool
//Around is the advice that executes around the node OnMsg method.
//If the return is false: the engine will not call the current node's OnMsg method,
//it needs to be manually triggered by Aspect, such as: ctx.Self().OnMsg (ctx, msg), or skip the current node's logic: ctx.TellNext .
//If it returns true: the engine will call the current node's OnMsg method.
Around(ctx RuleContext, msg RuleMsg, relationType string) (RuleMsg, bool)
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
The return value of the Around msg cannot affect the parameters of the next node; please use the before aspect or control it through ctx.TellNext(msg, relationType).
# Example
type AroundAspect struct {
Name string
}
func (aspect *AroundAspect) Order() int {
return 5
}
func (aspect *AroundAspect) New() types.Aspect {
return &AroundAspect{}
}
func (aspect *AroundAspect) PointCut(ctx types.RuleContext, msg types.RuleMsg, relationType string) bool {
return true
}
func (aspect *AroundAspect) Around(ctx types.RuleContext, msg types.RuleMsg, relationType string) (types.RuleMsg, bool) {
fmt.Printf("debug Around before ruleChainId:%s,flowType:%s,nodeId:%s,msg:%+v,relationType:%s \n", ctx.RuleChain().GetNodeId().Id, "Around", ctx.Self().GetNodeId().Id, msg, relationType)
msg.Metadata.PutValue(ctx.GetSelfId()+"_before", ctx.GetSelfId()+"_before")
// Execute the current node logic
ctx.Self().OnMsg(ctx, msg)
//get out result
//ctx.GetOut()
fmt.Printf("debug Around after ruleChainId:%s,flowType:%s,nodeId:%s,msg:%+v,relationType:%s \n", ctx.RuleChain().GetNodeId().Id, "Around", ctx.Self().GetNodeId().Id, msg, relationType)
//Return false,do not repeatedly execute this node logic outside of the framework.
return msg, false
}
func TestAroundAspect(t *testing.T) {
var chain = `
{
"ruleChain": {
"id": "rule8848",
"name": "test",
"root": true
},
"metadata": {
"nodes": [
{
"id": "s1",
"type": "jsFilter",
"name": "过滤",
"debugMode": true,
"configuration": {
"jsScript": "return msg.role=='admin';"
}
},
{
"id": "s2",
"type": "jsTransform",
"name": "转换",
"debugMode": true,
"configuration": {
"jsScript": "msg.userName=msg.userName+'NO-1';\n return {'msg':msg,'metadata':metadata,'msgType':msgType};"
}
}
],
"connections": [
{
"fromId": "s1",
"toId": "s2",
"type": "False"
}
]
}
}
`
chainId := "test_around_aspect"
config := NewConfig()
ruleEngine, err := DefaultPool.New(chainId, []byte(chain), WithConfig(config), types.WithAspects(
&AroundAspect{Name: "AroundAspect1"},
))
if err != nil {
t.Error(err)
}
metaData := types.NewMetadata()
metaData.PutValue("productType", "test01")
msg := types.NewMsg(0, "TEST_MSG_TYPE1", types.JSON, metaData, "{\"temperature\":41}")
ruleEngine.OnMsg(msg)
time.Sleep(time.Millisecond * 200)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
Edit this page on GitHub (opens new window)
Last Updated: 2024/10/23, 10:13:01