Print a startup or shutdown error once, without fx's event log (closes #359)
check / check (push) Canceled after 0s
check / check (push) Canceled after 0s
pixad builds its fx app with fx.NopLogger and runs start, wait and stop itself, so that it can print a start or stop error to stderr once. dig.RootCause strips the frames fx and dig wrap around the error, which leaves the line that names the setting. The exit status is as before. Model: opus-5-5
This commit is contained in:
1 parent
8aaf6dc794
commit
f416e73611
2 files changed
+43
-3
No files matched your search
@@ -17,6 +17,7 @@ require (
|
|||||||
github.com/prometheus/client_golang v1.23.2
|
github.com/prometheus/client_golang v1.23.2
|
||||||
github.com/slok/go-http-metrics v0.13.0
|
github.com/slok/go-http-metrics v0.13.0
|
||||||
github.com/spf13/cobra v1.10.2
|
github.com/spf13/cobra v1.10.2
|
||||||
|
go.uber.org/dig v1.19.0
|
||||||
go.uber.org/fx v1.24.0
|
go.uber.org/fx v1.24.0
|
||||||
golang.org/x/crypto v0.41.0
|
golang.org/x/crypto v0.41.0
|
||||||
golang.org/x/sync v0.19.0
|
golang.org/x/sync v0.19.0
|
||||||
@@ -126,7 +127,6 @@ require (
|
|||||||
go.opentelemetry.io/otel v1.36.0 // indirect
|
go.opentelemetry.io/otel v1.36.0 // indirect
|
||||||
go.opentelemetry.io/otel/metric v1.36.0 // indirect
|
go.opentelemetry.io/otel/metric v1.36.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.36.0 // indirect
|
go.opentelemetry.io/otel/trace v1.36.0 // indirect
|
||||||
go.uber.org/dig v1.19.0 // indirect
|
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.uber.org/zap v1.27.0 // indirect
|
go.uber.org/zap v1.27.0 // indirect
|
||||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||||
|
|||||||
+42
-2
@@ -2,6 +2,7 @@
|
|||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
@@ -9,6 +10,7 @@ import (
|
|||||||
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"go.uber.org/dig"
|
||||||
"go.uber.org/fx"
|
"go.uber.org/fx"
|
||||||
"sneak.berlin/go/pixa/internal/config"
|
"sneak.berlin/go/pixa/internal/config"
|
||||||
"sneak.berlin/go/pixa/internal/database"
|
"sneak.berlin/go/pixa/internal/database"
|
||||||
@@ -53,7 +55,10 @@ func run(_ *cobra.Command, _ []string) {
|
|||||||
// A write to a closed stdout or stderr must not end the process.
|
// A write to a closed stdout or stderr must not end the process.
|
||||||
signal.Ignore(syscall.SIGPIPE)
|
signal.Ignore(syscall.SIGPIPE)
|
||||||
|
|
||||||
fx.New(
|
app := fx.New(
|
||||||
|
// pixad logs with slog only; runApp prints a startup or shutdown
|
||||||
|
// error itself.
|
||||||
|
fx.NopLogger,
|
||||||
fx.Provide(
|
fx.Provide(
|
||||||
config.New,
|
config.New,
|
||||||
database.New,
|
database.New,
|
||||||
@@ -71,5 +76,40 @@ func run(_ *cobra.Command, _ []string) {
|
|||||||
func(log *logger.Logger) { log.Identify() },
|
func(log *logger.Logger) { log.Identify() },
|
||||||
func(*server.Server) {},
|
func(*server.Server) {},
|
||||||
),
|
),
|
||||||
).Run()
|
)
|
||||||
|
|
||||||
|
exitCode := runApp(app)
|
||||||
|
if exitCode != 0 {
|
||||||
|
os.Exit(exitCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// runApp starts app, waits for a signal or a shutdown request, stops app,
|
||||||
|
// and returns the status pixad exits with, as fx.App.Run does. It prints
|
||||||
|
// a start or stop error to stderr, once, as the error that caused it:
|
||||||
|
// dig.RootCause drops the frames fx and dig wrap around it.
|
||||||
|
func runApp(app *fx.App) int {
|
||||||
|
startCtx, cancelStart := context.WithTimeout(context.Background(), app.StartTimeout())
|
||||||
|
defer cancelStart()
|
||||||
|
|
||||||
|
err := app.Start(startCtx)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, dig.RootCause(err))
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
shutdown := <-app.Wait()
|
||||||
|
|
||||||
|
stopCtx, cancelStop := context.WithTimeout(context.Background(), app.StopTimeout())
|
||||||
|
defer cancelStop()
|
||||||
|
|
||||||
|
err = app.Stop(stopCtx)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, dig.RootCause(err))
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return shutdown.ExitCode
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user