Skip to content

Commit a2b40b7

Browse files
Adds a blocking flag to the init command and fixes a bug in the boot algorithm #31
1 parent dc1da72 commit a2b40b7

File tree

6 files changed

+118
-84
lines changed

6 files changed

+118
-84
lines changed

cli/cmd/init/init.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ import (
1111

1212
var (
1313
appsConfigOnly bool
14+
blocking bool
15+
arg1 string
16+
arg2 string
1417
)
1518

1619
var Cmd = &cobra.Command{
@@ -24,16 +27,19 @@ var Cmd = &cobra.Command{
2427

2528
func init() {
2629
Cmd.Flags().BoolVarP(&appsConfigOnly, "apps-config-only", "c", false, "only initialize processes specified in the Apps Config file")
30+
Cmd.Flags().BoolVarP(&blocking, "blocking", "b", false, "return a response only after all processes have been queued")
2731
}
2832

2933
func Initialize() {
3034
base.OpenSender()
3135
defer base.CloseSender()
32-
arg1 := ""
3336
if appsConfigOnly {
3437
arg1 = "apps-config-only"
3538
}
36-
sent := base.SendCmd("init", arg1)
39+
if blocking {
40+
arg2 = "blocking"
41+
}
42+
sent := base.SendCmdArg2("init", arg1, arg2)
3743
newCmdResp := base.GetResponse(sent)
3844
if len(newCmdResp.GetError()) > 0 {
3945
cli.Log.Fatalf(newCmdResp.GetError())

conf/appsconfig.go

+13-7
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,18 @@ type AppsConfigApp struct {
1616
Flags model.ExecFlags
1717
}
1818

19-
func ComputeDepGraph(apps []AppsConfigApp) (nonDependentApps []AppsConfigApp, dependentApps []AppsConfigApp, err error) {
19+
func ComputeDepGraph(apps []AppsConfigApp) (*[]AppsConfigApp, *[]AppsConfigApp, error) {
2020

2121
if len(apps) > 0 {
2222
g := depgraph.New()
23-
nonDependentApps = make([]AppsConfigApp, 0)
23+
nonDependentApps := make([]AppsConfigApp, 0)
2424
depAppNames := make(map[string]AppsConfigApp)
2525
nonDepAppNames := make(map[string]AppsConfigApp)
2626
for _, app := range apps {
2727
if len(app.Flags.Dependencies) > 0 {
2828
depAppNames[app.Flags.Name] = app
2929
for _, dep := range app.Flags.Dependencies {
30-
err = g.DependOn(app.Flags.Name, dep)
30+
err := g.DependOn(app.Flags.Name, dep)
3131
if err != nil {
3232
logrus.Errorf("encountered error building app dependency tree: %s", err)
3333
return nil, nil, err
@@ -40,7 +40,7 @@ func ComputeDepGraph(apps []AppsConfigApp) (nonDependentApps []AppsConfigApp, de
4040

4141
if len(g.Leaves()) > 0 {
4242

43-
dependentApps = make([]AppsConfigApp, 0)
43+
dependentApps := make([]AppsConfigApp, 0)
4444

4545
topoSortedLayers := g.TopoSortedLayers()
4646
for _, appNames := range topoSortedLayers {
@@ -60,18 +60,24 @@ func ComputeDepGraph(apps []AppsConfigApp) (nonDependentApps []AppsConfigApp, de
6060
nonDependentApps = append(nonDependentApps, nonDepAppNames[appName])
6161
}
6262

63-
return nonDependentApps, dependentApps, nil
63+
return &nonDependentApps, &dependentApps, nil
6464
} else {
6565

66-
return apps, nil, nil
66+
return &apps, nil, nil
6767
}
6868

6969
}
7070

7171
return nil, nil, nil
7272
}
7373

74-
func AppNames(appMap []AppsConfigApp) []string {
74+
func AppNames(appMapPtr *[]AppsConfigApp) []string {
75+
76+
if appMapPtr == nil {
77+
return []string{}
78+
}
79+
80+
appMap := *appMapPtr
7581

7682
if len(appMap) == 0 {
7783
return []string{}

pmond/controller/dgraph.go

+8-20
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"pmon3/pmond/db"
88
"pmon3/pmond/model"
99
"pmon3/pmond/protos"
10-
"slices"
1110
"strings"
1211
)
1312

@@ -36,31 +35,20 @@ func Dgraph(cmd *protos.Cmd) *protos.CmdResp {
3635
var qPs []model.Process
3736
qNm := map[string]bool{}
3837

39-
dbProcessNames := model.ProcessNames(&all)
40-
4138
for _, appConfigApp := range pmond.Config.AppsConfig.Apps {
42-
4339
processName := appConfigApp.Flags.Name
44-
45-
if slices.Contains(dbProcessNames, processName) {
46-
p := model.FromFileAndExecFlags(appConfigApp.File, &appConfigApp.Flags, "", nil)
47-
qPs = append(qPs, *p)
48-
pmond.Log.Infof("overwrite with conf: pushing to stack %s", processName)
49-
qNm[processName] = true
50-
} else {
51-
dbPs, _ := model.GetProcessByName(processName, &all)
52-
if dbPs != nil {
53-
qPs = append(qPs, *dbPs)
54-
qNm[processName] = true
55-
pmond.Log.Infof("append from db: pushing to stack %s", processName)
56-
}
57-
}
40+
p := model.FromFileAndExecFlags(appConfigApp.File, &appConfigApp.Flags, "", nil)
41+
qPs = append(qPs, *p)
42+
qNm[processName] = true
5843
}
5944

6045
for _, dbPs := range all {
61-
if !qNm[dbPs.Name] {
46+
processName := dbPs.Name
47+
if !qNm[processName] {
6248
qPs = append(qPs, dbPs)
63-
pmond.Log.Infof("append reamainder from db: pushing to stack %s", dbPs.Name)
49+
pmond.Log.Infof("append reamainder from db: pushing to stack %s", processName)
50+
} else {
51+
pmond.Log.Infof("overwritten with apps conf %s", processName)
6452
}
6553
}
6654

pmond/controller/init.go

+86-53
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"pmon3/pmond/model"
99
"pmon3/pmond/process"
1010
"pmon3/pmond/protos"
11-
"slices"
1211
"strings"
1312
"time"
1413
)
@@ -20,96 +19,130 @@ func Initialize(cmd *protos.Cmd) *protos.CmdResp {
2019
Name: cmd.GetName(),
2120
}
2221

22+
blocking := cmd.GetArg2() == "blocking"
23+
24+
var err error
25+
2326
if cmd.GetArg1() == "apps-config-only" {
24-
startedFromConfig := StartsAppsFromConfig()
25-
if !startedFromConfig {
26-
newCmdResp.Error = "no applications were started"
27-
}
28-
return &newCmdResp
27+
err = StartsAppsFromConfig(blocking)
2928
} else {
30-
if err := StartApps(); err != nil {
31-
newCmdResp.Error = err.Error()
32-
}
33-
34-
return &newCmdResp
29+
err = StartAppsFromBoth(blocking)
30+
}
31+
if err != nil {
32+
newCmdResp.Error = err.Error()
3533
}
34+
35+
return &newCmdResp
3636
}
3737

38-
func StartsAppsFromConfig() bool {
38+
func StartsAppsFromConfig(blocking bool) error {
3939

4040
if pmond.Config.AppsConfig == nil || len(pmond.Config.AppsConfig.Apps) == 0 {
41-
return false
41+
return nil
4242
}
4343

4444
nonDependentApps, dependentApps, err := conf.ComputeDepGraph(pmond.Config.AppsConfig.Apps)
4545
if err != nil {
46-
return false
46+
return err
4747
}
4848

49-
for _, app := range dependentApps {
50-
err := EnqueueProcess(app.File, &app.Flags)
51-
time.Sleep(pmond.Config.GetDependentProcessEnqueuedWait())
52-
if err != nil {
53-
pmond.Log.Errorf("encountered error attempting to enqueue process: %s", err)
54-
}
49+
if blocking {
50+
err = appConfAppEnqueueUsingDepGraphResults(nonDependentApps, dependentApps)
51+
} else {
52+
go appConfAppEnqueueUsingDepGraphResults(nonDependentApps, dependentApps)
5553
}
5654

57-
for _, app := range nonDependentApps {
58-
err := EnqueueProcess(app.File, &app.Flags)
59-
if err != nil {
60-
pmond.Log.Errorf("encountered error attempting to enqueue process: %s", err)
61-
}
55+
return err
56+
}
57+
58+
func StartAppsFromBoth(blocking bool) error {
59+
nonDependentApps, dependentApps, err := getQueueableFromBoth()
60+
if err != nil {
61+
return err
6262
}
6363

64-
return true
64+
if blocking {
65+
err = processEnqueueUsingDepGraphResults(nonDependentApps, dependentApps)
66+
} else {
67+
go processEnqueueUsingDepGraphResults(nonDependentApps, dependentApps)
68+
}
69+
70+
return err
6571
}
6672

67-
func StartApps() error {
73+
func getQueueableFromBoth() (*[]model.Process, *[]model.Process, error) {
6874
var all []model.Process
6975
err := db.Db().Find(&all).Error
7076
if err != nil {
71-
return err
77+
return nil, nil, err
7278
}
7379

7480
var qPs []model.Process
7581
qNm := map[string]bool{}
7682

77-
dbProcessNames := model.ProcessNames(&all)
78-
7983
for _, appConfigApp := range pmond.Config.AppsConfig.Apps {
80-
8184
processName := appConfigApp.Flags.Name
82-
83-
if slices.Contains(dbProcessNames, processName) {
84-
appLog, _ := getAppsConfigAppLogPath(&appConfigApp)
85-
appUser, _ := getAppsConfigAppUser(&appConfigApp)
86-
p := model.FromFileAndExecFlags(appConfigApp.File, &appConfigApp.Flags, appLog, appUser)
87-
qPs = append(qPs, *p)
88-
pmond.Log.Infof("overwrite with conf: pushing to stack %s", processName)
89-
qNm[processName] = true
90-
} else {
91-
dbPs, _ := model.GetProcessByName(processName, &all)
92-
if dbPs != nil {
93-
qPs = append(qPs, *dbPs)
94-
qNm[processName] = true
95-
pmond.Log.Infof("append from db: pushing to stack %s", processName)
96-
}
97-
}
85+
appLog, _ := getAppsConfigAppLogPath(&appConfigApp)
86+
appUser, _ := getAppsConfigAppUser(&appConfigApp)
87+
p := model.FromFileAndExecFlags(appConfigApp.File, &appConfigApp.Flags, appLog, appUser)
88+
qPs = append(qPs, *p)
89+
qNm[processName] = true
9890
}
9991

10092
for _, dbPs := range all {
101-
if !qNm[dbPs.Name] {
93+
processName := dbPs.Name
94+
if !qNm[processName] {
10295
qPs = append(qPs, dbPs)
103-
pmond.Log.Infof("append reamainder from db: pushing to stack %s", dbPs.Name)
96+
pmond.Log.Infof("append reamainder from db: pushing to stack %s", processName)
97+
} else {
98+
pmond.Log.Infof("overwritten with apps conf: %s", processName)
10499
}
105100
}
106101

107102
nonDependentApps, dependentApps, err := model.ComputeDepGraph(&qPs)
108103
if err != nil {
109104
pmond.Log.Errorf("encountered error attempting to prioritize databse processes from dep graph: %s", err)
110-
return err
105+
return nil, nil, err
106+
}
107+
108+
return nonDependentApps, dependentApps, nil
109+
}
110+
111+
func appConfAppEnqueueUsingDepGraphResults(nonDependentApps *[]conf.AppsConfigApp, dependentApps *[]conf.AppsConfigApp) error {
112+
113+
var retErr error
114+
115+
if dependentApps != nil {
116+
for _, app := range *dependentApps {
117+
pmond.Log.Infof("launch dependent %s", strings.Join(conf.AppNames(dependentApps), " "))
118+
err := EnqueueProcess(app.File, &app.Flags)
119+
time.Sleep(pmond.Config.GetDependentProcessEnqueuedWait())
120+
if err != nil {
121+
pmond.Log.Errorf("encountered error attempting to enqueue process: %s", err)
122+
retErr = err
123+
}
124+
}
111125
}
112126

127+
if nonDependentApps != nil {
128+
pmond.Log.Infof("launch independent %s", strings.Join(conf.AppNames(nonDependentApps), " "))
129+
130+
for _, app := range *nonDependentApps {
131+
err := EnqueueProcess(app.File, &app.Flags)
132+
if err != nil {
133+
pmond.Log.Errorf("encountered error attempting to enqueue process: %s", err)
134+
retErr = err
135+
}
136+
}
137+
}
138+
139+
return retErr
140+
}
141+
142+
func processEnqueueUsingDepGraphResults(nonDependentApps *[]model.Process, dependentApps *[]model.Process) error {
143+
144+
var retErr error
145+
113146
if dependentApps != nil {
114147
pmond.Log.Infof("launch dependent %s", strings.Join(model.ProcessNames(dependentApps), " "))
115148

@@ -119,7 +152,7 @@ func StartApps() error {
119152
time.Sleep(pmond.Config.GetDependentProcessEnqueuedWait())
120153
if err != nil {
121154
pmond.Log.Errorf("encountered error attempting to enqueue process: %s", err)
122-
return err
155+
retErr = err
123156
}
124157
}
125158
}
@@ -132,12 +165,12 @@ func StartApps() error {
132165
err := process.Enqueue(&app, true)
133166
if err != nil {
134167
pmond.Log.Errorf("encountered error attempting to enqueue process: %s", err)
135-
return err
168+
retErr = err
136169
}
137170
}
138171
}
139172

140-
return nil
173+
return retErr
141174
}
142175

143176
func getAppsConfigAppLogPath(app *conf.AppsConfigApp) (string, error) {

pmond/db/db.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package db
22

33
import (
4+
"errors"
45
"os"
56
"pmon3/conf"
67
"pmon3/pmond"
@@ -42,7 +43,7 @@ func Db() *gorm.DB {
4243
var pmondModel model.Pmond
4344
err = initDb.First(&pmondModel).Error
4445
if err != nil {
45-
if err == gorm.ErrRecordNotFound { // first version
46+
if errors.Is(err, gorm.ErrRecordNotFound) { // first version
4647
initDb.Create(&model.Pmond{Version: conf.Version})
4748
}
4849
}

pmond/god/god.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func runMonitor(uninterrupted *bool) {
6464

6565
go processRequests(uninterrupted, pmond.Log)
6666

67-
controller.StartApps()
67+
controller.StartAppsFromBoth(true)
6868

6969
isInitializing := true
7070

0 commit comments

Comments
 (0)