func (fn engine) ServeHTTP(w http.ResponseWriter, req *http.Request) { if shutdown.Lock() { if err := fn(w, req); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) } shutdown.Unlock() return } w.WriteHeader(http.StatusServiceUnavailable) }
func main() { // Make shutdown catch Ctrl+c and system terminate shutdown.OnSignal(0, os.Interrupt, syscall.SIGTERM) logStream = make(chan string, 100) // start a logger receiver go logger() // Start a webserver http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { if shutdown.Lock() { logStream <- req.URL.String() + "\n" shutdown.Unlock() } else { log.Println("Already shutting down") } }) log.Fatal(http.ListenAndServe(":8080", nil)) }
func main() { // Make shutdown catch Ctrl+c and system terminate shutdown.OnSignal(0, os.Interrupt, syscall.SIGTERM) // Create a log file var logFile *os.File logFile, _ = os.Create("log.txt") // When shutdown is initiated, close the file shutdown.FirstFunc(closeFile, logFile) // Start a webserver http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { // Get a lock, and write to the file if we get it. // While we have the lock the file will not be closed. if shutdown.Lock() { _, _ = logFile.WriteString(req.URL.String() + "\n") shutdown.Unlock() } }) log.Fatal(http.ListenAndServe(":8080", nil)) }
// SaveDroplets will save all Doplets in the current // inventory to a specified file. // If the file exists it will be overwritten. func (i *Inventory) SaveDroplets(file string) error { // We do not want to get interrupted while saving the inventory if shutdown.Lock() { defer shutdown.Unlock() } else { return fmt.Errorf("Unable to save inventory - server is shutting down.") } // Put into object drops := Droplets{} for _, be := range i.backends { drop, ok := be.(*dropletBackend) if ok { drops.Droplets = append(drops.Droplets, drop.Droplet) } } // Marshall the inventory. b, err := toml.Marshal(drops) if err != nil { return err } // Finally create the file and write f, err := os.Create(file) if err != nil { return err } defer f.Close() _, err = f.Write(b) if err != nil { return err } return nil }
// A Sample Webserver func HelloServer(w http.ResponseWriter, req *http.Request) { // Tracks all running requests if shutdown.Lock() { defer shutdown.Unlock() } else { // Shutdown has started, return that the service is unavailable w.WriteHeader(http.StatusServiceUnavailable) w.Write([]byte("Server is now shutting down")) return } if req.FormValue("shutdown") != "" { request <- "shutdown" log.Println("Requesting server shutdown") // We start the exit in a separate go-routine, otherwise this request will have // to wait for shutdown to be completed. go shutdown.Exit(0) } else { // Add artificial delay time.Sleep(time.Second * 5) request <- "greet" } io.WriteString(w, <-reply) }