gorulesengine

package
v2.0.0 Latest Latest
Warning

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

Go to latest
Published: Jan 21, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

package gorulesengine provides a powerful and flexible rules engine for Go. It allows you to define business rules in JSON or code, evaluate complex conditions, and trigger events based on dynamic facts.

Index

Constants

View Source
const (
	// SortByPriority is the string constant for priority-based sorting
	SortByPriority = "priority"
	// EngineOptionKeyCacheConditions is the option key for condition results caching
	EngineOptionKeyCacheConditions = "cacheConditions"
	// EngineOptionKeySmartSkip is the option key for enabling smart skip of rules
	EngineOptionKeySmartSkip = "smartSkip"
	// EngineOptionKeyAuditTrace is the option key for enabling rich audit trace
	EngineOptionKeyAuditTrace = "auditTrace"
	// EngineOptionKeyParallel is the option key for enabling parallel execution
	EngineOptionKeyParallel = "parallel"
	// EngineOptionKeyWorkerCount is the option key for specifying the number of workers for parallel execution
	EngineOptionKeyWorkerCount = "workerCount"
	// SortDefault is the default sort order
	SortDefault SortRule = iota
	// SortRuleASC sorts rules in ascending order
	SortRuleASC
	// SortRuleDESC sorts rules in descending order
	SortRuleDESC
)
View Source
const (
	// DecisionAuthorize indicates that conditions were met.
	DecisionAuthorize = "authorize"
	// DecisionDecline indicates that conditions were not met.
	DecisionDecline = "decline"
)
View Source
const AlmanacOptionKeyAllowUndefinedFacts = "allowUndefinedFacts"

AlmanacOptionKeyAllowUndefinedFacts is the option key for allowing undefined facts.

View Source
const AlmanacOptionKeyCacheConditions = "cacheConditions"

AlmanacOptionKeyCacheConditions is the option key for enabling condition results caching.

View Source
const ConstantFact = "__constant_fact__"

ConstantFact identifies a fact with a static, pre-defined value.

View Source
const DynamicFact = "__dynamic_fact__"

DynamicFact identifies a fact that computes its value dynamically using a function.

View Source
const FactOptionKeyCache = "cache"

FactOptionKeyCache is the key for the caching option in fact options.

View Source
const FactOptionKeyPriority = "priority"

FactOptionKeyPriority is the key for the priority option in fact options.

Variables

This section is empty.

Functions

func DefaultPathResolver

func DefaultPathResolver(value interface{}, path string) (interface{}, error)

DefaultPathResolver implements JSONPath resolution for accessing nested fact values. Example: "$.user.profile.age" accesses deeply nested data.

func RegisterOperator

func RegisterOperator(opType OperatorType, operator Operator)

RegisterOperator registers a custom operator in the global operator registry. This allows you to extend the engine with custom comparison logic.

Example:

type StartsWithOperator struct{}
func (o *StartsWithOperator) Evaluate(factValue, compareValue interface{}) (bool, error) {
    str, ok1 := factValue.(string)
    prefix, ok2 := compareValue.(string)
    if !ok1 || !ok2 {
        return false, fmt.Errorf("both values must be strings")
    }
    return strings.HasPrefix(str, prefix), nil
}
gre.RegisterOperator("starts_with", &StartsWithOperator{})

Types

type Almanac

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

Almanac stores facts and their computed values during rule evaluation. It maintains a cache for fact values, tracks events, and manages rule results. Almanac is thread-safe for concurrent access.

func NewAlmanac

func NewAlmanac(opts ...AlmanacOption) *Almanac

NewAlmanac creates a new Almanac instance with the provided facts and options. The almanac is initialized with default settings including undefined fact handling.

Example:

almanac := gre.NewAlmanac([]*gre.Fact{})
almanac.AddFact("age", 25)
almanac.AddFact("country", "FR")

func (*Almanac) AddFact

func (a *Almanac) AddFact(id FactID, valueOrMethod interface{}, opts ...FactOption) error

AddFact adds a fact to the almanac. The valueOrMethod can be either a static value or a function for dynamic facts. Optional FactOptions can be provided to configure caching and priority.

Example:

// Static fact
almanac.AddFact("age", 25)

// Dynamic fact
almanac.AddFact("temperature", func(params map[string]interface{}) interface{} {
    return fetchTemperature()
})

func (*Almanac) AddFacts

func (a *Almanac) AddFacts(facts ...*Fact)

AddFacts adds multiple facts to the almanac.

func (*Almanac) GetConditionResultFromCache

func (a *Almanac) GetConditionResultFromCache(key string) (interface{}, bool)

GetConditionResultFromCache retrieves a condition result from the cache.

func (*Almanac) GetFactValue

func (a *Almanac) GetFactValue(factID FactID, params map[string]interface{}, path string) (interface{}, error)

GetFactValue retrieves the value of a fact by its ID. For dynamic facts, params can be passed to the computation function. The path parameter allows accessing nested values using JSONPath.

Example:

// Simple fact access
age, _ := almanac.GetFactValue("age", nil, "")

// Nested access with JSONPath
city, _ := almanac.GetFactValue("user", nil, "$.address.city")

func (*Almanac) GetFactValueFromCache

func (a *Almanac) GetFactValueFromCache(factID FactID) (interface{}, bool)

GetFactValueFromCache retrieves a fact value directly from the cache

func (*Almanac) GetFacts

func (a *Almanac) GetFacts() map[FactID]*Fact

GetFacts returns the almanac's fact map

func (*Almanac) GetOptions

func (a *Almanac) GetOptions() map[string]interface{}

GetOptions returns the almanac options

func (*Almanac) IsConditionCachingEnabled

func (a *Almanac) IsConditionCachingEnabled() bool

IsConditionCachingEnabled checks if condition caching is enabled in the almanac.

func (*Almanac) PreCacheFactValue

func (a *Almanac) PreCacheFactValue(fact *Fact)

PreCacheFactValue computes and caches the value of a fact if caching is enabled.

func (*Almanac) SetConditionResultCache

func (a *Almanac) SetConditionResultCache(key string, result interface{})

SetConditionResultCache stores a condition result in the cache.

func (*Almanac) TraversePath

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

TraversePath is a helper to traverse nested structures based on a path expression. It uses the configured PathResolver to access nested values within complex data structures.

type AlmanacError

type AlmanacError struct {
	Payload string // Context about what was being accessed
	Err     error  // Underlying error
}

AlmanacError represents an error that occurred while accessing or managing facts in the almanac.

func (*AlmanacError) Error

func (e *AlmanacError) Error() string

Error methods to convert to RuleEngineError

func (*AlmanacError) Unwrap

func (e *AlmanacError) Unwrap() error

Unwrap returns the wrapped error

type AlmanacOption

type AlmanacOption func(*Almanac)

AlmanacOption defines a functional option for configuring an Almanac.

func AllowUndefinedFacts

func AllowUndefinedFacts() AlmanacOption

AllowUndefinedFacts configures the almanac to return nil instead of errors for undefined facts. This is useful when you want to gracefully handle missing data.

func WithAlmanacConditionCaching

func WithAlmanacConditionCaching() AlmanacOption

WithAlmanacConditionCaching enables caching of condition results.

type Condition

type Condition struct {
	Fact     FactID                 `json:"fact"`             // The fact identifier to evaluate
	Operator OperatorType           `json:"operator"`         // The comparison operator to use
	Value    interface{}            `json:"value"`            // The expected value to compare against
	Path     string                 `json:"path,omitempty"`   // Optional JSONPath to access nested fact values
	Params   map[string]interface{} `json:"params,omitempty"` // Optional parameters for dynamic facts
	// contains filtered or unexported fields
}

Condition represents a single condition that compares a fact value against an expected value using an operator. Conditions can optionally use JSONPath to access nested values within facts.

Example:

condition := &gre.Condition{
    Fact:     "age",
    Operator: "greater_than",
    Value:    18,
}

func Contains

func Contains(fact string, value interface{}) *Condition

Contains creates a condition that checks if fact contains value.

func Equal

func Equal(fact string, value interface{}) *Condition

Equal creates a condition that checks for equality.

func GreaterThan

func GreaterThan(fact string, value interface{}) *Condition

GreaterThan creates a condition that checks if fact > value.

func GreaterThanInclusive

func GreaterThanInclusive(fact string, value interface{}) *Condition

GreaterThanInclusive creates a condition that checks if fact >= value.

func In

func In(fact string, values interface{}) *Condition

In creates a condition that checks if fact is in a list.

func LessThan

func LessThan(fact string, value interface{}) *Condition

LessThan creates a condition that checks if fact < value.

func LessThanInclusive

func LessThanInclusive(fact string, value interface{}) *Condition

LessThanInclusive creates a condition that checks if fact <= value.

func NotContains

func NotContains(fact string, value interface{}) *Condition

NotContains creates a condition that checks if fact does not contain value.

func NotEqual

func NotEqual(fact string, value interface{}) *Condition

NotEqual creates a condition that checks for inequality.

func NotIn

func NotIn(fact string, values interface{}) *Condition

NotIn creates a condition that checks if fact is not in a list.

func Regex

func Regex(fact string, pattern string) *Condition

Regex creates a condition that checks if fact matches a regex pattern.

func (*Condition) Compile

func (c *Condition) Compile() error

Compile pre-calculates properties of the condition to speed up evaluation.

func (*Condition) Evaluate

func (c *Condition) Evaluate(almanac *Almanac) (*ConditionResult, error)

Evaluate evaluates the condition against the almanac

func (*Condition) GetCacheKey

func (c *Condition) GetCacheKey() (string, error)

GetCacheKey generates a unique cache key for the condition.

func (*Condition) GetRequiredFacts

func (c *Condition) GetRequiredFacts() []FactID

GetRequiredFacts returns the list of facts required by this condition.

type ConditionError

type ConditionError struct {
	Condition Condition // The condition that failed
	Err       error     // Underlying error
}

ConditionError represents an error that occurred while evaluating a condition.

func (*ConditionError) Error

func (e *ConditionError) Error() string

Error methods to convert to RuleEngineError

func (*ConditionError) Unwrap

func (e *ConditionError) Unwrap() error

Unwrap returns the wrapped error

type ConditionNode

type ConditionNode struct {
	Condition *Condition    // A single condition to evaluate
	SubSet    *ConditionSet // A nested set of conditions
}

ConditionNode represents either a single Condition or a nested ConditionSet. This allows for recursive nesting of conditions to build complex boolean expressions.

func (*ConditionNode) GetRequiredFacts

func (n *ConditionNode) GetRequiredFacts() []FactID

GetRequiredFacts returns the list of facts required by this condition node.

func (*ConditionNode) UnmarshalJSON

func (n *ConditionNode) UnmarshalJSON(data []byte) error

UnmarshalJSON implements custom JSON unmarshaling for ConditionNode. It attempts to unmarshal either a Condition or a ConditionSet from the JSON data.

type ConditionNodeResult

type ConditionNodeResult struct {
	Condition    *ConditionResult    `json:"condition,omitempty"`
	ConditionSet *ConditionSetResult `json:"conditionSet,omitempty"`
}

ConditionNodeResult represents the result of a single node within a ConditionSet.

type ConditionResult

type ConditionResult struct {
	Fact      FactID       `json:"fact"`
	Operator  OperatorType `json:"operator"`
	Value     interface{}  `json:"value"`          // The value to compare against
	FactValue interface{}  `json:"factValue"`      // The actual value fetched from the Almanac
	Path      string       `json:"path,omitempty"` // The JSONPath used, if any
	Result    bool         `json:"result"`
	Error     string       `json:"error,omitempty"`
}

ConditionResult represents the detailed evaluation result of a single Condition.

type ConditionSet

type ConditionSet struct {
	All  []ConditionNode `json:"all,omitempty"`  // All conditions must be true (AND)
	Any  []ConditionNode `json:"any,omitempty"`  // At least one condition must be true (OR)
	None []ConditionNode `json:"none,omitempty"` // No conditions must be true (NOT)
	// contains filtered or unexported fields
}

ConditionSet represents a group of conditions combined with logical operators (all/any/none). ConditionSets can be nested to create complex boolean logic.

Example:

conditionSet := gre.ConditionSet{
    All: []gre.ConditionNode{
        {Condition: &condition1},
        {Condition: &condition2},
    },
}

func All

func All(conditions ...*Condition) ConditionSet

All creates a ConditionSet where all conditions must be true.

func AllSets

func AllSets(sets ...ConditionSet) ConditionSet

AllSets creates a ConditionSet where all nested ConditionSets must be true.

func Any

func Any(conditions ...*Condition) ConditionSet

Any creates a ConditionSet where at least one condition must be true.

func AnySets

func AnySets(sets ...ConditionSet) ConditionSet

AnySets creates a ConditionSet where at least one nested ConditionSet must be true.

func None

func None(conditions ...*Condition) ConditionSet

None creates a ConditionSet where no conditions must be true.

func NoneSets

func NoneSets(sets ...ConditionSet) ConditionSet

NoneSets creates a ConditionSet where no nested ConditionSets must be true.

func (*ConditionSet) Compile

func (cs *ConditionSet) Compile() error

Compile pre-calculates properties for the entire condition set.

func (*ConditionSet) Evaluate

func (cs *ConditionSet) Evaluate(almanac *Almanac) (*ConditionSetResult, error)

Evaluate evaluates the condition set against the almanac

func (*ConditionSet) GetCacheKey

func (cs *ConditionSet) GetCacheKey() (string, error)

GetCacheKey generates a unique cache key for the condition set.

func (*ConditionSet) GetRequiredFacts

func (cs *ConditionSet) GetRequiredFacts() []FactID

GetRequiredFacts returns the list of all facts required by this condition set.

func (*ConditionSet) ReorderNodes

func (cs *ConditionSet) ReorderNodes(nodes []ConditionNode, almanac *Almanac) ([]ConditionNode, error)

ReorderNodes puts cached conditions at the beginning of the slice to optimize short-circuiting.

type ConditionSetResult

type ConditionSetResult struct {
	Type    ConditionType         `json:"type"`
	Result  bool                  `json:"result"`
	Results []ConditionNodeResult `json:"results"`
}

ConditionSetResult represents the evaluation result of a ConditionSet (All, Any, or None).

type ConditionType

type ConditionType string

ConditionType represents the type of logical operator for combining conditions.

const (
	// AllType represents a logical AND - all conditions must be true.
	AllType ConditionType = "all"

	// AnyType represents a logical OR - at least one condition must be true.
	AnyType ConditionType = "any"

	// NoneType represents a logical NOT - no conditions must be true.
	NoneType ConditionType = "none"
)

