How do you gracefully exit a go uber fx app

Viewed 878

How do you stop an uber fx as in shutdown the entire program. There seems to be no other way other than ctrl+c

func main() {
    fx.New(
        fx.Invoke(register)
    ).Run
}


func register() {
    time.Sleep(5*time.Seconds)
    // shutdown somehow
}
2 Answers

The docs are not particularly clear, but there's a Shutdowner interface available to any Fx module with a Shutdown method that requests graceful application shutdown.

Here's a modified part of the example package that will have it simply shutdown upon receiving a request:

func NewHandler(logger *log.Logger, shutdowner fx.Shutdowner) (http.Handler, error) {
    logger.Print("Executing NewHandler.")
    return http.HandlerFunc(func(http.ResponseWriter, *http.Request) {
        logger.Print("Got a request. Requesting shutdown now that I've gotten one request.")
        shutdowner.Shutdown()
    }), nil
}

Edit: Here's how you could modify your solution:

func register(shutdowner fx.Shutdowner) {
    time.Sleep(5*time.Seconds)
    shutdowner.Shutdown()
}

You can wrap it inside a go routine and use context to gracefully exit.

 import (
    "context"
    "log"
    " go.uber.org/fx"
)


func main() {
    f := fx.New(fx.Invoke(register))

    go func() {
        f.Run()
    }()

    stopCh := make(chan os.Signal)
    signal.Notify(stopCh, syscall.SIGINT, syscall.SIGTERM)
    <-stopCh

    if err := f.Stop(context.Background()); err != nil {
        log.Printf("error stopping gracefully")
    }
}


func register() {
    time.Sleep(5*time.Seconds)
    // shutdown somehow
}
Related