Add first cut at a pool
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
@@ -10,43 +11,45 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func runExpress(changes <-chan FileChange) {
|
||||
var currentProcess *exec.Cmd
|
||||
func runExpress(changes <-chan FileChange, numProcesses int, basePort int, pool *WorkerPool) {
|
||||
var currentProcesses []*exec.Cmd
|
||||
var mu sync.Mutex
|
||||
|
||||
// Helper to start the express process
|
||||
startExpress := func() *exec.Cmd {
|
||||
cmd := exec.Command("../express/run.sh")
|
||||
// Helper to start an express process on a specific port
|
||||
startExpress := func(port int) *exec.Cmd {
|
||||
listenAddr := fmt.Sprintf("127.0.0.1:%d", port)
|
||||
cmd := exec.Command("../express/run.sh", "--listen", listenAddr)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
log.Printf("[express] Failed to start: %v", err)
|
||||
log.Printf("[express:%d] Failed to start: %v", port, err)
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Printf("[express] Started (pid %d)", cmd.Process.Pid)
|
||||
log.Printf("[express:%d] Started (pid %d)", port, cmd.Process.Pid)
|
||||
|
||||
// Monitor the process in background
|
||||
go func() {
|
||||
go func(p int) {
|
||||
err := cmd.Wait()
|
||||
if err != nil {
|
||||
log.Printf("[express] Process exited: %v", err)
|
||||
log.Printf("[express:%d] Process exited: %v", p, err)
|
||||
} else {
|
||||
log.Printf("[express] Process exited normally")
|
||||
log.Printf("[express:%d] Process exited normally", p)
|
||||
}
|
||||
}()
|
||||
}(port)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Helper to stop the express process
|
||||
// Helper to stop an express process
|
||||
stopExpress := func(cmd *exec.Cmd) {
|
||||
if cmd == nil || cmd.Process == nil {
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("[express] Stopping (pid %d)", cmd.Process.Pid)
|
||||
pid := cmd.Process.Pid
|
||||
log.Printf("[express] Stopping (pid %d)", pid)
|
||||
cmd.Process.Signal(syscall.SIGTERM)
|
||||
|
||||
// Wait briefly for graceful shutdown
|
||||
@@ -58,13 +61,38 @@ func runExpress(changes <-chan FileChange) {
|
||||
|
||||
select {
|
||||
case <-done:
|
||||
log.Printf("[express] Stopped gracefully")
|
||||
log.Printf("[express] Stopped gracefully (pid %d)", pid)
|
||||
case <-time.After(5 * time.Second):
|
||||
log.Printf("[express] Force killing")
|
||||
log.Printf("[express] Force killing (pid %d)", pid)
|
||||
cmd.Process.Kill()
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to stop all express processes
|
||||
stopAllExpress := func(processes []*exec.Cmd) {
|
||||
for _, cmd := range processes {
|
||||
stopExpress(cmd)
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to start all express processes and update the worker pool
|
||||
startAllExpress := func() []*exec.Cmd {
|
||||
processes := make([]*exec.Cmd, 0, numProcesses)
|
||||
addresses := make([]string, 0, numProcesses)
|
||||
for i := 0; i < numProcesses; i++ {
|
||||
port := basePort + i
|
||||
addr := fmt.Sprintf("127.0.0.1:%d", port)
|
||||
cmd := startExpress(port)
|
||||
if cmd != nil {
|
||||
processes = append(processes, cmd)
|
||||
addresses = append(addresses, addr)
|
||||
}
|
||||
}
|
||||
// Update the worker pool with new worker addresses
|
||||
pool.SetWorkers(addresses)
|
||||
return processes
|
||||
}
|
||||
|
||||
// Helper to run the build
|
||||
runBuild := func() bool {
|
||||
log.Printf("[build] Starting ncc build...")
|
||||
@@ -97,6 +125,14 @@ func runExpress(changes <-chan FileChange) {
|
||||
var debounceTimer *time.Timer
|
||||
const debounceDelay = 100 * time.Millisecond
|
||||
|
||||
// Initial build and start
|
||||
log.Printf("[master] Initial build...")
|
||||
if runBuild() {
|
||||
currentProcesses = startAllExpress()
|
||||
} else {
|
||||
log.Printf("[master] Initial build failed")
|
||||
}
|
||||
|
||||
for change := range changes {
|
||||
log.Printf("[watch] %s: %s", change.Operation, change.Path)
|
||||
|
||||
@@ -107,18 +143,18 @@ func runExpress(changes <-chan FileChange) {
|
||||
|
||||
debounceTimer = time.AfterFunc(debounceDelay, func() {
|
||||
if !runBuild() {
|
||||
log.Printf("[master] Build failed, keeping current process")
|
||||
log.Printf("[master] Build failed, keeping current processes")
|
||||
return
|
||||
}
|
||||
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
|
||||
// Stop old process
|
||||
stopExpress(currentProcess)
|
||||
// Stop all old processes
|
||||
stopAllExpress(currentProcesses)
|
||||
|
||||
// Start new process
|
||||
currentProcess = startExpress()
|
||||
// Start all new processes
|
||||
currentProcesses = startAllExpress()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user