type ContainsOperator

type ContainsOperator struct{}

ContainsOperator checks if factValue contains compareValue (for strings and arrays).

func (*ContainsOperator) Evaluate

func (o *ContainsOperator) Evaluate(factValue interface{}, compareValue interface{}) (bool, error)

Evaluate checks if factValue contains compareValue. For strings, checks substring containment. For arrays/slices, checks element presence.

type Engine

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

Engine is the core rules engine that manages rules, facts, and event handlers. It evaluates rules against facts and triggers events when rules match.

func NewEngine

func NewEngine(opts ...EngineOption) *Engine

NewEngine creates a new rules engine instance

func (*Engine) AddRule

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

AddRule adds a rule to the engine

func (*Engine) AddRules

func (e *Engine) AddRules(rules ...*Rule)

AddRules adds multiple rules to the engine

func (*Engine) ClearRules

func (e *Engine) ClearRules()

ClearRules removes all rules from the engine.

func (*Engine) GenerateResponse

func (e *Engine) GenerateResponse() *EngineResponse

GenerateResponse builds the formatted Response object for JSON Marshalling.

func (*Engine) GetRules

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

GetRules returns all rules registered in the engine

func (*Engine) HandleEvent

func (e *Engine) HandleEvent(eventName string, ruleName string, result bool, almanac *Almanac, ruleParams map[string]interface{}) error

HandleEvent invokes the event handler for the given event with context. Supports both synchronous and asynchronous execution based on event mode. ruleParams are optional parameters passed from the rule itself and combined with event defaults.

func (*Engine) ReduceResults

func (e *Engine) ReduceResults() map[string]bool

ReduceResults converts a map of detailed RuleResults to a simple map of booleans.

func (*Engine) RegisterEvent

func (e *Engine) RegisterEvent(event Event)

RegisterEvent registers a named handler that can be referenced by rules. Handlers are invoked when rules succeed.

func (*Engine) RegisterEvents

func (e *Engine) RegisterEvents(events ...Event)

RegisterEvents registers a named handler that can be referenced by rules. Handlers are invoked when rules succeed.

func (*Engine) Results

func (e *Engine) Results() map[string]*RuleResult

Results returns the detailed results of rule evaluations.

func (*Engine) Run

func (e *Engine) Run(almanac *Almanac) (*Engine, error)

Run executes all rules in the engine against the provided almanac. Rules are evaluated in priority order (higher priority first). Returns a slice of RuleResults containing the outcome of each rule evaluation. If any error occurs during evaluation, execution stops and the error is returned. Run executes all registered rules against the facts in the provided Almanac. It returns a map of rule names to their evaluation results.

func (*Engine) SetEventHandler

func (e *Engine) SetEventHandler(handler EventHandler)

SetEventHandler sets the global event handler for the engine

func (*Engine) SetRules

func (e *Engine) SetRules(rules []*Rule)

SetRules replaces all rules in the engine with the provided ones.

type EngineOption

type EngineOption func(*Engine)

EngineOption defines a function type for configuring the Engine.

func WithAuditTrace

func WithAuditTrace() EngineOption

WithAuditTrace enables detailed audit trace for rule evaluations.

func WithConditionCaching

func WithConditionCaching() EngineOption

WithConditionCaching enables condition caching for all rules evaluated by the engine.

func WithMetrics

func WithMetrics(collector MetricsCollector) EngineOption

WithMetrics configures the engine with a metrics collector.

func WithParallelExecution

func WithParallelExecution(workers int) EngineOption

WithParallelExecution enables parallel execution of rules.

func WithPrioritySorting

func WithPrioritySorting(o *SortRule) EngineOption

WithPrioritySorting configures the engine to sort rules by priority before evaluation.

func WithSmartSkip

func WithSmartSkip() EngineOption

WithSmartSkip enables skipping rules that depend on facts not present in the almanac.

func WithoutAuditTrace

func WithoutAuditTrace() EngineOption

WithoutAuditTrace disables detailed audit trace for rule evaluations.

func WithoutConditionCaching

func WithoutConditionCaching() EngineOption

WithoutConditionCaching disables condition caching for all rules evaluated by the engine.

func WithoutParallelExecution

func WithoutParallelExecution() EngineOption

WithoutParallelExecution disables parallel execution of rules.

func WithoutPrioritySorting

func WithoutPrioritySorting() EngineOption

WithoutPrioritySorting configures the engine to not sort rules by priority.

type EngineResponse

type EngineResponse struct {
	Decision string                 `json:"decision"` // DecisionAuthorize or DecisionDecline
	Reason   interface{}            `json:"reason"`   // Detail of conditions (if AuditTrace is active)
	Events   []EventResponse        `json:"events"`   // List of triggered events
	Metadata map[string]interface{} `json:"metadata"` // Metadata from facts or other sources
}

EngineResponse represents the final formatted structure for your JSON response.

