RuleGo RuleGo
🏠Home
  • Quick Start
  • Rule Chain
  • Standard Components
  • Extension Components
  • Custom Components
  • Visualization
  • RuleGo-Server
  • RuleGo-MCP-Server
  • AOP
  • Trigger
  • Advanced Topics
  • Performance
  • Standard Components
  • Extension Components
  • Custom Components
  • Components Marketplace
  • Overview
  • Quick Start
  • Routing
  • DSL
  • API
  • Options
  • Components
🔥Editor (opens new window)
  • RuleGo Editor (opens new window)
  • RuleGo Server (opens new window)
  • Github (opens new window)
  • Gitee (opens new window)
  • Changelog (opens new window)
  • English
  • 简体中文
🏠Home
  • Quick Start
  • Rule Chain
  • Standard Components
  • Extension Components
  • Custom Components
  • Visualization
  • RuleGo-Server
  • RuleGo-MCP-Server
  • AOP
  • Trigger
  • Advanced Topics
  • Performance
  • Standard Components
  • Extension Components
  • Custom Components
  • Components Marketplace
  • Overview
  • Quick Start
  • Routing
  • DSL
  • API
  • Options
  • Components
🔥Editor (opens new window)
  • RuleGo Editor (opens new window)
  • RuleGo Server (opens new window)
  • Github (opens new window)
  • Gitee (opens new window)
  • Changelog (opens new window)
  • English
  • 简体中文

广告采用随机轮播方式显示 ❤️成为赞助商
  • Quick Start

  • Rule Chain

  • Standard Components

  • Extension Components

  • Custom Components

    • Custom Components Overview
      • Custom component
        • Component interface
        • Life cycle
        • Initialization
        • Handle messages
        • Example
      • go plugin method to provide components
        • Example
      • Visualization
      • Contribute Components
  • Components marketplace

  • Visualization

  • AOP

  • Trigger

  • Advanced Topic

  • RuleGo-Server

  • FAQ

  • Endpoint Module

  • Support

目录

Custom Components Overview

You can encapsulate your business logic or general logic into components, and then invoke them through rule nodes by configuring the rule chain. Steps:

  1. Implement the component interface.
  2. Register the custom component to the registrar.
  3. Invoke the component through the rule chain configuration.

# Custom component

# Component interface

Implement the types.Node (opens new window) interface:

// Node node component interface
// Encapsulate business or general logic into components, and then invoke the component through rule chain configuration
type Node interface {
    //New create a new component instance
    // Each rule node of the rule chain will create a new instance, the data is isolated
    New() Node
    //Type component type, the type cannot be repeated.
    // Used for rule chain, node.type configuration, initialize the corresponding component
    // It is recommended to use `/` to distinguish the namespace and prevent conflicts. For example: x/httpClient
    Type() string
    //Init component initialization, usually do some component parameter configuration or client initialization operations
    // The rule node in the rule chain will call it once during initialization
    Init(ruleConfig Config, configuration Configuration) error
    //OnMsg handle messages and control the flow to child nodes. Each data flowing into the component will be processed by this method
    //ctx: rule engine message processing context
    //msg: message
    OnMsg(ctx RuleContext, msg RuleMsg)
    //Destroy destroy, do some resource release operations
    Destroy()
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# Life cycle

  • New: Called when creating a node component instance.
  • Init: Used to parse the JSON configuration of the current node, initialized once when initializing the rule chain.
  • OnMsg: Used to handle messages and control the flow to child nodes. Each data flowing into the component will be processed by this function.
  • Destroy: Called when the node is destroyed. The rule engine will call this method when it is destroyed, or when the rule chain or node configuration is updated.

If the node configuration is dynamically updated, the Init method of the new instance of the node is called first, and then the Destroy method of the old instance is called after the initialization is successful.

# Initialization

Generally, we first define the configuration structure for the component. The configuration struct supports nested custom structs. Fields in nested structs are only allowed to be of basic types. Additionally, JSON tags must be used to define the encoding and decoding of fields, and field names should follow the camelCase naming convention.

Such as the following MQTT client configuration structure:

type MqttClientNodeConfiguration struct {
    Server   string `json:"server"`
    Username string `json:"username"`
    Password string `json:"password"`
	// Topic publishing topic, can use ${metadata.key} to read variables from metadata or use ${msg.key} to read variables from message payload for replacement
	Topic              string `json:"topic"`
	// MaxReconnectInterval Reconnection interval in seconds
    MaxReconnectInterval int `json:"maxReconnectInterval"`
    QOS                  uint8 `json:"qos"`
    CleanSession         bool `json:"cleanSession"`
    ClientID             string `json:"clientID"`
    CAFile               string `json:"cAFile"`
    CertFile             string `json:"certFile"`
    CertKeyFile          string `json:"certKeyFile"`
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

The component uses the Config field to customize the component configuration (the visual editor will generate a visual node configuration based on the structure of the Config field):

type MqttClientNode struct {
	// Node configuration
	Config MqttClientNodeConfiguration
	// Topic template
	topicTemplate str.Template
	// Client
	client *mqtt.Client
}
1
2
3
4
5
6
7
8

The following terms are reserved keywords: global, vars, secrets, label, desc, and icon.

Then, during component initialization, convert the node's instance configuration into the component configuration structure, such as the following node configuration:

{
     "id": "s3",
     "type": "mqttClient",
     "name": "mqtt data push",
     "debugMode": false,
     "configuration": {
       "Server": "127.0.0.1:1883",
       "Topic": "/device/msg"
     }
}
1
2
3
4
5
6
7
8
9
10

The Init method's configuration parameter passes the configuration data of this node configuration:

// Init Initialization
func (x *MqttClientNode) Init(ruleConfig types.Config, configuration types.Configuration) error {
	// Convert node configuration to component configuration structure
    err := maps.Map2Struct(configuration, &x.Config)
    // Other initialization
    return err
}
1
2
3
4
5
6
7

Finally, in OnMsg or other places where this configuration is used:

// OnMsg Process message
func (x *MqttClientNode) OnMsg(ctx types.RuleContext, msg types.RuleMsg) {
	// Use configuration
    topic := x.Config.Topic
}
1
2
3
4
5

# Handle messages

After the current rule node is processed, notify the next or multiple nodes through the following methods. The rule engine will query the child nodes that meet the relationship and trigger their OnMsg method to perform chain data flow calls

//TellSuccess notify the rule engine that the current message is processed successfully, and send the message to the next node through the `Success` relationship
TellSuccess(msg RuleMsg)
//TellNext use the specified relationTypes to send messages to the next node
TellNext(msg RuleMsg, relationTypes ...string)
//TellFailure notify the rule engine that the current message processing failed, and send the message to the next node through the `Failure` relationship
TellFailure(msg RuleMsg, err error)
1
2
3
4
5
6

Example:

// OnMsg Process message
func (x *MqttClientNode) OnMsg(ctx types.RuleContext, msg types.RuleMsg) {
	// Use the template to replace the topic
	topic := x.topicTemplate.ExecuteFn(func() map[string]any {
		return base.NodeUtils.GetEvnAndMetadata(ctx, msg)
	})
	// Get the MQTT client
	if client, err := x.SharedNode.Get(); err != nil {
		ctx.TellFailure(msg, err)
	} else {
		// Publish the output of the previous node to the MQTT broker
		if err := client.Publish(topic, x.Config.QOS, []byte(msg.Data)); err != nil {
			// If it fails, send the message to the next node via the failure chain
			ctx.TellFailure(msg, err)
		} else {
			// If it succeeds, send the message to the next node via the success chain without modifying the message payload
			ctx.TellSuccess(msg)
		}
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# Example

Implement the types.Node (opens new window) interface, define the component:

// UpperNode is a plugin that converts the message data to uppercase
type UpperNode struct{}

func (n *UpperNode) Type() string {
   return "test/upper"
}
func (n *UpperNode) New() types.Node {
  return &UpperNode{}
}
func (n *UpperNode) Init(ruleConfig types.Config, configuration types.Configuration) error {
  // Do some initialization work
  return nil
}
// Handle messages
func (n *UpperNode) OnMsg(ctx types.RuleContext, msg types.RuleMsg)  {
  msg.Data = strings.ToUpper(msg.Data)
  // Send the modified message to the next node
  ctx.TellSuccess(msg)
}

func (n *UpperNode) Destroy() {
// Do some cleanup work
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

Register the component to the registrar:

rulego.Registry.Register(&MyNode{})
1

Then use your custom component in the rule chain file:

{
  "ruleChain": {
    "name": "Test Rule Chain",
    "root": true,
    "debugMode": false
  },
  "metadata": {
    "nodes": [
      {
        "id": "s1",
        "type": "test/upper",
        "name": "Name",
        "debugMode": true,
        "configuration": {
          "field1": "Component-defined configuration parameters",
          "....": "..."
        }
      }
    ],
    "connections": [
      {
        "fromId": "s1",
        "toId": "Connect to the next component ID",
        "type": "The connection relationship with the component"
      }
    ]
  }
}
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

# go plugin method to provide components

This method supports dynamic loading of components, but it can only support non-windows systems. A plugin can provide multiple components.

Implement the types.PluginRegistry (opens new window) interface. And export the variable name: Plugins, refer to examples/plugin (opens new window)

# Example

Implement the types.PluginRegistry (opens new window) interface

// Export the plugin variable
var Plugins MyPlugins

type MyPlugins struct{}

func (p *MyPlugins) Init() error {
    return nil
}
func (p *MyPlugins) Components() []types.Node {
  // A plugin can provide multiple components
  return []types.Node{&UpperNode{}, &TimeNode{}, &FilterNode{}}
}
1
2
3
4
5
6
7
8
9
10
11
12

Compile the plugin:

# Compile the plugin, generate the plugin.so file, you need to compile it in a mac or linux environment
go build -buildmode=plugin -o plugin.so plugin.go
1
2

Register the component to the registrar:

rulego.Registry.RegisterPlugin("test", "./plugin.so")
1

# Visualization

  • Component Form Conventions
  • Custom component visualization reference: See the Get Component Configuration Form section.

# Contribute Components

The core feature of RuleGo is componentization, and all business logic is components, and they can be flexibly configured and reused. At present, RuleGo has built-in a lot of common components. However, we know that these components are far from meeting the needs of all users, so we hope that more developers can contribute extension components to RuleGo, making RuleGo's ecology more rich and powerful.

  • If the code for your component does not have third-party dependencies or is a general-purpose component, please submit it to the standard components components (opens new window) under the main repository.
  • Common components should be submitted to the extension component repository: rulego-components (opens new window)
  • CI/CD related components should be submitted to: rulego-components-ci (opens new window)
  • AI-related components should be submitted to: rulego-components-ai (opens new window)
  • IoT-related components should be submitted to: rulego-components-iot (opens new window)
Edit this page on GitHub (opens new window)
Last Updated: 2025/04/02, 01:29:50
Modbus Node
Dynamic Components

← Modbus Node Dynamic Components→

Theme by Vdoing | Copyright © 2023-2025 RuleGo Team | Apache 2.0 License

  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式