go: handle host+port combinations,shutdown better
* add log messages telling the user what went wrong if the app fails to start * improve existing log messages * cleanup: close channels when exiting * cleanup: stop listening for signals when exiting
This commit is contained in:
parent
a053103000
commit
9ab2d0ae0b
@ -45,7 +45,8 @@ let _ =
|
||||
|
||||
let Config =
|
||||
-- | define configuration schema.
|
||||
{ Port : Natural
|
||||
{ Host : Text
|
||||
, Port : Natural
|
||||
, AppName : Text
|
||||
, LiveMode : Bool
|
||||
, DevelMode : Bool
|
||||
@ -58,7 +59,8 @@ let defconf
|
||||
-- | TODO: have this reside on the Internet and import it similar to how
|
||||
-- | the Dhall Prelude is imported.
|
||||
: Config
|
||||
= { Port = 3000
|
||||
= { Host = ""
|
||||
, Port = 3000
|
||||
, AppName = "pcmt"
|
||||
, LiveMode = False
|
||||
, DevelMode = False
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Host string
|
||||
Port int
|
||||
AppName string
|
||||
LiveMode bool
|
||||
|
3
main.go
3
main.go
@ -10,8 +10,7 @@ func main() {
|
||||
err := run()
|
||||
if err != nil {
|
||||
l := slog.New(slog.NewJSONHandler(os.Stderr))
|
||||
// log.Fatalln(err)
|
||||
l.Error("error running app:", err)
|
||||
l.Error("unrecoverable failure, stopping the app", "error", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
58
run.go
58
run.go
@ -7,6 +7,7 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
@ -49,7 +50,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.`
|
||||
)
|
||||
|
||||
var (
|
||||
addr = flag.String("addr", ":3000", "TCP address:port to listen at")
|
||||
host = flag.String("host", "unset", "host address to listen on")
|
||||
port = flag.Int("port", 0, "TCP port to listen on")
|
||||
configFlag = flag.String("config", "config.dhall", "Default path of the config file")
|
||||
devel = flag.Bool("devel", false, "Run the application in dev mode, connect to a local browser-sync instance for hot-reloading")
|
||||
license = flag.Bool("license", false, "Print licensing information and exit")
|
||||
@ -129,11 +131,52 @@ func run() error {
|
||||
// }
|
||||
|
||||
e := a.E()
|
||||
go func() {
|
||||
if err = e.Start(*addr); err != nil && err != http.ErrServerClosed {
|
||||
log.Info("shutting down the server")
|
||||
|
||||
// channel used to check whether the app had troubles starting up.
|
||||
started := make(chan error, 1)
|
||||
|
||||
defer close(started)
|
||||
|
||||
go func(ok chan error) {
|
||||
p := conf.Port
|
||||
h := conf.Host
|
||||
|
||||
if flagPort := *port; flagPort != 0 && flagPort > 0 && flagPort < 65536 {
|
||||
p = flagPort
|
||||
}
|
||||
}()
|
||||
|
||||
if flagHost := *host; flagHost != "unset" {
|
||||
h = flagHost
|
||||
}
|
||||
|
||||
address := h + ":" + strconv.Itoa(p)
|
||||
|
||||
if err = e.Start(address); err != nil && err != http.ErrServerClosed {
|
||||
log.Error("troubles running the server, bailing", "error", err.Error())
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
|
||||
defer func() {
|
||||
cancel()
|
||||
started <- err
|
||||
}()
|
||||
|
||||
log.Info("shutting down the server")
|
||||
|
||||
if err := e.Shutdown(ctx); err != nil {
|
||||
log.Info("error shutting down", "error", err)
|
||||
started <- err
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
started <- err
|
||||
}(started)
|
||||
|
||||
err = <-started
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
quit := make(chan os.Signal, 1)
|
||||
|
||||
@ -148,6 +191,11 @@ func run() error {
|
||||
defer func() {
|
||||
log.Infof("Interrupt received, gracefully shutting down the server (timeout %s)", shutdownTimeout)
|
||||
cancel()
|
||||
|
||||
signal.Stop(quit)
|
||||
|
||||
close(quit)
|
||||
|
||||
log.Info("Bye!")
|
||||
}()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user