constructor: Add doc strings

This commit is contained in:
Łukasz Magiera 2019-07-04 22:06:02 +02:00
parent de604065fb
commit e78c378021
2 changed files with 46 additions and 22 deletions

View File

@ -9,6 +9,7 @@ import (
"github.com/libp2p/go-libp2p-core/peerstore" "github.com/libp2p/go-libp2p-core/peerstore"
"github.com/libp2p/go-libp2p-core/routing" "github.com/libp2p/go-libp2p-core/routing"
record "github.com/libp2p/go-libp2p-record" record "github.com/libp2p/go-libp2p-record"
"reflect"
"time" "time"
ci "github.com/libp2p/go-libp2p-core/crypto" ci "github.com/libp2p/go-libp2p-core/crypto"
@ -27,6 +28,7 @@ import (
// can't really be identified by the returned type // can't really be identified by the returned type
type special struct{ id int } type special struct{ id int }
// nolint
var ( var (
DefaultTransportsKey = special{0} // Libp2p option DefaultTransportsKey = special{0} // Libp2p option
PNetKey = special{1} // Option + multiret PNetKey = special{1} // Option + multiret
@ -38,19 +40,26 @@ var (
BaseRoutingKey = special{7} // fx groups + multiret BaseRoutingKey = special{7} // fx groups + multiret
NatPortMapKey = special{8} // Libp2p option NatPortMapKey = special{8} // Libp2p option
ConnectionManagerKey = special{9} // Libp2p option ConnectionManagerKey = special{9} // Libp2p option
) )
type invoke int type invoke int
const ( const (
// PstoreAddSelfKeysKey is a key for Override for PstoreAddSelfKeys
PstoreAddSelfKeysKey = invoke(iota) PstoreAddSelfKeysKey = invoke(iota)
// StartListeningKey is a key for Override for StartListening
StartListeningKey StartListeningKey
_nInvokes // keep this last _nInvokes // keep this last
) )
type settings struct { type settings struct {
// modules is a map of constructors for DI
//
// In most cases the index will be a reflect. Type of element returned by
// the constructor, but for some 'constructors' it's hard to specify what's
// the return type should be (or the constructor returns fx group)
modules map[interface{}]fx.Option modules map[interface{}]fx.Option
// invokes are separate from modules as they can't be referenced by return // invokes are separate from modules as they can't be referenced by return
@ -61,6 +70,26 @@ type settings struct {
config bool // Config option applied config bool // Config option applied
} }
// Override option changes constructor for a given type
func Override(typ, constructor interface{}) Option {
return func(s *settings) error {
if i, ok := typ.(invoke); ok {
s.invokes[i] = fx.Invoke(constructor)
return nil
}
if c, ok := typ.(special); ok {
s.modules[c] = fx.Provide(constructor)
return nil
}
ctor := as(constructor, typ)
rt := reflect.TypeOf(typ).Elem()
s.modules[rt] = fx.Provide(ctor)
return nil
}
}
var defConf = config.Default() var defConf = config.Default()
var defaults = []Option{ var defaults = []Option{
@ -72,8 +101,11 @@ var defaults = []Option{
Override(new(record.Validator), modules.RecordValidator), Override(new(record.Validator), modules.RecordValidator),
} }
// Online sets up basic libp2p node
func Online() Option { func Online() Option {
return Options( return Options(
// make sure that online is applied before Config.
// This is important because Config overrides some of Online units
func(s *settings) error { s.online = true; return nil }, func(s *settings) error { s.online = true; return nil },
applyIf(func(s *settings) bool { return s.config }, applyIf(func(s *settings) bool { return s.config },
Error(errors.New("the Online option must be set before Config option")), Error(errors.New("the Online option must be set before Config option")),
@ -105,6 +137,7 @@ func Online() Option {
) )
} }
// Config sets up constructors based on the provided config
func Config(cfg *config.Root) Option { func Config(cfg *config.Root) Option {
return Options( return Options(
func(s *settings) error { s.config = true; return nil }, func(s *settings) error { s.config = true; return nil },
@ -123,16 +156,18 @@ func New(ctx context.Context, opts ...Option) (api.API, error) {
invokes: make([]fx.Option, _nInvokes), invokes: make([]fx.Option, _nInvokes),
} }
// apply module options in the right order
if err := Options(Options(defaults...), Options(opts...))(&settings); err != nil { if err := Options(Options(defaults...), Options(opts...))(&settings); err != nil {
return nil, err return nil, err
} }
// gather constructors for fx.Options
ctors := make([]fx.Option, 0, len(settings.modules)) ctors := make([]fx.Option, 0, len(settings.modules))
for _, opt := range settings.modules { for _, opt := range settings.modules {
ctors = append(ctors, opt) ctors = append(ctors, opt)
} }
// fill holes in invokes // fill holes in invokes for use in fx.Options
for i, opt := range settings.invokes { for i, opt := range settings.invokes {
if opt == nil { if opt == nil {
settings.invokes[i] = fx.Options() settings.invokes[i] = fx.Options()
@ -147,6 +182,9 @@ func New(ctx context.Context, opts ...Option) (api.API, error) {
fx.Invoke(idAPI(&resAPI.Internal.ID)), fx.Invoke(idAPI(&resAPI.Internal.ID)),
) )
// TODO: we probably should have a 'firewall' for Closing signal
// on this context, and implement closing logic through lifecycles
// correctly
if err := app.Start(ctx); err != nil { if err := app.Start(ctx); err != nil {
return nil, err return nil, err
} }

View File

@ -1,31 +1,16 @@
package node package node
import ( import (
"go.uber.org/fx"
"reflect" "reflect"
) )
// Option is a functional option which can be used with the New function to
// change how the node is constructed
//
// Options are applied in sequence
type Option func(*settings) error type Option func(*settings) error
func Override(typ, constructor interface{}) Option { // Options groups multiple options into one
return func(s *settings) error {
if i, ok := typ.(invoke); ok {
s.invokes[i] = fx.Invoke(constructor)
return nil
}
if c, ok := typ.(special); ok {
s.modules[c] = fx.Provide(constructor)
return nil
}
ctor := as(constructor, typ)
rt := reflect.TypeOf(typ).Elem()
s.modules[rt] = fx.Provide(ctor)
return nil
}
}
func Options(opts ...Option) Option { func Options(opts ...Option) Option {
return func(s *settings) error { return func(s *settings) error {
for _, opt := range opts { for _, opt := range opts {
@ -37,6 +22,7 @@ func Options(opts ...Option) Option {
} }
} }
// Error is a special option which returns an error when applied
func Error(err error) Option { func Error(err error) Option {
return func(_ *settings) error { return func(_ *settings) error {
return err return err