rulesengine

package module
v0.2.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 22, 2024 License: ISC Imports: 13 Imported by: 0

README

json-rules-engine

GO-(json-rules-engine)

This projects strives to be a drop in replacement for the original json-rules-engine project, but written in Go. A big thanks on the team from cache-control for the current project With the goal of offering better performance and through go's concurrency model.

Project Status

The project is still in its initial stages and is not yet ready for production use, but we are working to get it there since we want to use it in production.

A rules engine expressed in JSON

Synopsis

json-rules-engine is a powerful, lightweight rules engine. Rules are composed of simple json structures, making them human readable and easy to persist.

Features

  • Rules expressed in simple, easy to read JSON
  • Full support for ALL and ANY boolean operators, including recursive nesting
  • Fast by default
  • Early stopping evaluation (short-circuiting)
  • Lightweight & extendable; w/few dependencies

Installation

$ go get github.com/nimbit-software/gojson-rules-engine

Contributions welcome!!!

TODOS

  • Better mascot. I am not a designer so the mascot is just a gopher with a hat
  • Better error handling. Error handling can always be better. I never want it to panic but handle error gracefully
  • More examples.
  • More operators. I want to add more operators to the engine
  • More documentation. I want to add more documentation to the engine
  • Move the "rules-engine" package to the top-level for better documentation visibility.
  • Reduce the use of any type and create more strongly-typed methods.
  • Separate methods with different input types for clarity.
  • Optimize for speed by creating a more strongly-typed Node structure.
  • Implement a two-pass approach for unmarshaling and creating strongly-typed nodes.
  • Add more unit tests to increase code coverage.
  • Operator decorators for the rules engine.
  • Create condition validation function
  • Add condition sharing
  • convert all rules to Json
ValueNode

The ValueNode is a strongly-typed node that can be used to represent any value in the rules engine. It is used to represent facts values and condition values in the rules engine.

const (
	Null DataType = iota
	Bool
	Number
	String
	Array
	Object
)

type ValueNode struct {
	Type   DataType
	Bool   bool
	Number float64
	String string
	Array  []ValueNode
	Object map[string]ValueNode
}
Operators

The engine comes with the following default operators: Either the operator itself or an alias can be used.

Operator Alias Data type Description Example
equal eq,= string, number boolean Strict equality { "fact": "age", "operator": "equal", "value": 21 }
notEqual ne,!= string, number boolean Strict inequality { "fact": "age", "operator": "notEqual", "value": 21 }
in in,contains array Value is in array { "fact": "age", "operator": "in", "value": [21, 22, 23] }
notIn nin,notContains array Value is not in array { "fact": "age", "operator": "notIn", "value": [21, 22, 23] }
lessThan lt,< number Less than { "fact": "age", "operator": "lessThan", "value": 21 }
lessThanInclusive lte,<= number Less than or equal { "fact": "age", "operator": "lessThanInclusive", "value": 21 }
greaterThan gt,> number Greater than { "fact": "age", "operator": "greaterThan", "value": 21 }
greaterThanInclusive gte,>= number Greater than or equal { "fact": "age", "operator": "greaterThanInclusive", "value": 21 }
startsWith string String starts with { "fact": "name", "operator": "startsWith", "value": "B" }
endsWith string String ends with { "fact": "name", "operator": "endsWith", "value": "b" }
includes string String includes { "fact": "name", "operator": "includes", "value": "op" }

Additional operators can be added via the AddOperator method.

	
// func NewOperator(name string, cb func(factValue, jsonValue interface{}) bool, factValueValidator func(factValue interface{}) bool) (*Operator, error)
    o, _ := NewOperator("startsWith", func(a, b interface{}) bool {
        aString, okA := a.(string)
        bString, okB := b.(string)
        return okA && okB && strings.HasPrefix(aString, bString)
    }, nil)umberValidator), nil)

    engine.AddOperator(o, nil)

Facts shared or calculated facts can be added to the engine via the AddFact or AddCalculatedFact method.

Calculated facts are facts that are calculated at runtime ONCE and then reused in the rules engine.

err := engine.AddCalculatedFact("personalFoulLimit", func(a *rulesEngine.Almanac, params ...interface{}) *rulesEngine.ValueNode {
    return &rulesEngine.ValueNode{Type: rulesEngine.Number, Number: 50}
}, nil)

// or

