mnet: use ListenerOpts pattern

This commit is contained in:
Brian Picciano 2019-03-01 14:06:25 -05:00
parent 4536db8968
commit 14de888300
3 changed files with 39 additions and 13 deletions

View File

@ -38,7 +38,7 @@ func WithListeningServer(ctx context.Context, h http.Handler) (context.Context,
} }
var listener *mnet.Listener var listener *mnet.Listener
srv.ctx, listener = mnet.WithListener(srv.ctx, "tcp", "") srv.ctx, listener = mnet.WithListener(srv.ctx)
listener.NoCloseOnStop = true // http.Server.Shutdown will do this listener.NoCloseOnStop = true // http.Server.Shutdown will do this
srv.ctx = mrun.WithStartHook(srv.ctx, func(context.Context) error { srv.ctx = mrun.WithStartHook(srv.ctx, func(context.Context) error {

View File

@ -23,18 +23,41 @@ type Listener struct {
NoCloseOnStop bool NoCloseOnStop bool
} }
type listenerOpts struct {
proto string
defaultAddr string
}
// ListenerOpt is a value which adjusts the behavior of WithListener.
type ListenerOpt func(*listenerOpts)
// ListenerProtocol adjusts the protocol which the Listener uses. The default is
// "tcp".
func ListenerProtocol(proto string) ListenerOpt {
return func(opts *listenerOpts) {
opts.proto = proto
}
}
// ListenerDefaultAddr adjusts the defaultAddr which the Listener will use. The
// addr will still be configurable via mcfg regardless of what this is set to.
// The default is ":0".
func ListenerAddr(defaultAddr string) ListenerOpt {
return func(opts *listenerOpts) {
opts.defaultAddr = defaultAddr
}
}
// WithListener returns a Listener which will be initialized when the start // WithListener returns a Listener which will be initialized when the start
// event is triggered on the returned Context (see mrun.Start), and closed when // event is triggered on the returned Context (see mrun.Start), and closed when
// the stop event is triggered on the returned Context (see mrun.Stop). // the stop event is triggered on the returned Context (see mrun.Stop).
// func WithListener(ctx context.Context, opts ...ListenerOpt) (context.Context, *Listener) {
// network defaults to "tcp" if empty. defaultAddr defaults to ":0" if empty, lOpts := listenerOpts{
// and will be configurable via mcfg. proto: "tcp",
func WithListener(ctx context.Context, network, defaultAddr string) (context.Context, *Listener) { defaultAddr: ":0",
if network == "" {
network = "tcp"
} }
if defaultAddr == "" { for _, opt := range opts {
defaultAddr = ":0" opt(&lOpts)
} }
l := &Listener{ l := &Listener{
@ -42,13 +65,16 @@ func WithListener(ctx context.Context, network, defaultAddr string) (context.Con
} }
var addr *string var addr *string
l.ctx, addr = mcfg.WithString(l.ctx, "listen-addr", defaultAddr, strings.ToUpper(network)+" address to listen on in format [host]:port. If port is 0 then a random one will be chosen") l.ctx, addr = mcfg.WithString(l.ctx, "listen-addr", lOpts.defaultAddr, strings.ToUpper(lOpts.proto)+" address to listen on in format [host]:port. If port is 0 then a random one will be chosen")
l.ctx = mrun.WithStartHook(l.ctx, func(context.Context) error { l.ctx = mrun.WithStartHook(l.ctx, func(context.Context) error {
var err error var err error
if l.Listener, err = net.Listen(network, *addr); err != nil { if l.Listener, err = net.Listen(lOpts.proto, *addr); err != nil {
return err return err
} }
l.ctx = mctx.Annotate(l.ctx, "addr", l.Addr().String()) l.ctx = mctx.Annotate(l.ctx,
"proto", lOpts.proto,
"addr", l.Addr().String())
mlog.Info("listening", l.ctx) mlog.Info("listening", l.ctx)
return nil return nil
}) })

View File

@ -37,7 +37,7 @@ func TestIsReservedIP(t *T) {
func TestWithListener(t *T) { func TestWithListener(t *T) {
ctx := mtest.Context() ctx := mtest.Context()
ctx, l := WithListener(ctx, "", "") ctx, l := WithListener(ctx)
mtest.Run(ctx, t, func() { mtest.Run(ctx, t, func() {
go func() { go func() {
conn, err := net.Dial("tcp", l.Addr().String()) conn, err := net.Dial("tcp", l.Addr().String())