type EqualOperator

type EqualOperator struct{}

EqualOperator checks if two values are equal.

func (*EqualOperator) Evaluate

func (o *EqualOperator) Evaluate(factValue interface{}, compareValue interface{}) (bool, error)

Evaluate checks if two values are equal using deep equality comparison. Returns false if the values have different types or if either value is nil.

type ErrorType

type ErrorType string

ErrorType identifies the category of error that occurred.

const (
	// ErrEngine indicates a general engine execution error.
	ErrEngine ErrorType = "ENGINE_ERROR"
	// ErrAlmanac indicates an error related to the almanac or fact management.
	ErrAlmanac ErrorType = "ALMANAC_ERROR"
	// ErrFact indicates an error computing or accessing a fact value.
	ErrFact ErrorType = "FACT_ERROR"
	// ErrRule indicates an error in rule definition or structure.
	ErrRule ErrorType = "RULE_ERROR"
	// ErrCondition indicates an error evaluating a condition.
	ErrCondition ErrorType = "CONDITION_ERROR"
	// ErrOperator indicates an error with an operator (not found, invalid, etc.).
	ErrOperator ErrorType = "OPERATOR_ERROR"
	// ErrEvent indicates an error related to event handling.
	ErrEvent ErrorType = "EVENT_ERROR"
	// ErrJSON indicates an error parsing or unmarshaling JSON.
	ErrJSON ErrorType = "JSON_ERROR"
	// ErrLoader indicates an error related to loading rules or data.
	ErrLoader ErrorType = "LOADER_ERROR"
)

type Event

type Event struct {
	Name   string                   // Name of the event
	Params map[string]interface{}   // Optional parameters passed with the event
	Action func(EventContext) error // Action to execute when the event is handled
	Mode   EventMode                // Execution mode (sync or async)
}

Event represents an event triggered by a rule when its conditions are met. Events can carry additional parameters in the Params map.

type EventContext

type EventContext struct {
	RuleName  string                 // Name of the rule that triggered the event
	Result    bool                   // Result of the rule evaluation (true=success, false=failure)
	Almanac   *Almanac               // Reference to the almanac used for evaluation
	Timestamp time.Time              // When the event was triggered
	Params    map[string]interface{} // Additional parameters from the event
}

EventContext provides context information about the rule execution that triggered an event

type EventHandler

type EventHandler interface {
	Handle(event Event, ctx EventContext) error
}

EventHandler defines the interface for handling events triggered by rules.

type EventMode

type EventMode int

EventMode defines how an event should be executed

const (
	// EventModeSync executes the event synchronously (blocking)
	EventModeSync EventMode = iota
	// EventModeAsync executes the event asynchronously (non-blocking)
	EventModeAsync
)

type EventOutcome

type EventOutcome string

EventOutcome represents an event outcome triggered by a rule.

const EventOutcomeFailure EventOutcome = "failure"

EventOutcomeFailure represents a failed event outcome.

const EventOutcomeSuccess EventOutcome = "success"

EventOutcomeSuccess represents a successful event outcome.

type EventResponse

type EventResponse struct {
	Type   string                 `json:"type"`
	Params map[string]interface{} `json:"params,omitempty"`
}

EventResponse represents a simplified event.

type Fact

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

Fact represents a piece of data (fact) that can be used in rule conditions. Facts can be static values or dynamic functions that compute values on demand.

Example:

// Static fact
fact := gre.NewFact("age", 25)

// Dynamic fact
fact := gre.NewFact("temperature", func(params map[string]interface{}) interface{} {
    return fetchTemperatureFromAPI()
})

func NewFact

func NewFact(id FactID, valueOrMethod interface{}, opts ...FactOption) Fact

NewFact creates a new fact with the given ID and value or computation function. If valueOrMethod is a function, the fact is dynamic and will compute its value on demand. Otherwise, the fact is static with a constant value.

Options can be provided to customize caching and priority behavior.

Example:

// Static fact
fact := gre.NewFact("age", 25)

// Dynamic fact with custom options
fact := gre.NewFact("temperature",
    func(params map[string]interface{}) interface{} {
        return fetchTemperature()
    },
    gre.WithCache(),
    gre.WithPriority(10),
)

func (*Fact) Calculate

func (f *Fact) Calculate(params map[string]interface{}) interface{}

Calculate executes the dynamic fact method or returns the constant fact value

func (*Fact) FactType

func (f *Fact) FactType() string

FactType returns the type of the fact: DYNAMIC_FACT or CONSTANT_FACT.

func (*Fact) GetCacheKey

func (f *Fact) GetCacheKey() (string, error)

GetCacheKey generates a unique cache key for the fact if it's cached

func (*Fact) GetOption

func (f *Fact) GetOption(key string) (interface{}, bool)

GetOption returns the value of a specific option and whether it exists.

func (*Fact) HasOption

func (f *Fact) HasOption(key string) bool

HasOption checks if an option exists

func (*Fact) ID