err := engine.AddFact("test.fact", &rulesEngine.ValueNode{Type: rulesEngine.Number, Number: 50}, nil)


Examples

Basic Example

This example demonstrates an engine for detecting whether a basketball player has fouled out (a player who commits five personal fouls over the course of a 40-minute game, or six in a 48-minute game, fouls out).

package main
import (
    "context"
    "encoding/json"
    "fmt"
    rulesEngine "github.com/nimbit-software/gojson-rules-engine/cmd"
    "os"
)

func main() {

	rule := []byte(`{
  "conditions": {
    "any": [
      {
        "all": [
          {
            "fact": "gameDuration",
            "operator": "equal",
            "value": 40
          },
          {
            "fact": "personalFoulCount",
            "operator": "greaterThanInclusive",
            "value": 5
          }
        ]
      },
      {
        "all": [
          {
            "fact": "gameDuration",
            "operator": "equal",
            "value": 48
          },
          {
            "fact": "personalFoulCount",
            "operator": "greaterThanInclusive",
            "value": 6
          }
        ]
      }
    ]
  },
  "event": {
    "type": "fouledOut",
    "params": {
      "message": "Player has fouled out!"
    }
  }
}`)

	// CONTEXT FOR EARLY-STOPPING 
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	// ENGINE OPTIONS
	ep := &rulesEngine.RuleEngineOptions{
		AllowUndefinedFacts: true,
	}
    // BUILD ENGINE
	engine := rulesEngine.NewEngine(nil, ep)

	// PARSE RULE
	var ruleConfig rulesEngine.RuleConfig
	if err := json.Unmarshal(rule, &ruleConfig); err != nil {
		panic(err)
	}

    // CREATE RULE
	rule, err := rulesEngine.NewRule(&ruleConfig)
	
	// ADD RULE TO ENGINE
	err = engine.AddRule(rule)

	facts := []byte(`{
            "personalFoulCount": 6,
            "gameDuration": 40,
            "name": "John",
            "user": {
                "lastName": "Jones"
            }
        }`)

    // THE ENGINE CAN RUN BOTH A MAP AND A JSON BYTE ARRAY
    res, err := engine.Run(ctx, facts)
	if err != nil {
		panic(err)
	}
    // OR 
	
	factMap := map[string]interface{}{
        "personalFoulCount": 6,
        "gameDuration": 40,
        "name": "John",
        "user": map[string]interface{}{
            "lastName": "Jones",
        },
    }
	
	res, err = engine.RunWithMap(ctx, factMap)
	if err != nil {
		panic(err)
	}
	
}	

More example coming soon

Debugging

To see what the engine is doing under the hood, debug output can be turned on via:

Environment Variables
DEBUG=json-rules-engine

Benchmarking

There is some very basic benchmarking to allow you to test the performance of the engine.

The first test is with a single go routine and the second one with 10 go routines.

go test ./benchmarks -bench=. -run=^$ -benchmem -v 

Current Results

# 1.000 iterations
BenchmarkRuleEngine took 35.2002ms for 1000 itterations
BenchmarkRuleEngineBasic-16                 1000             35200 ns/op            7338 B/op        108 allocs/op
BenchmarkRuleEngineWithPath took 2.9516ms for 1000 iterations
BenchmarkRuleEngineWithPath-16              1000              2952 ns/op            5595 B/op         76 allocs/op

# 10.000 iterations
BenchmarkRuleEngine took 316.1679ms for 10000 itterations
BenchmarkRuleEngineBasic-16                10000             31617 ns/op            6449 B/op        108 allocs/op
BenchmarkRuleEngineWithPath took 19.159ms for 10000 iterations
BenchmarkRuleEngineWithPath-16             10000              1916 ns/op            4930 B/op         77 allocs/op


# 100.000 iterations
BenchmarkRuleEngine took 3.2104305s for 100000 itterations
BenchmarkRuleEngineBasic-16               100000             32109 ns/op            6414 B/op        108 allocs/op
BenchmarkRuleEngineWithPath took 194.997ms for 100000 iterations
BenchmarkRuleEngineWithPath-16            100000              1950 ns/op            4847 B/op         75 allocs/op


License

ISC

Documentation

Index

Constants

View Source
const (
	READY    = "READY"
	RUNNING  = "RUNNING"
	FINISHED = "FINISHED"
)

Variables

This section is empty.

Functions

func Debug

func Debug(message string)

