Files
sablier/pkg/sabliercmd/start.go
Alexis Couvreur 0f4a3a2e93 refactor: add sabliercmd pkg (#727)
This will enable doc generation
2025-11-13 20:18:57 -05:00

115 lines
2.7 KiB
Go

package sabliercmd
import (
"context"
"fmt"
"log/slog"
"os/signal"
"syscall"
"time"
"github.com/sablierapp/sablier/internal/api"
"github.com/sablierapp/sablier/internal/server"
"github.com/sablierapp/sablier/pkg/config"
"github.com/sablierapp/sablier/pkg/sablier"
"github.com/sablierapp/sablier/pkg/store/inmemory"
"github.com/sablierapp/sablier/pkg/version"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var newStartCommand = func() *cobra.Command {
return &cobra.Command{
Use: "start",
Short: "Start the Sablier server",
Run: func(cmd *cobra.Command, args []string) {
err := viper.Unmarshal(&conf)
if err != nil {
panic(err)
}
err = Start(cmd.Context(), conf)
if err != nil {
panic(err)
}
},
}
}
// Start starts the Sablier server
func Start(ctx context.Context, conf config.Config) error {
// Create context that listens for the interrupt signal from the OS.
ctx, stop := signal.NotifyContext(ctx, syscall.SIGINT, syscall.SIGTERM)
defer stop()
logger := setupLogger(conf.Logging)
logger.Info("running Sablier version " + version.Info())
provider, err := setupProvider(ctx, logger, conf.Provider)
if err != nil {
return fmt.Errorf("cannot setup provider: %w", err)
}
store := inmemory.NewInMemory()
err = store.OnExpire(ctx, sablier.OnInstanceExpired(ctx, provider, logger))
if err != nil {
return err
}
s := sablier.New(logger, store, provider)
s.BlockingRefreshFrequency = conf.Strategy.Blocking.DefaultRefreshFrequency
groups, err := provider.InstanceGroups(ctx)
if err != nil {
logger.WarnContext(ctx, "initial group scan failed", slog.Any("reason", err))
} else {
s.SetGroups(groups)
}
go s.GroupWatch(ctx)
instanceStopped := make(chan string)
go provider.NotifyInstanceStopped(ctx, instanceStopped)
go func() {
for stopped := range instanceStopped {
err := s.RemoveInstance(ctx, stopped)
if err != nil {
logger.Warn("could not remove instance", slog.Any("error", err))
}
}
}()
if conf.Provider.AutoStopOnStartup {
err := s.StopAllUnregisteredInstances(ctx)
if err != nil {
logger.ErrorContext(ctx, "unable to stop unregistered instances", slog.Any("reason", err))
}
}
t, err := setupTheme(ctx, conf, logger)
if err != nil {
return fmt.Errorf("cannot setup theme: %w", err)
}
strategy := &api.ServeStrategy{
Theme: t,
Sablier: s,
StrategyConfig: conf.Strategy,
SessionsConfig: conf.Sessions,
}
go server.Start(ctx, logger, conf.Server, strategy)
// Listen for the interrupt signal.
<-ctx.Done()
stop()
logger.InfoContext(ctx, "shutting down gracefully, press Ctrl+C again to force")
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel()
logger.InfoContext(ctx, "Server exiting")
return nil
}