diff --git a/api.go b/api.go index 0e2bacfb9..6fa786aa4 100644 --- a/api.go +++ b/api.go @@ -3070,9 +3070,9 @@ func (api *API) Directive(ctx context.Context, d *dax.Directive) error { } // DirectiveApplied returns true if the computer's current Directive has been -// applied and is ready to be queried. This it temporary (primarily for tests) -// and needs to be refactored as we improve the logic around mds-to-computer -// communication. +// applied and is ready to be queried. This is temporary (primarily for tests) +// and needs to be refactored as we improve the logic around +// controller-to-computer communication. func (api *API) DirectiveApplied(ctx context.Context) (bool, error) { return api.holder.DirectiveApplied(), nil } @@ -3085,7 +3085,7 @@ func (api *API) SnapshotShardData(ctx context.Context, req *dax.SnapshotShardDat } // TODO(jaffee) confirm this node is actually responsible for the given // shard? Not sure we need to given that this request comes from - // MDS, but might be a belt&suspenders situation. + // the Controller, but might be a belt&suspenders situation. qtid := req.TableKey.QualifiedTableID() diff --git a/ctl/dax.go b/ctl/dax.go index cb607c5a2..9bee92028 100644 --- a/ctl/dax.go +++ b/ctl/dax.go @@ -14,15 +14,15 @@ func BuildDAXFlags(cmd *cobra.Command, srv *server.Command) { flags.BoolVar(&srv.Config.Verbose, "verbose", srv.Config.Verbose, "Enable verbose logging") flags.StringVar(&srv.Config.LogPath, "log-path", srv.Config.LogPath, "Log path") - // MDS - flags.BoolVar(&srv.Config.MDS.Run, "mds.run", srv.Config.MDS.Run, "Run the MDS service in process.") - flags.DurationVar(&srv.Config.MDS.Config.RegistrationBatchTimeout, "mds.config.registration-batch-timeout", srv.Config.MDS.Config.RegistrationBatchTimeout, "Timeout for node registration batches.") - flags.StringVar(&srv.Config.MDS.Config.DataDir, "mds.config.data-dir", srv.Config.MDS.Config.DataDir, "MDS directory to use in process.") - flags.DurationVar(&srv.Config.MDS.Config.SnappingTurtleTimeout, "mds.config.snapping-turtle-timeout", srv.Config.MDS.Config.SnappingTurtleTimeout, "Period for running automatic snapshotting routine.") + // Controller + flags.BoolVar(&srv.Config.Controller.Run, "controller.run", srv.Config.Controller.Run, "Run the Controller service in process.") + flags.DurationVar(&srv.Config.Controller.Config.RegistrationBatchTimeout, "controller.config.registration-batch-timeout", srv.Config.Controller.Config.RegistrationBatchTimeout, "Timeout for node registration batches.") + flags.StringVar(&srv.Config.Controller.Config.DataDir, "controller.config.data-dir", srv.Config.Controller.Config.DataDir, "Controller directory to use in process.") + flags.DurationVar(&srv.Config.Controller.Config.SnappingTurtleTimeout, "controller.config.snapping-turtle-timeout", srv.Config.Controller.Config.SnappingTurtleTimeout, "Period for running automatic snapshotting routine.") // Queryer flags.BoolVar(&srv.Config.Queryer.Run, "queryer.run", srv.Config.Queryer.Run, "Run the Queryer service in process.") - flags.StringVar(&srv.Config.Queryer.Config.MDSAddress, "queryer.config.mds-address", srv.Config.Queryer.Config.MDSAddress, "Address of remote MDS process.") + flags.StringVar(&srv.Config.Queryer.Config.ControllerAddress, "queryer.config.controller-address", srv.Config.Queryer.Config.ControllerAddress, "Address of remote Controller process.") // Computer flags.BoolVar(&srv.Config.Computer.Run, "computer.run", srv.Config.Computer.Run, "Run the Computer service in process.") diff --git a/ctl/server.go b/ctl/server.go index ec9416bf9..03261ffc2 100644 --- a/ctl/server.go +++ b/ctl/server.go @@ -33,7 +33,7 @@ func serverFlagSet(srv *server.Config, prefix string) *pflag.FlagSet { flags := pflag.NewFlagSet("featurebase", pflag.ExitOnError) flags.StringVar(&srv.Name, pre("name"), srv.Name, "Name of the node in the cluster.") - flags.StringVar(&srv.MDSAddress, pre("mds-address"), srv.MDSAddress, "MDS service to register with.") + flags.StringVar(&srv.ControllerAddress, pre("controller-address"), srv.ControllerAddress, "Controller service to register with.") flags.StringVar(&srv.WriteloggerDir, pre("writelogger-dir"), srv.WriteloggerDir, "Writelogger directory to read/write append logs.") flags.StringVar(&srv.SnapshotterDir, pre("snapshotter-dir"), srv.SnapshotterDir, "Snapshotter directory to read/write snapshots.") flags.StringVarP(&srv.DataDir, pre("data-dir"), short("d"), srv.DataDir, "Directory to store FeatureBase data files.") @@ -112,7 +112,7 @@ func serverFlagSet(srv *server.Config, prefix string) *pflag.FlagSet { flags.BoolVar(&srv.SQL.EndpointEnabled, pre("sql.endpoint-enabled"), srv.SQL.EndpointEnabled, "Enable FeatureBase SQL /sql endpoint (default false)") - flags.DurationVar(&srv.CheckInInterval, pre("check-in-interval"), srv.CheckInInterval, "Interval between check-ins to MDS") + flags.DurationVar(&srv.CheckInInterval, pre("check-in-interval"), srv.CheckInInterval, "Interval between check-ins to the Controller") // Future flags. flags.BoolVar(&srv.Future.Rename, pre("future.rename"), false, "Present application name as FeatureBase. Defaults to false, will default to true in an upcoming release.") diff --git a/dax/Makefile b/dax/Makefile index b89fe499f..158e7d8d1 100644 --- a/dax/Makefile +++ b/dax/Makefile @@ -15,10 +15,10 @@ testv: test-integration: mkdir -p ../coverage-from-docker - $(GO) test ./test/dax -count 1 -run TestDAXIntegration/$(RUN) + $(GO) test ./test/dax -count 1 -timeout 20m -run TestDAXIntegration/$(RUN) testv-integration: - $(GO) test -v ./test/dax -count 1 -run TestDAXIntegration/$(RUN) + $(GO) test -v ./test/dax -count 1 -timeout 20m -run TestDAXIntegration/$(RUN) ############################### AWS STUFF ############################### diff --git a/dax/computer/interfaces.go b/dax/computer/interfaces.go index a79f9743c..54caa0cea 100644 --- a/dax/computer/interfaces.go +++ b/dax/computer/interfaces.go @@ -8,7 +8,7 @@ import ( ) // Registrar represents the methods which Computer uses to register itself with -// MDS. +// the Controller. type Registrar interface { RegisterNode(ctx context.Context, node *dax.Node) error CheckInNode(ctx context.Context, node *dax.Node) error diff --git a/dax/computer/service/computer.go b/dax/computer/service/computer.go index f5f422686..f60462414 100644 --- a/dax/computer/service/computer.go +++ b/dax/computer/service/computer.go @@ -10,7 +10,7 @@ import ( featurebase "github.com/featurebasedb/featurebase/v3" "github.com/featurebasedb/featurebase/v3/dax" "github.com/featurebasedb/featurebase/v3/dax/computer" - mdsclient "github.com/featurebasedb/featurebase/v3/dax/mds/client" + controllerclient "github.com/featurebasedb/featurebase/v3/dax/controller/client" "github.com/featurebasedb/featurebase/v3/dax/snapshotter" "github.com/featurebasedb/featurebase/v3/dax/writelogger" "github.com/featurebasedb/featurebase/v3/errors" @@ -54,11 +54,11 @@ func (c *computerService) Start() error { c.computer = cmd } - if c.cfg.ComputerConfig.MDSAddress != "" { - mdsAddr := dax.Address(c.cfg.ComputerConfig.MDSAddress) - // Set mds (registrar) on computer. - if err := c.SetMDS(mdsAddr); err != nil { - return errors.Wrapf(err, "setting mds service on computer: %s", c.cfg.Name) + if c.cfg.ComputerConfig.ControllerAddress != "" { + controllerAddr := dax.Address(c.cfg.ComputerConfig.ControllerAddress) + // Set Controller (registrar) on computer. + if err := c.SetController(controllerAddr); err != nil { + return errors.Wrapf(err, "setting controller service on computer: %s", c.cfg.Name) } } } @@ -103,8 +103,8 @@ func (c *computerService) HTTPHandler() http.Handler { return c.computer.HTTPHandler() } -func (c *computerService) SetMDS(addr dax.Address) error { - c.computer.Registrar = mdsclient.New(addr, c.logger) +func (c *computerService) SetController(addr dax.Address) error { + c.computer.Registrar = controllerclient.New(addr, c.logger) return nil } diff --git a/dax/mds/controller/balancer.go b/dax/controller/balancer.go similarity index 100% rename from dax/mds/controller/balancer.go rename to dax/controller/balancer.go diff --git a/dax/mds/controller/balancer/balancer.go b/dax/controller/balancer/balancer.go similarity index 99% rename from dax/mds/controller/balancer/balancer.go rename to dax/controller/balancer/balancer.go index 1d10f1420..71609b39b 100644 --- a/dax/mds/controller/balancer/balancer.go +++ b/dax/controller/balancer/balancer.go @@ -1,4 +1,4 @@ -// Package balancer is an implementation of the controller's Balancer interface. +// Package balancer is an implementation of the controller.Balancer interface. package balancer import ( @@ -9,8 +9,8 @@ import ( "time" "github.com/featurebasedb/featurebase/v3/dax" - "github.com/featurebasedb/featurebase/v3/dax/mds/controller" - "github.com/featurebasedb/featurebase/v3/dax/mds/schemar" + "github.com/featurebasedb/featurebase/v3/dax/controller" + "github.com/featurebasedb/featurebase/v3/dax/controller/schemar" "github.com/featurebasedb/featurebase/v3/errors" "github.com/featurebasedb/featurebase/v3/logger" ) @@ -18,7 +18,7 @@ import ( // Ensure type implements interface. var _ controller.Balancer = (*Balancer)(nil) -// Balancer is an implementation of the controller.Balancer interface which +// Balancer is an implementation of the balancer.Balancer interface which // isolates workers and jobs by database. It helps manage the relationships // between workers and jobs. The logic it uses to balance jobs across workers is // very simple; it bases everything off the number of workers and number of diff --git a/dax/mds/controller/balancer/balancer_test.go b/dax/controller/balancer/balancer_test.go similarity index 99% rename from dax/mds/controller/balancer/balancer_test.go rename to dax/controller/balancer/balancer_test.go index e538ef388..7bfc78650 100644 --- a/dax/mds/controller/balancer/balancer_test.go +++ b/dax/controller/balancer/balancer_test.go @@ -8,9 +8,9 @@ import ( "github.com/featurebasedb/featurebase/v3/dax" daxbolt "github.com/featurebasedb/featurebase/v3/dax/boltdb" - "github.com/featurebasedb/featurebase/v3/dax/mds/controller" - "github.com/featurebasedb/featurebase/v3/dax/mds/controller/balancer/boltdb" - schemardb "github.com/featurebasedb/featurebase/v3/dax/mds/schemar/boltdb" + "github.com/featurebasedb/featurebase/v3/dax/controller" + "github.com/featurebasedb/featurebase/v3/dax/controller/balancer/boltdb" + schemardb "github.com/featurebasedb/featurebase/v3/dax/controller/schemar/boltdb" daxtest "github.com/featurebasedb/featurebase/v3/dax/test" testbolt "github.com/featurebasedb/featurebase/v3/dax/test/boltdb" "github.com/featurebasedb/featurebase/v3/logger" diff --git a/dax/mds/controller/balancer/boltdb/balancer.go b/dax/controller/balancer/boltdb/balancer.go similarity index 98% rename from dax/mds/controller/balancer/boltdb/balancer.go rename to dax/controller/balancer/boltdb/balancer.go index 950b6763b..bb2e85711 100644 --- a/dax/mds/controller/balancer/boltdb/balancer.go +++ b/dax/controller/balancer/boltdb/balancer.go @@ -9,9 +9,8 @@ import ( "github.com/featurebasedb/featurebase/v3/dax" "github.com/featurebasedb/featurebase/v3/dax/boltdb" - "github.com/featurebasedb/featurebase/v3/dax/mds/controller" - "github.com/featurebasedb/featurebase/v3/dax/mds/controller/balancer" - "github.com/featurebasedb/featurebase/v3/dax/mds/schemar" + balancer "github.com/featurebasedb/featurebase/v3/dax/controller/balancer" + "github.com/featurebasedb/featurebase/v3/dax/controller/schemar" "github.com/featurebasedb/featurebase/v3/errors" "github.com/featurebasedb/featurebase/v3/logger" ) @@ -27,7 +26,7 @@ var BalancerBuckets []boltdb.Bucket = []boltdb.Bucket{ } // NewBalancer returns a new instance of controller.Balancer. -func NewBalancer(db *boltdb.DB, schemar schemar.Schemar, logger logger.Logger) controller.Balancer { +func NewBalancer(db *boltdb.DB, schemar schemar.Schemar, logger logger.Logger) *balancer.Balancer { fjs := newFreeJobService(db) wjs := newWorkerJobService(db, logger) fws := newFreeWorkerService(db) diff --git a/dax/mds/controller/balancer/boltdb/node.go b/dax/controller/balancer/boltdb/node.go similarity index 98% rename from dax/mds/controller/balancer/boltdb/node.go rename to dax/controller/balancer/boltdb/node.go index a6214b2f9..f497982f0 100644 --- a/dax/mds/controller/balancer/boltdb/node.go +++ b/dax/controller/balancer/boltdb/node.go @@ -7,7 +7,7 @@ import ( "github.com/featurebasedb/featurebase/v3/dax" "github.com/featurebasedb/featurebase/v3/dax/boltdb" - "github.com/featurebasedb/featurebase/v3/dax/mds/controller" + "github.com/featurebasedb/featurebase/v3/dax/controller" "github.com/featurebasedb/featurebase/v3/errors" "github.com/featurebasedb/featurebase/v3/logger" ) diff --git a/dax/mds/controller/balancer/boltdb/node_test.go b/dax/controller/balancer/boltdb/node_test.go similarity index 94% rename from dax/mds/controller/balancer/boltdb/node_test.go rename to dax/controller/balancer/boltdb/node_test.go index 8a332f7b1..7b770cced 100644 --- a/dax/mds/controller/balancer/boltdb/node_test.go +++ b/dax/controller/balancer/boltdb/node_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/featurebasedb/featurebase/v3/dax" - "github.com/featurebasedb/featurebase/v3/dax/mds/controller/balancer/boltdb" + "github.com/featurebasedb/featurebase/v3/dax/controller/balancer/boltdb" testbolt "github.com/featurebasedb/featurebase/v3/dax/test/boltdb" "github.com/featurebasedb/featurebase/v3/errors" "github.com/featurebasedb/featurebase/v3/logger" diff --git a/dax/mds/controller/balancer/types.go b/dax/controller/balancer/types.go similarity index 100% rename from dax/mds/controller/balancer/types.go rename to dax/controller/balancer/types.go diff --git a/dax/mds/client/client.go b/dax/controller/client/client.go similarity index 95% rename from dax/mds/client/client.go rename to dax/controller/client/client.go index 721e86b78..055007a27 100644 --- a/dax/mds/client/client.go +++ b/dax/controller/client/client.go @@ -1,4 +1,4 @@ -// Package client is an HTTP client for MDS. +// Package client is an HTTP client for Controller. package client import ( @@ -11,7 +11,7 @@ import ( "github.com/featurebasedb/featurebase/v3/dax" "github.com/featurebasedb/featurebase/v3/dax/computer" - mdshttp "github.com/featurebasedb/featurebase/v3/dax/mds/http" + controllerhttp "github.com/featurebasedb/featurebase/v3/dax/controller/http" "github.com/featurebasedb/featurebase/v3/errors" "github.com/featurebasedb/featurebase/v3/logger" ) @@ -24,8 +24,8 @@ const ( var _ computer.Registrar = (*Client)(nil) var _ dax.Schemar = (*Client)(nil) -// Client is an HTTP client that operates on the MDS endpoints exposed by the -// main MDS service. +// Client is an HTTP client that operates on the Controller endpoints exposed by +// the main Controller service. type Client struct { address dax.Address logger logger.Logger @@ -137,7 +137,7 @@ func (c *Client) DatabaseByID(ctx context.Context, qdbid dax.QualifiedDatabaseID func (c *Client) DatabaseByName(ctx context.Context, orgID dax.OrganizationID, name dax.DatabaseName) (*dax.QualifiedDatabase, error) { url := fmt.Sprintf("%s/database-by-name", c.address.WithScheme(defaultScheme)) - req := &mdshttp.DatabaseByNameRequest{ + req := &controllerhttp.DatabaseByNameRequest{ OrganizationID: orgID, Name: name, } @@ -173,7 +173,7 @@ func (c *Client) DatabaseByName(ctx context.Context, orgID dax.OrganizationID, n func (c *Client) Databases(ctx context.Context, orgID dax.OrganizationID, ids ...dax.DatabaseID) ([]*dax.QualifiedDatabase, error) { url := fmt.Sprintf("%s/databases", c.address.WithScheme(defaultScheme)) - req := &mdshttp.DatabasesRequest{ + req := &controllerhttp.DatabasesRequest{ OrganizationID: orgID, DatabaseIDs: ids, } @@ -291,7 +291,7 @@ func (c *Client) TableID(ctx context.Context, qdbid dax.QualifiedDatabaseID, nam func (c *Client) Tables(ctx context.Context, qdbid dax.QualifiedDatabaseID, ids ...dax.TableID) ([]*dax.QualifiedTable, error) { url := fmt.Sprintf("%s/tables", c.address.WithScheme(defaultScheme)) - req := mdshttp.TablesRequest{ + req := controllerhttp.TablesRequest{ OrganizationID: qdbid.OrganizationID, DatabaseID: qdbid.DatabaseID, TableIDs: ids, @@ -377,7 +377,7 @@ func (c *Client) DropTable(ctx context.Context, qtid dax.QualifiedTableID) error func (c *Client) CreateField(ctx context.Context, qtid dax.QualifiedTableID, fld *dax.Field) error { url := fmt.Sprintf("%s/create-field", c.address.WithScheme(defaultScheme)) - req := mdshttp.CreateFieldRequest{ + req := controllerhttp.CreateFieldRequest{ TableKey: qtid.Key(), Field: fld, } @@ -407,7 +407,7 @@ func (c *Client) DropField(ctx context.Context, qtid dax.QualifiedTableID, fldNa url := fmt.Sprintf("%s/drop-field", c.address.WithScheme(defaultScheme)) // Encode the request. - req := mdshttp.DropFieldRequest{ + req := controllerhttp.DropFieldRequest{ Table: qtid, Field: fldName, } @@ -438,7 +438,7 @@ func (c *Client) IngestShard(ctx context.Context, qtid dax.QualifiedTableID, sha var host dax.Address - req := &mdshttp.IngestShardRequest{ + req := &controllerhttp.IngestShardRequest{ Table: qtid, Shard: shard, } @@ -462,7 +462,7 @@ func (c *Client) IngestShard(ctx context.Context, qtid dax.QualifiedTableID, sha return host, errors.Errorf("status code: %d: %s", resp.StatusCode, b) } - var isr *mdshttp.IngestShardResponse + var isr *controllerhttp.IngestShardResponse if err := json.NewDecoder(resp.Body).Decode(&isr); err != nil { return host, errors.Wrap(err, "reading response body") } @@ -475,7 +475,7 @@ func (c *Client) IngestPartition(ctx context.Context, qtid dax.QualifiedTableID, var host dax.Address - req := &mdshttp.IngestPartitionRequest{ + req := &controllerhttp.IngestPartitionRequest{ Table: qtid, Partition: partition, } @@ -499,7 +499,7 @@ func (c *Client) IngestPartition(ctx context.Context, qtid dax.QualifiedTableID, return host, errors.Errorf("status code: %d: %s", resp.StatusCode, b) } - var isr *mdshttp.IngestPartitionResponse + var isr *controllerhttp.IngestPartitionResponse if err := json.NewDecoder(resp.Body).Decode(&isr); err != nil { return host, errors.Wrap(err, "reading response body") } @@ -513,7 +513,7 @@ func (c *Client) ComputeNodes(ctx context.Context, qtid dax.QualifiedTableID, sh var nodes []dax.ComputeNode - req := &mdshttp.ComputeNodesRequest{ + req := &controllerhttp.ComputeNodesRequest{ Table: qtid, Shards: shards, } @@ -537,7 +537,7 @@ func (c *Client) ComputeNodes(ctx context.Context, qtid dax.QualifiedTableID, sh return nodes, errors.Errorf("status code: %d: %s", resp.StatusCode, b) } - var cnr *mdshttp.ComputeNodesResponse + var cnr *controllerhttp.ComputeNodesResponse if err := json.NewDecoder(resp.Body).Decode(&cnr); err != nil { return nodes, errors.Wrap(err, "reading response body") } @@ -551,7 +551,7 @@ func (c *Client) TranslateNodes(ctx context.Context, qtid dax.QualifiedTableID, var nodes []dax.TranslateNode - req := &mdshttp.TranslateNodesRequest{ + req := &controllerhttp.TranslateNodesRequest{ Table: qtid, Partitions: partitions, } @@ -575,7 +575,7 @@ func (c *Client) TranslateNodes(ctx context.Context, qtid dax.QualifiedTableID, return nodes, errors.Errorf("status code: %d: %s", resp.StatusCode, b) } - var cnr *mdshttp.TranslateNodesResponse + var cnr *controllerhttp.TranslateNodesResponse if err := json.NewDecoder(resp.Body).Decode(&cnr); err != nil { return nodes, errors.Wrap(err, "reading response body") } @@ -587,7 +587,7 @@ func (c *Client) RegisterNode(ctx context.Context, node *dax.Node) error { url := fmt.Sprintf("%s/register-node", c.address.WithScheme(defaultScheme)) c.logger.Debugf("RegisterNode: %s, url: %s", node.Address, url) - req := &mdshttp.RegisterNodeRequest{ + req := &controllerhttp.RegisterNodeRequest{ Address: node.Address, RoleTypes: node.RoleTypes, } @@ -618,7 +618,7 @@ func (c *Client) CheckInNode(ctx context.Context, node *dax.Node) error { url := fmt.Sprintf("%s/check-in-node", c.address.WithScheme(defaultScheme)) c.logger.Debugf("CheckInNode url: %s", url) - req := &mdshttp.CheckInNodeRequest{ + req := &controllerhttp.CheckInNodeRequest{ Address: node.Address, RoleTypes: node.RoleTypes, } diff --git a/dax/mds/controller/config.go b/dax/controller/config.go similarity index 75% rename from dax/mds/controller/config.go rename to dax/controller/config.go index 368090e3b..a39c5979e 100644 --- a/dax/mds/controller/config.go +++ b/dax/controller/config.go @@ -3,8 +3,6 @@ package controller import ( "time" - "github.com/featurebasedb/featurebase/v3/dax/boltdb" - "github.com/featurebasedb/featurebase/v3/dax/mds/schemar" "github.com/featurebasedb/featurebase/v3/logger" ) @@ -12,15 +10,16 @@ type NewBalancerFn func(string, logger.Logger) Balancer type Config struct { Director Director - Schemar schemar.Schemar - Balancer Balancer + // Poller + PollInterval time.Duration `toml:"poll-interval"` - StorageMethod string - BoltDB *boltdb.DB + // Storage + StorageMethod string `toml:"-"` + DataDir string `toml:"-"` - SnapshotterDir string - WriteloggerDir string + SnapshotterDir string `toml:"snapshotter-dir"` + WriteloggerDir string `toml:"writelogger-dir"` // RegistrationBatchTimeout is the time that the controller will // wait after a node registers itself to see if any more nodes @@ -35,5 +34,5 @@ type Config struct { // until the timeout expires to start another round of snapshots. SnappingTurtleTimeout time.Duration - Logger logger.Logger + Logger logger.Logger `toml:"-"` } diff --git a/dax/mds/controller/controller.go b/dax/controller/controller.go similarity index 95% rename from dax/mds/controller/controller.go rename to dax/controller/controller.go index 72f983727..0fbf0f520 100644 --- a/dax/mds/controller/controller.go +++ b/dax/controller/controller.go @@ -10,7 +10,8 @@ import ( "github.com/featurebasedb/featurebase/v3/dax" "github.com/featurebasedb/featurebase/v3/dax/boltdb" "github.com/featurebasedb/featurebase/v3/dax/computer" - "github.com/featurebasedb/featurebase/v3/dax/mds/schemar" + "github.com/featurebasedb/featurebase/v3/dax/controller/poller" + "github.com/featurebasedb/featurebase/v3/dax/controller/schemar" "github.com/featurebasedb/featurebase/v3/dax/snapshotter" "github.com/featurebasedb/featurebase/v3/dax/writelogger" "github.com/featurebasedb/featurebase/v3/errors" @@ -24,21 +25,26 @@ var _ dax.Schemar = (*Controller)(nil) var _ dax.NodeService = (*Controller)(nil) type Controller struct { - // Schemar used by the controller to get table information. The controller - // should NOT call Schemar methods which modify data. Schema mutations are - // made outside of the controller (at this point that happens in MDS). - Schemar schemar.Schemar - - boltDB *boltdb.DB + // Schemar is used by the controller to get table, and other schema, + // information. + Schemar schemar.Schemar Balancer Balancer + // Because we stopped using a storage method interface, and always use bolt, + // we need to be sure to close the boltDBs that are created in controller.New() + // whenever controller.Stop() is called. These are pointers to that DB so we can + // close it. + BoltDB *boltdb.DB + Snapshotter *snapshotter.Snapshotter Writelogger *writelogger.Writelogger // Director is used to send directives to computer workers. Director Director - directiveVersion dax.DirectiveVersion + DirectiveVersion dax.DirectiveVersion + + poller *poller.Poller registrationBatchTimeout time.Duration nodeChan chan *dax.Node @@ -56,11 +62,16 @@ var supportedRoleTypes []dax.RoleType = []dax.RoleType{ // New returns a new instance of Controller with default values. func New(cfg Config) *Controller { + // Set up logger. + var logr logger.Logger = logger.StderrLogger + if cfg.Logger != nil { + logr = cfg.Logger + } + c := &Controller{ Schemar: schemar.NewNopSchemar(), - boltDB: cfg.BoltDB, - Balancer: cfg.Balancer, + Balancer: NewNopBalancer(), Director: NewNopDirector(), @@ -70,38 +81,32 @@ func New(cfg Config) *Controller { snapControl: make(chan struct{}), stopping: make(chan struct{}), - logger: logger.NopLogger, + logger: logr, } - if cfg.Logger != nil { - c.logger = cfg.Logger + // Poller. + pollerCfg := poller.Config{ + AddressManager: c, + NodeService: c, + NodePoller: poller.NewHTTPNodePoller(logr), + PollInterval: cfg.PollInterval, + Logger: logr, } + c.poller = poller.New(pollerCfg) + // Snapshotter. c.Snapshotter = snapshotter.New(cfg.SnapshotterDir, c.logger) - c.Writelogger = writelogger.New(cfg.WriteloggerDir, c.logger) - switch cfg.StorageMethod { - case "boltdb": - if err := cfg.BoltDB.InitializeBuckets(boltdb.DirectiveBuckets...); err != nil { - c.logger.Panicf("initializing directive buckets: %v", err) - } - c.directiveVersion = boltdb.NewDirectiveVersion(cfg.BoltDB) - default: - c.logger.Panicf("storage method '%s' unsupported. (hint: try boltdb)", cfg.StorageMethod) - } - - if cfg.Director != nil { - c.Director = cfg.Director - } - if cfg.Schemar != nil { - c.Schemar = cfg.Schemar - } + // Writelogger. + c.Writelogger = writelogger.New(cfg.WriteloggerDir, c.logger) return c } -// Run starts long running subroutines. -func (c *Controller) Run() error { +// Start starts long running subroutines. +func (c *Controller) Start() error { + c.poller.Run() + go c.nodeRegistrationRoutine(c.nodeChan, c.registrationBatchTimeout) go c.snappingTurtleRoutine(c.snappingTurtleTimeout, c.snapControl) @@ -109,8 +114,12 @@ func (c *Controller) Run() error { } // Stop stops the node registration routine. -func (c *Controller) Stop() { +func (c *Controller) Stop() error { + c.poller.Stop() + close(c.stopping) + + return nil } // RegisterNodes adds nodes to the controller's list of registered @@ -118,7 +127,7 @@ func (c *Controller) Stop() { func (c *Controller) RegisterNodes(ctx context.Context, nodes ...*dax.Node) error { c.logger.Printf("c.RegisterNodes(): %s", dax.Nodes(nodes)) - tx, err := c.boltDB.BeginTx(ctx, true) + tx, err := c.BoltDB.BeginTx(ctx, true) if err != nil { return errors.Wrap(err, "beginning tx") } @@ -229,7 +238,7 @@ func (c *Controller) RegisterNode(ctx context.Context, n *dax.Node) error { } } - tx, err := c.boltDB.BeginTx(ctx, false) + tx, err := c.BoltDB.BeginTx(ctx, false) if err != nil { return errors.Wrap(err, "beginning tx") } @@ -251,7 +260,7 @@ func (c *Controller) RegisterNode(ctx context.Context, n *dax.Node) error { // from its list (perhaps due to a network fault) and therefore the node needs // to be re-registered. func (c *Controller) CheckInNode(ctx context.Context, n *dax.Node) error { - tx, err := c.boltDB.BeginTx(ctx, false) + tx, err := c.BoltDB.BeginTx(ctx, false) if err != nil { return errors.Wrap(err, "beginning tx") } @@ -274,7 +283,7 @@ func (c *Controller) CheckInNode(ctx context.Context, n *dax.Node) error { // DeregisterNodes removes nodes from the controller's list of registered nodes. // It sends directives to the removed nodes, but ignores errors. func (c *Controller) DeregisterNodes(ctx context.Context, addresses ...dax.Address) error { - tx, err := c.boltDB.BeginTx(ctx, true) + tx, err := c.BoltDB.BeginTx(ctx, true) if err != nil { return errors.Wrap(err, "beginning tx") } @@ -567,7 +576,7 @@ func (c *Controller) translateWorkersToAssignedNodes(tx dax.Transaction, workers // CreateDatabase adds a database to the schemar. func (c *Controller) CreateDatabase(ctx context.Context, qdb *dax.QualifiedDatabase) error { - tx, err := c.boltDB.BeginTx(ctx, true) + tx, err := c.BoltDB.BeginTx(ctx, true) if err != nil { return errors.Wrap(err, "beginning tx") } @@ -581,7 +590,7 @@ func (c *Controller) CreateDatabase(ctx context.Context, qdb *dax.QualifiedDatab } func (c *Controller) DropDatabase(ctx context.Context, qdbid dax.QualifiedDatabaseID) error { - tx, err := c.boltDB.BeginTx(ctx, true) + tx, err := c.BoltDB.BeginTx(ctx, true) if err != nil { return errors.Wrap(err, "beginning tx") } @@ -625,7 +634,7 @@ func (c *Controller) DropDatabase(ctx context.Context, qdbid dax.QualifiedDataba // DatabaseByName returns the database for the given name. func (c *Controller) DatabaseByName(ctx context.Context, orgID dax.OrganizationID, dbname dax.DatabaseName) (*dax.QualifiedDatabase, error) { - tx, err := c.boltDB.BeginTx(ctx, false) + tx, err := c.BoltDB.BeginTx(ctx, false) if err != nil { return nil, errors.Wrap(err, "beginning tx") } @@ -641,7 +650,7 @@ func (c *Controller) DatabaseByName(ctx context.Context, orgID dax.OrganizationI // DatabaseByID returns the database for the given id. func (c *Controller) DatabaseByID(ctx context.Context, qdbid dax.QualifiedDatabaseID) (*dax.QualifiedDatabase, error) { - tx, err := c.boltDB.BeginTx(ctx, false) + tx, err := c.BoltDB.BeginTx(ctx, false) if err != nil { return nil, errors.Wrap(err, "beginning tx") } @@ -657,7 +666,7 @@ func (c *Controller) DatabaseByID(ctx context.Context, qdbid dax.QualifiedDataba // SetDatabaseOptions sets the options on the given database. func (c *Controller) SetDatabaseOptions(ctx context.Context, qdbid dax.QualifiedDatabaseID, opts dax.DatabaseOptions) error { - tx, err := c.boltDB.BeginTx(ctx, true) + tx, err := c.BoltDB.BeginTx(ctx, true) if err != nil { return errors.Wrap(err, "beginning tx") } @@ -671,7 +680,7 @@ func (c *Controller) SetDatabaseOptions(ctx context.Context, qdbid dax.Qualified } func (c *Controller) Databases(ctx context.Context, orgID dax.OrganizationID, ids ...dax.DatabaseID) ([]*dax.QualifiedDatabase, error) { - tx, err := c.boltDB.BeginTx(ctx, false) + tx, err := c.BoltDB.BeginTx(ctx, false) if err != nil { return nil, errors.Wrap(err, "beginning tx") } @@ -684,7 +693,7 @@ func (c *Controller) Databases(ctx context.Context, orgID dax.OrganizationID, id // CreateTable adds a table to the schemar, and then sends directives to all // affected nodes based on the change. func (c *Controller) CreateTable(ctx context.Context, qtbl *dax.QualifiedTable) error { - tx, err := c.boltDB.BeginTx(ctx, true) + tx, err := c.BoltDB.BeginTx(ctx, true) if err != nil { return errors.Wrap(err, "beginning tx") } @@ -772,7 +781,7 @@ func (c *Controller) CreateTable(ctx context.Context, qtbl *dax.QualifiedTable) // DropTable removes a table from the schema and sends directives to all affected // nodes based on the change. func (c *Controller) DropTable(ctx context.Context, qtid dax.QualifiedTableID) error { - tx, err := c.boltDB.BeginTx(ctx, true) + tx, err := c.BoltDB.BeginTx(ctx, true) if err != nil { return errors.Wrap(err, "beginning tx") } @@ -840,7 +849,7 @@ func (c *Controller) dropTable(tx dax.Transaction, qtid dax.QualifiedTableID) (A // TableByID returns a table by quaified table id. func (c *Controller) TableByID(ctx context.Context, qtid dax.QualifiedTableID) (*dax.QualifiedTable, error) { - tx, err := c.boltDB.BeginTx(ctx, false) + tx, err := c.BoltDB.BeginTx(ctx, false) if err != nil { return nil, errors.Wrap(err, "beginning tx") } @@ -852,7 +861,7 @@ func (c *Controller) TableByID(ctx context.Context, qtid dax.QualifiedTableID) ( // Tables returns a list of tables by name. func (c *Controller) Tables(ctx context.Context, qdbid dax.QualifiedDatabaseID, ids ...dax.TableID) ([]*dax.QualifiedTable, error) { - tx, err := c.boltDB.BeginTx(ctx, false) + tx, err := c.BoltDB.BeginTx(ctx, false) if err != nil { return nil, errors.Wrap(err, "beginning tx") } @@ -865,7 +874,7 @@ func (c *Controller) Tables(ctx context.Context, qdbid dax.QualifiedDatabaseID, // RemoveShards deregisters the table/shard combinations with the controller and // sends the necessary directives. func (c *Controller) RemoveShards(ctx context.Context, qtid dax.QualifiedTableID, shards ...dax.ShardNum) error { - tx, err := c.boltDB.BeginTx(ctx, true) + tx, err := c.BoltDB.BeginTx(ctx, true) if err != nil { return errors.Wrap(err, "beginning tx") } @@ -981,7 +990,7 @@ func (c *Controller) buildDirectives(tx dax.Transaction, addrs []addressMethod) directives := make([]*dax.Directive, len(addrs)) for i, addressMethod := range addrs { - dVersion, err := c.directiveVersion.Increment(tx, 1) + dVersion, err := c.DirectiveVersion.Increment(tx, 1) if err != nil { return nil, errors.Wrap(err, "incrementing directive version") } @@ -1083,8 +1092,8 @@ func (c *Controller) buildDirectives(tx dax.Transaction, addrs []addressMethod) // the same way we handle shards and partitions, by maintaining a // distinct balancer for FieldVersions. But because the query side isn't // currently set up to look for field translation anywhere but on the - // local node (or in the case of MDS, on partition 0), we're keeping - // everything that way for now. + // local node (or in the case of Serverless, on partition 0), we're + // keeping everything that way for now. for tkey := range ownsPartition0 { qtid := tkey.QualifiedTableID() table, err := c.Schemar.Table(tx, qtid) @@ -1154,7 +1163,7 @@ func (c *Controller) SnapshotTable(ctx context.Context, qtid dax.QualifiedTableI // snapshot that shard, then increment its shard version for logs written to the // Writelogger. func (c *Controller) SnapshotShardData(ctx context.Context, qtid dax.QualifiedTableID, shardNum dax.ShardNum) error { - tx, err := c.boltDB.BeginTx(ctx, false) + tx, err := c.BoltDB.BeginTx(ctx, false) if err != nil { return errors.Wrap(err, "beginning tx") } @@ -1197,7 +1206,7 @@ func (c *Controller) snapshotShardData(tx dax.Transaction, qtid dax.QualifiedTab // partition to snapshot the table keys for that partition, then increment its // version for logs written to the Writelogger. func (c *Controller) SnapshotTableKeys(ctx context.Context, qtid dax.QualifiedTableID, partitionNum dax.PartitionNum) error { - tx, err := c.boltDB.BeginTx(ctx, false) + tx, err := c.BoltDB.BeginTx(ctx, false) if err != nil { return errors.Wrap(err, "beginning tx") } @@ -1240,7 +1249,7 @@ func (c *Controller) snapshotTableKeys(tx dax.Transaction, qtid dax.QualifiedTab // to snapshot the keys for that field, then increment its version for logs // written to the Writelogger. func (c *Controller) SnapshotFieldKeys(ctx context.Context, qtid dax.QualifiedTableID, field dax.FieldName) error { - tx, err := c.boltDB.BeginTx(ctx, false) + tx, err := c.BoltDB.BeginTx(ctx, false) if err != nil { return errors.Wrap(err, "beginning tx") } @@ -1294,7 +1303,7 @@ func (c *Controller) ComputeNodes(ctx context.Context, qtid dax.QualifiedTableID } qdbid := qtid.QualifiedDatabaseID - tx, err := c.boltDB.BeginTx(ctx, false) + tx, err := c.BoltDB.BeginTx(ctx, false) if err != nil { return nil, errors.Wrap(err, "beginning tx") } @@ -1356,7 +1365,7 @@ func (c *Controller) TranslateNodes(ctx context.Context, qtid dax.QualifiedTable } qdbid := qtid.QualifiedDatabaseID - tx, err := c.boltDB.BeginTx(ctx, false) + tx, err := c.BoltDB.BeginTx(ctx, false) if err != nil { return nil, errors.Wrap(err, "beginning tx") } @@ -1431,7 +1440,7 @@ func (c *Controller) IngestPartition(ctx context.Context, qtid dax.QualifiedTabl qdbid := qtid.QualifiedDatabaseID // Try with a read transaction first. - tx, err := c.boltDB.BeginTx(ctx, false) + tx, err := c.BoltDB.BeginTx(ctx, false) if err != nil { return "", errors.Wrap(err, "beginning tx") } @@ -1456,7 +1465,7 @@ func (c *Controller) IngestPartition(ctx context.Context, qtid dax.QualifiedTabl if retryAsWrite { tx.Rollback() - tx, err = c.boltDB.BeginTx(ctx, true) + tx, err = c.BoltDB.BeginTx(ctx, true) if err != nil { return "", errors.Wrap(err, "beginning tx") } @@ -1515,7 +1524,7 @@ func (c *Controller) IngestShard(ctx context.Context, qtid dax.QualifiedTableID, qdbid := qtid.QualifiedDatabaseID // Try with a read transaction first. - tx, err := c.boltDB.BeginTx(ctx, false) + tx, err := c.BoltDB.BeginTx(ctx, false) if err != nil { return "", errors.Wrap(err, "beginning tx") } @@ -1540,7 +1549,7 @@ func (c *Controller) IngestShard(ctx context.Context, qtid dax.QualifiedTableID, if retryAsWrite { tx.Rollback() - tx, err = c.boltDB.BeginTx(ctx, true) + tx, err = c.BoltDB.BeginTx(ctx, true) if err != nil { return "", errors.Wrap(err, "beginning tx") } @@ -1590,7 +1599,7 @@ func (c *Controller) IngestShard(ctx context.Context, qtid dax.QualifiedTableID, //// func (c *Controller) CreateField(ctx context.Context, qtid dax.QualifiedTableID, fld *dax.Field) error { - tx, err := c.boltDB.BeginTx(ctx, true) + tx, err := c.BoltDB.BeginTx(ctx, true) if err != nil { return errors.Wrap(err, "beginning tx") } @@ -1651,7 +1660,7 @@ func (c *Controller) CreateField(ctx context.Context, qtid dax.QualifiedTableID, } func (c *Controller) DropField(ctx context.Context, qtid dax.QualifiedTableID, fldName dax.FieldName) error { - tx, err := c.boltDB.BeginTx(ctx, true) + tx, err := c.BoltDB.BeginTx(ctx, true) if err != nil { return errors.Wrap(err, "beginning tx") } @@ -1723,7 +1732,7 @@ func (c *Controller) RemoveAddresses(ctx context.Context, addrs ...dax.Address) } func (c *Controller) DebugNodes(ctx context.Context) ([]*dax.Node, error) { - tx, err := c.boltDB.BeginTx(ctx, false) + tx, err := c.BoltDB.BeginTx(ctx, false) if err != nil { return nil, errors.Wrap(err, "beginning tx") } @@ -1747,7 +1756,7 @@ func (c *Controller) sanitizeQTID(tx dax.Transaction, qtid *dax.QualifiedTableID // TableByName gets the full table by name. func (c *Controller) TableByName(ctx context.Context, qdbid dax.QualifiedDatabaseID, name dax.TableName) (*dax.QualifiedTable, error) { - tx, err := c.boltDB.BeginTx(ctx, false) + tx, err := c.BoltDB.BeginTx(ctx, false) if err != nil { return nil, errors.Wrap(err, "beginning tx") } @@ -1765,7 +1774,7 @@ func (c *Controller) TableByName(ctx context.Context, qdbid dax.QualifiedDatabas // TableID returns the table id by table name. // TODO(tlt): try to phase this out in favor of TableByName(). func (c *Controller) TableID(ctx context.Context, qdbid dax.QualifiedDatabaseID, name dax.TableName) (dax.QualifiedTableID, error) { - tx, err := c.boltDB.BeginTx(ctx, false) + tx, err := c.BoltDB.BeginTx(ctx, false) if err != nil { return dax.QualifiedTableID{}, errors.Wrap(err, "beginning tx") } @@ -1786,7 +1795,7 @@ func (c *Controller) DeleteNode(context.Context, dax.Address) error { return errors.Errorf("Controller.DeleteNode() not implemented") } func (c *Controller) Nodes(ctx context.Context) ([]*dax.Node, error) { - tx, err := c.boltDB.BeginTx(ctx, false) + tx, err := c.BoltDB.BeginTx(ctx, false) if err != nil { return nil, errors.Wrap(err, "beginning tx") } diff --git a/dax/mds/controller/controller_test.go b/dax/controller/controller_test.go similarity index 95% rename from dax/mds/controller/controller_test.go rename to dax/controller/controller_test.go index fd8dea179..3fda6e218 100644 --- a/dax/mds/controller/controller_test.go +++ b/dax/controller/controller_test.go @@ -8,9 +8,10 @@ import ( "testing" "github.com/featurebasedb/featurebase/v3/dax" - "github.com/featurebasedb/featurebase/v3/dax/mds/controller" - balancerdb "github.com/featurebasedb/featurebase/v3/dax/mds/controller/balancer/boltdb" - schemardb "github.com/featurebasedb/featurebase/v3/dax/mds/schemar/boltdb" + directivedb "github.com/featurebasedb/featurebase/v3/dax/boltdb" + "github.com/featurebasedb/featurebase/v3/dax/controller" + balancerdb "github.com/featurebasedb/featurebase/v3/dax/controller/balancer/boltdb" + schemardb "github.com/featurebasedb/featurebase/v3/dax/controller/schemar/boltdb" daxtest "github.com/featurebasedb/featurebase/v3/dax/test" testbolt "github.com/featurebasedb/featurebase/v3/dax/test/boltdb" "github.com/featurebasedb/featurebase/v3/errors" @@ -35,12 +36,11 @@ func TestController(t *testing.T) { testbolt.CleanupDB(t, db.Path()) }() - cfg := controller.Config{ - Director: director, - Schemar: schemar, - BoltDB: db, - } + cfg := controller.Config{} con := controller.New(cfg) + con.Schemar = schemar + con.BoltDB = db + con.Director = director // Register a node with an invalid role type. node0 := &dax.Node{ @@ -73,19 +73,19 @@ func TestController(t *testing.T) { db := testbolt.MustOpenDB(t) db.InitializeBuckets(balancerdb.BalancerBuckets...) db.InitializeBuckets(schemardb.SchemarBuckets...) + db.InitializeBuckets(directivedb.DirectiveBuckets...) defer func() { testbolt.MustCloseDB(t, db) testbolt.CleanupDB(t, db.Path()) }() - cfg := controller.Config{ - Director: director, - Schemar: schemar, - BoltDB: db, - StorageMethod: "boltdb", - Balancer: balancerdb.NewBalancer(db, schemar, logger.StderrLogger), - } + cfg := controller.Config{} con := controller.New(cfg) + con.Schemar = schemar + con.Balancer = balancerdb.NewBalancer(db, schemar, logger.StderrLogger) + con.DirectiveVersion = directivedb.NewDirectiveVersion(db) + con.Director = director + con.BoltDB = db var exp []*dax.Directive @@ -592,19 +592,19 @@ func TestController(t *testing.T) { db := testbolt.MustOpenDB(t) db.InitializeBuckets(balancerdb.BalancerBuckets...) db.InitializeBuckets(schemardb.SchemarBuckets...) + db.InitializeBuckets(directivedb.DirectiveBuckets...) defer func() { testbolt.MustCloseDB(t, db) testbolt.CleanupDB(t, db.Path()) }() - cfg := controller.Config{ - Director: director, - Schemar: schemar, - BoltDB: db, - StorageMethod: "boltdb", - Balancer: balancerdb.NewBalancer(db, schemar, logger.StderrLogger), - } + cfg := controller.Config{} con := controller.New(cfg) + con.Schemar = schemar + con.Balancer = balancerdb.NewBalancer(db, schemar, logger.StderrLogger) + con.DirectiveVersion = directivedb.NewDirectiveVersion(db) + con.BoltDB = db + con.Director = director var exp []*dax.Directive @@ -908,18 +908,18 @@ func TestController(t *testing.T) { db := testbolt.MustOpenDB(t) db.InitializeBuckets(balancerdb.BalancerBuckets...) db.InitializeBuckets(schemardb.SchemarBuckets...) + db.InitializeBuckets(directivedb.DirectiveBuckets...) defer func() { testbolt.MustCloseDB(t, db) testbolt.CleanupDB(t, db.Path()) }() - cfg := controller.Config{ - Schemar: schemar, - BoltDB: db, - StorageMethod: "boltdb", - Balancer: balancerdb.NewBalancer(db, schemar, logger.StderrLogger), - } + cfg := controller.Config{} con := controller.New(cfg) + con.Schemar = schemar + con.Balancer = balancerdb.NewBalancer(db, schemar, logger.StderrLogger) + con.DirectiveVersion = directivedb.NewDirectiveVersion(db) + con.BoltDB = db // Register two nodes. node0 := &dax.Node{ diff --git a/dax/mds/controller/director.go b/dax/controller/director.go similarity index 100% rename from dax/mds/controller/director.go rename to dax/controller/director.go diff --git a/dax/mds/controller/errors.go b/dax/controller/errors.go similarity index 100% rename from dax/mds/controller/errors.go rename to dax/controller/errors.go diff --git a/dax/mds/http/addressmanager.go b/dax/controller/http/addressmanager.go similarity index 100% rename from dax/mds/http/addressmanager.go rename to dax/controller/http/addressmanager.go diff --git a/dax/mds/controller/http/director.go b/dax/controller/http/director.go similarity index 98% rename from dax/mds/controller/http/director.go rename to dax/controller/http/director.go index c7969cc2e..429b80d72 100644 --- a/dax/mds/controller/http/director.go +++ b/dax/controller/http/director.go @@ -12,7 +12,7 @@ import ( "time" "github.com/featurebasedb/featurebase/v3/dax" - "github.com/featurebasedb/featurebase/v3/dax/mds/controller" + "github.com/featurebasedb/featurebase/v3/dax/controller" "github.com/featurebasedb/featurebase/v3/errors" "github.com/featurebasedb/featurebase/v3/logger" ) diff --git a/dax/mds/http/handler.go b/dax/controller/http/handler.go similarity index 91% rename from dax/mds/http/handler.go rename to dax/controller/http/handler.go index a371907b2..cb07735bd 100644 --- a/dax/mds/http/handler.go +++ b/dax/controller/http/handler.go @@ -5,19 +5,19 @@ import ( "net/http" "github.com/featurebasedb/featurebase/v3/dax" - "github.com/featurebasedb/featurebase/v3/dax/mds" + "github.com/featurebasedb/featurebase/v3/dax/controller" "github.com/gorilla/mux" ) -func Handler(mds *mds.MDS) http.Handler { +func Handler(c *controller.Controller) http.Handler { server := &server{ - mds: mds, + controller: c, } router := mux.NewRouter() router.HandleFunc("/health", server.getHealth).Methods("GET").Name("GetHealth") - // mds endpoints. + // controller endpoints. router.HandleFunc("/create-database", server.postCreateDatabase).Methods("POST").Name("PostCreateDatabase") router.HandleFunc("/drop-database", server.postDropDatabase).Methods("POST").Name("PostDropDatabase") router.HandleFunc("/database-by-id", server.postDatabaseByID).Methods("POST").Name("PostDatabaseByID") @@ -55,7 +55,7 @@ func Handler(mds *mds.MDS) http.Handler { } type server struct { - mds *mds.MDS + controller *controller.Controller } // GET /health @@ -76,7 +76,7 @@ func (s *server) postCreateDatabase(w http.ResponseWriter, r *http.Request) { return } - err := s.mds.CreateDatabase(ctx, req) + err := s.controller.CreateDatabase(ctx, req) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return @@ -101,7 +101,7 @@ func (s *server) postDropDatabase(w http.ResponseWriter, r *http.Request) { return } - err := s.mds.DropDatabase(ctx, req) + err := s.controller.DropDatabase(ctx, req) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return @@ -120,7 +120,7 @@ func (s *server) postDatabaseByID(w http.ResponseWriter, r *http.Request) { http.Error(w, err.Error(), http.StatusBadRequest) return } - resp, err := s.mds.DatabaseByID(ctx, qdbid) + resp, err := s.controller.DatabaseByID(ctx, qdbid) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return @@ -144,7 +144,7 @@ func (s *server) postDatabaseByName(w http.ResponseWriter, r *http.Request) { http.Error(w, err.Error(), http.StatusBadRequest) return } - resp, err := s.mds.DatabaseByName(ctx, req.OrganizationID, req.Name) + resp, err := s.controller.DatabaseByName(ctx, req.OrganizationID, req.Name) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return @@ -176,7 +176,7 @@ func (s *server) postDatabases(w http.ResponseWriter, r *http.Request) { ids := req.DatabaseIDs - resp, err := s.mds.Databases(ctx, req.OrganizationID, ids...) + resp, err := s.controller.Databases(ctx, req.OrganizationID, ids...) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return @@ -207,7 +207,7 @@ func (s *server) postCreateTable(w http.ResponseWriter, r *http.Request) { return } - err := s.mds.CreateTable(ctx, req) + err := s.controller.CreateTable(ctx, req) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return @@ -231,7 +231,7 @@ func (s *server) postTable(w http.ResponseWriter, r *http.Request) { http.Error(w, err.Error(), http.StatusBadRequest) return } - resp, err := s.mds.TableByID(ctx, qtid) + resp, err := s.controller.TableByID(ctx, qtid) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return @@ -256,7 +256,7 @@ func (s *server) postTableID(w http.ResponseWriter, r *http.Request) { return } - qtbl, err := s.mds.TableByName(ctx, req.QualifiedDatabaseID, req.Name) + qtbl, err := s.controller.TableByName(ctx, req.QualifiedDatabaseID, req.Name) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return @@ -282,7 +282,7 @@ func (s *server) postDropTable(w http.ResponseWriter, r *http.Request) { return } - err := s.mds.DropTable(ctx, req) + err := s.controller.DropTable(ctx, req) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return @@ -304,7 +304,7 @@ func (s *server) postCreateField(w http.ResponseWriter, r *http.Request) { qtid := req.TableKey.QualifiedTableID() - err := s.mds.CreateField(ctx, qtid, req.Field) + err := s.controller.CreateField(ctx, qtid, req.Field) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return @@ -331,7 +331,7 @@ func (s *server) postDropField(w http.ResponseWriter, r *http.Request) { qtid := req.Table - err := s.mds.DropField(ctx, qtid, req.Field) + err := s.controller.DropField(ctx, qtid, req.Field) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return @@ -359,7 +359,7 @@ func (s *server) postTables(w http.ResponseWriter, r *http.Request) { qdbid := dax.NewQualifiedDatabaseID(req.OrganizationID, req.DatabaseID) ids := req.TableIDs - resp, err := s.mds.Tables(ctx, qdbid, ids...) + resp, err := s.controller.Tables(ctx, qdbid, ids...) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return @@ -393,7 +393,7 @@ func (s *server) postIngestPartition(w http.ResponseWriter, r *http.Request) { qtid := req.Table - addr, err := s.mds.IngestPartition(ctx, qtid, req.Partition) + addr, err := s.controller.IngestPartition(ctx, qtid, req.Partition) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return @@ -433,7 +433,7 @@ func (s *server) postIngestShard(w http.ResponseWriter, r *http.Request) { qtid := req.Table - addr, err := s.mds.IngestShard(ctx, qtid, req.Shard) + addr, err := s.controller.IngestShard(ctx, qtid, req.Shard) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return @@ -472,7 +472,7 @@ func (s *server) postSnapshot(w http.ResponseWriter, r *http.Request) { return } - if err := s.mds.SnapshotTable(ctx, req); err != nil { + if err := s.controller.SnapshotTable(ctx, req); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } @@ -494,7 +494,7 @@ func (s *server) postSnapshotShardData(w http.ResponseWriter, r *http.Request) { qtid := req.Table - if err := s.mds.SnapshotShardData(ctx, qtid, req.Shard); err != nil { + if err := s.controller.SnapshotShardData(ctx, qtid, req.Shard); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } @@ -523,7 +523,7 @@ func (s *server) postSnapshotTableKeys(w http.ResponseWriter, r *http.Request) { qtid := req.Table - if err := s.mds.SnapshotTableKeys(ctx, qtid, req.Partition); err != nil { + if err := s.controller.SnapshotTableKeys(ctx, qtid, req.Partition); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } @@ -553,7 +553,7 @@ func (s *server) postSnapshotFieldKeys(w http.ResponseWriter, r *http.Request) { qtid := req.Table - if err := s.mds.SnapshotFieldKeys(ctx, qtid, req.Field); err != nil { + if err := s.controller.SnapshotFieldKeys(ctx, qtid, req.Field); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } @@ -585,7 +585,7 @@ func (s *server) postRegisterNode(w http.ResponseWriter, r *http.Request) { RoleTypes: req.RoleTypes, } - if err := s.mds.RegisterNode(ctx, node); err != nil { + if err := s.controller.RegisterNode(ctx, node); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } @@ -615,7 +615,7 @@ func (s *server) postRegisterNodes(w http.ResponseWriter, r *http.Request) { return } - if err := s.mds.RegisterNodes(ctx, req.Nodes...); err != nil { + if err := s.controller.RegisterNodes(ctx, req.Nodes...); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } @@ -640,7 +640,7 @@ func (s *server) postDeregisterNodes(w http.ResponseWriter, r *http.Request) { return } - if err := s.mds.DeregisterNodes(ctx, req.Addresses...); err != nil { + if err := s.controller.DeregisterNodes(ctx, req.Addresses...); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } @@ -670,7 +670,7 @@ func (s *server) postCheckInNode(w http.ResponseWriter, r *http.Request) { RoleTypes: req.RoleTypes, } - if err := s.mds.CheckInNode(ctx, node); err != nil { + if err := s.controller.CheckInNode(ctx, node); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } @@ -702,7 +702,7 @@ func (s *server) postComputeNodes(w http.ResponseWriter, r *http.Request) { qtid := req.Table - nodes, err := s.mds.ComputeNodes(ctx, qtid, req.Shards...) + nodes, err := s.controller.ComputeNodes(ctx, qtid, req.Shards) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return @@ -719,7 +719,7 @@ func (s *server) postComputeNodes(w http.ResponseWriter, r *http.Request) { } func (s *server) getDebugNodes(w http.ResponseWriter, r *http.Request) { - nodes, err := s.mds.DebugNodes(r.Context()) + nodes, err := s.controller.DebugNodes(r.Context()) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return @@ -765,7 +765,7 @@ func (s *server) postTranslateNodes(w http.ResponseWriter, r *http.Request) { qtid := req.Table - nodes, err := s.mds.TranslateNodes(ctx, qtid, req.Partitions...) + nodes, err := s.controller.TranslateNodes(ctx, qtid, req.Partitions) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return diff --git a/dax/mds/controller/node.go b/dax/controller/node.go similarity index 100% rename from dax/mds/controller/node.go rename to dax/controller/node.go diff --git a/dax/mds/controller/node_registerer.go b/dax/controller/node_registerer.go similarity index 100% rename from dax/mds/controller/node_registerer.go rename to dax/controller/node_registerer.go diff --git a/dax/mds/controller/partitioner/partitioner.go b/dax/controller/partitioner/partitioner.go similarity index 100% rename from dax/mds/controller/partitioner/partitioner.go rename to dax/controller/partitioner/partitioner.go diff --git a/dax/mds/controller/partitioner/partitioner_test.go b/dax/controller/partitioner/partitioner_test.go similarity index 95% rename from dax/mds/controller/partitioner/partitioner_test.go rename to dax/controller/partitioner/partitioner_test.go index 92faf000a..fc6dc71a7 100644 --- a/dax/mds/controller/partitioner/partitioner_test.go +++ b/dax/controller/partitioner/partitioner_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/featurebasedb/featurebase/v3/dax" - "github.com/featurebasedb/featurebase/v3/dax/mds/controller/partitioner" + "github.com/featurebasedb/featurebase/v3/dax/controller/partitioner" "github.com/stretchr/testify/assert" ) diff --git a/dax/mds/poller/config.go b/dax/controller/poller/config.go similarity index 100% rename from dax/mds/poller/config.go rename to dax/controller/poller/config.go diff --git a/dax/mds/poller/interfaces.go b/dax/controller/poller/interfaces.go similarity index 100% rename from dax/mds/poller/interfaces.go rename to dax/controller/poller/interfaces.go diff --git a/dax/mds/poller/poller.go b/dax/controller/poller/poller.go similarity index 100% rename from dax/mds/poller/poller.go rename to dax/controller/poller/poller.go diff --git a/dax/mds/poller/poller_test.go b/dax/controller/poller/poller_test.go similarity index 95% rename from dax/mds/poller/poller_test.go rename to dax/controller/poller/poller_test.go index 9db836a01..56746c25f 100644 --- a/dax/mds/poller/poller_test.go +++ b/dax/controller/poller/poller_test.go @@ -11,8 +11,8 @@ import ( "time" "github.com/featurebasedb/featurebase/v3/dax" - mdshttp "github.com/featurebasedb/featurebase/v3/dax/mds/http" - "github.com/featurebasedb/featurebase/v3/dax/mds/poller" + controllerhttp "github.com/featurebasedb/featurebase/v3/dax/controller/http" + "github.com/featurebasedb/featurebase/v3/dax/controller/poller" "github.com/featurebasedb/featurebase/v3/errors" "github.com/featurebasedb/featurebase/v3/logger" "github.com/stretchr/testify/assert" @@ -50,7 +50,7 @@ func TestPoller(t *testing.T) { t.Run("Poller", func(t *testing.T) { cfg := poller.Config{ - AddressManager: mdshttp.NewAddressManager(managerAddr), + AddressManager: controllerhttp.NewAddressManager(managerAddr), NodePoller: poller.NewHTTPNodePoller(logger.NopLogger), NodeService: nodeService, } @@ -110,7 +110,7 @@ func newMockManager(t *testing.T, ctx context.Context, deregisterPath string, no body := r.Body defer body.Close() - req := mdshttp.DeregisterNodesRequest{} + req := controllerhttp.DeregisterNodesRequest{} if err := json.NewDecoder(body).Decode(&req); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return diff --git a/dax/mds/schemar/boltdb/schemar.go b/dax/controller/schemar/boltdb/schemar.go similarity index 99% rename from dax/mds/schemar/boltdb/schemar.go rename to dax/controller/schemar/boltdb/schemar.go index 10d3c5710..5e2fcc5ab 100644 --- a/dax/mds/schemar/boltdb/schemar.go +++ b/dax/controller/schemar/boltdb/schemar.go @@ -11,7 +11,7 @@ import ( "github.com/featurebasedb/featurebase/v3/dax" "github.com/featurebasedb/featurebase/v3/dax/boltdb" - "github.com/featurebasedb/featurebase/v3/dax/mds/schemar" + "github.com/featurebasedb/featurebase/v3/dax/controller/schemar" "github.com/featurebasedb/featurebase/v3/errors" "github.com/featurebasedb/featurebase/v3/logger" ) diff --git a/dax/mds/schemar/boltdb/schemar_test.go b/dax/controller/schemar/boltdb/schemar_test.go similarity index 98% rename from dax/mds/schemar/boltdb/schemar_test.go rename to dax/controller/schemar/boltdb/schemar_test.go index 20a1d4e27..9d31266f8 100644 --- a/dax/mds/schemar/boltdb/schemar_test.go +++ b/dax/controller/schemar/boltdb/schemar_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/featurebasedb/featurebase/v3/dax" - "github.com/featurebasedb/featurebase/v3/dax/mds/schemar/boltdb" + "github.com/featurebasedb/featurebase/v3/dax/controller/schemar/boltdb" daxtest "github.com/featurebasedb/featurebase/v3/dax/test" testbolt "github.com/featurebasedb/featurebase/v3/dax/test/boltdb" "github.com/featurebasedb/featurebase/v3/errors" diff --git a/dax/mds/schemar/errors.go b/dax/controller/schemar/errors.go similarity index 100% rename from dax/mds/schemar/errors.go rename to dax/controller/schemar/errors.go diff --git a/dax/mds/schemar/schemar.go b/dax/controller/schemar/schemar.go similarity index 100% rename from dax/mds/schemar/schemar.go rename to dax/controller/schemar/schemar.go diff --git a/dax/controller/service/controller.go b/dax/controller/service/controller.go new file mode 100644 index 000000000..027c6d5d9 --- /dev/null +++ b/dax/controller/service/controller.go @@ -0,0 +1,119 @@ +package service + +import ( + "net/http" + "os" + + "github.com/featurebasedb/featurebase/v3/dax" + "github.com/featurebasedb/featurebase/v3/dax/boltdb" + "github.com/featurebasedb/featurebase/v3/dax/controller" + balancerboltdb "github.com/featurebasedb/featurebase/v3/dax/controller/balancer/boltdb" + controllerhttp "github.com/featurebasedb/featurebase/v3/dax/controller/http" + schemarboltdb "github.com/featurebasedb/featurebase/v3/dax/controller/schemar/boltdb" + "github.com/featurebasedb/featurebase/v3/errors" + "github.com/featurebasedb/featurebase/v3/logger" + fbnet "github.com/featurebasedb/featurebase/v3/net" +) + +// Ensure type implements interface. +var _ dax.Service = (*controllerService)(nil) + +type controllerService struct { + uri *fbnet.URI + controller *controller.Controller + + // Because we stopped using a storage method interface, and always use bolt, + // we need to be sure to close the boltDBs that are created in controller.New() + // whenever controller.Stop() is called. These are pointers to that DB so we can + // close it. + boltDB *boltdb.DB + + logger logger.Logger +} + +func New(uri *fbnet.URI, cfg controller.Config) *controllerService { + // Set up logger. + var logr logger.Logger = logger.StderrLogger + if cfg.Logger != nil { + logr = cfg.Logger + } + + // Storage methods. + if cfg.StorageMethod != "boltdb" && cfg.StorageMethod != "" { + logr.Printf("storagemethod %s not supported, try 'boltdb'", cfg.StorageMethod) + } + + if cfg.DataDir == "" { + dir, err := os.MkdirTemp("", "controller_*") + if err != nil { + logr.Printf("Making temp dir for Controller storage: %v", err) + os.Exit(1) + } + cfg.DataDir = dir + logr.Warnf("no DataDir given (like '/path/to/directory'); using temp dir at '%s'", cfg.DataDir) + } + + buckets := append(schemarboltdb.SchemarBuckets, balancerboltdb.BalancerBuckets...) + + controllerDB, err := boltdb.NewSvcBolt(cfg.DataDir, "controller", buckets...) + if err != nil { + logr.Printf(errors.Wrap(err, "creating controller bolt").Error()) + os.Exit(1) + } + + schemar := schemarboltdb.NewSchemar(controllerDB, logr) + balancer := balancerboltdb.NewBalancer(controllerDB, schemar, logr) + + // Directive version. + if err := controllerDB.InitializeBuckets(boltdb.DirectiveBuckets...); err != nil { + logr.Panicf("initializing directive buckets: %v", err) + } + directiveVersion := boltdb.NewDirectiveVersion(controllerDB) + + // Controller. + controller := controller.New(cfg) + controller.Schemar = schemar + controller.Balancer = balancer + controller.DirectiveVersion = directiveVersion + controller.BoltDB = controllerDB + + if cfg.Director != nil { + controller.Director = cfg.Director + } + + return &controllerService{ + uri: uri, + controller: controller, + boltDB: controllerDB, + logger: logr, + } +} + +func (m *controllerService) Start() error { + // Start controller service. + if err := m.controller.Start(); err != nil { + return errors.Wrap(err, "starting controller") + } + return nil +} + +func (m *controllerService) Stop() error { + err := m.controller.Stop() + if err != nil { + m.logger.Warnf("error stopping controller: %v", err) + } + + if m.boltDB != nil { + m.boltDB.Close() + } + + return err +} + +func (m *controllerService) Address() dax.Address { + return dax.Address(m.uri.HostPort() + "/" + dax.ServicePrefixController) +} + +func (m *controllerService) HTTPHandler() http.Handler { + return controllerhttp.Handler(m.controller) +} diff --git a/dax/mds/controller/sets.go b/dax/controller/sets.go similarity index 100% rename from dax/mds/controller/sets.go rename to dax/controller/sets.go diff --git a/dax/mds/controller/snapping_turtle.go b/dax/controller/snapping_turtle.go similarity index 98% rename from dax/mds/controller/snapping_turtle.go rename to dax/controller/snapping_turtle.go index 641555927..76ca5eb84 100644 --- a/dax/mds/controller/snapping_turtle.go +++ b/dax/controller/snapping_turtle.go @@ -31,7 +31,7 @@ func (c *Controller) snapAll() { c.logger.Debugf("TURTLE: snapAll") ctx := context.Background() - tx, err := c.boltDB.BeginTx(ctx, false) + tx, err := c.BoltDB.BeginTx(ctx, false) if err != nil { c.logger.Printf("Error getting transaction for snapping turtle: %v", err) return diff --git a/dax/mds/controller/stringers.go b/dax/controller/stringers.go similarity index 100% rename from dax/mds/controller/stringers.go rename to dax/controller/stringers.go diff --git a/dax/dax.go b/dax/dax.go index 301521b86..48c4314c1 100644 --- a/dax/dax.go +++ b/dax/dax.go @@ -4,7 +4,7 @@ package dax // ServicePrefixes are used as the service prefix value in http handlers. const ( ServicePrefixComputer = "computer" - ServicePrefixMDS = "mds" + ServicePrefixController = "controller" ServicePrefixQueryer = "queryer" ServicePrefixSnapshotter = "snapshotter" ServicePrefixWritelogger = "writelogger" diff --git a/dax/directive.go b/dax/directive.go index c7ffde19a..4247ea0ef 100644 --- a/dax/directive.go +++ b/dax/directive.go @@ -1,8 +1,8 @@ package dax -// Directive contains the instructions, sent from MDS, which a compute node is -// to follow. A Directive is typically JSON-encoded and POSTed to a compute -// node's `/directive` endpoint. +// Directive contains the instructions, sent from the Controller, which a +// compute node is to follow. A Directive is typically JSON-encoded and POSTed +// to a compute node's `/directive` endpoint. type Directive struct { Address Address `json:"address"` diff --git a/dax/docker-compose.yml b/dax/docker-compose.yml index a22fa75fc..4b8b9592a 100644 --- a/dax/docker-compose.yml +++ b/dax/docker-compose.yml @@ -1,15 +1,15 @@ version: '3' services: - mds: + controller: build: context: ../.quick dockerfile: ../Dockerfile-dax-quick environment: FEATUREBASE_BIND: 0.0.0.0:8080 FEATUREBASE_VERBOSE: "true" - FEATUREBASE_MDS_RUN: "true" - FEATUREBASE_CONFIG_DATA_DIR: file:/dax-data/mds + FEATUREBASE_CONTROLLER_RUN: "true" + FEATUREBASE_CONFIG_DATA_DIR: file:/dax-data/controller ports: - "8081:8080" @@ -21,9 +21,9 @@ services: FEATUREBASE_BIND: 0.0.0.0:8080 FEATUREBASE_VERBOSE: "true" FEATUREBASE_QUERYER_RUN: "true" - FEATUREBASE_QUERYER_CONFIG_MDS_ADDRESS: "mds:8080/mds" + FEATUREBASE_QUERYER_CONFIG_CONTROLLER_ADDRESS: "controller:8080/controller" depends_on: - - mds + - controller ports: - "8080:8080" @@ -33,7 +33,7 @@ services: dockerfile: ../Dockerfile-dax-quick environment: FEATUREBASE_COMPUTER_RUN: "true" - FEATUREBASE_COMPUTER_CONFIG_MDS_ADDRESS: "mds:8080/mds" + FEATUREBASE_COMPUTER_CONFIG_CONTROLLER_ADDRESS: "controller:8080/controller" FEATUREBASE_COMPUTER_CONFIG_DATA_DIR: /dax-data/computer FEATUREBASE_COMPUTER_CONFIG_VERBOSE: true FEATUREBASE_BIND: 0.0.0.0:8080 @@ -45,7 +45,7 @@ services: - "./dax-data/writelogger:/dax-data/writelogger" - "./dax-data/snapshotter:/dax-data/snapshotter" depends_on: - - mds + - controller deploy: replicas: 1 @@ -60,5 +60,5 @@ services: GEN_FEATUREBASE_DB_ID: "testdb" GEN_USE_SHARD_TRANSACTIONAL_ENDPOINT: "true" GEN_SOURCE: "custom" - GEN_TARGET: "mds" - GEN_MDS_ADDRESS: "mds:8080/mds" + GEN_TARGET: "serverless" + GEN_CONTROLLER_ADDRESS: "controller:8080/controller" diff --git a/dax/http/handler.go b/dax/http/handler.go index 78211a8a4..0d4793403 100644 --- a/dax/http/handler.go +++ b/dax/http/handler.go @@ -7,7 +7,7 @@ import ( "runtime/debug" "time" - "github.com/featurebasedb/featurebase/v3/dax/mds" + "github.com/featurebasedb/featurebase/v3/dax/controller" "github.com/featurebasedb/featurebase/v3/dax/queryer" "github.com/featurebasedb/featurebase/v3/dax/snapshotter" "github.com/featurebasedb/featurebase/v3/dax/writelogger" @@ -29,7 +29,7 @@ type Handler struct { server *http.Server - mds *mds.MDS + controller *controller.Controller writeLogger *writelogger.Writelogger snapshotter *snapshotter.Snapshotter queryer *queryer.Queryer @@ -49,9 +49,9 @@ func OptHandlerBind(b string) HandlerOption { } } -func OptHandlerMDS(m *mds.MDS) HandlerOption { +func OptHandlerController(c *controller.Controller) HandlerOption { return func(h *Handler) error { - h.mds = m + h.controller = c return nil } } diff --git a/dax/mds/api/openapi.yaml b/dax/mds/api/openapi.yaml deleted file mode 100644 index bf4f84488..000000000 --- a/dax/mds/api/openapi.yaml +++ /dev/null @@ -1,548 +0,0 @@ -openapi: 3.0.3 - -info: - title: MDS - description: Metadata Services. - version: 0.0.0 - -paths: - /mds/health: - get: - summary: Health check endpoint. - description: Provides an endpoint to check the overall health of the MDS service. - operationId: GetHealth - responses: - 200: - description: Service is healthy. - - /mds/create-table: - post: - summary: Create a table. - description: Create a table based on the provided schema. - operationId: PostCreateTable - requestBody: - content: - application/json: - examples: - table: - $ref: '#/components/examples/Table' - schema: - $ref: '#/components/schemas/Table' - responses: - 200: - $ref: '#/components/responses/CreateTableResponse' - - /mds/drop-table: - post: - summary: Drop a table. - description: Drop a table based on the provided table name. - operationId: PostDropTable - requestBody: - content: - application/json: - example: - name: tbl - schema: - type: object - properties: - name: - type: string - responses: - 200: - description: Table was dropped. - - /mds/create-field: - post: - summary: Create a field. - description: Create a field based on the provided table and schema. - operationId: PostCreateField - requestBody: - content: - application/json: - example: - table: tbl - field: - name: a_string - type: string - options: - cacheType: ranked - cacheSize: 50000 - schema: - $ref: '#/components/schemas/TableField' - responses: - 200: - description: Field was created. - - /mds/drop-field: - post: - summary: Drop a field. - description: Drop a field based on the provided table and field name. - operationId: PostDropField - requestBody: - content: - application/json: - example: - table: tbl - field: fld - schema: - type: object - properties: - table: - type: string - field: - type: string - responses: - 200: - description: Field was dropped. - - /mds/table: - post: - summary: Get a table. - description: Get a table based on the provided table name. - operationId: PostTable - requestBody: - content: - application/json: - example: - name: tbl - schema: - type: object - properties: - name: - type: string - responses: - 200: - $ref: '#/components/responses/Table' - - /mds/tables: - post: - summary: Get a list of table. - description: Get a list of tables. If a filter is provided, only those tables will be included in the result. - operationId: PostTables - requestBody: - content: - application/json: - example: - names: - - tbl1 - - tbl2 - schema: - type: object - properties: - names: - type: array - items: - type: string - responses: - 200: - $ref: '#/components/responses/Tables' - - /mds/ingest-partition: - post: - summary: Request to ingest partition data. - description: Request to ingest (write) partition data. The address of the compute node responsible is returned. - operationId: PostIngestPartition - requestBody: - content: - application/json: - example: - table: tbl - partition: 7 - schema: - type: object - properties: - table: - type: string - partition: - type: integer - format: int32 - responses: - 200: - $ref: '#/components/responses/Address' - - /mds/ingest-shard: - post: - summary: Request to ingest shard data. - description: Request to ingest (write) shard data. The address of the compute node responsible is returned. - operationId: PostIngestShard - requestBody: - content: - application/json: - example: - table: tbl - shard: 12 - schema: - type: object - properties: - table: - type: string - shard: - type: integer - format: int64 - responses: - 200: - $ref: '#/components/responses/Address' - - /mds/snapshot/shard-data: - post: - summary: Request to snapshot shard data. - description: Request to snapshot shard data. - operationId: PostSnapshotShardData - requestBody: - content: - application/json: - example: - table: tbl - shard: 12 - schema: - type: object - properties: - table: - type: string - shard: - type: integer - format: int64 - responses: - 200: - description: Shard snapshot was successful. - - /mds/snapshot/table-keys: - post: - summary: Request to snapshot table keys. - description: Request to snapshot table keys. - operationId: PostSnapshotTableKeys - requestBody: - content: - application/json: - example: - table: tbl - partition: 7 - schema: - type: object - properties: - table: - type: string - partition: - type: integer - format: int32 - responses: - 200: - description: Table keys snapshot was successful. - - /mds/snapshot/field-keys: - post: - summary: Request to snapshot field keys. - description: Request to snapshot field keys. - operationId: PostSnapshotFieldKeys - requestBody: - content: - application/json: - example: - table: tbl - field: fld - schema: - type: object - properties: - table: - type: string - field: - type: string - responses: - 200: - description: Field keys snapshot was successful. - - /mds/register-node: - post: - summary: Register node. - description: Register a node with MDS. - operationId: PostRegisterNode - requestBody: - content: - application/json: - example: - address: 10.0.0.1:8000 - roleTypes: - - compute - - translate - schema: - type: object - properties: - address: - type: string - roleTypes: - type: array - items: - types: string - responses: - 200: - description: Node registration was successful. - - /mds/deregister-nodes: - post: - summary: Deregister nodes. - description: Deregister nodes with MDS. - operationId: PostDeregisterNodes - requestBody: - content: - application/json: - example: - address: 10.0.0.1:8000 - schema: - type: object - properties: - address: - type: string - responses: - 200: - description: Node deregistration was successful. - - /mds/compute-nodes: - post: - summary: Get compute nodes. - description: Get the compute nodes responsible for the given shards. - operationId: PostComputeNodes - requestBody: - content: - application/json: - example: - table: tbl - shards: - - 10 - - 11 - - 12 - isWrite: false - schema: - type: object - properties: - table: - type: string - shards: - type: array - items: - type: integer - format: int64 - isWrite: - type: boolean - responses: - 200: - $ref: '#/components/responses/ComputeNodes' - - /mds/translate-nodes: - post: - summary: Get translate nodes. - description: Get the translate nodes responsible for the given partitions. - operationId: PostTranslateNodes - requestBody: - content: - application/json: - example: - table: tbl - partitions: - - 6 - - 7 - isWrite: false - schema: - type: object - properties: - table: - type: string - partitions: - type: array - items: - type: integer - format: int32 - isWrite: - type: boolean - responses: - 200: - $ref: '#/components/responses/TranslateNodes' - -components: - responses: - CreateTableResponse: - description: Placeholder response. - content: - application/json: - schema: - type: object - - Address: - description: Single node address. - content: - application/json: - schema: - type: object - properties: - address: - type: string - - Table: - description: Table response. - content: - application/json: - schema: - $ref: '#/components/schemas/Table' - - Tables: - description: Tables response. - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/Table' - - ComputeNodes: - description: Compute nodes response. - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/ComputeNode' - - TranslateNodes: - description: Translate nodes response. - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/TranslateNode' - - schemas: - ComputeNode: - type: object - properties: - address: - type: string - table: - type: string - shards: - type: array - items: - type: integer - format: int64 - - TranslateNode: - type: object - properties: - address: - type: string - table: - type: string - partitions: - type: array - items: - type: integer - format: int32 - - Table: - type: object - properties: - name: - type: string - fields: - type: array - items: - $ref: '#/components/schemas/Field' - partitionN: - type: integer - format: int32 - - TableField: - type: object - properties: - table: - type: string - field: - $ref: '#/components/schemas/Field' - - Field: - type: object - properties: - name: - type: string - type: - type: string - enum: - - bool - - decimal - - id - - idset - - int - - string - - stringset - - timestamp - options: - type: object - properties: - min: - type: integer - format: int64 - max: - type: integer - format: int64 - scale: - type: integer - format: int64 - minimum: 0 - noStandardView: - type: boolean - cacheType: - type: string - cacheSize: - type: integer - format: int32 - timeUnit: - type: string - epoch: - type: string - format: date-time - timeQuantum: - type: string - ttl: - type: string - foreignIndex: - type: string - - examples: - Table: - name: tbl - fields: - - name: _id - type: string - - name: a_bool - type: bool - - name: an_id - type: id - options: - cacheType: ranked - cacheSize: 50000 - - name: an_id_set - type: idset - options: - cacheType: ranked - cacheSize: 50000 - - name: a_string - type: string - options: - cacheType: ranked - cacheSize: 50000 - - name: a_string_set - type: stringset - options: - cacheType: ranked - cacheSize: 50000 - - name: an_int - type: int - options: - min: -100 - max: 500 - - name: a_decimal - type: decimal - options: - min: -10.24 - max: 50.75 - scale: 2 - partitionN: 16 diff --git a/dax/mds/mds.go b/dax/mds/mds.go deleted file mode 100644 index ed155d42f..000000000 --- a/dax/mds/mds.go +++ /dev/null @@ -1,300 +0,0 @@ -// Package mds provides the overall interface to Metadata Services. -package mds - -import ( - "context" - "os" - "sync" - "time" - - "github.com/featurebasedb/featurebase/v3/dax" - "github.com/featurebasedb/featurebase/v3/dax/boltdb" - "github.com/featurebasedb/featurebase/v3/dax/computer" - "github.com/featurebasedb/featurebase/v3/dax/mds/controller" - balancerboltdb "github.com/featurebasedb/featurebase/v3/dax/mds/controller/balancer/boltdb" - "github.com/featurebasedb/featurebase/v3/dax/mds/poller" - "github.com/featurebasedb/featurebase/v3/dax/mds/schemar" - schemarboltdb "github.com/featurebasedb/featurebase/v3/dax/mds/schemar/boltdb" - "github.com/featurebasedb/featurebase/v3/errors" - "github.com/featurebasedb/featurebase/v3/logger" -) - -type Config struct { - // TODO(jaffee) director on config is a bit weird? Shouldn't this be set up internally? - Director controller.Director `toml:"-"` - // RegistrationBatchTimeout is the time that the controller will - // wait after a node registers itself to see if any more nodes - // will register before sending out directives to all nodes which - // have been registered. - RegistrationBatchTimeout time.Duration `toml:"registration-batch-timeout"` - - SnappingTurtleTimeout time.Duration - - // Poller - PollInterval time.Duration `toml:"poll-interval"` - - // Storage - StorageMethod string `toml:"-"` - DataDir string `toml:"-"` - - SnapshotterDir string `toml:"snapshotter-dir"` - WriteloggerDir string `toml:"writelogger-dir"` - - // Logger - Logger logger.Logger `toml:"-"` -} - -// Ensure type implements interface. -var _ computer.Registrar = (*MDS)(nil) -var _ dax.Schemar = (*MDS)(nil) - -// MDS provides public MDS methods for an MDS service. -type MDS struct { - mu sync.RWMutex - - controller *controller.Controller - poller *poller.Poller - schemar schemar.Schemar - - // Because we stopped using a storage method interface, and always use bolt, - // we need to be sure to close the boltDBs that are created in mds.New() - // whenever mds.Close() is called. These are pointers to those DBs so we can - // close them. - controllerDB *boltdb.DB - - logger logger.Logger -} - -// New returns a new instance of MDS. -func New(cfg Config) *MDS { - // Set up logger. - var logr logger.Logger = logger.StderrLogger - if cfg.Logger != nil { - logr = cfg.Logger - } - - // Storage methods. - if cfg.StorageMethod != "boltdb" && cfg.StorageMethod != "" { - logr.Printf("storagemethod %s not supported, try 'boltdb'", cfg.StorageMethod) - } - - cfg.StorageMethod = "boltdb" - - if cfg.DataDir == "" { - dir, err := os.MkdirTemp("", "mds_*") - if err != nil { - logr.Printf("Making temp dir for MDS storage: %v", err) - os.Exit(1) - } - cfg.DataDir = dir - logr.Warnf("no DataDir given (like '/path/to/directory') using temp dir at '%s'", cfg.DataDir) - } - - buckets := append(schemarboltdb.SchemarBuckets, balancerboltdb.BalancerBuckets...) - controllerDB, err := boltdb.NewSvcBolt(cfg.DataDir, "controller", buckets...) - if err != nil { - logr.Printf(errors.Wrap(err, "creating controller bolt").Error()) - os.Exit(1) - } - - schemar := schemarboltdb.NewSchemar(controllerDB, logr) - - controllerCfg := controller.Config{ - Director: cfg.Director, - Schemar: schemar, - - Balancer: balancerboltdb.NewBalancer(controllerDB, schemar, logr), - - RegistrationBatchTimeout: cfg.RegistrationBatchTimeout, - SnappingTurtleTimeout: cfg.SnappingTurtleTimeout, - SnapshotterDir: cfg.SnapshotterDir, - WriteloggerDir: cfg.WriteloggerDir, - - StorageMethod: cfg.StorageMethod, - // just reusing this bolt for internal controller svcs - // rn... ultimately controller shouldn't know what bolt is at - // all - BoltDB: controllerDB, - - Logger: logr, - } - controller := controller.New(controllerCfg) - - pollerCfg := poller.Config{ - AddressManager: controller, - NodeService: controller, - NodePoller: poller.NewHTTPNodePoller(logr), - PollInterval: cfg.PollInterval, - Logger: logr, - } - poller := poller.New(pollerCfg) - - return &MDS{ - controller: controller, - poller: poller, - schemar: schemar, - - controllerDB: controllerDB, - - logger: logr, - } -} - -//////////////////////////////////////////////////// -// mds specific endpoints -//////////////////////////////////////////////////// - -// Start starts MDS services, such as the Poller. -func (m *MDS) Start() error { - m.poller.Run() - return m.controller.Run() -} - -// Stop stops MDS services, such as the Poller and the controller's node -// registration routine. -func (m *MDS) Stop() error { - m.poller.Stop() - m.controller.Stop() - - if m.controllerDB != nil { - m.controllerDB.Close() - } - - return nil -} - -// CreateDatabase handles a create table request. -func (m *MDS) CreateDatabase(ctx context.Context, qdb *dax.QualifiedDatabase) error { - return m.controller.CreateDatabase(ctx, qdb) -} - -func (m *MDS) DropDatabase(ctx context.Context, qdbid dax.QualifiedDatabaseID) error { - return m.controller.DropDatabase(ctx, qdbid) -} - -func (m *MDS) DatabaseByName(ctx context.Context, orgID dax.OrganizationID, dbname dax.DatabaseName) (*dax.QualifiedDatabase, error) { - return m.controller.DatabaseByName(ctx, orgID, dbname) -} - -func (m *MDS) DatabaseByID(ctx context.Context, qdbid dax.QualifiedDatabaseID) (*dax.QualifiedDatabase, error) { - return m.controller.DatabaseByID(ctx, qdbid) -} - -func (m *MDS) Databases(ctx context.Context, orgID dax.OrganizationID, ids ...dax.DatabaseID) ([]*dax.QualifiedDatabase, error) { - return m.controller.Databases(ctx, orgID, ids...) -} - -// CreateTable handles a create table request. -func (m *MDS) CreateTable(ctx context.Context, qtbl *dax.QualifiedTable) error { - return m.controller.CreateTable(ctx, qtbl) -} - -// DropTable handles a drop table request. // TODO(jaffee) how do we -// reason about consistency here? What if controller DropTable -// succeeds, but schemar fails? -func (m *MDS) DropTable(ctx context.Context, qtid dax.QualifiedTableID) error { - return m.controller.DropTable(ctx, qtid) -} - -// CreateField handles a create Field request. -func (m *MDS) CreateField(ctx context.Context, qtid dax.QualifiedTableID, fld *dax.Field) error { - return m.controller.CreateField(ctx, qtid, fld) -} - -// DropField handles a drop Field request. -func (m *MDS) DropField(ctx context.Context, qtid dax.QualifiedTableID, fldName dax.FieldName) error { - return m.controller.DropField(ctx, qtid, fldName) -} - -// TableByID handles a table request. -func (m *MDS) TableByID(ctx context.Context, qtid dax.QualifiedTableID) (*dax.QualifiedTable, error) { - return m.controller.TableByID(ctx, qtid) -} - -// Tables handles a tables request. -func (m *MDS) Tables(ctx context.Context, qdbid dax.QualifiedDatabaseID, ids ...dax.TableID) ([]*dax.QualifiedTable, error) { - return m.controller.Tables(ctx, qdbid, ids...) -} - -// TableByName handles a table id (i.e. by name) request. -func (m *MDS) TableByName(ctx context.Context, qdbid dax.QualifiedDatabaseID, name dax.TableName) (*dax.QualifiedTable, error) { - return m.controller.TableByName(ctx, qdbid, name) -} - -// IngestPartition handles an ingest partition request. -func (m *MDS) IngestPartition(ctx context.Context, qtid dax.QualifiedTableID, partnNum dax.PartitionNum) (dax.Address, error) { - return m.controller.IngestPartition(ctx, qtid, partnNum) -} - -// IngestShard handles an ingest shard request. -func (m *MDS) IngestShard(ctx context.Context, qtid dax.QualifiedTableID, shrdNum dax.ShardNum) (dax.Address, error) { - return m.controller.IngestShard(ctx, qtid, shrdNum) -} - -// SnapshotTable handles a snapshot table request. -func (m *MDS) SnapshotTable(ctx context.Context, qtid dax.QualifiedTableID) error { - return m.controller.SnapshotTable(ctx, qtid) -} - -// SnapshotShardData handles a snapshot shard request. -func (m *MDS) SnapshotShardData(ctx context.Context, qtid dax.QualifiedTableID, shardNum dax.ShardNum) error { - return m.controller.SnapshotShardData(ctx, qtid, shardNum) -} - -// SnapshotTableKeys handles a snapshot table/keys request. -func (m *MDS) SnapshotTableKeys(ctx context.Context, qtid dax.QualifiedTableID, partitionNum dax.PartitionNum) error { - return m.controller.SnapshotTableKeys(ctx, qtid, partitionNum) -} - -// SnapshotFieldKeys handles a snapshot field/keys request. -func (m *MDS) SnapshotFieldKeys(ctx context.Context, qtid dax.QualifiedTableID, fldName dax.FieldName) error { - return m.controller.SnapshotFieldKeys(ctx, qtid, fldName) -} - -//////////////////////////////////////////////////// -// controller specific endpoints -// These are just pass-throughs for now. -//////////////////////////////////////////////////// - -// RegisterNode handles a node registration request. It does not -// synchronously do much of anything, but the node will eventually -// probably get a directive... unless the MDS crashes or something in -// which case the fact that this endpoint was ever called will be lost -// to time. -func (m *MDS) RegisterNode(ctx context.Context, node *dax.Node) error { - return m.controller.RegisterNode(ctx, node) -} - -// CheckInNode handles a node check-in request. If MDS is not aware of the node, -// it will be sent through the RegisterNode process. -func (m *MDS) CheckInNode(ctx context.Context, node *dax.Node) error { - return m.controller.CheckInNode(ctx, node) -} - -// RegisterNodes immediately registers the given nodes and sends out -// new directives synchronously, bypassing the wait time of the -// RegisterNode endpoint. -func (m *MDS) RegisterNodes(ctx context.Context, nodes ...*dax.Node) error { - return m.controller.RegisterNodes(ctx, nodes...) -} - -// DeregisterNodes handles a request to deregister multiple nodes at once. -func (m *MDS) DeregisterNodes(ctx context.Context, addrs ...dax.Address) error { - return m.controller.DeregisterNodes(ctx, addrs...) -} - -// ComputeNodes gets the compute nodes responsible for the table/shards -// specified in the ComputeNodeRequest. -func (m *MDS) ComputeNodes(ctx context.Context, qtid dax.QualifiedTableID, shardNums ...dax.ShardNum) ([]dax.ComputeNode, error) { - return m.controller.ComputeNodes(ctx, qtid, shardNums) -} - -func (m *MDS) DebugNodes(ctx context.Context) ([]*dax.Node, error) { - return m.controller.DebugNodes(ctx) -} - -// TranslateNodes gets the translate nodes responsible for the table/partitions -// specified in the TranslateNodeRequest. -func (m *MDS) TranslateNodes(ctx context.Context, qtid dax.QualifiedTableID, partitionNums ...dax.PartitionNum) ([]dax.TranslateNode, error) { - return m.controller.TranslateNodes(ctx, qtid, partitionNums) -} diff --git a/dax/mds/service/mds.go b/dax/mds/service/mds.go deleted file mode 100644 index b4912effd..000000000 --- a/dax/mds/service/mds.go +++ /dev/null @@ -1,46 +0,0 @@ -package service - -import ( - "net/http" - - "github.com/featurebasedb/featurebase/v3/dax" - "github.com/featurebasedb/featurebase/v3/dax/mds" - mdshttp "github.com/featurebasedb/featurebase/v3/dax/mds/http" - "github.com/featurebasedb/featurebase/v3/errors" - fbnet "github.com/featurebasedb/featurebase/v3/net" -) - -// Ensure type implements interface. -var _ dax.Service = (*mdsService)(nil) - -type mdsService struct { - uri *fbnet.URI - mds *mds.MDS -} - -func New(uri *fbnet.URI, mds *mds.MDS) *mdsService { - return &mdsService{ - uri: uri, - mds: mds, - } -} - -func (m *mdsService) Start() error { - // Start mds service. - if err := m.mds.Start(); err != nil { - return errors.Wrap(err, "starting mds") - } - return nil -} - -func (m *mdsService) Stop() error { - return m.mds.Stop() -} - -func (m *mdsService) Address() dax.Address { - return dax.Address(m.uri.HostPort() + "/" + dax.ServicePrefixMDS) -} - -func (m *mdsService) HTTPHandler() http.Handler { - return mdshttp.Handler(m.mds) -} diff --git a/dax/queryer/client/client.go b/dax/queryer/client/client.go index eead12ca8..0e9dec772 100644 --- a/dax/queryer/client/client.go +++ b/dax/queryer/client/client.go @@ -1,4 +1,4 @@ -// Package client is an HTTP client for MDS. +// Package client is an HTTP client for the Queryer. package client import ( @@ -20,8 +20,8 @@ const ( defaultScheme = "http" ) -// Client is an HTTP client that operates on the MDS endpoints exposed by the -// main MDS service. +// Client is an HTTP client that operates on the Controller endpoints exposed by +// the main Controller service. type Client struct { address dax.Address logger logger.Logger diff --git a/dax/queryer/config.go b/dax/queryer/config.go index 9fcc04134..28fc36d38 100644 --- a/dax/queryer/config.go +++ b/dax/queryer/config.go @@ -12,6 +12,6 @@ import ( // We initially did that with something called "Injections", but that separation // was a bit premature. type Config struct { - MDSAddress string `toml:"mds-address"` - Logger logger.Logger `toml:"-"` + ControllerAddress string `toml:"controller-address"` + Logger logger.Logger `toml:"-"` } diff --git a/dax/queryer/orchestrator.go b/dax/queryer/orchestrator.go index 23caf109e..9ff35381d 100644 --- a/dax/queryer/orchestrator.go +++ b/dax/queryer/orchestrator.go @@ -44,17 +44,17 @@ type Topologer interface { ComputeNodes(ctx context.Context, index string, shards []uint64) ([]dax.ComputeNode, error) } -type MDSTopology struct { +type ServerlessTopology struct { controller dax.Controller } -func (m *MDSTopology) ComputeNodes(ctx context.Context, index string, shards []uint64) ([]dax.ComputeNode, error) { +func (m *ServerlessTopology) ComputeNodes(ctx context.Context, index string, shards []uint64) ([]dax.ComputeNode, error) { var daxShards = make(dax.ShardNums, len(shards)) for i, s := range shards { daxShards[i] = dax.ShardNum(s) } - // TODO(tlt): this needs review; MDSTopology is converting from + // TODO(tlt): this needs review; ServerlessTopology is converting from // string/uint64 to qtid/shardNum?? Perhaps we can get rid of the Topologer // interface altogether and replace it with dax.Noder. qtid := dax.TableKey(index).QualifiedTableID() @@ -64,7 +64,7 @@ func (m *MDSTopology) ComputeNodes(ctx context.Context, index string, shards []u // TODO(jaffee) we need version info in here ASAP. whenever schema or topo // changes, version gets bumped and nodes know to reject queries -// and update their info from the MDS instead of querying it every +// and update their info from the Controller instead of querying it every // time. type Translator interface { CreateIndexKeys(ctx context.Context, index string, keys []string) (map[string]uint64, error) @@ -2177,7 +2177,7 @@ func (o *orchestrator) mapper(ctx context.Context, eg *errgroup.Group, ch chan m // replica) and a valid error from a healthy node. In the case of // the latter, there's no need to retry a replica, we should trust // the error from the healthy node and return that immediately. - // TODO(jaffee) retries should contact MDS and find out who is up and has access to shards needed + // TODO(jaffee) retries should contact Controller and find out who is up and has access to shards needed results, err := o.remoteExec(ctx, node.Address, index, &pql.Query{Calls: []*pql.Call{c}}, shards, embeddedRowsForNode) if len(results) > 0 { resp.result = results[0] diff --git a/dax/queryer/queryer.go b/dax/queryer/queryer.go index 33fd93dc8..64e9e8dc5 100644 --- a/dax/queryer/queryer.go +++ b/dax/queryer/queryer.go @@ -14,7 +14,7 @@ import ( "github.com/featurebasedb/featurebase/v3/dax" "github.com/featurebasedb/featurebase/v3/encoding/proto" "github.com/featurebasedb/featurebase/v3/errors" - idkmds "github.com/featurebasedb/featurebase/v3/idk/mds" + idkserverless "github.com/featurebasedb/featurebase/v3/idk/serverless" "github.com/featurebasedb/featurebase/v3/logger" featurebase_pql "github.com/featurebasedb/featurebase/v3/pql" fbproto "github.com/featurebasedb/featurebase/v3/proto" @@ -82,8 +82,8 @@ func (q *Queryer) Orchestrator(qdbid dax.QualifiedDatabaseID) *qualifiedOrchestr orch := &orchestrator{ schema: sapi, - trans: NewMDSTranslator(q.controller), - topology: &MDSTopology{controller: q.controller}, + trans: NewServerlessTranslator(q.controller), + topology: &ServerlessTopology{controller: q.controller}, // TODO(jaffee) using default http.Client probably bad... need to set some timeouts. client: q.fbClient, logger: q.logger, @@ -168,7 +168,7 @@ func (q *Queryer) QuerySQL(ctx context.Context, qdbid dax.QualifiedDatabaseID, s sapi := newQualifiedSchemaAPI(qdbid, q.controller) // Importer - imp := idkmds.NewImporter(q.controller, qdbid, nil) + imp := idkserverless.NewImporter(q.controller, qdbid, nil) // TODO(tlt): We need a dax-compatible implementation of the SystemAPI. sysapi := &featurebase.NopSystemAPI{} diff --git a/dax/queryer/service/queryer.go b/dax/queryer/service/queryer.go index cf1954620..1d7d1f7b9 100644 --- a/dax/queryer/service/queryer.go +++ b/dax/queryer/service/queryer.go @@ -4,7 +4,7 @@ import ( "net/http" "github.com/featurebasedb/featurebase/v3/dax" - mdsclient "github.com/featurebasedb/featurebase/v3/dax/mds/client" + controllerclient "github.com/featurebasedb/featurebase/v3/dax/controller/client" "github.com/featurebasedb/featurebase/v3/dax/queryer" queryerhttp "github.com/featurebasedb/featurebase/v3/dax/queryer/http" "github.com/featurebasedb/featurebase/v3/errors" @@ -49,8 +49,8 @@ func (q *queryerService) HTTPHandler() http.Handler { return queryerhttp.Handler(q.queryer) } -func (q *queryerService) SetMDS(addr dax.Address) error { - mdscli := mdsclient.New(addr, q.logger) - q.queryer.SetController(mdscli) +func (q *queryerService) SetController(addr dax.Address) error { + controllercli := controllerclient.New(addr, q.logger) + q.queryer.SetController(controllercli) return nil } diff --git a/dax/queryer/translator.go b/dax/queryer/translator.go index 46b529f43..de771942d 100644 --- a/dax/queryer/translator.go +++ b/dax/queryer/translator.go @@ -7,21 +7,21 @@ import ( pilosa "github.com/featurebasedb/featurebase/v3" featurebase_client "github.com/featurebasedb/featurebase/v3/client" "github.com/featurebasedb/featurebase/v3/dax" - "github.com/featurebasedb/featurebase/v3/dax/mds/controller/partitioner" + "github.com/featurebasedb/featurebase/v3/dax/controller/partitioner" "github.com/featurebasedb/featurebase/v3/disco" "github.com/featurebasedb/featurebase/v3/encoding/proto" "github.com/featurebasedb/featurebase/v3/errors" ) // Ensure type implements interface. -var _ Translator = (*mdsTranslator)(nil) +var _ Translator = (*serverlessTranslator)(nil) -type mdsTranslator struct { +type serverlessTranslator struct { controller dax.Controller } -func NewMDSTranslator(controller dax.Controller) *mdsTranslator { - return &mdsTranslator{ +func NewServerlessTranslator(controller dax.Controller) *serverlessTranslator { + return &serverlessTranslator{ controller: controller, } } @@ -37,7 +37,7 @@ func fbClient(address dax.Address) (*featurebase_client.Client, error) { ) } -func (m *mdsTranslator) CreateIndexKeys(ctx context.Context, table string, keys []string) (map[string]uint64, error) { +func (m *serverlessTranslator) CreateIndexKeys(ctx context.Context, table string, keys []string) (map[string]uint64, error) { tkey := dax.TableKey(table) qtid := tkey.QualifiedTableID() @@ -78,7 +78,7 @@ func (m *mdsTranslator) CreateIndexKeys(ctx context.Context, table string, keys return out, nil } -func (m *mdsTranslator) CreateFieldKeys(ctx context.Context, table string, field string, keys []string) (map[string]uint64, error) { +func (m *serverlessTranslator) CreateFieldKeys(ctx context.Context, table string, field string, keys []string) (map[string]uint64, error) { qtid := dax.TableKey(table).QualifiedTableID() address, err := m.controller.IngestPartition(ctx, qtid, dax.PartitionNum(0)) if err != nil { @@ -96,7 +96,7 @@ func (m *mdsTranslator) CreateFieldKeys(ctx context.Context, table string, field return fbClient.CreateFieldKeys(fld, keys...) } -func (m *mdsTranslator) FindIndexKeys(ctx context.Context, table string, keys []string) (map[string]uint64, error) { +func (m *serverlessTranslator) FindIndexKeys(ctx context.Context, table string, keys []string) (map[string]uint64, error) { tkey := dax.TableKey(table) qtid := tkey.QualifiedTableID() @@ -149,7 +149,7 @@ func (m *mdsTranslator) FindIndexKeys(ctx context.Context, table string, keys [] return out, nil } -func (m *mdsTranslator) FindFieldKeys(ctx context.Context, table, field string, keys []string) (map[string]uint64, error) { +func (m *serverlessTranslator) FindFieldKeys(ctx context.Context, table, field string, keys []string) (map[string]uint64, error) { qtid := dax.TableKey(table).QualifiedTableID() address, err := m.controller.IngestPartition(ctx, qtid, dax.PartitionNum(0)) if err != nil { @@ -167,7 +167,7 @@ func (m *mdsTranslator) FindFieldKeys(ctx context.Context, table, field string, return fbClient.FindFieldKeys(fld, keys...) } -func (m *mdsTranslator) TranslateIndexIDs(ctx context.Context, index string, ids []uint64) ([]string, error) { +func (m *serverlessTranslator) TranslateIndexIDs(ctx context.Context, index string, ids []uint64) ([]string, error) { idsByPartition := splitIDsByPartition(index, ids, 1<<20) // TODO(jaffee), don't hardcode shardwidth...need to get this from index info daxPartitions := make([]dax.PartitionNum, 0) for partition := range idsByPartition { @@ -210,7 +210,7 @@ func (m *mdsTranslator) TranslateIndexIDs(ctx context.Context, index string, ids return ret, nil } -func (m *mdsTranslator) TranslateIndexIDSet(ctx context.Context, table string, ids map[uint64]struct{}) (map[uint64]string, error) { +func (m *serverlessTranslator) TranslateIndexIDSet(ctx context.Context, table string, ids map[uint64]struct{}) (map[uint64]string, error) { idList := make([]uint64, 0, len(ids)) for id := range ids { idList = append(idList, id) @@ -227,7 +227,7 @@ func (m *mdsTranslator) TranslateIndexIDSet(ctx context.Context, table string, i } return ret, nil } -func (m *mdsTranslator) TranslateFieldIDs(ctx context.Context, tableKeyer dax.TableKeyer, field string, ids map[uint64]struct{}) (map[uint64]string, error) { +func (m *serverlessTranslator) TranslateFieldIDs(ctx context.Context, tableKeyer dax.TableKeyer, field string, ids map[uint64]struct{}) (map[uint64]string, error) { idList := make([]uint64, 0, len(ids)) for id := range ids { idList = append(idList, id) @@ -248,7 +248,7 @@ func (m *mdsTranslator) TranslateFieldIDs(ctx context.Context, tableKeyer dax.Ta } return ret, nil } -func (m *mdsTranslator) TranslateFieldListIDs(ctx context.Context, index, field string, ids []uint64) ([]string, error) { +func (m *serverlessTranslator) TranslateFieldListIDs(ctx context.Context, index, field string, ids []uint64) ([]string, error) { qtid := dax.TableKey(index).QualifiedTableID() address, err := m.controller.IngestPartition(ctx, qtid, dax.PartitionNum(0)) if err != nil { diff --git a/dax/server/config.go b/dax/server/config.go index e039e237f..c41e7755b 100644 --- a/dax/server/config.go +++ b/dax/server/config.go @@ -10,7 +10,7 @@ import ( "strings" "time" - "github.com/featurebasedb/featurebase/v3/dax/mds" + "github.com/featurebasedb/featurebase/v3/dax/controller" "github.com/featurebasedb/featurebase/v3/dax/queryer" "github.com/featurebasedb/featurebase/v3/errors" fbserver "github.com/featurebasedb/featurebase/v3/server" @@ -43,14 +43,14 @@ type Config struct { // LogPath configures where Pilosa will write logs. LogPath string `toml:"log-path"` - MDS MDSOptions `toml:"mds"` - Queryer QueryerOptions `toml:"queryer"` - Computer ComputerOptions `toml:"computer"` + Controller ControllerOptions `toml:"controller"` + Queryer QueryerOptions `toml:"queryer"` + Computer ComputerOptions `toml:"computer"` } -type MDSOptions struct { - Run bool `toml:"run"` - Config mds.Config `toml:"config"` +type ControllerOptions struct { + Run bool `toml:"run"` + Config controller.Config `toml:"config"` } type QueryerOptions struct { @@ -67,8 +67,8 @@ type ComputerOptions struct { // NewConfig returns an instance of Config with default options. func NewConfig() *Config { c := &Config{ - MDS: MDSOptions{ - Config: mds.Config{ + Controller: ControllerOptions{ + Config: controller.Config{ RegistrationBatchTimeout: time.Second * 3, StorageMethod: defaultStorageMethod, SnappingTurtleTimeout: time.Second * 10, diff --git a/dax/server/server.go b/dax/server/server.go index e4d28beb4..c682da3f7 100644 --- a/dax/server/server.go +++ b/dax/server/server.go @@ -25,10 +25,9 @@ import ( featurebase "github.com/featurebasedb/featurebase/v3" "github.com/featurebasedb/featurebase/v3/dax" computersvc "github.com/featurebasedb/featurebase/v3/dax/computer/service" + controllerhttp "github.com/featurebasedb/featurebase/v3/dax/controller/http" + controllersvc "github.com/featurebasedb/featurebase/v3/dax/controller/service" daxhttp "github.com/featurebasedb/featurebase/v3/dax/http" - "github.com/featurebasedb/featurebase/v3/dax/mds" - controllerhttp "github.com/featurebasedb/featurebase/v3/dax/mds/controller/http" - mdssvc "github.com/featurebasedb/featurebase/v3/dax/mds/service" "github.com/featurebasedb/featurebase/v3/dax/queryer" queryersvc "github.com/featurebasedb/featurebase/v3/dax/queryer/service" "github.com/featurebasedb/featurebase/v3/errors" @@ -277,20 +276,20 @@ func (m *Command) setupServer() error { // setupServices uses the configuration to set up the configured services. func (m *Command) setupServices() error { - // Set up MDS. - if m.Config.MDS.Run { - mdsCfg := m.Config.MDS.Config - mdsCfg.Logger = m.logger - mdsCfg.Director = controllerhttp.NewDirector( + // Set up Controller. + if m.Config.Controller.Run { + controllerCfg := m.Config.Controller.Config + controllerCfg.Logger = m.logger + controllerCfg.Director = controllerhttp.NewDirector( controllerhttp.DirectorConfig{ DirectivePath: "directive", SnapshotRequestPath: "snapshot", Logger: m.logger, }) - m.svcmgr.MDS = mdssvc.New(m.advertiseURI, mds.New(mdsCfg)) - if err := m.svcmgr.MDSStart(); err != nil { - return errors.Wrap(err, "starting mds service") + m.svcmgr.Controller = controllersvc.New(m.advertiseURI, controllerCfg) + if err := m.svcmgr.ControllerStart(); err != nil { + return errors.Wrap(err, "starting controller service") } } @@ -302,18 +301,18 @@ func (m *Command) setupServices() error { m.svcmgr.Queryer = queryersvc.New(m.advertiseURI, queryer.New(qryrCfg), m.logger) - var mdsAddr dax.Address - if m.Config.Queryer.Config.MDSAddress != "" { - mdsAddr = dax.Address(m.Config.Queryer.Config.MDSAddress) - } else if m.svcmgr.MDS != nil { - mdsAddr = m.svcmgr.MDS.Address() + var controllerAddr dax.Address + if m.Config.Queryer.Config.ControllerAddress != "" { + controllerAddr = dax.Address(m.Config.Queryer.Config.ControllerAddress) + } else if m.svcmgr.Controller != nil { + controllerAddr = m.svcmgr.Controller.Address() } else { - return errors.Errorf("queryer requires MDS") + return errors.Errorf("queryer requires Controller") } - // Set MDS - if err := m.svcmgr.Queryer.SetMDS(mdsAddr); err != nil { - return errors.Wrap(err, "setting mds") + // Set Controller + if err := m.svcmgr.Queryer.SetController(controllerAddr); err != nil { + return errors.Wrap(err, "setting controller") } // Start queryer. @@ -348,8 +347,8 @@ func (m *Command) setupServices() error { Logger: m.logger, } - if cfg.ComputerConfig.MDSAddress == "" && m.svcmgr.MDS != nil { - cfg.ComputerConfig.MDSAddress = string(m.svcmgr.MDS.Address()) + if cfg.ComputerConfig.ControllerAddress == "" && m.svcmgr.Controller != nil { + cfg.ComputerConfig.ControllerAddress = string(m.svcmgr.Controller.Address()) } // Add new computer service. diff --git a/dax/server/test/managed.go b/dax/server/test/managed.go index 7f6ef3131..efc3ca875 100644 --- a/dax/server/test/managed.go +++ b/dax/server/test/managed.go @@ -13,8 +13,8 @@ import ( "github.com/featurebasedb/featurebase/v3/dax" computersvc "github.com/featurebasedb/featurebase/v3/dax/computer/service" - "github.com/featurebasedb/featurebase/v3/dax/mds" - mdssvc "github.com/featurebasedb/featurebase/v3/dax/mds/service" + "github.com/featurebasedb/featurebase/v3/dax/controller" + controllersvc "github.com/featurebasedb/featurebase/v3/dax/controller/service" "github.com/featurebasedb/featurebase/v3/dax/queryer" queryersvc "github.com/featurebasedb/featurebase/v3/dax/queryer/service" "github.com/featurebasedb/featurebase/v3/dax/server" @@ -62,13 +62,13 @@ func (mc *ManagedCommand) Close() error { return mc.Command.Close() } -// NewMDS adds a new MDSService to the ManagedCommands ServiceManager. -func (mc *ManagedCommand) NewMDS(cfg mds.Config) dax.ServiceKey { +// NewController adds a new ControllerService to the ManagedCommands ServiceManager. +func (mc *ManagedCommand) NewController(cfg controller.Config) dax.ServiceKey { uri := mc.URI() cfg.Logger = mc.svcmgr.Logger - mc.svcmgr.MDS = mdssvc.New(uri, mds.New(cfg)) + mc.svcmgr.Controller = controllersvc.New(uri, cfg) - return dax.ServicePrefixMDS + return dax.ServicePrefixController } // NewQueryer adds a new QueryerService to the ManagedCommands ServiceManager. @@ -78,16 +78,16 @@ func (mc *ManagedCommand) NewQueryer(cfg queryer.Config) dax.ServiceKey { cfg.Logger = logger mc.svcmgr.Queryer = queryersvc.New(uri, queryer.New(cfg), logger) - var mdsAddr dax.Address - if cfg.MDSAddress != "" { - mdsAddr = dax.Address(cfg.MDSAddress + "/" + dax.ServicePrefixMDS) - } else if mc.svcmgr.MDS != nil { - mdsAddr = mc.svcmgr.MDS.Address() + var controllerAddr dax.Address + if cfg.ControllerAddress != "" { + controllerAddr = dax.Address(cfg.ControllerAddress + "/" + dax.ServicePrefixController) + } else if mc.svcmgr.Controller != nil { + controllerAddr = mc.svcmgr.Controller.Address() } - // Set MDS - if err := mc.svcmgr.Queryer.SetMDS(mdsAddr); err != nil { - logger.Panicf(errors.Wrap(err, "setting mds").Error()) + // Set Controller + if err := mc.svcmgr.Queryer.SetController(controllerAddr); err != nil { + logger.Panicf(errors.Wrap(err, "setting controller").Error()) } return dax.ServicePrefixQueryer @@ -104,7 +104,7 @@ func (mc *ManagedCommand) NewComputer() dax.ServiceKey { Logger: mc.svcmgr.Logger, } - cfg.ComputerConfig.MDSAddress = mc.svcmgr.MDS.Address().String() + cfg.ComputerConfig.ControllerAddress = mc.svcmgr.Controller.Address().String() // Add new computer service. return mc.svcmgr.AddComputer( @@ -186,12 +186,12 @@ func NewManagedCommand(tb fbtest.DirCleaner, opts ...server.CommandOption) *Mana mc.svcmgr = svcmgr mc.Config.Bind = "http://localhost:0" - mc.Config.MDS.Config.DataDir = path + "/mds" + mc.Config.Controller.Config.DataDir = path + "/controller" mc.Config.Computer.Config.DataDir = path mc.Config.Computer.Config.WriteloggerDir = path + "/wl" - mc.Config.MDS.Config.WriteloggerDir = path + "/wl" + mc.Config.Controller.Config.WriteloggerDir = path + "/wl" mc.Config.Computer.Config.SnapshotterDir = path + "/sn" - mc.Config.MDS.Config.SnapshotterDir = path + "/sn" + mc.Config.Controller.Config.SnapshotterDir = path + "/sn" return mc } @@ -200,8 +200,8 @@ func NewManagedCommand(tb fbtest.DirCleaner, opts ...server.CommandOption) *Mana func DefaultConfig() *server.Config { cfg := server.NewConfig() cfg.Verbose = true - cfg.MDS.Run = true - cfg.MDS.Config.RegistrationBatchTimeout = 0 + cfg.Controller.Run = true + cfg.Controller.Config.RegistrationBatchTimeout = 0 cfg.Queryer.Run = true cfg.Computer.Run = true cfg.Computer.N = 1 @@ -231,7 +231,7 @@ func MustRunManagedCommand(tb testing.TB, opts ...server.CommandOption) *Managed } if basic { - assert.True(tb, mc.Healthy(dax.ServicePrefixMDS)) + assert.True(tb, mc.Healthy(dax.ServicePrefixController)) assert.True(tb, mc.Healthy(dax.ServicePrefixQueryer)) assert.True(tb, mc.Healthy(dax.ServicePrefixComputer+"0")) } diff --git a/dax/service_manager.go b/dax/service_manager.go index cbd8b57db..04c0c7cee 100644 --- a/dax/service_manager.go +++ b/dax/service_manager.go @@ -5,8 +5,11 @@ import ( "net/http" "sync" + _ "net/http/pprof" // Imported for its side-effect of registering pprof endpoints with the server. + "github.com/featurebasedb/featurebase/v3/errors" "github.com/featurebasedb/featurebase/v3/logger" + "github.com/felixge/fgprof" "github.com/gorilla/mux" ) @@ -20,9 +23,9 @@ type ServiceKey string type ServiceManager struct { mu sync.RWMutex - // MDS - MDS MDSService - mdsStarted bool + // Controller + Controller ControllerService + controllerStarted bool // Queryer Queryer QueryerService @@ -62,9 +65,9 @@ func (s *ServiceManager) HTTPHandler() http.Handler { // StartAll starts all services which have been added to ServiceManager. func (s *ServiceManager) StartAll() error { - // MDS - if err := s.MDSStart(); err != nil { - return errors.Wrap(err, "starting mds") + // Controller + if err := s.ControllerStart(); err != nil { + return errors.Wrap(err, "starting controller") } // Queryer @@ -91,51 +94,51 @@ func (s *ServiceManager) StopAll() error { if err := s.QueryerStop(); err != nil { s.Logger.Printf("stopping queryer: %v", err) } - return s.MDSStop() + return s.ControllerStop() } -// MDSStart starts the MDS service. -func (s *ServiceManager) MDSStart() error { - if s.MDS == nil { +// ControllerStart starts the Controller service. +func (s *ServiceManager) ControllerStart() error { + if s.Controller == nil { return nil } s.mu.Lock() defer s.mu.Unlock() - if s.mdsStarted { + if s.controllerStarted { return nil } - s.mdsStarted = true + s.controllerStarted = true s.resetRouter() - if err := s.MDS.Start(); err != nil { - s.mdsStarted = false - return errors.Wrap(err, "starting mds") + if err := s.Controller.Start(); err != nil { + s.controllerStarted = false + return errors.Wrap(err, "starting controller") } return nil } -// MDSStop stops the MDS service. -func (s *ServiceManager) MDSStop() error { - if s.MDS == nil { +// ControllerStop stops the Controller service. +func (s *ServiceManager) ControllerStop() error { + if s.Controller == nil { return nil } s.mu.Lock() defer s.mu.Unlock() - if !s.mdsStarted { + if !s.controllerStarted { return nil } - s.mdsStarted = false + s.controllerStarted = false s.resetRouter() - if err := s.MDS.Stop(); err != nil { - s.mdsStarted = true + if err := s.Controller.Stop(); err != nil { + s.controllerStarted = true return errors.Wrap(err, "stopping controller") } @@ -313,12 +316,14 @@ func (s *ServiceManager) resetRouter() { func (s *ServiceManager) buildRouter() *mux.Router { router := mux.NewRouter() router.HandleFunc("/health", getHealth).Methods("GET").Name("GetHealth") + router.PathPrefix("/debug/pprof/").Handler(http.DefaultServeMux).Methods("GET") + router.PathPrefix("/debug/fgprof").Handler(fgprof.Handler()).Methods("GET") - // MDS. - if s.MDS != nil && s.mdsStarted { - pre := "/" + ServicePrefixMDS + // Controller. + if s.Controller != nil && s.controllerStarted { + pre := "/" + ServicePrefixController router.PathPrefix(pre + "/").Handler( - http.StripPrefix(pre, s.MDS.HTTPHandler())) + http.StripPrefix(pre, s.Controller.HTTPHandler())) } // Computers. @@ -363,20 +368,20 @@ type MultiService interface { Key() ServiceKey } -type MDSService interface { +type ControllerService interface { Service } type ComputerService interface { MultiService - SetMDS(Address) error + SetController(Address) error } type QueryerService interface { Service - SetMDS(Address) error + SetController(Address) error } ////////////////////////////////////////// diff --git a/dax/test/dax/dax_test.go b/dax/test/dax/dax_test.go index cf11765d0..62fa4af13 100644 --- a/dax/test/dax/dax_test.go +++ b/dax/test/dax/dax_test.go @@ -12,7 +12,7 @@ import ( featurebase "github.com/featurebasedb/featurebase/v3" "github.com/featurebasedb/featurebase/v3/dax" - mdsclient "github.com/featurebasedb/featurebase/v3/dax/mds/client" + controllerclient "github.com/featurebasedb/featurebase/v3/dax/controller/client" queryerclient "github.com/featurebasedb/featurebase/v3/dax/queryer/client" "github.com/featurebasedb/featurebase/v3/dax/server" "github.com/featurebasedb/featurebase/v3/dax/server/test" @@ -63,20 +63,20 @@ func TestDAXIntegration(t *testing.T) { svcmgr := mc.Manage() - var mdsKey dax.ServiceKey + var controllerKey dax.ServiceKey var queryerKey dax.ServiceKey var computerKey0 dax.ServiceKey var computerKey1 dax.ServiceKey - assert.False(t, mc.Healthy(mdsKey)) + assert.False(t, mc.Healthy(controllerKey)) assert.False(t, mc.Healthy(queryerKey)) assert.False(t, mc.Healthy(computerKey0)) assert.False(t, mc.Healthy(computerKey1)) - // Start MDS. - mdsKey = mc.NewMDS(cfg.MDS.Config) - assert.NoError(t, svcmgr.MDSStart()) - assert.True(t, mc.Healthy(mdsKey)) + // Start Controller. + controllerKey = mc.NewController(cfg.Controller.Config) + assert.NoError(t, svcmgr.ControllerStart()) + assert.True(t, mc.Healthy(controllerKey)) assert.False(t, mc.Healthy(queryerKey)) assert.False(t, mc.Healthy(computerKey0)) assert.False(t, mc.Healthy(computerKey1)) @@ -84,7 +84,7 @@ func TestDAXIntegration(t *testing.T) { // Start Queryer. queryerKey = mc.NewQueryer(cfg.Queryer.Config) assert.NoError(t, svcmgr.QueryerStart()) - assert.True(t, mc.Healthy(mdsKey)) + assert.True(t, mc.Healthy(controllerKey)) assert.True(t, mc.Healthy(queryerKey)) assert.False(t, mc.Healthy(computerKey0)) assert.False(t, mc.Healthy(computerKey1)) @@ -92,7 +92,7 @@ func TestDAXIntegration(t *testing.T) { // New and Start Computer 0. computerKey0 = mc.NewComputer() assert.NoError(t, svcmgr.ComputerStart(computerKey0)) - assert.True(t, mc.Healthy(mdsKey)) + assert.True(t, mc.Healthy(controllerKey)) assert.True(t, mc.Healthy(queryerKey)) assert.True(t, mc.Healthy(computerKey0)) assert.False(t, mc.Healthy(computerKey1)) @@ -100,14 +100,14 @@ func TestDAXIntegration(t *testing.T) { // New and Start Computer 1. computerKey1 = mc.NewComputer() assert.NoError(t, svcmgr.ComputerStart(computerKey1)) - assert.True(t, mc.Healthy(mdsKey)) + assert.True(t, mc.Healthy(controllerKey)) assert.True(t, mc.Healthy(queryerKey)) assert.True(t, mc.Healthy(computerKey0)) assert.True(t, mc.Healthy(computerKey1)) // Stop Computer 1. assert.NoError(t, svcmgr.ComputerStop(computerKey0)) - assert.True(t, mc.Healthy(mdsKey)) + assert.True(t, mc.Healthy(controllerKey)) assert.True(t, mc.Healthy(queryerKey)) assert.False(t, mc.Healthy(computerKey0)) assert.True(t, mc.Healthy(computerKey1)) @@ -120,13 +120,13 @@ func TestDAXIntegration(t *testing.T) { svcmgr := mc.Manage() - // Set up MDS client. - mdsClient := mdsclient.New(svcmgr.MDS.Address(), svcmgr.Logger) + // Set up Controller client. + controllerClient := controllerclient.New(svcmgr.Controller.Address(), svcmgr.Logger) // Create database. qdb.Options.WorkersMin = 1 qdb.Options.WorkersMax = 1 - assert.NoError(t, mdsClient.CreateDatabase(context.Background(), qdb)) + assert.NoError(t, controllerClient.CreateDatabase(context.Background(), qdb)) // skips is a list of tests which are currently not passing in dax. We // need to get these passing before alpha. @@ -194,13 +194,13 @@ func TestDAXIntegration(t *testing.T) { svcmgr := mc.Manage() - // Set up MDS client. - mdsClient := mdsclient.New(svcmgr.MDS.Address(), svcmgr.Logger) + // Set up Controller client. + controllerClient := controllerclient.New(svcmgr.Controller.Address(), svcmgr.Logger) // Create database. qdb.Options.WorkersMin = 1 qdb.Options.WorkersMax = 1 - assert.NoError(t, mdsClient.CreateDatabase(context.Background(), qdb)) + assert.NoError(t, controllerClient.CreateDatabase(context.Background(), qdb)) runTableTests(t, mc.Manage().Queryer.Address(), @@ -216,13 +216,13 @@ func TestDAXIntegration(t *testing.T) { svcmgr := mc.Manage() - // Set up MDS client. - mdsClient := mdsclient.New(svcmgr.MDS.Address(), svcmgr.Logger) + // Set up Controller client. + controllerClient := controllerclient.New(svcmgr.Controller.Address(), svcmgr.Logger) // Create database. qdb.Options.WorkersMin = 2 qdb.Options.WorkersMax = 2 - assert.NoError(t, mdsClient.CreateDatabase(context.Background(), qdb)) + assert.NoError(t, controllerClient.CreateDatabase(context.Background(), qdb)) computers := svcmgr.Computers() computerKey0 := dax.ServiceKey(dax.ServicePrefixComputer + "0") @@ -234,7 +234,7 @@ func TestDAXIntegration(t *testing.T) { basicTableTestConfig(qdbid, defs.Keyed)..., ) - qtid, err := mdsClient.TableID(context.Background(), qdbid, dax.TableName(defs.Keyed.Name(0))) + qtid, err := controllerClient.TableID(context.Background(), qdbid, dax.TableName(defs.Keyed.Name(0))) assert.NoError(t, err) // ensure partitions are covered @@ -243,7 +243,7 @@ func TestDAXIntegration(t *testing.T) { allPartitions := append(partitions0, partitions1...) sort.Sort(allPartitions) - nodes, err := mdsClient.TranslateNodes(context.Background(), qtid, allPartitions...) + nodes, err := controllerClient.TranslateNodes(context.Background(), qtid, allPartitions...) assert.NoError(t, err) if assert.Len(t, nodes, 2) { // computer0 (node0) @@ -262,7 +262,7 @@ func TestDAXIntegration(t *testing.T) { time.Sleep(5 * time.Second) // ensure paritions are still covered - nodes, err = mdsClient.TranslateNodes(context.Background(), qtid, append(partitions0, partitions1...)...) + nodes, err = controllerClient.TranslateNodes(context.Background(), qtid, append(partitions0, partitions1...)...) assert.NoError(t, err) if assert.Len(t, nodes, 1) { // computer1 (node0) @@ -277,13 +277,13 @@ func TestDAXIntegration(t *testing.T) { svcmgr := mc.Manage() - // Set up MDS client. - mdsClient := mdsclient.New(svcmgr.MDS.Address(), svcmgr.Logger) + // Set up Controller client. + controllerClient := controllerclient.New(svcmgr.Controller.Address(), svcmgr.Logger) // Create database. qdb.Options.WorkersMin = 1 qdb.Options.WorkersMax = 1 - assert.NoError(t, mdsClient.CreateDatabase(context.Background(), qdb)) + assert.NoError(t, controllerClient.CreateDatabase(context.Background(), qdb)) computerKey0 := dax.ServiceKey(dax.ServicePrefixComputer + "0") @@ -331,13 +331,13 @@ func TestDAXIntegration(t *testing.T) { svcmgr := mc.Manage() - // Set up MDS client. - mdsClient := mdsclient.New(svcmgr.MDS.Address(), svcmgr.Logger) + // Set up Controller client. + controllerClient := controllerclient.New(svcmgr.Controller.Address(), svcmgr.Logger) // Create database. qdb.Options.WorkersMin = 1 qdb.Options.WorkersMax = 1 - assert.NoError(t, mdsClient.CreateDatabase(context.Background(), qdb)) + assert.NoError(t, controllerClient.CreateDatabase(context.Background(), qdb)) computerKey0 := dax.ServiceKey(dax.ServicePrefixComputer + "0") @@ -355,10 +355,10 @@ func TestDAXIntegration(t *testing.T) { // Snapshot table ctx := context.Background() - qtid, err := mdsClient.TableID(ctx, qdbid, dax.TableName(defs.Keyed.Name(0))) + qtid, err := controllerClient.TableID(ctx, qdbid, dax.TableName(defs.Keyed.Name(0))) assert.NoError(t, err) - mdsClient.SnapshotTable(ctx, qtid) + controllerClient.SnapshotTable(ctx, qtid) // Ingest more data. t.Run("ingest and query more data", func(t *testing.T) { @@ -403,24 +403,24 @@ func TestDAXIntegration(t *testing.T) { }) }) - t.Run("MDS_Persistence", func(t *testing.T) { + t.Run("Controller_Persistence", func(t *testing.T) { mc := test.MustRunManagedCommand(t) defer mc.Close() svcmgr := mc.Manage() - // Set up MDS client. - mdsClient := mdsclient.New(svcmgr.MDS.Address(), svcmgr.Logger) + // Set up Controller client. + controllerClient := controllerclient.New(svcmgr.Controller.Address(), svcmgr.Logger) // Create database. qdb.Options.WorkersMin = 1 qdb.Options.WorkersMax = 1 - assert.NoError(t, mdsClient.CreateDatabase(context.Background(), qdb)) + assert.NoError(t, controllerClient.CreateDatabase(context.Background(), qdb)) computerKey0 := dax.ServiceKey(dax.ServicePrefixComputer + "0") - mdsKey := dax.ServiceKey(dax.ServicePrefixMDS) - assert.True(t, mc.Healthy(mdsKey)) + controllerKey := dax.ServiceKey(dax.ServicePrefixController) + assert.True(t, mc.Healthy(controllerKey)) // Ingest and query some data. runTableTests(t, @@ -428,13 +428,13 @@ func TestDAXIntegration(t *testing.T) { basicTableTestConfig(qdbid, defs.Keyed)..., ) - qtid, err := mdsClient.TableID(context.Background(), qdbid, dax.TableName(defs.Keyed.Name(0))) + qtid, err := controllerClient.TableID(context.Background(), qdbid, dax.TableName(defs.Keyed.Name(0))) assert.NoError(t, err) // ensure partitions are covered partitions := dax.PartitionNums{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11} - nodes, err := mdsClient.TranslateNodes(context.Background(), qtid, partitions...) + nodes, err := controllerClient.TranslateNodes(context.Background(), qtid, partitions...) assert.NoError(t, err) if assert.Len(t, nodes, 1) { // computer0 (node0) @@ -442,17 +442,17 @@ func TestDAXIntegration(t *testing.T) { assert.Equal(t, partitions, nodes[0].Partitions) } - // Stop MDS. - assert.NoError(t, svcmgr.MDSStop()) - assert.False(t, mc.Healthy(mdsKey)) + // Stop Controller. + assert.NoError(t, svcmgr.ControllerStop()) + assert.False(t, mc.Healthy(controllerKey)) - // Start New MDS. - mdsKey = mc.NewMDS(mc.Config.MDS.Config) - assert.NoError(t, svcmgr.MDSStart()) - assert.True(t, mc.Healthy(mdsKey)) + // Start New Controller. + controllerKey = mc.NewController(mc.Config.Controller.Config) + assert.NoError(t, svcmgr.ControllerStart()) + assert.True(t, mc.Healthy(controllerKey)) // ensure paritions are still covered - nodes, err = mdsClient.TranslateNodes(context.Background(), qtid, partitions...) + nodes, err = controllerClient.TranslateNodes(context.Background(), qtid, partitions...) assert.NoError(t, err) if assert.Len(t, nodes, 1) { // computer0 (node0) @@ -467,13 +467,13 @@ func TestDAXIntegration(t *testing.T) { svcmgr := mc.Manage() - // Set up MDS client. - mdsClient := mdsclient.New(svcmgr.MDS.Address(), svcmgr.Logger) + // Set up Controller client. + controllerClient := controllerclient.New(svcmgr.Controller.Address(), svcmgr.Logger) // Create database. qdb.Options.WorkersMin = 1 qdb.Options.WorkersMax = 1 - assert.NoError(t, mdsClient.CreateDatabase(context.Background(), qdb)) + assert.NoError(t, controllerClient.CreateDatabase(context.Background(), qdb)) computerKey0 := dax.ServiceKey(dax.ServicePrefixComputer + "0") @@ -520,13 +520,13 @@ func TestDAXIntegration(t *testing.T) { ctx := context.Background() - // Set up MDS client. - mdsClient := mdsclient.New(svcmgr.MDS.Address(), svcmgr.Logger) + // Set up Controller client. + controllerClient := controllerclient.New(svcmgr.Controller.Address(), svcmgr.Logger) // Create database. qdb.Options.WorkersMin = 1 qdb.Options.WorkersMax = 1 - assert.NoError(t, mdsClient.CreateDatabase(context.Background(), qdb)) + assert.NoError(t, controllerClient.CreateDatabase(context.Background(), qdb)) // Create two tables with data. Query the data to ensure it exists. runTableTests(t, @@ -535,23 +535,23 @@ func TestDAXIntegration(t *testing.T) { ) // Make sure the database and tables exist. - db, err := mdsClient.DatabaseByName(ctx, orgID, dbname) + db, err := controllerClient.DatabaseByName(ctx, orgID, dbname) assert.NoError(t, err) assert.NotNil(t, db) - tbl1, err := mdsClient.TableByName(ctx, qdbid, dax.TableName(defs.Keyed.Name(0))) + tbl1, err := controllerClient.TableByName(ctx, qdbid, dax.TableName(defs.Keyed.Name(0))) assert.NoError(t, err) assert.NotNil(t, tbl1) - tbl2, err := mdsClient.TableByName(ctx, qdbid, dax.TableName(defs.Unkeyed.Name(0))) + tbl2, err := controllerClient.TableByName(ctx, qdbid, dax.TableName(defs.Unkeyed.Name(0))) assert.NoError(t, err) assert.NotNil(t, tbl2) // Drop the database - assert.NoError(t, mdsClient.DropDatabase(ctx, qdbid)) + assert.NoError(t, controllerClient.DropDatabase(ctx, qdbid)) // Make sure the database and tables no longer exist. - db, err = mdsClient.DatabaseByName(ctx, orgID, dbname) + db, err = controllerClient.DatabaseByName(ctx, orgID, dbname) if assert.Error(t, err) { assert.Contains(t, err.Error(), "database name 'dbname1' does not exist") // TODO(tlt): replace the previous line with the following once we @@ -560,7 +560,7 @@ func TestDAXIntegration(t *testing.T) { } assert.Nil(t, db) - tbl1, err = mdsClient.TableByName(ctx, qdbid, dax.TableName(defs.Keyed.Name(0))) + tbl1, err = controllerClient.TableByName(ctx, qdbid, dax.TableName(defs.Keyed.Name(0))) if assert.Error(t, err) { assert.Contains(t, err.Error(), "table name 'keyed' does not exist") // TODO(tlt): replace the previous line with the following once we @@ -569,7 +569,7 @@ func TestDAXIntegration(t *testing.T) { } assert.Nil(t, tbl1) - tbl2, err = mdsClient.TableByName(ctx, qdbid, dax.TableName(defs.Unkeyed.Name(0))) + tbl2, err = controllerClient.TableByName(ctx, qdbid, dax.TableName(defs.Unkeyed.Name(0))) if assert.Error(t, err) { assert.Contains(t, err.Error(), "table name 'unkeyed' does not exist") // TODO(tlt): replace the previous line with the following once we @@ -584,13 +584,13 @@ func TestDAXIntegration(t *testing.T) { defer mc.Close() svcmgr := mc.Manage() - // Set up MDS client. - mdsClient := mdsclient.New(svcmgr.MDS.Address(), svcmgr.Logger) + // Set up Controller client. + controllerClient := controllerclient.New(svcmgr.Controller.Address(), svcmgr.Logger) // Create database. qdb.Options.WorkersMin = 1 qdb.Options.WorkersMax = 1 - assert.NoError(t, mdsClient.CreateDatabase(context.Background(), qdb)) + assert.NoError(t, controllerClient.CreateDatabase(context.Background(), qdb)) testconfigs := basicTableTestConfig(qdbid, defs.Keyed) for i := range testconfigs { @@ -606,7 +606,7 @@ func TestDAXIntegration(t *testing.T) { // Ensure the index and writelogger directories are empty. assert.False(t, dirIsEmpty(t, rootDir+"/computer0")) assert.False(t, dirIsEmpty(t, rootDir+"/computer0/indexes")) - assert.False(t, dirIsEmpty(t, rootDir+"/mds")) + assert.False(t, dirIsEmpty(t, rootDir+"/controller")) assert.False(t, dirIsEmpty(t, rootDir+"/wl")) resp := runSQL(t, svcmgr.Queryer.Address(), testconfigs[0].qdbid, "drop table keyed") @@ -615,7 +615,7 @@ func TestDAXIntegration(t *testing.T) { // Ensure the index and writelogger directories are empty. assert.False(t, dirIsEmpty(t, rootDir+"/computer0")) assert.True(t, dirIsEmpty(t, rootDir+"/computer0/indexes")) - assert.False(t, dirIsEmpty(t, rootDir+"/mds")) + assert.False(t, dirIsEmpty(t, rootDir+"/controller")) assert.True(t, dirIsEmpty(t, rootDir+"/wl")) }) } diff --git a/dax/test/schemar.go b/dax/test/schemar.go index 7a1c6291d..0f01bc98b 100644 --- a/dax/test/schemar.go +++ b/dax/test/schemar.go @@ -5,8 +5,8 @@ import ( "testing" "github.com/featurebasedb/featurebase/v3/dax/boltdb" - "github.com/featurebasedb/featurebase/v3/dax/mds/schemar" - schemarbolt "github.com/featurebasedb/featurebase/v3/dax/mds/schemar/boltdb" + "github.com/featurebasedb/featurebase/v3/dax/controller/schemar" + schemarbolt "github.com/featurebasedb/featurebase/v3/dax/controller/schemar/boltdb" testbolt "github.com/featurebasedb/featurebase/v3/dax/test/boltdb" "github.com/featurebasedb/featurebase/v3/logger" ) diff --git a/holder.go b/holder.go index b7e127750..7a0751bc9 100644 --- a/holder.go +++ b/holder.go @@ -137,11 +137,11 @@ type Holder struct { directive *dax.Directive // directiveApplied is used for testing (in an attempt to avoid sleeps). It - // should be removed once we sort out the logic between MDS and computer - // nodes. For example, MDS really needs to send out directives - // asynchronously and allow a computer to load data from - // snapshotter/writelogger; then MDS should only start directing queries to - // that computer once it has completed applying the snapshot. + // should be removed once we sort out the logic between controller and + // computer nodes. For example, the Controller really needs to send out + // directives asynchronously and allow a computer to load data from + // snapshotter/writelogger; then the Controller should only start directing + // queries to that computer once it has completed applying the snapshot. directiveApplied bool } diff --git a/idk/datagen/cmd.go b/idk/datagen/cmd.go index 6a18b5a96..d99fcb968 100644 --- a/idk/datagen/cmd.go +++ b/idk/datagen/cmd.go @@ -26,7 +26,7 @@ const ( TargetFeaturebase = "featurebase" TargetKafka = "kafka" TargetKafkaStatic = "kafkastatic" - TargetMDS = "mds" + TargetServerless = "serverless" ) // Main is the top-level datagen struct. It represents datagen-specific @@ -61,7 +61,7 @@ type Main struct { // Used strictly for configuration of the targets. Pilosa PilosaConfig Kafka KafkaConfig - MDS MDSConfig + Serverless ServerlessConfig FeatureBase FeatureBaseConfig `flag:"featurebase" help:"qualified featurebase table"` DryRun bool `help:"Dry run - just flag parsing."` @@ -103,11 +103,11 @@ type KafkaConfig struct { NumPartitions int `short:"" help:"set partition for kafka cluster"` } -// MDSConfig represents the configuration options to be used when target = mds. -// These are really just a sub-set of idk.Main, containing only those arguments -// that really apply to datagen. -type MDSConfig struct { - Address string `short:"" help:"MDS host:port to connect to"` +// ServerlessConfig represents the configuration options to be used when target +// = serverless. These are really just a sub-set of idk.Main, containing only +// those arguments that really apply to datagen. +type ServerlessConfig struct { + Address string `short:"" help:"Controller host:port to connect to"` } // NewMain returns a new instance of Main. @@ -286,7 +286,7 @@ func (m *Main) Preload() error { m.KafkaPut.FBIDField = m.idkMain.IDField m.KafkaPut.FBIndexName = m.Pilosa.Index - case TargetMDS: + case TargetServerless: m.idkMain.Namespace = "ingester_datagen" m.idkMain.Concurrency = m.Concurrency m.idkMain.CacheLength = m.Pilosa.CacheLength @@ -298,8 +298,8 @@ func (m *Main) Preload() error { m.idkMain.BatchSize = m.Pilosa.BatchSize } - // MDS-specific - m.idkMain.MDSAddress = m.MDS.Address + // Serverless-specific + m.idkMain.ControllerAddress = m.Serverless.Address m.idkMain.OrganizationID = dax.OrganizationID(m.FeatureBase.OrganizationID) m.idkMain.DatabaseID = dax.DatabaseID(m.FeatureBase.DatabaseID) m.idkMain.TableName = dax.TableName(m.FeatureBase.TableName) diff --git a/idk/docker-compose.yml b/idk/docker-compose.yml index 5bcde33b3..bc22c7581 100644 --- a/idk/docker-compose.yml +++ b/idk/docker-compose.yml @@ -141,8 +141,8 @@ services: FEATUREBASE_BIND: 0.0.0.0:8080 FEATUREBASE_VERBOSE: "true" FEATUREBASE_QUERYER_RUN: "true" - FEATUREBASE_MDS_RUN: "true" - FEATUREBASE_MDS_CONFIG_DATA_DIR: /dax-data/mds + FEATUREBASE_CONTROLLER_RUN: "true" + FEATUREBASE_CONTROLLER_CONFIG_DATA_DIR: /dax-data/controller FEATUREBASE_COMPUTER_RUN: "true" FEATUREBASE_COMPUTER_CONFIG_DATA_DIR: /dax-data/computer FEATUREBASE_COMPUTER_CONFIG_WRITELOGGER_DIR: /dax-data/wl diff --git a/idk/ingest.go b/idk/ingest.go index 1f514ecab..aa2c2e4f4 100644 --- a/idk/ingest.go +++ b/idk/ingest.go @@ -29,8 +29,8 @@ import ( pilosaclient "github.com/featurebasedb/featurebase/v3/client" client_types "github.com/featurebasedb/featurebase/v3/client/types" "github.com/featurebasedb/featurebase/v3/dax" - mdsclient "github.com/featurebasedb/featurebase/v3/dax/mds/client" - "github.com/featurebasedb/featurebase/v3/idk/mds" + controllerclient "github.com/featurebasedb/featurebase/v3/dax/controller/client" + "github.com/featurebasedb/featurebase/v3/idk/serverless" "github.com/featurebasedb/featurebase/v3/logger" "github.com/featurebasedb/featurebase/v3/pql" proto "github.com/featurebasedb/featurebase/v3/proto" @@ -97,10 +97,10 @@ type Main struct { UseShardTransactionalEndpoint bool `flag:"use-shard-transactional-endpoint" help:"Use alternate import endpoint that ingests data for all fields in a shard in a single atomic request. No negative performance impact and better consistency. Recommended."` - MDSAddress string `short:"" help:"MDS address."` - OrganizationID dax.OrganizationID `short:"" help:"auto-assigned organization ID"` - DatabaseID dax.DatabaseID `short:"" help:"auto-assigned database ID"` - TableName dax.TableName `short:"" help:"human friendly table name"` + ControllerAddress string `short:"" help:"Controller address."` + OrganizationID dax.OrganizationID `short:"" help:"auto-assigned organization ID"` + DatabaseID dax.DatabaseID `short:"" help:"auto-assigned database ID"` + TableName dax.TableName `short:"" help:"human friendly table name"` csvWriter *csv.Writer csvFile *os.File @@ -984,7 +984,7 @@ func (m *Main) setupClient() (*tls.Config, error) { ) } - if m.useMDS() { + if m.useController() { // We should only have one "pilosa host" here. Get the path from that // and use it as the client path prefix. var prefix string @@ -1003,28 +1003,28 @@ func (m *Main) setupClient() (*tls.Config, error) { } // Set up the SchemaManager - if m.useMDS() { + if m.useController() { ctx := context.Background() - // MDS doesn't auto-create a table based on IDK ingest; the table must - // already exist. - mdsClient := mdsclient.New(dax.Address(m.MDSAddress), m.log) + // Controller doesn't auto-create a table based on IDK ingest; the table + // must already exist. + controllerClient := controllerclient.New(dax.Address(m.ControllerAddress), m.log) qdbid := dax.NewQualifiedDatabaseID(m.OrganizationID, m.DatabaseID) - qtid, err := mdsClient.TableID(ctx, qdbid, m.TableName) + qtid, err := controllerClient.TableID(ctx, qdbid, m.TableName) if err != nil { return nil, errors.Wrapf(err, "getting table id: qual: %s, table name: %s", qdbid, m.TableName) } - qtbl, err := mdsClient.Table(ctx, qtid) + qtbl, err := controllerClient.Table(ctx, qtid) if err != nil { return nil, errors.Wrapf(err, "getting table id: qtid: %s", qtid) } m.Qtbl = qtbl m.Index = string(qtbl.Key()) - m.SchemaManager = mds.NewSchemaManager(dax.Address(m.MDSAddress), qdbid, m.log) + m.SchemaManager = serverless.NewSchemaManager(dax.Address(m.ControllerAddress), qdbid, m.log) m.NewImporterFn = func() pilosacore.Importer { - return mds.NewImporter(mdsClient, qtbl.Qualifier(), &qtbl.Table) + return serverless.NewImporter(controllerClient, qtbl.Qualifier(), &qtbl.Table) } } else { m.SchemaManager = m.client @@ -1815,10 +1815,10 @@ func (m *Main) batchFromSchema(schema []Field) ([]Recordizer, pilosabatch.Record } // The table name we use to look up in the index in the schema returned from - // SchemaManager.Schema() differs depending on whether this is MDS supported - // or not (i.e. whether it has a table qualifier). + // SchemaManager.Schema() differs depending on whether this is Serverless + // supported or not (i.e. whether it has a table qualifier). tblName := m.index.Name() - if m.useMDS() { + if m.useController() { tblName = string(m.Qtbl.Key()) } @@ -1847,7 +1847,7 @@ func (m *Main) newBatch(fields []*pilosaclient.Field) (pilosabatch.RecordBatch, pilosabatch.OptUseShardTransactionalEndpoint(m.UseShardTransactionalEndpoint), } var importer pilosacore.Importer - if m.useMDS() { + if m.useController() { importer = m.NewImporterFn() } else { sapi := pilosaclient.NewSchemaAPI(m.client) @@ -2157,7 +2157,7 @@ func (m *Main) validate() error { return errors.New("must set exactly one of --primary-key-field , --id-field , --auto-generate") } - if m.useMDS() { + if m.useController() { if m.OrganizationID == "" { return errors.New("must set an organization with --featurebase.org-id") } else if m.DatabaseID == "" { @@ -2189,6 +2189,6 @@ func (m *Main) allowError(err error) bool { } } -func (m *Main) useMDS() bool { - return m.MDSAddress != "" +func (m *Main) useController() bool { + return m.ControllerAddress != "" } diff --git a/idk/ingest_test.go b/idk/ingest_test.go index 1cf096550..40253ba18 100644 --- a/idk/ingest_test.go +++ b/idk/ingest_test.go @@ -19,9 +19,9 @@ import ( batch "github.com/featurebasedb/featurebase/v3/batch" pilosaclient "github.com/featurebasedb/featurebase/v3/client" "github.com/featurebasedb/featurebase/v3/dax" - mdsclient "github.com/featurebasedb/featurebase/v3/dax/mds/client" + controllerclient "github.com/featurebasedb/featurebase/v3/dax/controller/client" "github.com/featurebasedb/featurebase/v3/idk/idktest" - "github.com/featurebasedb/featurebase/v3/idk/mds" + "github.com/featurebasedb/featurebase/v3/idk/serverless" "github.com/featurebasedb/featurebase/v3/logger" "github.com/featurebasedb/featurebase/v3/pql" "github.com/golang-jwt/jwt" @@ -44,8 +44,8 @@ func configureTestFlags(main *Main) { main.Stats = "" } -func configureTestFlagsMDS(main *Main, address dax.Address, qtbl *dax.QualifiedTable) { - main.MDSAddress = address.String() +func configureTestFlagsController(main *Main, address dax.Address, qtbl *dax.QualifiedTable) { + main.ControllerAddress = address.String() main.Stats = "" main.Pprof = "" main.PackBools = "" @@ -53,12 +53,12 @@ func configureTestFlagsMDS(main *Main, address dax.Address, qtbl *dax.QualifiedT main.DatabaseID = qtbl.Qualifier().DatabaseID main.TableName = qtbl.Name main.Qtbl = qtbl - main.SchemaManager = mds.NewSchemaManager(address, qtbl.Qualifier(), logger.StderrLogger) + main.SchemaManager = serverless.NewSchemaManager(address, qtbl.Qualifier(), logger.StderrLogger) main.Index = string(qtbl.Key()) - mdsClient := mdsclient.New(dax.Address(address), logger.StderrLogger) + controllerClient := controllerclient.New(dax.Address(address), logger.StderrLogger) main.NewImporterFn = func() pilosa.Importer { - return mds.NewImporter(mdsClient, qtbl.QualifiedDatabaseID, &qtbl.Table) + return serverless.NewImporter(controllerClient, qtbl.QualifiedDatabaseID, &qtbl.Table) } } @@ -1744,19 +1744,19 @@ func TestBoolIngest(t *testing.T) { } } -func TestBatchTargetMDS(t *testing.T) { - var mdsHost string - if mds, ok := os.LookupEnv("IDK_TEST_MDS_HOST"); ok { - mdsHost = mds +func TestBatchTargetServerless(t *testing.T) { + var controllerHost string + if controller, ok := os.LookupEnv("IDK_TEST_CONTROLLER_HOST"); ok { + controllerHost = controller } else { - mdsHost = "dax:8080" + controllerHost = "dax:8080" } - mdsAddress := dax.Address(mdsHost + "/" + dax.ServicePrefixMDS) + controllerAddress := dax.Address(controllerHost + "/" + dax.ServicePrefixController) orgID := dax.OrganizationID("acme") dbID := dax.DatabaseID("db1") - mdsClient := mdsclient.New(mdsAddress, logger.StderrLogger) + controllerClient := controllerclient.New(controllerAddress, logger.StderrLogger) ctx := context.Background() @@ -1772,7 +1772,7 @@ func TestBatchTargetMDS(t *testing.T) { }, }, } - mdsClient.CreateDatabase(ctx, qdb) + controllerClient.CreateDatabase(ctx, qdb) t.Run("FieldTypes", func(t *testing.T) { tests := []struct { @@ -1850,7 +1850,7 @@ func TestBatchTargetMDS(t *testing.T) { {1, time.Now()}, {2, time.Now()}, }, - fieldOptions: dax.FieldOptions{TimeUnit: "s", Epoch: time.Unix(0, 0)}, // TODO w/o this, it used to silently fail (just logs in the mds svc). Eventually should probably have a default unit and not fail at all. + fieldOptions: dax.FieldOptions{TimeUnit: "s", Epoch: time.Unix(0, 0)}, // TODO w/o this, it used to silently fail (just logs in the controller svc). Eventually should probably have a default unit and not fail at all. }, } for i, test := range tests { @@ -1881,14 +1881,14 @@ func TestBatchTargetMDS(t *testing.T) { tbl, ) - // Create the table in MDS Schemar. - if err := mdsClient.CreateTable(ctx, qtbl); err != nil { + // Create the table in Controller Schemar. + if err := controllerClient.CreateTable(ctx, qtbl); err != nil { t.Fatalf("creating table: %v", err) } - // qtblWithID is the same as qtbl above, but now MDS has + // qtblWithID is the same as qtbl above, but now Controller has // assigned the table a unique ID. - qtblWithID, err := mdsClient.Table(ctx, qtbl.QualifiedID()) + qtblWithID, err := controllerClient.Table(ctx, qtbl.QualifiedID()) assert.NoError(t, err) ts := newTestSource([]Field{ @@ -1897,7 +1897,7 @@ func TestBatchTargetMDS(t *testing.T) { }, test.in) ingester := NewMain() - configureTestFlagsMDS(ingester, mdsAddress, qtblWithID) + configureTestFlagsController(ingester, controllerAddress, qtblWithID) ingester.NewSource = func() (Source, error) { return ts, nil } ingester.BatchSize = 10 diff --git a/idk/interfaces.go b/idk/interfaces.go index 6e24ce29c..186abb226 100644 --- a/idk/interfaces.go +++ b/idk/interfaces.go @@ -1312,13 +1312,13 @@ func (f Fields) ContainsBool() bool { // SchemaManager is meant to be an interface for managing schema information; // i.e. for interacting with a single source of truth for schema information, -// like the MDS Schemar. But... it currently contains methods which are not -// related to schema because the first goal was just to introduce an interface -// in ingest.go for any methods being called on *m.client. We don't want a -// FeatureBase client directly called from ingest, rather, we want to call these -// interface methods and allow for different implementations (such as an MDS -// implementation which uses the Schemar in MDS as opposed to a FeatureBase node -// or cluster). +// like the Serverless Schemar. But... it currently contains methods which are +// not related to schema because the first goal was just to introduce an +// interface in ingest.go for any methods being called on *m.client. We don't +// want a FeatureBase client directly called from ingest, rather, we want to +// call these interface methods and allow for different implementations (such as +// a Serverless implementation which uses the Schemar in Serverless as opposed +// to a FeatureBase node or cluster). type SchemaManager interface { StartTransaction(id string, timeout time.Duration, exclusive bool, requestTimeout time.Duration) (*pilosacore.Transaction, error) FinishTransaction(id string) (*pilosacore.Transaction, error) diff --git a/idk/mds/importer.go b/idk/serverless/importer.go similarity index 99% rename from idk/mds/importer.go rename to idk/serverless/importer.go index 27a2757c3..4e8501de7 100644 --- a/idk/mds/importer.go +++ b/idk/serverless/importer.go @@ -1,4 +1,4 @@ -package mds +package serverless import ( "context" @@ -8,7 +8,7 @@ import ( featurebase "github.com/featurebasedb/featurebase/v3" featurebaseclient "github.com/featurebasedb/featurebase/v3/client" "github.com/featurebasedb/featurebase/v3/dax" - "github.com/featurebasedb/featurebase/v3/dax/mds/controller/partitioner" + "github.com/featurebasedb/featurebase/v3/dax/controller/partitioner" "github.com/featurebasedb/featurebase/v3/roaring" "github.com/pkg/errors" ) diff --git a/idk/mds/schemamanager.go b/idk/serverless/schemamanager.go similarity index 91% rename from idk/mds/schemamanager.go rename to idk/serverless/schemamanager.go index d1e691c06..e6ddadd1d 100644 --- a/idk/mds/schemamanager.go +++ b/idk/serverless/schemamanager.go @@ -1,4 +1,4 @@ -package mds +package serverless import ( "context" @@ -7,7 +7,7 @@ import ( featurebase "github.com/featurebasedb/featurebase/v3" featurebase_client "github.com/featurebasedb/featurebase/v3/client" "github.com/featurebasedb/featurebase/v3/dax" - mdsclient "github.com/featurebasedb/featurebase/v3/dax/mds/client" + controllerclient "github.com/featurebasedb/featurebase/v3/dax/controller/client" "github.com/featurebasedb/featurebase/v3/errors" "github.com/featurebasedb/featurebase/v3/logger" ) @@ -17,14 +17,14 @@ import ( // schemaManager type schemaManager struct { - client *mdsclient.Client + client *controllerclient.Client qdbid dax.QualifiedDatabaseID logger logger.Logger } -func NewSchemaManager(mdsAddress dax.Address, qdbid dax.QualifiedDatabaseID, logger logger.Logger) *schemaManager { +func NewSchemaManager(controllerAddress dax.Address, qdbid dax.QualifiedDatabaseID, logger logger.Logger) *schemaManager { return &schemaManager{ - client: mdsclient.New(mdsAddress, logger), + client: controllerclient.New(controllerAddress, logger), qdbid: qdbid, logger: logger, } diff --git a/server/config.go b/server/config.go index d1e72a38b..8af0776a6 100644 --- a/server/config.go +++ b/server/config.go @@ -52,11 +52,11 @@ type Config struct { // Name a unique name for this node in the cluster. Name string `toml:"name"` - // MDSAddress is the location at which this node should register itself and - // retrieve its instructions. For example, after registring, the MDS service - // might tell this node that it is responsible for specific shards for a - // particular index. - MDSAddress string `toml:"mds-address"` + // ControllerAddress is the location at which this node should register + // itself and retrieve its instructions. For example, after registring, the + // Controller service might tell this node that it is responsible for + // specific shards for a particular index. + ControllerAddress string `toml:"controller-address"` // WriteloggerDir is the location at which this node should // read/write change logs. Typically a network mounted filesystem @@ -210,7 +210,7 @@ type Config struct { } `toml:"sql"` // CheckInTimeout is the amount of time between compute node check-ins to - // MDS. + // Controller. CheckInInterval time.Duration `toml:"check-in-interval"` // Storage.Backend determines which Tx implementation the holder/Index will diff --git a/server/server.go b/server/server.go index a4188aa34..a837ecd20 100644 --- a/server/server.go +++ b/server/server.go @@ -123,7 +123,7 @@ func OptCommandConfig(config *Config) CommandOption { c.Config.Etcd = config.Etcd c.Config.Auth = config.Auth c.Config.TLS = config.TLS - c.Config.MDSAddress = config.MDSAddress + c.Config.ControllerAddress = config.ControllerAddress c.Config.SQL.EndpointEnabled = config.SQL.EndpointEnabled return nil } @@ -280,7 +280,7 @@ func (m *Command) StartNoServe(addr dax.Address) (err error) { } // Start the "check-in" background process which periodically checks in with - // MDS. + // the Controller. go m.checkIn(addr) return nil @@ -303,7 +303,7 @@ func (m *Command) checkIn(addr dax.Address) { m.logger.Debugf("node check-in in last %s, address: %s", interval, m.Config.Advertise) if m.Registrar == nil { - m.logger.Printf("no MDS implementation with which to check-in on node: %s", m.Config.Advertise) + m.logger.Printf("no Controller implementation with which to check-in on node: %s", m.Config.Advertise) } node := &dax.Node{