Debug logs the message if the DEBUG environment variable contains "json-rules-engine"

func EvalEndsWith

func EvalEndsWith(a, b *ValueNode) bool

EvalEndsWith checks if the string in the first ValueNode ends with the string in the second ValueNode. Both 'a' and 'b' must be strings for the comparison to be valid. Returns true if 'a' ends with 'b', false otherwise.

func EvalEqual

func EvalEqual(a, b *ValueNode) bool

EvalEqual checks if two ValueNode instances are equal. It compares their types first, and if they match, it evaluates their values. Supported types: String, Number, Bool, Array. Returns true if both nodes have the same type and value, false otherwise.

func EvalGreaterOrEqual

func EvalGreaterOrEqual(a, b *ValueNode) bool

EvalGreaterOrEqual checks if the first ValueNode is greater than or equal to the second. Both 'a' and 'b' must be numbers for the comparison to be valid. Returns true if 'a' is greater than or equal to 'b', false otherwise.

func EvalGreaterThan

func EvalGreaterThan(a, b *ValueNode) bool

EvalGreaterThan checks if the first ValueNode is greater than the second. Both 'a' and 'b' must be numbers for the comparison to be valid. Returns true if 'a' is greater than 'b', false otherwise.

func EvalIn

func EvalIn(a, b *ValueNode) bool

EvalIn checks if a ValueNode instance is present in an array of ValueNode instances. It assumes that 'b' is an array and iterates through it to find a match with 'a'. Returns true if 'a' is found in 'b', false otherwise.

func EvalIncludes

func EvalIncludes(a, b *ValueNode) bool

EvalIncludes checks if the string in the first ValueNode contains with the string in the second ValueNode. Both 'a' and 'b' must be strings for the comparison to be valid. Returns true if 'a' ends with 'b', false otherwise.

func EvalLessThan

func EvalLessThan(a, b *ValueNode) bool

EvalLessThan checks if the first ValueNode is less than the second. Both 'a' and 'b' must be numbers for the comparison to be valid. Returns true if 'a' is less than 'b', false otherwise.

func EvalLessThanOrEqual

func EvalLessThanOrEqual(a, b *ValueNode) bool

EvalLessThanOrEqual checks if the first ValueNode is less than or equal to the second. Both 'a' and 'b' must be numbers for the comparison to be valid. Returns true if 'a' is less than or equal to 'b', false otherwise.

func EvalNotEquals

func EvalNotEquals(a, b *ValueNode) bool

EvalNotEquals checks if two ValueNode instances are not equal. It returns the negation of the EvalEqual function. Returns true if the nodes are not equal, false otherwise.

func EvalNotIn

func EvalNotIn(a, b *ValueNode) bool

EvalNotIn checks if a ValueNode instance is not present in an array of ValueNode instances. It returns the negation of EvalIn. Returns true if 'a' is not found in 'b', false otherwise.

func EvalStartsWith

func EvalStartsWith(a, b *ValueNode) bool

EvalStartsWith checks if the string in the first ValueNode starts with the string in the second ValueNode. Both 'a' and 'b' must be strings for the comparison to be valid. Returns true if 'a' starts with 'b', false otherwise.

func HashString

func HashString(data string) uint64

func IsObjectLike

func IsObjectLike(value interface{}) bool

isObjectLike checks if the value is an object-like structure

Types

type Almanac

type Almanac struct {
	// contains filtered or unexported fields
}

Almanac is a struct that manages fact results lookup and caching within a rules engine. It allows storing raw facts, caching results of rules, and logging events (success/failure). The Almanac plays a key role in the rules engine by allowing rules to evaluate facts efficiently.

func NewAlmanac

func NewAlmanac(rf gjson.Result, options Options, initialCapacity int) *Almanac

NewAlmanac creates and returns a new Almanac instance. Params: - rf: Raw facts in the form of a gjson.Result. - options: Custom settings such as allowing undefined facts. - initialCapacity: The initial capacity to allocate for rule results. Returns a pointer to a new Almanac.

func (*Almanac) AddEvent

func (a *Almanac) AddEvent(event Event, outcome EventOutcome) error

AddEvent logs an event in the Almanac, marking it as either a success or failure. Params: - event: The event to be added. - outcome: The outcome of the event ("success" or "failure"). Returns an error if the outcome is invalid.

func (*Almanac) AddFact

func (a *Almanac) AddFact(key string, value *Fact)

func (*Almanac) AddResult