func (f *Fact) ID() FactID

ID returns the unique identifier of the fact.

func (*Fact) IsDynamic

func (f *Fact) IsDynamic() bool

IsDynamic returns true if the fact computes its value dynamically using a function.

func (*Fact) Metadata

func (f *Fact) Metadata() map[string]interface{}

Metadata returns the metadata associated with the fact.

func (*Fact) ValueOrMethod

func (f *Fact) ValueOrMethod() interface{}

ValueOrMethod returns the fact's value (for static facts) or computation function (for dynamic facts).

type FactError

type FactError struct {
	Fact Fact  // The fact that caused the error
	Err  error // Underlying error
}

FactError represents an error that occurred while computing or accessing a fact value.

func (*FactError) Error

func (e *FactError) Error() string

Error methods to convert to RuleEngineError

func (*FactError) Unwrap

func (e *FactError) Unwrap() error

Unwrap returns the wrapped error

type FactID

type FactID string

FactID is a unique identifier for a fact.

type FactOption

type FactOption func(*Fact)

FactOption defines a functional option for configuring facts.

func WithCache

func WithCache() FactOption

WithCache enables caching for dynamic facts. When enabled, the fact's value will be computed once and reused.

func WithMetadata

func WithMetadata(metadata map[string]interface{}) FactOption

WithMetadata adds metadata to the fact.

func WithPriority

func WithPriority(priority int) FactOption

WithPriority sets the evaluation priority of the fact. Higher priority facts may be evaluated before lower priority facts.

func WithoutCache

func WithoutCache() FactOption

WithoutCache disables caching for facts. When disabled, dynamic facts will be re-evaluated on each access.

type GreaterThanInclusiveOperator

type GreaterThanInclusiveOperator struct{}

GreaterThanInclusiveOperator checks if factValue >= compareValue.

func (*GreaterThanInclusiveOperator) Evaluate

func (o *GreaterThanInclusiveOperator) Evaluate(factValue interface{}, compareValue interface{}) (bool, error)

Evaluate checks if factValue is greater than or equal to compareValue. Both values must be numeric types.

type GreaterThanOperator

type GreaterThanOperator struct{}

GreaterThanOperator checks if factValue > compareValue.

func (*GreaterThanOperator) Evaluate

func (o *GreaterThanOperator) Evaluate(factValue interface{}, compareValue interface{}) (bool, error)

Evaluate checks if factValue is greater than compareValue. Both values must be numeric types.

type HTTPRuleProvider

type HTTPRuleProvider struct {
	URL        string
	Client     *http.Client
	LastUpdate time.Time
	ETag       string
}

HTTPRuleProvider implements RuleProvider for fetching rules from a URL.

func NewHTTPRuleProvider

func NewHTTPRuleProvider(url string) *HTTPRuleProvider

NewHTTPRuleProvider creates a new HTTP rule provider.

func (*HTTPRuleProvider) FetchRules

func (p *HTTPRuleProvider) FetchRules(ctx context.Context) ([]*Rule, error)

FetchRules fetches rules from the configured URL. It expects a JSON array of rules.

type HotReloader

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

HotReloader manages the periodic reloading of rules from a provider.

func NewHotReloader

func NewHotReloader(engine *Engine, provider RuleProvider, interval time.Duration) *HotReloader

NewHotReloader creates a new hot reloader for an engine.

func (*HotReloader) OnError

func (h *HotReloader) OnError(callback func(error))

OnError sets a callback to be called whenever an error occurs during reload.

func (*HotReloader) OnUpdate

func (h *HotReloader) OnUpdate(callback func([]*Rule))

OnUpdate sets a callback to be called whenever rules are updated.

func (*HotReloader) Start

func (h *HotReloader) Start(ctx context.Context)

Start begins the periodic reloading process.

func (*HotReloader) Stop

func (h *HotReloader) Stop()

Stop stops the hot reloader.

type InOperator

type InOperator struct{}

InOperator checks if factValue is contained in compareValue (array).

func (*InOperator) Evaluate

func (o *InOperator) Evaluate(factValue interface{}, compareValue interface{}) (bool, error)

Evaluate checks if factValue is contained in the compareValue array. compareValue must be a slice or array.

type LessThanInclusiveOperator

type LessThanInclusiveOperator struct{}

LessThanInclusiveOperator checks if factValue <= compareValue.

func (*LessThanInclusiveOperator) Evaluate

func (o *LessThanInclusiveOperator) Evaluate(factValue interface{}, compareValue interface{}) (bool, error)

Evaluate checks if factValue is less than or equal to compareValue. Both values must be numeric types.

type LessThanOperator

type LessThanOperator struct{}

LessThanOperator checks if factValue < compareValue.

func (*LessThanOperator) Evaluate

func (o *LessThanOperator) Evaluate(factValue interface{}, compareValue interface{}) (bool, error)

Evaluate checks if factValue is less than compareValue. Both values must be numeric types.

type MetricsCollector

