forked from nyaruka/goflow
-
Notifications
You must be signed in to change notification settings - Fork 0
/
random_once.go
77 lines (65 loc) · 1.96 KB
/
random_once.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package routers
import (
"fmt"
"math/rand"
"time"
"github.com/nyaruka/goflow/flows"
"github.com/nyaruka/goflow/utils"
)
// TypeRandomOnce is the constant for our random once router
const TypeRandomOnce string = "random_once"
// RandomOnceRouter exits of our exits once (randomly) before taking exit
type RandomOnceRouter struct {
Exit flows.ExitUUID `json:"exit" validate:"required"`
BaseRouter
}
// Type returns the type of our router
func (r *RandomOnceRouter) Type() string { return TypeRandomOnce }
// Validate validates the parameters on this router
func (r *RandomOnceRouter) Validate(exits []flows.Exit) error {
err := utils.ValidateAll(r)
if err != nil {
// check that our exit is valid
found := false
for _, e := range exits {
if r.Exit == e.UUID() {
found = true
break
}
}
if !found {
err = fmt.Errorf("Invalid exit uuid: '%s'", r.Exit)
}
}
return err
}
// PickRoute will attempt to take a random exit it hasn't taken before. If all exits have been taken, then it will
// take the exit specified in it's Exit parameter
func (r *RandomOnceRouter) PickRoute(run flows.FlowRun, exits []flows.Exit, step flows.Step) (flows.Route, error) {
if len(exits) == 0 {
return flows.NoRoute, nil
}
// find all the exits we have taken
exited := make(map[flows.ExitUUID]bool)
for _, s := range run.Path() {
if s.NodeUUID() == step.NodeUUID() {
exited[s.ExitUUID()] = true
}
}
// build up a list of the valid exits
var validExits []flows.ExitUUID
for i := range exits {
// this isn't our default exit and we haven't used it yet
if exits[i].UUID() != r.Exit && !exited[exits[i].UUID()] {
validExits = append(validExits, exits[i].UUID())
}
}
// no valid choices? exit!
if len(validExits) == 0 {
return flows.NewRoute(r.Exit, "0"), nil
}
// ok, now pick one randomly
random := rand.New(rand.NewSource(time.Now().UnixNano()))
exitN := random.Intn(len(validExits))
return flows.NewRoute(validExits[exitN], string(exitN)), nil
}