func (a *Almanac) AddResult(ruleResult *RuleResult)

AddResult adds a rule evaluation result to the Almanac. This function stores the result of a rule once it has been evaluated.

func (*Almanac) AddRuntimeFact

func (a *Almanac) AddRuntimeFact(path string, value ValueNode) error

AddRuntimeFact adds a constant fact during runtime

func (*Almanac) FactValue

func (a *Almanac) FactValue(path string) (*Fact, error)

func (*Almanac) GetEvents

func (a *Almanac) GetEvents(outcome EventOutcome) *[]Event

GetEvents retrieves events logged in the Almanac based on the specified outcome. If the outcome is "success" or "failure", it returns the events for that outcome. If the outcome is an empty string, it returns all events (success and failure combined). Params: - outcome: The desired outcome ("success", "failure", or empty string for all events). Returns a pointer to a slice of events for the specified outcome.

func (*Almanac) GetResults

func (a *Almanac) GetResults() []RuleResult

GetResults retrieves all rule results

func (*Almanac) GetValue

func (a *Almanac) GetValue(path string) (interface{}, error)

type Condition

type Condition struct {
	Priority   *int
	Name       string
	Operator   string
	Value      ValueNode
	Fact       string
	FactResult Fact
	Result     bool
	Params     map[string]interface{}
	Condition  string
	All        []*Condition
	Any        []*Condition
	Not        *Condition
}

Condition represents an individual condition within a rule in the rules engine. Conditions can compare facts to values using operators, and they can also nest other conditions. Fields: - Priority: Optional priority of the condition, must be greater than zero if set. - Name: The name of the condition. - Operator: The operator to be applied for comparison (e.g., equals, greaterThan). - Value: The value to compare the fact to. - Fact: The fact that is being evaluated in the condition. - FactResult: The result of fact evaluation. - Result: The evaluation result of the condition (true/false). - Params: Additional parameters that may affect the condition's evaluation. - Condition: Raw condition string (for debugging or custom use cases). - All, Any: Nested conditions that require all or any of the sub-conditions to be true. - Not: A nested condition that negates its result.

func (*Condition) Evaluate

func (c *Condition) Evaluate(almanac *Almanac, operatorMap map[string]Operator) (*EvaluationResult, error)

Evaluate evaluates the condition against the given almanac and operator map

func (*Condition) IsBooleanOperator

func (c *Condition) IsBooleanOperator() bool

IsBooleanOperator returns whether the operator is boolean ('all', 'any', 'not')

func (*Condition) IsConditionReference

func (c *Condition) IsConditionReference() bool

isConditionReference returns whether the condition represents a reference to a condition

func (*Condition) ToJSON

func (c *Condition) ToJSON(stringify bool) (interface{}, error)

ToJSON converts the Condition instance to a JSON string representation. Useful for serializing the condition for storage or transmission.

func (*Condition) UnmarshalJSON

func (c *Condition) UnmarshalJSON(data []byte) error

UnmarshalJSON is a custom JSON unmarshaller for the Condition struct. It validates the condition after unmarshalling to ensure it adheres to the rules. Params: - data: JSON data representing the condition. Returns an error if the condition is invalid after unmarshalling.

func (*Condition) Validate

func (c *Condition) Validate() error

Validate checks if the Condition is valid based on business rules. It verifies that if a value, fact, or operator are set, all three must be set. It also ensures that if nested conditions (Any, All, Not) are provided, no value, fact, or operator is set. Returns an error if the condition is invalid

type ConditionMap

type ConditionMap struct {
	sync.Map
}

func (*ConditionMap) Load

func (m *ConditionMap) Load(key string) (Condition, bool)

func (*ConditionMap) Store

func (m *ConditionMap) Store(key string, value Condition)

type ConditionProperties

type ConditionProperties struct {
	Fact     string                 `json:"fact"`
	Operator string                 `json:"operator"`
	Value    interface{}            `json:"value"`
	Path     *string                `json:"path,omitempty"`
	Priority *int                   `json:"priority,omitempty"`
	Params   map[string]interface{} `json:"params,omitempty"`
	Name     *string                `json:"name,omitempty"`
}

ConditionProperties represents a condition inEvaluator the rule.

func (*ConditionProperties) SetName

func (c *ConditionProperties) SetName(name string)

func (*ConditionProperties) SetPriority

func (c *ConditionProperties) SetPriority(priority int)