type MetricsCollector interface {
	// ObserveRuleEvaluation records the result and duration of a single rule evaluation.
	ObserveRuleEvaluation(ruleName string, result bool, duration time.Duration)
	// ObserveEngineRun records the total duration and rule count of an engine execution.
	ObserveEngineRun(ruleCount int, duration time.Duration)
	// ObserveEventExecution records the duration and result of an event handler execution.
	ObserveEventExecution(eventName string, ruleName string, result bool, duration time.Duration)
}

MetricsCollector defines an interface for monitoring the rules engine's performance and execution results. Implementations can use Prometheus, OpenTelemetry, or other monitoring systems.

type NotContainsOperator

type NotContainsOperator struct{}

NotContainsOperator checks if factValue does not contain compareValue.

func (*NotContainsOperator) Evaluate

func (o *NotContainsOperator) Evaluate(factValue interface{}, compareValue interface{}) (bool, error)

Evaluate checks if factValue does not contain compareValue. Returns the inverse of the ContainsOperator result.

type NotEqualOperator

type NotEqualOperator struct{}

NotEqualOperator checks if two values are not equal.

func (*NotEqualOperator) Evaluate

func (o *NotEqualOperator) Evaluate(factValue interface{}, compareValue interface{}) (bool, error)

Evaluate checks if two values are not equal. Returns the inverse of the EqualOperator result.

type NotInOperator

type NotInOperator struct{}

NotInOperator checks if factValue is not contained in compareValue (array).

func (*NotInOperator) Evaluate

func (o *NotInOperator) Evaluate(factValue interface{}, compareValue interface{}) (bool, error)

Evaluate checks if factValue is not contained in the compareValue array. Returns the inverse of the InOperator result.

type Operator

type Operator interface {
	// Evaluate compares a fact value against a condition value and returns true if the comparison succeeds.
	Evaluate(factValue interface{}, compareValue interface{}) (bool, error)
}

Operator defines the interface for all comparison operators. Custom operators can be registered by implementing this interface.

func GetOperator

func GetOperator(opType OperatorType) (Operator, error)

GetOperator retrieves an operator from the registry by its type. Returns an error if the operator is not registered.

type OperatorError

type OperatorError struct {
	Operator     OperatorType // The operator that failed
	Value        interface{}  // The fact value being compared
	CompareValue interface{}  // The expected value
	Err          error        // Underlying error
}

OperatorError represents an error related to a specific operator evaluation.

func (*OperatorError) Error

func (e *OperatorError) Error() string

Error methods to convert to RuleEngineError

func (*OperatorError) Unwrap

func (e *OperatorError) Unwrap() error

Unwrap returns the wrapped error

type OperatorType

type OperatorType string

OperatorType represents the type of comparison operator used in conditions.

const (
	OperatorEqual OperatorType = "equal"

	// OperatorNotEqual checks if the fact value is not equal to the condition value.
	OperatorNotEqual OperatorType = "not_equal"

	// OperatorLessThan checks if the fact value is less than the condition value.
	OperatorLessThan OperatorType = "less_than"

	// OperatorLessThanInclusive checks if the fact value is less than or equal to the condition value.
	OperatorLessThanInclusive OperatorType = "less_than_inclusive"

	// OperatorGreaterThan checks if the fact value is greater than the condition value.
	OperatorGreaterThan OperatorType = "greater_than"

	// OperatorGreaterThanInclusive checks if the fact value is greater than or equal to the condition value.
	OperatorGreaterThanInclusive OperatorType = "greater_than_inclusive"

	// OperatorIn checks if the fact value is contained in the condition value (array).
	OperatorIn OperatorType = "in"

	// OperatorNotIn checks if the fact value is not contained in the condition value (array).
	OperatorNotIn OperatorType = "not_in"

	// OperatorContains checks if the fact value contains the condition value (for strings and arrays).
	OperatorContains OperatorType = "contains"

	// OperatorNotContains checks if the fact value does not contain the condition value.
	OperatorNotContains OperatorType = "not_contains"

	// OperatorRegex checks if the fact value matches the regex pattern in the condition value.
	OperatorRegex OperatorType = "regex"
)

OperatorEqual checks if the fact value equals the condition value.

type PathResolver

type PathResolver func(value interface{}, path string) (interface{}, error)

PathResolver resolves nested values within facts using a path expression (e.g., JSONPath).

type RegexOperator

type RegexOperator struct{}

RegexOperator checks if factValue matches the regex pattern in compareValue.

func (*RegexOperator) Evaluate

func (o *RegexOperator) Evaluate(factValue interface{}, compareValue interface{}) (bool, error)

Evaluate checks if factValue matches the regex pattern in compareValue. Both values must be strings. Returns an error if regex evaluation fails.

type Rule

type Rule struct {
	Name       string       `json:"name,omitempty"`
	Priority   int          `json:"priority,omitempty"` // Higher priority rules are evaluated first
	Conditions ConditionSet `json:"conditions"`
	OnSuccess  []RuleEvent  `json:"onSuccess,omitempty"` // Events to invoke on success
	OnFailure  []RuleEvent  `json:"onFailure,omitempty"` // Events to invoke on failure
	Result     bool
}

