github.com/lauslim12/expert-systems@v0.0.0-20221115131159-018513aad29c/cmd/expert-systems/main.go (about)

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"log"
     7  	"net/http"
     8  	"os"
     9  	"os/signal"
    10  	"syscall"
    11  	"time"
    12  
    13  	"github.com/lauslim12/expert-systems/internal/application"
    14  )
    15  
    16  // Constant for the web frontend location.
    17  const pathToWebDirectory = "./web/build"
    18  
    19  // Get port from environment variable. If it does not exist, use '8080'.
    20  func getPort() string {
    21  	port := os.Getenv("PORT")
    22  	if port == "" {
    23  		return ":8080"
    24  	}
    25  
    26  	return fmt.Sprintf(":%s", port)
    27  }
    28  
    29  // Get application mode from environment variable 'GO_ENV'. If it does not exist, use 'development'.
    30  func getMode() string {
    31  	mode := os.Getenv("GO_ENV")
    32  	if mode != "production" {
    33  		return "development"
    34  	}
    35  
    36  	return "production"
    37  }
    38  
    39  // Starting point, initialize server.
    40  func main() {
    41  	// HTTP server initialization.
    42  	server := &http.Server{Addr: getPort(), Handler: application.Configure(pathToWebDirectory, getMode())}
    43  
    44  	// Prepare context for graceful shutdown.
    45  	serverCtx, serverStopCtx := context.WithCancel(context.Background())
    46  
    47  	// Listen for syscall signals for process to interrupt or quit.
    48  	sig := make(chan os.Signal, 1)
    49  	signal.Notify(sig, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
    50  	go func() {
    51  		<-sig
    52  
    53  		// Shutdown signal with grace period of 30 seconds.
    54  		shutdownCtx, shutdownCtxCancel := context.WithTimeout(serverCtx, 30*time.Second)
    55  		defer shutdownCtxCancel()
    56  		log.Println("Server starting to shutdown in 30 seconds...")
    57  
    58  		go func() {
    59  			<-shutdownCtx.Done()
    60  			if shutdownCtx.Err() == context.DeadlineExceeded {
    61  				log.Fatal("Graceful shutdown timeout, forcing exit.")
    62  			}
    63  		}()
    64  
    65  		// Trigger graceful shutdown here.
    66  		server.SetKeepAlivesEnabled(false)
    67  		if err := server.Shutdown(shutdownCtx); err != nil {
    68  			log.Fatalf("Could not gracefully shutdown the server: %v\n", err)
    69  		}
    70  		serverStopCtx()
    71  	}()
    72  
    73  	// Run our server and print out starting message.
    74  	log.Printf("Server has started on port %s with environment %s!", getPort(), getMode())
    75  	err := server.ListenAndServe()
    76  	if err != nil && err != http.ErrServerClosed {
    77  		log.Fatal(err)
    78  	}
    79  
    80  	// Wait for server context to be stopped.
    81  	<-serverCtx.Done()
    82  	log.Println("Server shut down successfully!")
    83  }