Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Decouple net config #2258

Merged
merged 7 commits into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Read the documentation on [docs.source.network](https://docs.source.network/).
- [Install](#install)
- [Start](#start)
- [Configuration](#configuration)
- [External port binding](#external-port-binding)
- [Add a schema type](#add-a-schema-type)
- [Create a document instance](#create-a-document-instance)
- [Query documents](#query-documents)
Expand Down Expand Up @@ -72,6 +73,14 @@ In this document, we use the default configuration, which has the following beha

The GraphQL endpoint can be used with a GraphQL client (e.g., Altair) to conveniently perform requests (`query`, `mutation`) and obtain schema introspection.

## External port binding

By default the HTTP API and P2P network will use localhost. If you want to expose the ports externally you need to specify the addresses in the config or command line parameters.

```
defradb start --p2paddr /ip4/0.0.0.0/tcp/9171 --url 0.0.0.0:9181
```

## Add a schema type

Schemas are used to structure documents using a type system.
Expand Down Expand Up @@ -235,7 +244,6 @@ DQL is compatible with GraphQL but features various extensions.

Read its documentation at [docs.source.network](https://docs.source.network/references/query-specification/query-language-overview) to discover its filtering, ordering, limiting, relationships, variables, aggregate functions, and other useful features.


## Peer-to-peer data synchronization

DefraDB leverages peer-to-peer networking for data exchange, synchronization, and replication of documents and commits.
Expand Down Expand Up @@ -280,14 +288,14 @@ In this example, we use `12D3KooWNXm3dmrwCYSxGoRUyZstaKYiHPdt8uZH5vgVaEJyzU8B`,
For *nodeB*, we provide the following configuration:

```shell
defradb start --rootdir ~/.defradb-nodeB --url localhost:9182 --p2paddr /ip4/0.0.0.0/tcp/9172 --peers /ip4/0.0.0.0/tcp/9171/p2p/12D3KooWNXm3dmrwCYSxGoRUyZstaKYiHPdt8uZH5vgVaEJyzU8B
defradb start --rootdir ~/.defradb-nodeB --url localhost:9182 --p2paddr /ip4/127.0.0.1/tcp/9172 --peers /ip4/127.0.0.1/tcp/9171/p2p/12D3KooWNXm3dmrwCYSxGoRUyZstaKYiHPdt8uZH5vgVaEJyzU8B
```

About the flags:

- `--rootdir` specifies the root dir (config and data) to use
- `--url` is the address to listen on for the client HTTP and GraphQL API
- `--p2paddr` is the multiaddress for the P2P networking to listen on
- `--p2paddr` is a comma-separated list of multiaddresses to listen on for p2p networking
- `--peers` is a comma-separated list of peer multiaddresses

This starts two nodes and connects them via pubsub networking.
Expand Down
14 changes: 8 additions & 6 deletions cli/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,11 @@
log.FeedbackFatalE(context.Background(), "Could not bind datastore.badger.valuelogfilesize", err)
}

cmd.Flags().String(
"p2paddr", cfg.Net.P2PAddress,
"Listener address for the p2p network (formatted as a libp2p MultiAddr)",
cmd.Flags().StringSlice(
"p2paddr", cfg.Net.P2PAddresses,
"Listen addresses for the p2p network (formatted as a libp2p MultiAddr)",
)
err = cfg.BindFlag("net.p2paddress", cmd.Flags().Lookup("p2paddr"))
err = cfg.BindFlag("net.p2paddresses", cmd.Flags().Lookup("p2paddr"))
if err != nil {
log.FeedbackFatalE(context.Background(), "Could not bind net.p2paddress", err)
}
Expand Down Expand Up @@ -220,7 +220,9 @@
var node *net.Node
if !cfg.Net.P2PDisabled {
nodeOpts := []net.NodeOpt{
net.WithConfig(cfg),
net.WithListenAddresses(cfg.Net.P2PAddresses...),
net.WithEnablePubSub(cfg.Net.PubSubEnabled),
net.WithEnableRelay(cfg.Net.RelayEnabled),

Check warning on line 225 in cli/start.go

View check run for this annotation

Codecov / codecov/patch

cli/start.go#L223-L225

Added lines #L223 - L225 were not covered by tests
}
if cfg.Datastore.Store == badgerDatastoreName {
// It would be ideal to not have the key path tied to the datastore.
Expand All @@ -233,7 +235,7 @@
}
nodeOpts = append(nodeOpts, net.WithPrivateKey(key))
}
log.FeedbackInfo(ctx, "Starting P2P node", logging.NewKV("P2P address", cfg.Net.P2PAddress))
log.FeedbackInfo(ctx, "Starting P2P node", logging.NewKV("P2P addresses", cfg.Net.P2PAddresses))

Check warning on line 238 in cli/start.go

View check run for this annotation

Codecov / codecov/patch

cli/start.go#L238

Added line #L238 was not covered by tests
node, err = net.NewNode(ctx, db, nodeOpts...)
if err != nil {
db.Close()
Expand Down
14 changes: 8 additions & 6 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@

// NetConfig configures aspects of network and peer-to-peer.
type NetConfig struct {
P2PAddress string
P2PAddresses []string
P2PDisabled bool
Peers string
PubSubEnabled bool `mapstructure:"pubsub"`
Expand All @@ -363,7 +363,7 @@

func defaultNetConfig() *NetConfig {
return &NetConfig{
P2PAddress: "/ip4/0.0.0.0/tcp/9171",
P2PAddresses: []string{"/ip4/127.0.0.1/tcp/9171"},
P2PDisabled: false,
Peers: "",
PubSubEnabled: true,
Expand All @@ -372,9 +372,11 @@
}

func (netcfg *NetConfig) validate() error {
_, err := ma.NewMultiaddr(netcfg.P2PAddress)
if err != nil {
return NewErrInvalidP2PAddress(err, netcfg.P2PAddress)
for _, addr := range netcfg.P2PAddresses {
_, err := ma.NewMultiaddr(addr)
if err != nil {
return NewErrInvalidP2PAddress(err, addr)
}

Check warning on line 379 in config/config.go

View check run for this annotation

Codecov / codecov/patch

config/config.go#L378-L379

Added lines #L378 - L379 were not covered by tests
}
if len(netcfg.Peers) > 0 {
peers := strings.Split(netcfg.Peers, ",")
Expand Down Expand Up @@ -688,12 +690,12 @@
}

func (c *Config) toBytes() ([]byte, error) {
var buffer bytes.Buffer
tmpl := template.New("configTemplate")
configTemplate, err := tmpl.Parse(defaultConfigTemplate)
if err != nil {
return nil, NewErrConfigTemplateFailed(err)
}
var buffer bytes.Buffer
if err := configTemplate.Execute(&buffer, c); err != nil {
return nil, NewErrConfigTemplateFailed(err)
}
Expand Down
6 changes: 3 additions & 3 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ var envVarsDifferent = map[string]string{
"DEFRA_DATASTORE_BADGER_PATH": "defra_data",
"DEFRA_API_ADDRESS": "localhost:9999",
"DEFRA_NET_P2PDISABLED": "true",
"DEFRA_NET_P2PADDRESS": "/ip4/0.0.0.0/tcp/9876",
"DEFRA_NET_P2PADDRESSES": "/ip4/0.0.0.0/tcp/9876",
"DEFRA_NET_PUBSUB": "false",
"DEFRA_NET_RELAY": "false",
"DEFRA_LOG_LEVEL": "error",
Expand All @@ -37,7 +37,7 @@ var envVarsInvalid = map[string]string{
"DEFRA_DATASTORE_BADGER_PATH": "^=+()&**()*(&))",
"DEFRA_API_ADDRESS": "^=+()&**()*(&))",
"DEFRA_NET_P2PDISABLED": "^=+()&**()*(&))",
"DEFRA_NET_P2PADDRESS": "^=+()&**()*(&))",
"DEFRA_NET_P2PADDRESSES": "^=+()&**()*(&))",
"DEFRA_NET_PUBSUB": "^=+()&**()*(&))",
"DEFRA_NET_RELAY": "^=+()&**()*(&))",
"DEFRA_LOG_LEVEL": "^=+()&**()*(&))",
Expand Down Expand Up @@ -172,7 +172,7 @@ func TestEnvVariablesAllConsidered(t *testing.T) {
assert.Equal(t, filepath.Join(cfg.Rootdir, "defra_data"), cfg.Datastore.Badger.Path)
assert.Equal(t, "memory", cfg.Datastore.Store)
assert.Equal(t, true, cfg.Net.P2PDisabled)
assert.Equal(t, "/ip4/0.0.0.0/tcp/9876", cfg.Net.P2PAddress)
assert.Equal(t, []string{"/ip4/0.0.0.0/tcp/9876"}, cfg.Net.P2PAddresses)
assert.Equal(t, false, cfg.Net.PubSubEnabled)
assert.Equal(t, false, cfg.Net.RelayEnabled)
assert.Equal(t, "error", cfg.Log.Level)
Expand Down
5 changes: 4 additions & 1 deletion config/configfile_yaml.gotmpl
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ net:
# Whether the P2P is disabled
p2pdisabled: {{ .Net.P2PDisabled }}
# Listening address of the P2P network
p2paddress: {{ .Net.P2PAddress }}
p2paddresses:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thought: p2paddresses: {{ .Net.P2PAddresses }} would also work.

{{ range $addr := .Net.P2PAddresses }}
- {{ . }}
{{ end }}
# Whether the node has pubsub enabled or not
pubsub: {{ .Net.PubSubEnabled }}
# Enable libp2p's Circuit relay transport protocol https://docs.libp2p.io/concepts/circuit-relay/
Expand Down
92 changes: 17 additions & 75 deletions net/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,113 +13,55 @@
package net

import (
"time"

cconnmgr "github.com/libp2p/go-libp2p/core/connmgr"
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/p2p/net/connmgr"
ma "github.com/multiformats/go-multiaddr"
"google.golang.org/grpc"

"github.com/sourcenetwork/defradb/config"
)

// Options is the node options.
type Options struct {
ListenAddrs []ma.Multiaddr
ListenAddresses []string
PrivateKey crypto.PrivKey
EnablePubSub bool
EnableRelay bool
GRPCServerOptions []grpc.ServerOption
GRPCDialOptions []grpc.DialOption
ConnManager cconnmgr.ConnManager
}

type NodeOpt func(*Options) error

// NewMergedOptions obtains Options by applying given NodeOpts.
func NewMergedOptions(opts ...NodeOpt) (*Options, error) {
var options Options
for _, opt := range opts {
if opt == nil {
continue
}
if err := opt(&options); err != nil {
return nil, err
}
// DefaultOptions returns the default net options.
func DefaultOptions() *Options {
return &Options{
ListenAddresses: []string{"/ip4/0.0.0.0/tcp/9171"},
EnablePubSub: true,
EnableRelay: false,
}
return &options, nil
}

// NewConnManager gives a new ConnManager.
func NewConnManager(low int, high int, grace time.Duration) (cconnmgr.ConnManager, error) {
c, err := connmgr.NewConnManager(low, high, connmgr.WithGracePeriod(grace))
if err != nil {
return nil, err
}
return c, nil
}

// WithConfig provides the Node-specific configuration, from the top-level Net config.
func WithConfig(cfg *config.Config) NodeOpt {
return func(opt *Options) error {
var err error
err = WithListenP2PAddrStrings(cfg.Net.P2PAddress)(opt)
if err != nil {
return err
}
opt.EnableRelay = cfg.Net.RelayEnabled
opt.EnablePubSub = cfg.Net.PubSubEnabled
opt.ConnManager, err = NewConnManager(100, 400, time.Second*20)
if err != nil {
return err
}
return nil
}
}
type NodeOpt func(*Options)

// WithPrivateKey sets the p2p host private key.
func WithPrivateKey(priv crypto.PrivKey) NodeOpt {
return func(opt *Options) error {
return func(opt *Options) {
opt.PrivateKey = priv
return nil
}
}

// WithPubSub enables the pubsub feature.
func WithPubSub(enable bool) NodeOpt {
return func(opt *Options) error {
// WithEnablePubSub enables the pubsub feature.
func WithEnablePubSub(enable bool) NodeOpt {
return func(opt *Options) {
opt.EnablePubSub = enable
return nil
}
}

// WithEnableRelay enables the relay feature.
func WithEnableRelay(enable bool) NodeOpt {
return func(opt *Options) error {
return func(opt *Options) {
opt.EnableRelay = enable
return nil
}
}

// ListenP2PAddrStrings sets the address to listen on given as strings.
func WithListenP2PAddrStrings(addrs ...string) NodeOpt {
return func(opt *Options) error {
for _, addrstr := range addrs {
a, err := ma.NewMultiaddr(addrstr)
if err != nil {
return err
}
opt.ListenAddrs = append(opt.ListenAddrs, a)
}
return nil
}
}

// ListenAddrs sets the address to listen on given as MultiAddr(s).
func WithListenAddrs(addrs ...ma.Multiaddr) NodeOpt {
return func(opt *Options) error {
opt.ListenAddrs = addrs
return nil
// WithListenAddress sets the address to listen on given as a multiaddress string.
func WithListenAddresses(addresses ...string) NodeOpt {
return func(opt *Options) {
opt.ListenAddresses = addresses
}
}
Loading
Loading