| @@ -17,7 +17,6 @@ import ( | |||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
| 	"github.com/micro/go-micro/config/options" |  | ||||||
| 	"github.com/micro/go-micro/store" | 	"github.com/micro/go-micro/store" | ||||||
| 	"github.com/pkg/errors" | 	"github.com/pkg/errors" | ||||||
| ) | ) | ||||||
| @@ -27,7 +26,7 @@ const ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| type workersKV struct { | type workersKV struct { | ||||||
| 	options.Options | 	options store.Options | ||||||
| 	// cf account id | 	// cf account id | ||||||
| 	account string | 	account string | ||||||
| 	// cf api token | 	// cf api token | ||||||
| @@ -291,38 +290,25 @@ func (w *workersKV) request(ctx context.Context, method, path string, body inter | |||||||
| // CF_API_TOKEN to a cloudflare API token scoped to Workers KV. | // CF_API_TOKEN to a cloudflare API token scoped to Workers KV. | ||||||
| // CF_ACCOUNT_ID to contain a string with your cloudflare account ID. | // CF_ACCOUNT_ID to contain a string with your cloudflare account ID. | ||||||
| // KV_NAMESPACE_ID to contain the namespace UUID for your KV storage. | // KV_NAMESPACE_ID to contain the namespace UUID for your KV storage. | ||||||
| func NewStore(opts ...options.Option) store.Store { | func NewStore(opts ...store.Option) store.Store { | ||||||
| 	// create new Options | 	var options store.Options | ||||||
| 	options := options.NewOptions(opts...) | 	for _, o := range opts { | ||||||
|  | 		o(&options) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	// get values from the environment | 	// get options from environment | ||||||
| 	account, token, namespace := getOptions() | 	account, token, namespace := getOptions() | ||||||
|  |  | ||||||
| 	// set api token from options if exists | 	if len(account) == 0 { | ||||||
| 	if apiToken, ok := options.Values().Get("CF_API_TOKEN"); ok { | 		account = getAccount(options.Context) | ||||||
| 		tk, ok := apiToken.(string) |  | ||||||
| 		if !ok { |  | ||||||
| 			log.Fatal("Store: Option CF_API_TOKEN contains a non-string") |  | ||||||
| 		} |  | ||||||
| 		token = tk |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// set account id from options if exists | 	if len(token) == 0 { | ||||||
| 	if accountID, ok := options.Values().Get("CF_ACCOUNT_ID"); ok { | 		token = getToken(options.Context) | ||||||
| 		id, ok := accountID.(string) |  | ||||||
| 		if !ok { |  | ||||||
| 			log.Fatal("Store: Option CF_ACCOUNT_ID contains a non-string") |  | ||||||
| 		} |  | ||||||
| 		account = id |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// set namespace from options if exists | 	if len(namespace) == 0 { | ||||||
| 	if uuid, ok := options.Values().Get("KV_NAMESPACE_ID"); ok { | 		namespace = getNamespace(options.Context) | ||||||
| 		ns, ok := uuid.(string) |  | ||||||
| 		if !ok { |  | ||||||
| 			log.Fatal("Store: Option KV_NAMESPACE_ID contains a non-string") |  | ||||||
| 		} |  | ||||||
| 		namespace = ns |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// validate options are not blank or log.Fatal | 	// validate options are not blank or log.Fatal | ||||||
| @@ -332,7 +318,7 @@ func NewStore(opts ...options.Option) store.Store { | |||||||
| 		account:    account, | 		account:    account, | ||||||
| 		namespace:  namespace, | 		namespace:  namespace, | ||||||
| 		token:      token, | 		token:      token, | ||||||
| 		Options:    options, | 		options:    options, | ||||||
| 		httpClient: &http.Client{}, | 		httpClient: &http.Client{}, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,23 +1,60 @@ | |||||||
| package cloudflare | package cloudflare | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"github.com/micro/go-micro/config/options" | 	"context" | ||||||
|  |  | ||||||
|  | 	"github.com/micro/go-micro/store" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | func getOption(ctx context.Context, key string) string { | ||||||
|  | 	if ctx == nil { | ||||||
|  | 		return "" | ||||||
|  | 	} | ||||||
|  | 	val, ok := ctx.Value(key).(string) | ||||||
|  | 	if !ok { | ||||||
|  | 		return "" | ||||||
|  | 	} | ||||||
|  | 	return val | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func getToken(ctx context.Context) string { | ||||||
|  | 	return getOption(ctx, "CF_API_TOKEN") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func getAccount(ctx context.Context) string { | ||||||
|  | 	return getOption(ctx, "CF_ACCOUNT_ID") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func getNamespace(ctx context.Context) string { | ||||||
|  | 	return getOption(ctx, "KV_NAMESPACE_ID") | ||||||
|  | } | ||||||
|  |  | ||||||
| // Token sets the cloudflare api token | // Token sets the cloudflare api token | ||||||
| func Token(t string) options.Option { | func Token(t string) store.Option { | ||||||
| 	// TODO: change to store.cf.api_token | 	return func(o *store.Options) { | ||||||
| 	return options.WithValue("CF_API_TOKEN", t) | 		if o.Context == nil { | ||||||
|  | 			o.Context = context.Background() | ||||||
|  | 		} | ||||||
|  | 		o.Context = context.WithValue(o.Context, "CF_API_TOKEN", t) | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // Account sets the cloudflare account id | // Account sets the cloudflare account id | ||||||
| func Account(id string) options.Option { | func Account(id string) store.Option { | ||||||
| 	// TODO: change to store.cf.account_id | 	return func(o *store.Options) { | ||||||
| 	return options.WithValue("CF_ACCOUNT_ID", id) | 		if o.Context == nil { | ||||||
|  | 			o.Context = context.Background() | ||||||
|  | 		} | ||||||
|  | 		o.Context = context.WithValue(o.Context, "CF_ACCOUNT_ID", id) | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // Namespace sets the KV namespace | // Namespace sets the KV namespace | ||||||
| func Namespace(ns string) options.Option { | func Namespace(ns string) store.Option { | ||||||
| 	// TODO: change to store.cf.namespace | 	return func(o *store.Options) { | ||||||
| 	return options.WithValue("KV_NAMESPACE_ID", ns) | 		if o.Context == nil { | ||||||
|  | 			o.Context = context.Background() | ||||||
|  | 		} | ||||||
|  | 		o.Context = context.WithValue(o.Context, "KV_NAMESPACE_ID", ns) | ||||||
|  | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -7,12 +7,11 @@ import ( | |||||||
|  |  | ||||||
| 	client "github.com/coreos/etcd/clientv3" | 	client "github.com/coreos/etcd/clientv3" | ||||||
| 	"github.com/coreos/etcd/mvcc/mvccpb" | 	"github.com/coreos/etcd/mvcc/mvccpb" | ||||||
| 	"github.com/micro/go-micro/config/options" |  | ||||||
| 	"github.com/micro/go-micro/store" | 	"github.com/micro/go-micro/store" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type ekv struct { | type ekv struct { | ||||||
| 	options.Options | 	options store.Options | ||||||
| 	kv      client.KV | 	kv      client.KV | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -91,15 +90,15 @@ func (e *ekv) String() string { | |||||||
| 	return "etcd" | 	return "etcd" | ||||||
| } | } | ||||||
|  |  | ||||||
| func NewStore(opts ...options.Option) store.Store { | func NewStore(opts ...store.Option) store.Store { | ||||||
| 	options := options.NewOptions(opts...) | 	var options store.Options | ||||||
|  | 	for _, o := range opts { | ||||||
| 	var endpoints []string | 		o(&options) | ||||||
|  |  | ||||||
| 	if e, ok := options.Values().Get("store.nodes"); ok { |  | ||||||
| 		endpoints = e.([]string) |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// get the endpoints | ||||||
|  | 	endpoints := options.Nodes | ||||||
|  |  | ||||||
| 	if len(endpoints) == 0 { | 	if len(endpoints) == 0 { | ||||||
| 		endpoints = []string{"http://127.0.0.1:2379"} | 		endpoints = []string{"http://127.0.0.1:2379"} | ||||||
| 	} | 	} | ||||||
| @@ -113,7 +112,7 @@ func NewStore(opts ...options.Option) store.Store { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return &ekv{ | 	return &ekv{ | ||||||
| 		Options: options, | 		options: options, | ||||||
| 		kv:      client.NewKV(c), | 		kv:      client.NewKV(c), | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -5,12 +5,11 @@ import ( | |||||||
| 	"sync" | 	"sync" | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
| 	"github.com/micro/go-micro/config/options" |  | ||||||
| 	"github.com/micro/go-micro/store" | 	"github.com/micro/go-micro/store" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type memoryStore struct { | type memoryStore struct { | ||||||
| 	options.Options | 	options store.Options | ||||||
|  |  | ||||||
| 	sync.RWMutex | 	sync.RWMutex | ||||||
| 	values map[string]*memoryRecord | 	values map[string]*memoryRecord | ||||||
| @@ -110,11 +109,14 @@ func (m *memoryStore) Delete(keys ...string) error { | |||||||
| } | } | ||||||
|  |  | ||||||
| // NewStore returns a new store.Store | // NewStore returns a new store.Store | ||||||
| func NewStore(opts ...options.Option) store.Store { | func NewStore(opts ...store.Option) store.Store { | ||||||
| 	options := options.NewOptions(opts...) | 	var options store.Options | ||||||
|  | 	for _, o := range opts { | ||||||
|  | 		o(&options) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return &memoryStore{ | 	return &memoryStore{ | ||||||
| 		Options: options, | 		options: options, | ||||||
| 		values:  make(map[string]*memoryRecord), | 		values:  make(map[string]*memoryRecord), | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| package store | package store | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"github.com/micro/go-micro/config/options" | 	"context" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type Options struct { | type Options struct { | ||||||
| @@ -11,20 +11,30 @@ type Options struct { | |||||||
| 	Namespace string | 	Namespace string | ||||||
| 	// Prefix of the keys used | 	// Prefix of the keys used | ||||||
| 	Prefix string | 	Prefix string | ||||||
|  | 	// Alternative options | ||||||
|  | 	Context context.Context | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type Option func(o *Options) | ||||||
|  |  | ||||||
| // Nodes is a list of nodes used to back the store | // Nodes is a list of nodes used to back the store | ||||||
| func Nodes(a ...string) options.Option { | func Nodes(a ...string) Option { | ||||||
| 	return options.WithValue("store.nodes", a) | 	return func(o *Options) { | ||||||
|  | 		o.Nodes = a | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // Prefix sets a prefix to any key ids used | // Prefix sets a prefix to any key ids used | ||||||
| func Prefix(p string) options.Option { | func Prefix(p string) Option { | ||||||
| 	return options.WithValue("store.prefix", p) | 	return func(o *Options) { | ||||||
|  | 		o.Prefix = p | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // Namespace offers a way to have multiple isolated | // Namespace offers a way to have multiple isolated | ||||||
| // stores in the same backend, if supported. | // stores in the same backend, if supported. | ||||||
| func Namespace(n string) options.Option { | func Namespace(ns string) Option { | ||||||
| 	return options.WithValue("store.namespace", n) | 	return func(o *Options) { | ||||||
|  | 		o.Namespace = ns | ||||||
|  | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -4,15 +4,13 @@ package postgresql | |||||||
| import ( | import ( | ||||||
| 	"database/sql" | 	"database/sql" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"strings" |  | ||||||
| 	"time" | 	"time" | ||||||
| 	"unicode" | 	"unicode" | ||||||
|  |  | ||||||
| 	"github.com/lib/pq" | 	"github.com/lib/pq" | ||||||
| 	"github.com/pkg/errors" |  | ||||||
|  |  | ||||||
| 	"github.com/micro/go-micro/config/options" |  | ||||||
| 	"github.com/micro/go-micro/store" | 	"github.com/micro/go-micro/store" | ||||||
|  | 	"github.com/micro/go-micro/util/log" | ||||||
|  | 	"github.com/pkg/errors" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // DefaultNamespace is the namespace that the sql store | // DefaultNamespace is the namespace that the sql store | ||||||
| @@ -27,7 +25,8 @@ type sqlStore struct { | |||||||
|  |  | ||||||
| 	database string | 	database string | ||||||
| 	table    string | 	table    string | ||||||
| 	options.Options |  | ||||||
|  | 	options store.Options | ||||||
| } | } | ||||||
|  |  | ||||||
| // List all the known records | // List all the known records | ||||||
| @@ -151,38 +150,16 @@ func (s *sqlStore) Delete(keys ...string) error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (s *sqlStore) initDB(options options.Options) error { | func (s *sqlStore) initDB() { | ||||||
| 	// Get the store.namespace option, or use sql.DefaultNamespace |  | ||||||
| 	namespaceOpt, found := options.Values().Get("store.namespace") |  | ||||||
| 	if !found { |  | ||||||
| 		s.database = DefaultNamespace |  | ||||||
| 	} else { |  | ||||||
| 		if namespace, ok := namespaceOpt.(string); ok { |  | ||||||
| 			s.database = namespace |  | ||||||
| 		} else { |  | ||||||
| 			return errors.New("store.namespace option must be a string") |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	// Get the store.namespace option, or use sql.DefaultNamespace |  | ||||||
| 	prefixOpt, found := options.Values().Get("store.prefix") |  | ||||||
| 	if !found { |  | ||||||
| 		s.table = DefaultPrefix |  | ||||||
| 	} else { |  | ||||||
| 		if prefix, ok := prefixOpt.(string); ok { |  | ||||||
| 			s.table = prefix |  | ||||||
| 		} else { |  | ||||||
| 			return errors.New("store.namespace option must be a string") |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// Create "micro" schema | 	// Create "micro" schema | ||||||
| 	schema, err := s.db.Prepare(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s ;", s.database)) | 	schema, err := s.db.Prepare(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s ;", s.database)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		log.Fatal(err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	_, err = schema.Exec() | 	_, err = schema.Exec() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return errors.Wrap(err, "Couldn't create database") | 		log.Fatal(errors.Wrap(err, "Couldn't create database")) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Create a table for the Store namespace | 	// Create a table for the Store namespace | ||||||
| @@ -194,73 +171,59 @@ func (s *sqlStore) initDB(options options.Options) error { | |||||||
| 		CONSTRAINT %s_pkey PRIMARY KEY (key) | 		CONSTRAINT %s_pkey PRIMARY KEY (key) | ||||||
| 	);`, s.database, s.table, s.table)) | 	);`, s.database, s.table, s.table)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return errors.Wrap(err, "SQL statement preparation failed") | 		log.Fatal(errors.Wrap(err, "SQL statement preparation failed")) | ||||||
| 	} |  | ||||||
| 	_, err = tableq.Exec() |  | ||||||
| 	if err != nil { |  | ||||||
| 		return errors.Wrap(err, "Couldn't create table") |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return nil | 	_, err = tableq.Exec() | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(errors.Wrap(err, "Couldn't create table")) | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // New returns a new micro Store backed by sql | // New returns a new micro Store backed by sql | ||||||
| func New(opts ...options.Option) (store.Store, error) { | func New(opts ...store.Option) store.Store { | ||||||
| 	options := options.NewOptions(opts...) | 	var options store.Options | ||||||
| 	driver, dataSourceName, err := validateOptions(options) | 	for _, o := range opts { | ||||||
| 	if err != nil { | 		o(&options) | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	if !strings.Contains(dataSourceName, " ") { |  | ||||||
| 		dataSourceName = fmt.Sprintf("host=%s", dataSourceName) |  | ||||||
| 	} |  | ||||||
| 	db, err := sql.Open(driver, dataSourceName) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	if err := db.Ping(); err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	s := &sqlStore{ |  | ||||||
| 		db: db, |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return s, s.initDB(options) | 	nodes := options.Nodes | ||||||
|  | 	if len(nodes) == 0 { | ||||||
|  | 		nodes = []string{"localhost:26257"} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| // validateOptions checks whether the provided options are valid, then returns the driver | 	namespace := options.Namespace | ||||||
| // and data source name. | 	if len(namespace) == 0 { | ||||||
| func validateOptions(options options.Options) (driver, dataSourceName string, err error) { | 		namespace = DefaultNamespace | ||||||
| 	driverOpt, found := options.Values().Get("store.sql.driver") |  | ||||||
| 	if !found { |  | ||||||
| 		return "", "", errors.New("No store.sql.driver option specified") |  | ||||||
| 	} | 	} | ||||||
| 	nodesOpt, found := options.Values().Get("store.nodes") |  | ||||||
| 	if !found { | 	prefix := options.Prefix | ||||||
| 		return "", "", errors.New("No store.nodes option specified (expected a database connection string)") | 	if len(prefix) == 0 { | ||||||
| 	} | 		prefix = DefaultPrefix | ||||||
| 	driver, ok := driverOpt.(string) |  | ||||||
| 	if !ok { |  | ||||||
| 		return "", "", errors.New("store.sql.driver option must be a string") |  | ||||||
| 	} |  | ||||||
| 	nodes, ok := nodesOpt.([]string) |  | ||||||
| 	if !ok { |  | ||||||
| 		return "", "", errors.New("store.nodes option must be a []string") |  | ||||||
| 	} |  | ||||||
| 	if len(nodes) != 1 { |  | ||||||
| 		return "", "", errors.New("expected only 1 store.nodes option") |  | ||||||
| 	} |  | ||||||
| 	namespaceOpt, found := options.Values().Get("store.namespace") |  | ||||||
| 	if found { |  | ||||||
| 		namespace, ok := namespaceOpt.(string) |  | ||||||
| 		if !ok { |  | ||||||
| 			return "", "", errors.New("store.namespace must me a string") |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for _, r := range namespace { | 	for _, r := range namespace { | ||||||
| 		if !unicode.IsLetter(r) { | 		if !unicode.IsLetter(r) { | ||||||
| 				return "", "", errors.New("store.namespace must only contain letters") | 			log.Fatal("store.namespace must only contain letters") | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// create source from first node | ||||||
|  | 	source := fmt.Sprintf("host=%s", nodes[0]) | ||||||
|  | 	db, err := sql.Open("pq", source) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
| 	} | 	} | ||||||
| 	return driver, nodes[0], nil |  | ||||||
|  | 	if err := db.Ping(); err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	s := &sqlStore{ | ||||||
|  | 		db:       db, | ||||||
|  | 		database: namespace, | ||||||
|  | 		table:    prefix, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return s | ||||||
| } | } | ||||||
|   | |||||||
| @@ -27,13 +27,10 @@ func TestSQL(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| 	db.Close() | 	db.Close() | ||||||
|  |  | ||||||
| 	sqlStore, err := New( | 	sqlStore := New( | ||||||
| 		store.Namespace("testsql"), | 		store.Namespace("testsql"), | ||||||
| 		store.Nodes(connection), | 		store.Nodes(connection), | ||||||
| 	) | 	) | ||||||
| 	if err != nil { |  | ||||||
| 		t.Fatal(err.Error()) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	records, err := sqlStore.List() | 	records, err := sqlStore.List() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|   | |||||||
| @@ -7,14 +7,13 @@ import ( | |||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
| 	"github.com/micro/go-micro/client" | 	"github.com/micro/go-micro/client" | ||||||
| 	"github.com/micro/go-micro/config/options" |  | ||||||
| 	"github.com/micro/go-micro/metadata" | 	"github.com/micro/go-micro/metadata" | ||||||
| 	"github.com/micro/go-micro/store" | 	"github.com/micro/go-micro/store" | ||||||
| 	pb "github.com/micro/go-micro/store/service/proto" | 	pb "github.com/micro/go-micro/store/service/proto" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type serviceStore struct { | type serviceStore struct { | ||||||
| 	options.Options | 	options store.Options | ||||||
|  |  | ||||||
| 	// Namespace to use | 	// Namespace to use | ||||||
| 	Namespace string | 	Namespace string | ||||||
| @@ -123,33 +122,17 @@ func (s *serviceStore) Delete(keys ...string) error { | |||||||
| } | } | ||||||
|  |  | ||||||
| // NewStore returns a new store service implementation | // NewStore returns a new store service implementation | ||||||
| func NewStore(opts ...options.Option) store.Store { | func NewStore(opts ...store.Option) store.Store { | ||||||
| 	options := options.NewOptions(opts...) | 	var options store.Options | ||||||
|  | 	for _, o := range opts { | ||||||
| 	var nodes []string | 		o(&options) | ||||||
| 	var namespace string |  | ||||||
| 	var prefix string |  | ||||||
|  |  | ||||||
| 	n, ok := options.Values().Get("store.nodes") |  | ||||||
| 	if ok { |  | ||||||
| 		nodes = n.([]string) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	ns, ok := options.Values().Get("store.namespace") |  | ||||||
| 	if ok { |  | ||||||
| 		namespace = ns.(string) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	prx, ok := options.Values().Get("store.prefix") |  | ||||||
| 	if ok { |  | ||||||
| 		prefix = prx.(string) |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	service := &serviceStore{ | 	service := &serviceStore{ | ||||||
| 		Options:   options, | 		options:   options, | ||||||
| 		Namespace: namespace, | 		Namespace: options.Namespace, | ||||||
| 		Prefix:    prefix, | 		Prefix:    options.Prefix, | ||||||
| 		Nodes:     nodes, | 		Nodes:     options.Nodes, | ||||||
| 		Client:    pb.NewStoreService("go.micro.store", client.DefaultClient), | 		Client:    pb.NewStoreService("go.micro.store", client.DefaultClient), | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user