Skip to content

Commit 0165901

Browse files
committed
run BackgroundStruct as a long-lived background process
1 parent 20b56cc commit 0165901

4 files changed

Lines changed: 30 additions & 2 deletions

File tree

engine/config.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,12 @@ func readGitIgnore(path string) []string {
237237
}
238238

239239
func (e *Engine) generateProcess() {
240+
// A configured background command is started once at startup, survives
241+
// reloads, and is killed on shutdown — regardless of any Type set on it.
242+
if bg := e.Config.BackgroundStruct; bg.Cmd != "" {
243+
_ = e.ProcessManager.AddProcess(bg.Cmd, string(process.Background), bg.ChangeDir)
244+
}
240245
for _, ex := range e.Config.ExecStruct {
241-
e.ProcessManager.AddProcess(ex.Cmd, string(ex.Type), ex.ChangeDir)
246+
_ = e.ProcessManager.AddProcess(ex.Cmd, string(ex.Type), ex.ChangeDir)
242247
}
243248
}

engine/config_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,21 @@ func TestVerifyExecuteRequiresAtLeastOne(t *testing.T) {
7979
}
8080
}
8181

82+
func TestBackgroundStructBecomesProcess(t *testing.T) {
83+
eng, err := NewEngineFromConfig(Config{
84+
RootPath: ".",
85+
BackgroundStruct: process.Execute{Cmd: "echo bg"},
86+
ExecStruct: []process.Execute{{Cmd: "./app", Type: process.Primary}},
87+
})
88+
if err != nil {
89+
t.Fatal(err)
90+
}
91+
// The background command is registered ahead of the configured executes.
92+
if got := eng.ProcessManager.GetExecutes(); len(got) != 2 || got[0] != "echo bg" || got[1] != "./app" {
93+
t.Errorf("executes = %v, want [echo bg, ./app]", got)
94+
}
95+
}
96+
8297
func TestNormalizeExecutesPrefersStruct(t *testing.T) {
8398
e := &Engine{Config: Config{
8499
RootPath: ".",

examples/kitchen-sink/main.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ func buildConfig(root string) engine.Config {
3030
RootPath: root,
3131
LogLevel: "info",
3232
Debounce: 300,
33+
// A standalone background service: started once, survives reloads, and is
34+
// killed only on shutdown (e.g. `npm run dev`).
35+
BackgroundStruct: engine.Execute{
36+
Cmd: "mkdir -p artifacts && echo up >> artifacts/bgstruct.log && sleep 3600",
37+
},
3338
Ignore: engine.Ignore{
3439
WatchedExten: []string{"*.go"}, // only react to Go changes
3540
Dir: []string{".git", "artifacts"}, // never react to our own output

examples/kitchen-sink/main_test.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ func TestKitchenSinkIntegration(t *testing.T) {
103103
if !waitFor(func() bool { return lines(art("primary.log")) == 1 }) {
104104
t.Fatalf("primary did not start (primary.log = %d lines)", lines(art("primary.log")))
105105
}
106-
for _, f := range []string{"once.log", "background.log", "blocking.log"} {
106+
for _, f := range []string{"once.log", "background.log", "bgstruct.log", "blocking.log"} {
107107
if !waitFor(func() bool { return lines(art(f)) >= 1 }) {
108108
t.Fatalf("%s was not written on startup", f)
109109
}
@@ -161,6 +161,9 @@ func TestKitchenSinkIntegration(t *testing.T) {
161161
if got := lines(art("background.log")); got != 1 {
162162
t.Errorf("background execute restarted (%d lines), want 1 (it should survive reloads)", got)
163163
}
164+
if got := lines(art("bgstruct.log")); got != 1 {
165+
t.Errorf("BackgroundStruct restarted (%d lines), want 1 (it should run once and survive reloads)", got)
166+
}
164167
}
165168

166169
func mustMkdir(t *testing.T, path string) {

0 commit comments

Comments
 (0)