Last active
May 17, 2025 16:24
-
-
Save torniker/c2dfa3e4aa3fc3331e8679437e4ee7a1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
func Start(name string, handler http.Handler, port string) { | |
if port == "" { | |
panic("port not provided") | |
} | |
srv := http.Server{ | |
Addr: ":" + port, | |
Handler: handler, | |
} | |
log.Printf("Listening on :%s", port) | |
go func() { | |
start(srv.ListenAndServe, name) | |
log.Println("Stopped serving new connections.") | |
}() | |
sigChan := make(chan os.Signal, 1) | |
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) | |
<-sigChan | |
shutdownCtx, shutdownRelease := context.WithTimeout(context.Background(), 30*time.Second) | |
defer shutdownRelease() | |
if err := srv.Shutdown(shutdownCtx); err != nil { | |
log.Fatalf("HTTP shutdown error: %v", err) | |
} | |
log.Println("Graceful shutdown complete.") | |
} | |
// Start web server | |
func start(start Starter, name string) { | |
var err error | |
basePath, err = os.Getwd() | |
if err != nil { | |
if err := start(); err != nil { | |
log.Printf("shutting down, error: %s\n", err) | |
} | |
return | |
} | |
binPath = fmt.Sprintf("%s/bin/%s", basePath, name) | |
binFilename = filepath.Base(binPath) | |
mainGoPath = fmt.Sprintf("%s/cmd/%s", basePath, binFilename) | |
if os.Getenv("ENV") == "local" { | |
autorestart.WatchFilename = binPath | |
restart := autorestart.GetNotifier() | |
go func() { | |
<-restart | |
fmt.Println("\033[36mI will restart shortly\033[00m") | |
spin.Stop() | |
}() | |
if fileExists(autorestart.WatchFilename) { | |
autorestart.StartWatcher() | |
go watch() | |
} else { | |
fmt.Println("watcher did not start") | |
} | |
} | |
if err := start(); err != nil { | |
log.Printf("shutting down the server, error: %s\n", err) | |
} | |
} | |
func fileExists(filename string) bool { | |
info, err := os.Stat(filename) | |
if os.IsNotExist(err) { | |
return false | |
} | |
return !info.IsDir() | |
} | |
func rebuild() { | |
cmd := exec.Command("go", "build", "-o", binPath, mainGoPath) | |
cmd.Stdout = os.Stdout | |
cmd.Stderr = os.Stderr | |
err := cmd.Run() | |
if err != nil { | |
log.Fatal(err) | |
} | |
} | |
// Watch file changes and restart server | |
func watch() { | |
watcher, err := fsnotify.NewWatcher() | |
if err != nil { | |
log.Fatal(err) | |
} | |
defer watcher.Close() | |
done := make(chan bool) | |
go func() { | |
for { | |
select { | |
case event, ok := <-watcher.Events: | |
if !ok { | |
return | |
} | |
if event.Op&fsnotify.Write == fsnotify.Write { | |
if filepath.Ext(event.Name) == ".go" { | |
spin.Color("blue") | |
spin.Suffix = "\033[33m Building... \033[00m" | |
spin.Start() | |
rebuild() | |
} | |
} | |
case err, ok := <-watcher.Errors: | |
if !ok { | |
return | |
} | |
log.Fatal(err) | |
} | |
} | |
}() | |
err = filepath.Walk(basePath, | |
func(path string, info os.FileInfo, err error) error { | |
if err != nil { | |
return err | |
} | |
if !info.IsDir() && filepath.Ext(info.Name()) == ".go" { | |
err = watcher.Add(filepath.Dir(path)) | |
if err != nil { | |
log.Fatal(err) | |
} | |
} | |
return nil | |
}, | |
) | |
if err != nil { | |
log.Fatal(err) | |
} | |
<-done | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment