package service import ( "context" "database/sql" httpsrv "go.unistack.org/micro-server-http/v4" "go.unistack.org/micro/v4" "go.unistack.org/micro/v4/config" microcfg "go.unistack.org/micro/v4/config" "go.unistack.org/micro/v4/logger" "go.unistack.org/micro/v4/options" "go.unistack.org/micro/v4/register" "go.unistack.org/micro/v4/server" intcfg "go.unistack.org/unistack-org/pkgdash/config" "go.unistack.org/unistack-org/pkgdash/handler" pb "go.unistack.org/unistack-org/pkgdash/proto" "go.unistack.org/unistack-org/pkgdash/service/client_git" "go.unistack.org/unistack-org/pkgdash/storage" "net/url" "strings" ) func NewService(ctx context.Context) (micro.Service, error) { var reg register.Register cfg := intcfg.NewConfig() cs := microcfg.NewConfig(config.Struct(cfg)) // TODO mgsrv := httpsrv.NewServer( options.Register(reg), ) svc := micro.NewService( micro.Config(cs), ) h := handler.NewHandler(svc, client_git.NewClient(5)) if err := svc.Init( micro.AfterStart(func(_ context.Context) error { return h.Init(svc.Options().Context) }), micro.BeforeStart(func(ctx context.Context) error { if err := config.Load(ctx, []config.Config{cs}, config.LoadOverride(true)); err != nil { return err } if err := config.Validate(ctx, cfg); err != nil { return err } if err := svc.Init( micro.Name(intcfg.ServiceName), micro.Version(intcfg.ServiceVersion), ); err != nil { return err } if err := svc.Server("http").Init( options.Address(cfg.Address), options.Name(cfg.App.Name), server.Version(cfg.App.Version), ); err != nil { return err } return nil }), micro.BeforeStart(func(_ context.Context) error { log := logger.NewLogger( logger.WithLevel(logger.ParseLevel(cfg.LogLevel)), logger.WithCallerSkipCount(3), ) return svc.Init(micro.Logger(log)) }), micro.BeforeStart(func(ctx context.Context) error { var connstr string if v, ok := cfg.StorageDSN[cfg.App.Name]; ok { connstr = v } else if v, ok = cfg.StorageDSN["all"]; ok { connstr = v } scheme, dsn, err := storageOptions(connstr) if err != nil { return err } conn, err := connectDataBase(scheme, dsn) if err != nil { return err } store, err := storage.NewStorage(scheme, conn) if err != nil { return err } ctx = storage.InContext(ctx, store) return svc.Init(micro.Context(ctx)) }), ); err != nil { return nil, err } if err := pb.RegisterPkgdashServiceServer(mgsrv, h); err != nil { logger.Fatalf(ctx, "failed to register handler: %v", err) } return svc, nil } func storageOptions(dsn string) (string, string, error) { u, err := url.Parse(dsn) if err != nil { return "", "", err } scheme := u.Scheme if idx := strings.Index(u.Scheme, "+"); idx > 0 { scheme = u.Scheme[:idx] u.Scheme = u.Scheme[idx+1:] } return scheme, u.String(), nil } func connectDataBase(driverName, dsn string) (*sql.DB, error) { conn, err := sql.Open(driverName, dsn) if err != nil { return nil, err } if err = conn.Ping(); err != nil { return nil, err } return conn, err }