Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chore/panic #398

Merged
merged 7 commits into from
Aug 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ast/ExpressionAtom.go
Original file line number Diff line number Diff line change
Expand Up @@ -413,5 +413,5 @@ func (e *ExpressionAtom) Evaluate(dataContext IDataContext, memory *WorkingMemor
return e.Value, nil
}

panic("should not be reached")
return reflect.Value{}, fmt.Errorf("this portion of code should not be reached")
}
31 changes: 20 additions & 11 deletions ast/KnowledgeBase.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"bytes"
"fmt"
"github.com/google/uuid"
"github.com/sirupsen/logrus"
"io"
"sort"
"strings"
Expand Down Expand Up @@ -84,7 +83,6 @@ func (lib *KnowledgeLibrary) LoadKnowledgeBaseFromReader(reader io.Reader, overw
if r := recover(); r != nil {
retKb = nil
retErr = fmt.Errorf("panic recovered during LoadKnowledgeBaseFromReader, recover \"%v\". send us your report to https://github.com/hyperjumptech/grule-rule-engine/issues", r)
logrus.Panicf("panic recovered during LoadKnowledgeBaseFromReader, recover \"%v\". send us your report to https://github.com/hyperjumptech/grule-rule-engine/issues", r)
}
}()

Expand All @@ -94,7 +92,10 @@ func (lib *KnowledgeLibrary) LoadKnowledgeBaseFromReader(reader io.Reader, overw

return nil, err
}
knowledgeBase := catalog.BuildKnowledgeBase()
knowledgeBase, err := catalog.BuildKnowledgeBase()
if err != nil {
return nil, err
}
if overwrite {
lib.Library[fmt.Sprintf("%s:%s", knowledgeBase.Name, knowledgeBase.Version)] = knowledgeBase

Expand Down Expand Up @@ -127,21 +128,25 @@ func (lib *KnowledgeLibrary) StoreKnowledgeBaseToWriter(writer io.Writer, name,

// NewKnowledgeBaseInstance will create a new instance based on KnowledgeBase blue print
// identified by its name and version
func (lib *KnowledgeLibrary) NewKnowledgeBaseInstance(name, version string) *KnowledgeBase {
func (lib *KnowledgeLibrary) NewKnowledgeBaseInstance(name, version string) (*KnowledgeBase, error) {
knowledgeBase, ok := lib.Library[fmt.Sprintf("%s:%s", name, version)]
if ok {
newClone := knowledgeBase.Clone(pkg.NewCloneTable())
newClone, err := knowledgeBase.Clone(pkg.NewCloneTable())
if err != nil {
return nil, err
}
if knowledgeBase.IsIdentical(newClone) {
AstLog.Debugf("Successfully create instance [%s:%s]", newClone.Name, newClone.Version)

return newClone
return newClone, nil
}
AstLog.Fatalf("ORIGIN : %s", knowledgeBase.GetSnapshot())
AstLog.Fatalf("CLONE : %s", newClone.GetSnapshot())
panic("The clone is not identical")

return nil, fmt.Errorf("the clone is not identical")
}

return nil
return nil, fmt.Errorf("specified knowledge base name and version not exist")
}

// KnowledgeBase is a collection of RuleEntries. It has a name and version.
Expand Down Expand Up @@ -210,7 +215,7 @@ func (e *KnowledgeBase) GetSnapshot() string {
}

// Clone will clone this instance of KnowledgeBase and produce another (structure wise) identical instance.
func (e *KnowledgeBase) Clone(cloneTable *pkg.CloneTable) *KnowledgeBase {
func (e *KnowledgeBase) Clone(cloneTable *pkg.CloneTable) (*KnowledgeBase, error) {
clone := &KnowledgeBase{
Name: e.Name,
Version: e.Version,
Expand All @@ -228,10 +233,14 @@ func (e *KnowledgeBase) Clone(cloneTable *pkg.CloneTable) *KnowledgeBase {
}
}
if e.WorkingMemory != nil {
clone.WorkingMemory = e.WorkingMemory.Clone(cloneTable)
wm, err := e.WorkingMemory.Clone(cloneTable)
if err != nil {
return nil, err
}
clone.WorkingMemory = wm
}

return clone
return clone, nil
}

// AddRuleEntry add ruleentry into this knowledge base.
Expand Down
3 changes: 2 additions & 1 deletion ast/RuleEntry.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,8 @@ func (e *RuleEntry) Evaluate(ctx context.Context, dataContext IDataContext, memo
}
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("Error while evaluating rule %s, panic recovered", e.RuleName)
err = fmt.Errorf("error while evaluating rule %s, panic recovered", e.RuleName)
can = false
}
}()
if e.Retracted {
Expand Down
8 changes: 4 additions & 4 deletions ast/Serializer.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ type Catalog struct {
// BuildKnowledgeBase will rebuild a knowledgebase from this Catalog.
// the rebuilt KnowledgeBase is identical to the original KnowledgeBase from
// which this Catalog was built.
func (cat *Catalog) BuildKnowledgeBase() *KnowledgeBase {
func (cat *Catalog) BuildKnowledgeBase() (*KnowledgeBase, error) {
workingMem := &WorkingMemory{
Name: cat.MemoryName,
Version: cat.MemoryVersion,
Expand Down Expand Up @@ -280,7 +280,7 @@ func (cat *Catalog) BuildKnowledgeBase() *KnowledgeBase {
}
importTable[amet.AstID] = n
default:
panic("Unrecognized meta type")
return nil, fmt.Errorf("unrecognized meta type")
}
}

Expand Down Expand Up @@ -407,7 +407,7 @@ func (cat *Catalog) BuildKnowledgeBase() *KnowledgeBase {
whenScope.Expression = importTable[amet.ExpressionID].(*Expression)
}
default:
panic("Unrecognized meta type")
return nil, fmt.Errorf("unknown AST type")
}
}

Expand Down Expand Up @@ -450,7 +450,7 @@ func (cat *Catalog) BuildKnowledgeBase() *KnowledgeBase {
}
}

return knowledgeBase
return knowledgeBase, nil
}

// Equals used for testing purpose, to ensure that two catalog
Expand Down
20 changes: 10 additions & 10 deletions ast/WorkingMemory.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ func (workingMem *WorkingMemory) Equals(that *WorkingMemory) bool {
}

// Clone will clone this WorkingMemory. The new clone will have an identical structure
func (workingMem *WorkingMemory) Clone(cloneTable *pkg.CloneTable) *WorkingMemory {
func (workingMem *WorkingMemory) Clone(cloneTable *pkg.CloneTable) (*WorkingMemory, error) {
AstLog.Debugf("Cloning working memory %s:%s", workingMem.Name, workingMem.Version)
clone := NewWorkingMemory(workingMem.Name, workingMem.Version)

Expand All @@ -154,7 +154,7 @@ func (workingMem *WorkingMemory) Clone(cloneTable *pkg.CloneTable) *WorkingMemor
clone.expressionSnapshotMap[k] = cloneTable.Records[expr.AstID].CloneInstance.(*Expression)
} else {

panic(fmt.Sprintf("expression %s is not on the clone table - %s", expr.GrlText, expr.GetSnapshot()))
return nil, fmt.Errorf("expression %s is not on the clone table - %s", expr.GrlText, expr.GetSnapshot())
}
}
}
Expand All @@ -166,7 +166,7 @@ func (workingMem *WorkingMemory) Clone(cloneTable *pkg.CloneTable) *WorkingMemor
clone.expressionAtomSnapshotMap[k] = cloneTable.Records[exprAtm.AstID].CloneInstance.(*ExpressionAtom)
} else {

panic(fmt.Sprintf("expression atom %s is not on the clone table. ASTID %s", exprAtm.GrlText, exprAtm.AstID))
return nil, fmt.Errorf("expression atom %s is not on the clone table. ASTID %s", exprAtm.GrlText, exprAtm.AstID)
}
}
}
Expand All @@ -178,7 +178,7 @@ func (workingMem *WorkingMemory) Clone(cloneTable *pkg.CloneTable) *WorkingMemor
clone.variableSnapshotMap[key] = cloneTable.Records[variable.AstID].CloneInstance.(*Variable)
} else {

panic(fmt.Sprintf("variable %s is not on the clone table", variable.GrlText))
return nil, fmt.Errorf("variable %s is not on the clone table", variable.GrlText)
}
}
}
Expand All @@ -194,12 +194,12 @@ func (workingMem *WorkingMemory) Clone(cloneTable *pkg.CloneTable) *WorkingMemor
clone.expressionVariableMap[clonedVari][k2] = cloneTable.Records[expr.AstID].CloneInstance.(*Expression)
} else {

panic(fmt.Sprintf("expression %s is not on the clone table", expr.GrlText))
return nil, fmt.Errorf("expression %s is not on the clone table", expr.GrlText)
}
}
} else {

panic(fmt.Sprintf("variable %s is not on the clone table", key.GrlText))
return nil, fmt.Errorf("variable %s is not on the clone table", key.GrlText)
}
}
}
Expand All @@ -215,23 +215,23 @@ func (workingMem *WorkingMemory) Clone(cloneTable *pkg.CloneTable) *WorkingMemor
clone.expressionAtomVariableMap[clonedVari][k2] = cloneTable.Records[expr.AstID].CloneInstance.(*ExpressionAtom)
} else {

panic(fmt.Sprintf("expression atom %s is not on the clone table", expr.GrlText))
return nil, fmt.Errorf("expression atom %s is not on the clone table", expr.GrlText)
}
}
} else {

panic(fmt.Sprintf("variable %s is not on the clone table", key.GrlText))
return nil, fmt.Errorf("variable %s is not on the clone table", key.GrlText)
}
}
}

if workingMem.Equals(clone) {
clone.DebugContent()

return clone
return clone, nil
}

panic("Clone not equals the origin.")
return nil, fmt.Errorf("clone not equals the origin")
}

// IndexVariables will index all expression and expression atoms that contains a speciffic variable name
Expand Down
2 changes: 0 additions & 2 deletions examples/Issue328_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,11 @@ func TestMethodCall_SliceOOR(t *testing.T) {
err = rb.BuildRuleFromResource("Test", "0.1.1", pkg.NewBytesResource([]byte(SliceOORRule)))
assert.NoError(t, err)

// expect no panic and no error (ReturnErrOnFailedRuleEvaluation = false)
eng1 := &engine.GruleEngine{MaxCycle: 5}
kb := lib.NewKnowledgeBaseInstance("Test", "0.1.1")
err = eng1.Execute(dataContext, kb)
assert.NoError(t, err)

// expect no panic and execute to return an error here
eng1 = &engine.GruleEngine{MaxCycle: 5, ReturnErrOnFailedRuleEvaluation: true}
kb = lib.NewKnowledgeBaseInstance("Test", "0.1.1")
err = eng1.Execute(dataContext, kb)
Expand Down
Loading
Loading