Rule represents a business rule with conditions and an associated event. Rules are evaluated against facts in an Almanac. When all conditions are met, the rule's event is triggered and any registered callbacks are invoked.

Example:

rule := &gre.Rule{
    Name:     "adult-user",
    Priority: 10,
    Conditions: gre.ConditionSet{
        All: []gre.ConditionNode{
            {Condition: &gre.Condition{
                Fact:     "age",
                Operator: "greater_than",
                Value:    18,
            }},
        },
    },
    OnSuccess: []RuleEvent{
        {Name: "send-welcome-email", Params: map[string]interface{}{"template": "welcome"}},
    },
}

func (*Rule) Compile

func (r *Rule) Compile() error

Compile pre-calculates and optimizes rule's properties.

func (*Rule) GetRequiredFacts

func (r *Rule) GetRequiredFacts() []FactID

GetRequiredFacts returns the list of all facts required by this rule.

type RuleBuilder

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

RuleBuilder provides a fluent API for building rules.

func NewRuleBuilder

func NewRuleBuilder() *RuleBuilder

NewRuleBuilder creates a new RuleBuilder instance.

func (*RuleBuilder) Build

func (rb *RuleBuilder) Build() *Rule

Build returns the constructed Rule.

func (*RuleBuilder) WithConditions

func (rb *RuleBuilder) WithConditions(node ConditionNode) *RuleBuilder

WithConditions sets the conditions for the rule.

func (*RuleBuilder) WithName

func (rb *RuleBuilder) WithName(name string) *RuleBuilder

WithName sets the name of the rule.

func (*RuleBuilder) WithOnFailure

func (rb *RuleBuilder) WithOnFailure(eventNames ...string) *RuleBuilder

WithOnFailure sets the event names for the rule.

func (*RuleBuilder) WithOnFailureEvent

func (rb *RuleBuilder) WithOnFailureEvent(event RuleEvent) *RuleBuilder

WithOnFailureEvent adds a detailed event with parameters to the rule.

func (*RuleBuilder) WithOnSuccess

func (rb *RuleBuilder) WithOnSuccess(eventNames ...string) *RuleBuilder

WithOnSuccess sets the event names for the rule.

func (*RuleBuilder) WithOnSuccessEvent

func (rb *RuleBuilder) WithOnSuccessEvent(event RuleEvent) *RuleBuilder

WithOnSuccessEvent adds a detailed event with parameters to the rule.

func (*RuleBuilder) WithPriority

func (rb *RuleBuilder) WithPriority(priority int) *RuleBuilder

WithPriority sets the priority of the rule.

type RuleEngineError

type RuleEngineError struct {
	Type ErrorType // The category of error
	Msg  string    // Human-readable error message
	Err  error     // Wrapped underlying error (optional)
}

RuleEngineError is the base error type for all errors in the rule engine. It categorizes errors by type and optionally wraps underlying errors.

func (*RuleEngineError) Error

func (e *RuleEngineError) Error() string

Error implements the error interface

func (*RuleEngineError) Unwrap

func (e *RuleEngineError) Unwrap() error

Unwrap returns the wrapped error

type RuleError

type RuleError struct {
	Rule Rule  // The rule that caused the error
	Err  error // Underlying error
}

RuleError represents an error related to a specific rule evaluation or definition.

func (*RuleError) Error

func (e *RuleError) Error() string

Error methods to convert to RuleEngineError

func (*RuleError) Unwrap

func (e *RuleError) Unwrap() error

Unwrap returns the wrapped error

type RuleEvent

type RuleEvent struct {
	Name   string                 `json:"name"`
	Params map[string]interface{} `json:"params,omitempty"`
}

RuleEvent represents an event reference within a rule, optionally with parameters.

func (*RuleEvent) UnmarshalJSON

func (re *RuleEvent) UnmarshalJSON(data []byte) error

UnmarshalJSON implements custom JSON unmarshaling for RuleEvent. It supports both a simple string (event name) or a full object with parameters.

type RuleProvider

type RuleProvider interface {
	// FetchRules retrieves a list of rules from the source.
	FetchRules(ctx context.Context) ([]*Rule, error)
}

RuleProvider defines the interface for fetching rules from external sources.

type RuleResult

type RuleResult struct {
	Name       string              `json:"name"`
	Priority   int                 `json:"priority"`
	Result     bool                `json:"result"`
	Conditions *ConditionSetResult `json:"conditions"`
	OnSuccess  []RuleEvent         `json:"onSuccess,omitempty"`
	OnFailure  []RuleEvent         `json:"onFailure,omitempty"`
}

RuleResult represents the complete evaluation result of a single rule.

type SortRule

type SortRule int

SortRule defines the sort order for rules.

Jump to

Keyboard shortcuts

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