type DataType

type DataType int
const (
	Null DataType = iota
	Bool
	Number
	String
	Array
	Object
)

type DynamicFactCallback

type DynamicFactCallback func(almanac *Almanac, params ...interface{}) *ValueNode

type Engine

type Engine struct {
	Rules                     []*Rule
	AllowUndefinedFacts       bool
	AllowUndefinedConditions  bool
	ReplaceFactsInEventParams bool
	Operators                 map[string]Operator
	Facts                     FactMap
	Conditions                ConditionMap
	Status                    string
	// contains filtered or unexported fields
}

func NewEngine

func NewEngine(rules []*Rule, options *RuleEngineOptions) *Engine

NewEngine creates a new Engine instance with the provided rules and options. If no options are passed, default options are used. Params: - rules: A slice of rules to be added to the engine. - options: Configuration options for the engine (can be nil). Returns a pointer to the newly created Engine.

func (*Engine) AddCalculatedFact

func (e *Engine) AddCalculatedFact(path string, method DynamicFactCallback, options *FactOptions) error

AddCalculatedFact adds a calculated fact definition to the engine Params: path: The path of the fact. method: The callback function to be executed when the fact is evaluated. options: Additional options for the fact. Returns an error if the fact cannot be added.

func (*Engine) AddFact

func (e *Engine) AddFact(path string, value *ValueNode, options *FactOptions) error

AddFact adds a fact definition to the engine Params: path: The path of the fact. value: The value of the fact. options: Additional options for the fact. Returns an error if the fact cannot be added.

func (*Engine) AddOperator

func (e *Engine) AddOperator(operatorOrName interface{}, cb func(*ValueNode, *ValueNode) bool)

AddOperator adds a custom operator definition Params: - operatorOrName: The operator to be added, or the name of the operator. - cb: The callback function to be executed when the operator is evaluated.

func (*Engine) AddRule

func (e *Engine) AddRule(rule *Rule) error

AddRule adds a single rule to the rules engine. The rule is linked to the engine and stored in the engine's rules list. Params: - rule: The rule to be added to the engine. Returns an error if the rule is invalid or cannot be added.

func (*Engine) AddRuleFromMap

func (e *Engine) AddRuleFromMap(rp *RuleConfig) error

AddRuleFromMap adds a rule to the engine from a configuration map. The rule is created from the map and then added to the engine. Params: - rp: The rule configuration in map form. Returns an error if the rule configuration is invalid.

func (*Engine) AddRules

func (e *Engine) AddRules(rules []*Rule) error

AddRules adds multiple rules to the engine in a single operation. Each rule is validated and added to the engine. Params: - rules: A slice of rules to be added to the engine. Returns an error if any rule cannot be added.

func (*Engine) EvaluateRules

func (e *Engine) EvaluateRules(rules []*Rule, almanac *Almanac, ctx *ExecutionContext) error

EvaluateRules runs an array of rules Params: - rules: The rules to be evaluated. - almanac: The almanac containing facts and results. - ctx: The execution context for the rules. Returns an error if any rule evaluation fails.

func (*Engine) GetFact

func (e *Engine) GetFact(path string) *Fact

GetFact returns a fact by path Params: path: The path of the fact to be retrieved. Returns the fact if it exists, or nil if it does not.

func (*Engine) GetRules

func (e *Engine) GetRules() []*Rule

GetRules returns all rules in the engine. Returns a slice of all rules in the engine.

func (*Engine) PrioritizeRules

func (e *Engine) PrioritizeRules() [][]*Rule

PrioritizeRules iterates over the engine rules, organizing them by highest -> lowest priority Returns a 2D slice of rules, where each inner slice contains rules of the same priority

func (*Engine) RemoveCondition

func (e *Engine) RemoveCondition(name string) bool

RemoveCondition removes a condition that has previously been added to this engine Params: - name: The name of the condition to be removed. Returns true if the condition was removed, false if it was not found.

func (*Engine) RemoveFact

func (e *Engine) RemoveFact(path string) bool

RemoveFact removes a fact from the engine Params: path: The path of the fact to be removed. Returns true if the fact was removed, false if it was not found.

func (*Engine) RemoveOperator

func (e *Engine) RemoveOperator(operatorOrName interface{}) bool

RemoveOperator removes a custom operator definition Params: - operatorOrName: The operator to be removed, or the name of the operator. Returns true if the operator was removed, false if it was not found.

func (*Engine) RemoveRule

func (e *Engine) RemoveRule(rule *Rule) bool

RemoveRule removes an existing rule in the engine. Params: - r: The updated rule. Returns an error if the rule cannot be found or updated.

func (*Engine) RemoveRuleByName

func (e *Engine) RemoveRuleByName(name string) bool

RemoveRuleByName removes an existing rule in the engine by its name. Params: - name: The name of the rule to be removed. Returns true if the rule was removed, false if it was not found.

func (*Engine) Run

func (e *Engine) Run(ctx context.Context, input []byte) (map[string]interface{}, error)

func (*Engine) RunWithMap

func (e *Engine) RunWithMap(ctx context.Context, input map[string]interface{}) (map[string]interface{}, error)

func (*Engine) Stop

func (e *Engine) Stop() *Engine

Stop stops the rules engine from running the next priority set of Rules Returns the engine instance

func (*Engine) UpdateRule

func (e *Engine) UpdateRule(r *Rule) error

UpdateRule updates an existing rule in the engine by its name. If the rule exists, it is replaced by the new version. Params: - r: The updated rule. Returns an error if the rule cannot be found or updated.

type EvaluationResult

type EvaluationResult struct {
	Result             bool        `json:"Result"`
	LeftHandSideValue  Fact        `json:"LeftHandSideValue"`
	RightHandSideValue interface{} `json:"RightHandSideValue"`
	Operator           string      `json:"Operator"`
}

type Event

type Event struct {
	Type   string
	Params map[string]interface{}
}

type EventCallback

type EventCallback func(result *RuleResult) interface{}

type EventConfig

type EventConfig struct {
	Type   string
	Params *map[string]interface{}
}

type EventHandler

type EventHandler func(event Event, almanac Almanac, ruleResult RuleResult)

EventHandler represents an event handler function.

type EventOutcome

type EventOutcome string
const (
	Success EventOutcome = "success"
	Failure EventOutcome = "failure"
)

type ExecutionContext

type ExecutionContext struct {
	context.Context
	Cancel    context.CancelFunc
	StopEarly bool
	Message   string
	Errors    []error
}

ExecutionContext holds metadata and control flags for rule execution.

func NewEvaluationContext

func NewEvaluationContext(ctx context.Context) *ExecutionContext

func (*ExecutionContext) AddError

func (c *ExecutionContext) AddError(err error)

type Fact

type Fact struct {
	Value             *ValueNode
	Path              string
	CalculationMethod DynamicFactCallback
	Cached            bool
	Priority          int
	Dynamic           bool
}

Fact represents a fact within the rules engine. It holds a value (as a ValueNode), a path identifying the fact, and optional metadata about how the value was calculated.

func NewCalculatedFact

func NewCalculatedFact(path string, method DynamicFactCallback, options *FactOptions) *Fact

NewCalculatedFact creates a new Fact instance with a dynamic calculation method. Params: path: The path identifying the fact. method: The method to calculate the fact value. options: Optional configuration options for the fact.

func NewFact

func NewFact(path string, value ValueNode, options *FactOptions) (*Fact, error)

NewFact creates a new Fact instance with a static value. Params: path: The path identifying the fact. value: The value of the fact. options: Optional configuration options for the fact.

func (*Fact) Calculate

func (f *Fact) Calculate(almanac *Almanac, params ...interface{}) *Fact

Calculate evaluates the fact value using the provided Almanac and optional parameters. If the fact is dynamic, it uses the calculation method to determine the value. Params: almanac: The Almanac instance to use for calculation. params: Optional parameters to pass to the calculation method.

type FactMap

type FactMap struct {
	// contains filtered or unexported fields
}

FactMap is a thread-safe map used to store and manage facts in the rules engine. It provides methods for setting, loading, and deleting facts, as well as iterating over the map.

func (*FactMap) Delete

func (m *FactMap) Delete(key string)

Delete removes a fact from the FactMap using the hashed key. Params: - key: The key associated with the fact to be removed.

func (*FactMap) Load

func (m *FactMap) Load(key string) (*Fact, bool)

Load retrieves a fact from the FactMap using the hashed key. Params: - key: The key associated with the fact. Returns: - A pointer to the Fact, and a boolean indicating whether the fact was found.

func (*FactMap) LoadOrStore

func (m *FactMap) LoadOrStore(key string, value *Fact) (*Fact, bool)

LoadOrStore retrieves a fact from the FactMap if it exists, or stores the provided fact if it does not. Params: - key: The key to associate with the fact. - value: The fact to store if the key does not exist. Returns: - A pointer to the actual fact (either loaded or newly stored), and a boolean indicating if it was already present.

func (*FactMap) Range

func (m *FactMap) Range(f func(key string, value *Fact) bool)

Range iterates over all key-value pairs in the FactMap, applying the provided function to each. The function should return true to continue iteration, or false to stop. Params: - f: The function to apply to each key-value pair.

func (*FactMap) Set

func (m *FactMap) Set(key string, value *Fact)

Set stores a fact in the FactMap using the hashed key for efficient lookup. Params: - key: The key to associate with the fact. - value: The fact to store.

type FactOptions

type FactOptions struct {
	Cache    bool
	Priority int
}

type InvalidRuleError

type InvalidRuleError struct {
	Message string
	Code    string
}

InvalidRuleError represents an error for an invalid rule

func NewInvalidPriorityTypeError

func NewInvalidPriorityTypeError() *InvalidRuleError

func NewInvalidPriorityValueError

func NewInvalidPriorityValueError() *InvalidRuleError

func NewInvalidRuleError

func NewInvalidRuleError(message string, code string) *InvalidRuleError

func NewPriorityNotSetError

func NewPriorityNotSetError() *InvalidRuleError

func (*InvalidRuleError) Error

func (e *InvalidRuleError) Error() string

type Operator

type Operator struct {
	Name               string
	Callback           func(a, b *ValueNode) bool
	FactValueValidator func(factValue *ValueNode) bool
}

Operator defines a function that compares two ValueNodes and returns a boolean result. Operators are used in conditions to perform comparisons like equals, greater than, etc.

func DefaultOperators

func DefaultOperators() []Operator

DefaultOperators returns a slice of default operators

func NewOperator

func NewOperator(name string, cb func(a, b *ValueNode) bool, factValueValidator func(factValue *ValueNode) bool) (*Operator, error)

NewOperator adds a new operator to the engine. Params: - name: The name of the operator. - op: The operator function to be added.

func (*Operator) Evaluate

func (o *Operator) Evaluate(a, b *ValueNode) bool

Evaluate takes the fact result and compares it to the condition 'value' using the callback function. Params: - a: The fact value. - b: The condition value. Returns true if the condition is met, false otherwise.

type Options

type Options struct {
	AllowUndefinedFacts *bool // Optional flag to allow undefined facts
}

Options defines the optional settings for the Almanac. It includes a flag to allow or disallow the use of undefined facts during rule evaluation.

type Rule

type Rule struct {
	Priority   int
	Name       string
	Conditions Condition
	RuleEvent  Event
	Engine     *Engine
	// contains filtered or unexported fields
}

Rule represents a rule in the engine. A rule has conditions, actions, and a priority level that determines its order of execution.

func NewRule

func NewRule(config *RuleConfig) (*Rule, error)

NewRule creates a new Rule instance

func (*Rule) Evaluate

func (r *Rule) Evaluate(ctx *ExecutionContext, almanac *Almanac) (*RuleResult, error)

Evaluate checks if the conditions of the rule are satisfied based on the given facts. Params: - almanac: The almanac containing facts for evaluation. Returns true if the rule's conditions are met, false otherwise.

func (*Rule) GetConditions

func (r *Rule) GetConditions() *Condition

GetConditions returns the event object

func (*Rule) GetEngine

func (r *Rule) GetEngine() *Engine

GetEngine returns the engine object

func (*Rule) GetEvent

func (r *Rule) GetEvent() Event

GetEvent returns the event object

func (*Rule) GetPriority

func (r *Rule) GetPriority() int

GetPriority returns the priority

func (*Rule) SetEngine

func (r *Rule) SetEngine(engine *Engine)

SetEngine sets the engine to run the rules under

func (*Rule) ToJSON

func (r *Rule) ToJSON(stringify bool) (interface{}, error)

ToJSON converts the rule to a JSON-friendly structure

type RuleConfig

type RuleConfig struct {
	Name       string      `json:"name"`
	Priority   *int        `json:"priority"`
	Conditions Condition   `json:"conditions"`
	Event      EventConfig `json:"event"`
	OnSuccess  func(result *RuleResult) interface{}
	OnFailure  func(result *RuleResult) interface{}
}

func (*RuleConfig) UnmarshalJSON

func (r *RuleConfig) UnmarshalJSON(data []byte) error

UnmarshalJSON is a custom JSON unmarshaller for RuleConfig to ensure proper unmarshaling of Condition

type RuleEngineOptions

type RuleEngineOptions struct {
	AllowUndefinedFacts       bool
	AllowUndefinedConditions  bool
	ReplaceFactsInEventParams bool
}

func DefaultRuleEngineOptions

func DefaultRuleEngineOptions() *RuleEngineOptions

DefaultRuleEngineOptions returns a default set of options for the rules engine. This includes whether undefined facts or conditions are allowed, and if facts should be replaced in event parameters.

type RuleProperties

type RuleProperties struct {
	Conditions TopLevelCondition `json:"conditions"`
	Event      Event             `json:"event"`
	Name       *string           `json:"name,omitempty"`
	Priority   *int              `json:"priority,omitempty"`
	OnSuccess  *EventHandler     `json:"onSuccess,omitempty"`
	OnFailure  *EventHandler     `json:"onFailure,omitempty"`
}

RuleProperties represents the properties of a rule.

type RuleResult

type RuleResult struct {
	Conditions Condition
	Event      Event
	Priority   int
	Name       string
	Result     *bool
	// contains filtered or unexported fields
}

RuleResult represents the result of a rule evaluation

func NewRuleResult

func NewRuleResult(conditions Condition, event Event, priority int, name string) *RuleResult

NewRuleResult creates a new RuleResult instance

func (*RuleResult) ResolveEventParams

func (rr *RuleResult) ResolveEventParams(almanac *Almanac) error

ResolveEventParams resolves the event parameters using the given almanac

func (*RuleResult) SetResult

func (rr *RuleResult) SetResult(result *bool)

SetResult sets the result of the rule evaluation

func (*RuleResult) ToJSON

func (rr *RuleResult) ToJSON(stringify bool) (interface{}, error)

ToJSON converts the rule result to a JSON-friendly structure

type TopLevelCondition

type TopLevelCondition struct {
	All       *[]ConditionProperties `json:"all,omitempty"`
	Any       *[]ConditionProperties `json:"any,omitempty"`
	Not       *ConditionProperties   `json:"not,omitempty"`
	Condition *string                `json:"condition,omitempty"`
	Name      *string                `json:"name,omitempty"`
	Priority  *int                   `json:"priority,omitempty"`
}

TopLevelCondition represents the top-level condition, which can be AllConditions, AnyConditions, NotConditions, or ConditionReference.

type UndefinedFactError

type UndefinedFactError struct {
	Message string
	Code    string
}

UndefinedFactError represents an error for an undefined fact

func NewUndefinedFactError

func NewUndefinedFactError(message string) *UndefinedFactError

NewUndefinedFactError creates a new UndefinedFactError instance

func (*UndefinedFactError) Error

func (e *UndefinedFactError) Error() string

Error implements the error interface for UndefinedFactError

type ValueNode

type ValueNode struct {
	Type   DataType
	Bool   bool
	Number float64
	String string
	Array  []ValueNode
	Object map[string]ValueNode
}

ValueNode represents a value used in conditions and comparisons. It supports types such as strings, numbers, booleans, arrays, and null.

func NewValueFromGjson

func NewValueFromGjson(result gjson.Result) *ValueNode

NewValueFromGjson converts a gjson.Result into a ValueNode. It handles various data types such as null, string, number, boolean, and arrays. Params: - result: The gjson.Result to be converted. Returns a pointer to a ValueNode representing the result.

func (*ValueNode) IsArray

func (v *ValueNode) IsArray() bool

func (*ValueNode) IsBool

func (v *ValueNode) IsBool() bool

func (*ValueNode) IsNull

func (v *ValueNode) IsNull() bool

func (*ValueNode) IsNumber

func (v *ValueNode) IsNumber() bool

func (*ValueNode) IsObject

func (v *ValueNode) IsObject() bool

func (*ValueNode) IsString

func (v *ValueNode) IsString() bool

func (*ValueNode) Raw

func (v *ValueNode) Raw() interface{}

func (*ValueNode) SameType

func (v *ValueNode) SameType(other *ValueNode) bool

func (*ValueNode) UnmarshalJSON

func (v *ValueNode) UnmarshalJSON(data []byte) error

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL