-
Notifications
You must be signed in to change notification settings - Fork 3
/
cmd.go
124 lines (97 loc) · 2.78 KB
/
cmd.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package cmd
import (
"context"
"github.com/alexfalkowski/go-service/errors"
"github.com/alexfalkowski/go-service/os"
"github.com/alexfalkowski/go-service/time"
"github.com/spf13/cobra"
"go.uber.org/dig"
"go.uber.org/fx"
)
// Command for application.
type Command struct {
root *cobra.Command
}
// New command.
func New(version string) *Command {
name := os.ExecutableName()
root := &cobra.Command{
Use: name,
Short: name,
Long: name,
SilenceUsage: true,
Version: version,
}
root.SetErrPrefix(name + ":")
root.PersistentFlags().StringVarP(&inputFlag, "input", "i", "env:CONFIG_FILE", "input config location (format kind:location, default env:CONFIG_FILE)")
return &Command{root: root}
}
// AddServer to the command.
func (c *Command) AddServer(opts ...fx.Option) *cobra.Command {
return c.AddServerCommand("server", "Start the server.", opts...)
}
// AddClient to the command.
func (c *Command) AddClient(opts ...fx.Option) *cobra.Command {
return c.AddClientCommand("client", "Start the client.", opts...)
}
// AddServerCommand to root.
func (c *Command) AddServerCommand(name, description string, opts ...fx.Option) *cobra.Command {
cmd := &cobra.Command{
Use: name,
Short: description,
Long: description,
SilenceUsage: true,
RunE: func(c *cobra.Command, _ []string) error {
return RunServer(c.Context(), opts...)
},
}
c.root.AddCommand(cmd)
return cmd
}
// AddClientCommand to root.
func (c *Command) AddClientCommand(name, description string, opts ...fx.Option) *cobra.Command {
cmd := &cobra.Command{
Use: name,
Short: description,
Long: description,
SilenceUsage: true,
RunE: func(c *cobra.Command, _ []string) error {
return RunClient(c.Context(), opts...)
},
}
c.root.AddCommand(cmd)
return cmd
}
// Run the command with a an arg.
func (c *Command) RunWithArgs(args []string) error {
c.root.SetArgs(args)
return c.root.Execute()
}
// Run the command.
func (c *Command) Run() error {
return c.root.Execute()
}
// RunServer with args and a timeout.
func RunServer(ctx context.Context, opts ...fx.Option) error {
app := fx.New(options(opts)...)
done := app.Done()
if err := app.Start(ctx); err != nil {
return prefix("server", err)
}
<-done
return prefix("server", app.Stop(ctx))
}
// RunClient with args and a timeout.
func RunClient(ctx context.Context, opts ...fx.Option) error {
app := fx.New(options(opts)...)
if err := app.Start(ctx); err != nil {
return prefix("client", err)
}
return prefix("client", app.Stop(ctx))
}
func options(opts []fx.Option) []fx.Option {
return append(opts, fx.StartTimeout(time.Timeout), fx.StopTimeout(time.Timeout), fx.NopLogger)
}
func prefix(p string, err error) error {
return errors.Prefix(p, dig.RootCause(err))
}