forked from stellar/go
/
init.go
72 lines (59 loc) · 1.45 KB
/
init.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
package horizon
import (
"github.com/stellar/go/services/horizon/internal/log"
)
// InitFn is a function that contributes to the initialization of an App struct
type InitFn func(*App)
type initializer struct {
Name string
Fn InitFn
Deps []string
}
type initializerSet []initializer
var appInit initializerSet
// Add adds a new initializer into the chain
func (is *initializerSet) Add(name string, fn InitFn, deps ...string) {
*is = append(*is, initializer{
Name: name,
Fn: fn,
Deps: deps,
})
}
// Run initializes the provided application, but running every Initializer
func (is *initializerSet) Run(app *App) {
init := *is
alreadyRun := make(map[string]bool)
for {
ranInitializer := false
for _, i := range init {
runnable := true
// if we've already been run, skip
if _, ok := alreadyRun[i.Name]; ok {
runnable = false
}
// if any of our dependencies haven't been run, skip
for _, d := range i.Deps {
if _, ok := alreadyRun[d]; !ok {
runnable = false
break
}
}
if !runnable {
continue
}
log.WithField("init_name", i.Name).Debug("running initializer")
i.Fn(app)
alreadyRun[i.Name] = true
ranInitializer = true
}
// If, after a full loop through the initializers we ran nothing
// we are done
if !ranInitializer {
break
}
}
// if we didn't get to run all initializers, we have a cycle
if len(alreadyRun) != len(init) {
log.Panic("initializer cycle detected")
}
}