Package discovery implements cluster discovery helpers for Tarantool 3.0 implemented in Go language according to the design document.
The main example demonstrates how to create a pool of connections based on a cluster configuration in etcd.
NOTE: the public API is not stable and could be changed until release v1.0.0.
package main
import (
"context"
"errors"
"fmt"
"time"
clientv3 "go.etcd.io/etcd/client/v3"
"github.com/tarantool/go-tarantool/v2"
"github.com/tarantool/go-discovery"
"github.com/tarantool/go-discovery/dial"
"github.com/tarantool/go-discovery/discoverer"
"github.com/tarantool/go-discovery/filter"
"github.com/tarantool/go-discovery/pool"
"github.com/tarantool/go-discovery/scheduler"
"github.com/tarantool/go-discovery/subscriber"
)
func main() {
// We need to create a etcd client. The client will use a default port
// for a local etcd instance. You could change the settings.
etcd, err := clientv3.New(clientv3.Config{
Endpoints: []string{"http://127.0.0.1:2379"},
})
if err != nil {
fmt.Println("Unable to start etcd client:", err)
return
}
defer etcd.Close()
// The pool will try to connect to instances without TLS. It will send
// requests in round-robin. But you could use pool.PriorityBalancer to
// send requests by instances priority.
examplePool, err := pool.NewPool(
dial.NewNetDialerFactory("testuser", "testpass", tarantool.Opts{
Timeout: 5 * time.Second,
}),
pool.NewRoundRobinBalancer(),
)
if err != nil {
fmt.Println("Unable to create a pool:", err)
return
}
for {
// The scheduler will watch for updates from etcd.
sched := scheduler.NewEtcdWatch(etcd, "/prefix")
defer sched.Stop()
disc := discoverer.NewFilter(
// The base discoverer gets a list of instance configurations from
// etcd.
discoverer.NewEtcd(etcd, "/prefix"),
// The filter filters the list and leaves only instances with
// Group == "foo".
filter.GroupOneOf{Groups: []string{"foo"}},
// You can play with other filters here, see:
// https://github.com/tarantool/go-discovery/filter/
// subpackage.
)
// The Subscriber will send instance configurations into the pool
// on updates.
etcdSubscriber := subscriber.NewFilter(
// The base subscriber watches for updates from etcd and generates
// a list of update events from it.
subscriber.NewSchedule(sched, disc),
// The filter filters the list of updates and leaves only instances
// with Name == "instance1".
filter.NameOneOf{Names: []string{"instance1"}},
)
// Subscribe the pool for updates from the subscriber. Subscription
// only to single subscriber at a moment is supported.
err := etcdSubscriber.Subscribe(context.Background(), examplePool)
if err != nil {
fmt.Println("Failed to subscribe:", err)
return
}
defer etcdSubscriber.Unsubscribe(examplePool)
for {
// Any request from go-tarantool could be used.
request := tarantool.NewEvalRequest("return box.cfg.listen")
// You could use discovery.ModeRW or discovery.ModeRO to send
// requests to only RW or RO instances.
result, err := examplePool.Do(request, discovery.ModeAny).Get()
if errors.Is(err, pool.ErrUnsubscribed) {
// Something happened with a scheduler (see log messages), we
// need to recreate scheduler and subscribe to it again.
time.Sleep(time.Second)
fmt.Println("Unsubscribed from a scheduler.")
break
}
if errors.Is(err, pool.ErrNoConnectedInstances) {
// The pool is not connected to an instance yet. We could just
// repeat the request. You need to make a more complex
// business logic.
fmt.Println("No instances.")
time.Sleep(time.Second)
continue
}
fmt.Println("Result:", result)
fmt.Println("Error:", err)
fmt.Println("Done.")
return
}
}
}To run default set of tests:
go test -v ./...To generate code, you need to install two utilities:
go install golang.org/x/tools/cmd/stringer@latest
go install github.com/posener/goreadme/cmd/goreadme@latestAfter that, you could generate the code.
go generate ./...In addition, you need to install linter:
go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.51.1You could run the linter with the command.
golangci-lint --config .golangci.yml runFinally, codespell:
pip3 install codespell
codespellYou could also use our Makefile targets:
make deps
make format
make generate
make lint
make test
make testraceYou could run the godoc server on localhost:6060 with the command:
make godoc_runAnd open the generated documentation in another terminal or use the link:
make godoc_open