Skip to content

Fast, scalable and flexible rule engine for Go.

License

Notifications You must be signed in to change notification settings

hungpdn/grule-plus

grule-plus

Go Version CI codecov Go Report Card License: MIT

grule-plus is a high-performance, extensible rule engine built on top of Grule Rule Engine. It provides advanced caching, partitioning, and flexible configuration for scalable rule evaluation in Go applications.


Features

  • Pluggable Cache Engines: Supports LRU (Least Recently Used), LFU (Least Frequently Used), ARC (Adaptive Replacement Cache), and RANDOM cache strategies.
  • Partitioned Rule Engine: Scale horizontally with partitioned engines for concurrent rule evaluation.
  • Consistent Hashing: Efficient key distribution across partitions with minimal remapping on node changes.
  • Flexible TTL & Cleanup: Per-rule time-to-live and periodic cleanup for cache entries.
  • Structured Logging: Integrated with Go's slog for context-aware, structured logs.
  • Runtime Stats: Built-in runtime statistics for monitoring and debugging.
  • Thread-Safe: Safe for concurrent use in multi-goroutine environments.

Benchmarks

Comprehensive benchmarks are available in the benchmark/ directory, testing cache performance, engine throughput, and memory usage across different configurations. See benchmark/README.md for detailed results and usage instructions.


Getting Started

Installation

go get github.com/hungpdn/grule-plus

Example Usage

import (
    "context"
    "github.com/hungpdn/grule-plus/engine"
)

func main() {
    cfg := engine.Config{
        Type:            engine.LRU,
        Size:            1000,
        CleanupInterval: 10,
        TTL:             60,
        Partition:       1,
        FactName:        "DiscountFact",
    }
    grule := engine.NewPartitionEngine(cfg, nil)

    rule := "DiscountRule"
    statement := `rule DiscountRule "Apply discount" salience 10 { 
                when 
                    DiscountFact.Amount > 100 
                then 
                    DiscountFact.Discount = 10; 
                    Retract("DiscountRule");
                }`
    _ = grule.AddRule(rule, statement, 60)

    fact := struct {
        Amount   int
        Discount int
    }{Amount: 150}

    _ = grule.Execute(context.Background(), rule, &fact)
    
    fmt.Printf("fact.Discount = 10: %v", fact.Discount)
}

Configuration

See engine.Config for all available options:

  • Type: Cache type (LRU, LFU, ARC, TWOQ, RANDOM)
  • Size: Maximum cache size
  • CleanupInterval: Cache cleanup interval (seconds)
  • TTL: Default time-to-live for rules (seconds)
  • Partition: Number of partitions for parallelism

Documentation

Comprehensive documentation is available in the docs/ directory:

Building Documentation

# Install MkDocs (optional)
pip install mkdocs mkdocs-material

# Serve docs locally
cd docs && mkdocs serve

# Or use godoc for API docs
godoc -http=:6060

Security

Please report security vulnerabilities by LinkedIn hungpdn (not through public issues). See SECURITY.md for details.


TODO

  • Metrics & Monitoring System (execution time, success/failure rates, cache hit/miss ratios, ...)

Contributing

We welcome contributions! Please see our Contributing Guide for details.

License

This project is licensed under the MIT License - see the LICENSE file for details.

About

Fast, scalable and flexible rule engine for Go.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Sponsor this project

Packages

No packages published