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

Multiple task handler match sort by weight #63

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
44 changes: 41 additions & 3 deletions pkg/bpmn_engine/task_handler.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package bpmn_engine

import "github.com/nitram509/lib-bpmn-engine/pkg/spec/BPMN20"
import (
"sort"

"github.com/nitram509/lib-bpmn-engine/pkg/spec/BPMN20"
)

type taskMatcher func(element *BPMN20.TaskElement) bool

Expand All @@ -17,12 +21,29 @@ type taskHandler struct {
handlerType taskHandlerType
matches taskMatcher
handler func(job ActivatedJob)
weight int32
}

type taskHandlers []*taskHandler

func (s taskHandlers) Len() int {
return len(s)
}

func (s taskHandlers) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}

// sort by weight des
func (s taskHandlers) Less(i, j int) bool {
return s[i].weight > s[j].weight
}

type newTaskHandlerCommand struct {
handlerType taskHandlerType
matcher taskMatcher
append func(handler *taskHandler)
weight int32
}

type NewTaskHandlerCommand2 interface {
Expand All @@ -48,6 +69,9 @@ type NewTaskHandlerCommand1 interface {
// For the handler you can specify one or more groups.
// If at least one matches a given user task, the handler will be called.
CandidateGroups(groups ...string) NewTaskHandlerCommand2

// Set taskHandler weight
Weight(weight int32) NewTaskHandlerCommand1
}

// NewTaskHandler registers a handler function to be called for service tasks with a given taskId
Expand All @@ -56,6 +80,7 @@ func (state *BpmnEngineState) NewTaskHandler() NewTaskHandlerCommand1 {
append: func(handler *taskHandler) {
state.taskHandlers = append(state.taskHandlers, handler)
},
weight: 1,
}
return cmd
}
Expand All @@ -69,6 +94,11 @@ func (thc newTaskHandlerCommand) Id(id string) NewTaskHandlerCommand2 {
return thc
}

func (thc newTaskHandlerCommand) Weight(weight int32) NewTaskHandlerCommand1 {
thc.weight = weight
return thc
}

// Type implements NewTaskHandlerCommand1
func (thc newTaskHandlerCommand) Type(taskType string) NewTaskHandlerCommand2 {
thc.matcher = func(element *BPMN20.TaskElement) bool {
Expand All @@ -84,6 +114,7 @@ func (thc newTaskHandlerCommand) Handler(f func(job ActivatedJob)) {
handlerType: thc.handlerType,
matches: thc.matcher,
handler: f,
weight: thc.weight,
}
thc.append(&th)
}
Expand Down Expand Up @@ -113,6 +144,7 @@ func (thc newTaskHandlerCommand) CandidateGroups(groups ...string) NewTaskHandle

func (state *BpmnEngineState) findTaskHandler(element *BPMN20.TaskElement) func(job ActivatedJob) {
searchOrder := []taskHandlerType{taskHandlerForId}
var handlers taskHandlers
if (*element).GetType() == BPMN20.ServiceTask {
searchOrder = append(searchOrder, taskHandlerForType)
}
Expand All @@ -123,10 +155,16 @@ func (state *BpmnEngineState) findTaskHandler(element *BPMN20.TaskElement) func(
for _, handler := range state.taskHandlers {
if handler.handlerType == handlerType {
if handler.matches(element) {
return handler.handler
handlers = append(handlers, handler)
}
}
}
}
return nil
// sort by weight
sort.Sort(handlers)
if len(handlers) > 0 {
return handlers[0].handler
} else {
return nil
}
}
36 changes: 36 additions & 0 deletions pkg/bpmn_engine/task_handler_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package bpmn_engine

import (
"testing"

"github.com/corbym/gocrest/is"
"github.com/corbym/gocrest/then"
)

func TestMultipleTaskHanler(t *testing.T) {
// setup
bpmnEngine := New("name")
cp := CallPath{}

// given
process, _ := bpmnEngine.LoadFromFile("../../test-cases/exclusive-gateway-with-condition.bpmn")
bpmnEngine.NewTaskHandler().Id("task-a").Handler(cp.CallPathHandler)
bpmnEngine.NewTaskHandler().Weight(10).Id("task-b").Handler(func(job ActivatedJob) {
if len(cp.CallPath) > 0 {
cp.CallPath += ","
}
cp.CallPath += job.GetElementId()
cp.CallPath += "10"
job.Complete()
})
bpmnEngine.NewTaskHandler().Id("task-b").Handler(cp.CallPathHandler)
variables := map[string]interface{}{
"price": -50,
}

// when
bpmnEngine.CreateAndRunInstance(process.ProcessKey, variables)

// then
then.AssertThat(t, cp.CallPath, is.EqualTo("task-b10"))
}