add Ping operation to`store` interface. (#757)

* add `Ping` operation.

* add `Ping` implementation of GA components

* add context to an argument for Ping

* add `Ping` implementation of blobstorage

* fix error string for passing lint

* Update blobstorage.go

Co-authored-by: Artur Souza <artursouza.ms@outlook.com>
This commit is contained in:
문찬용 2021-05-26 15:48:46 +09:00 committed by GitHub
parent efd198026f
commit b387fcdff3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 142 additions and 3 deletions

View File

@ -230,6 +230,10 @@ func (aspike *Aerospike) Delete(req *state.DeleteRequest) error {
return nil
}
func (aspike *Aerospike) Ping() error {
return nil
}
func parseHosts(hostsMeta string) ([]*as.Host, error) {
hostPorts := []*as.Host{}
for _, hostPort := range strings.Split(hostsMeta, ",") {

View File

@ -51,6 +51,10 @@ func (d *StateStore) Init(metadata state.Metadata) error {
return nil
}
func (d *StateStore) Ping() error {
return nil
}
// Features returns the features available in this state store
func (d *StateStore) Features() []state.Feature {
return nil

View File

@ -138,6 +138,16 @@ func (r *StateStore) Set(req *state.SetRequest) error {
return r.writeFile(req)
}
func (r *StateStore) Ping() error {
accessConditions := azblob.BlobAccessConditions{}
if _, err := r.containerURL.GetProperties(context.Background(), accessConditions.LeaseAccessConditions); err != nil {
return fmt.Errorf("blob storage: error connecting to Blob storage at %s: %s", r.containerURL.URL().Host, err)
}
return nil
}
// NewAzureBlobStorageStore instance
func NewAzureBlobStorageStore(logger logger.Logger) *StateStore {
s := &StateStore{

View File

@ -28,6 +28,7 @@ type StateStore struct {
collection *documentdb.Collection
db *documentdb.Database
sp *documentdb.Sproc
metadata metadata
contentType string
features []state.Feature
@ -139,6 +140,7 @@ func (c *StateStore) Init(meta state.Metadata) error {
return fmt.Errorf("collection %s for CosmosDB state store not found. This must be created before Dapr uses it", m.Collection)
}
c.metadata = m
c.collection = &colls[0]
c.client = client
c.contentType = m.ContentType
@ -359,6 +361,24 @@ func (c *StateStore) Multi(request *state.TransactionalStateRequest) error {
return nil
}
func (c *StateStore) Ping() error {
m := c.metadata
colls, err := c.client.QueryCollections(c.db.Self, &documentdb.Query{
Query: "SELECT * FROM ROOT r WHERE r.id=@id",
Parameters: []documentdb.Parameter{
{Name: "@id", Value: m.Collection},
},
})
if err != nil {
return err
} else if len(colls) == 0 {
return fmt.Errorf("collection %s for CosmosDB state store not found", m.Collection)
}
return nil
}
func createUpsertItem(contentType string, req state.SetRequest, partitionKey string) CosmosItem {
byteArray, isBinary := req.Value.([]uint8)
if isBinary {

View File

@ -236,6 +236,10 @@ func (r *StateStore) deleteRow(req *state.DeleteRequest) error {
return entity.Delete(true, nil)
}
func (r *StateStore) Ping() error {
return nil
}
func getPartitionAndRowKey(key string) (string, string) {
pr := strings.Split(key, keyDelimiter)
if len(pr) != 2 {

View File

@ -289,6 +289,10 @@ func (c *Cassandra) Set(req *state.SetRequest) error {
return session.Query("INSERT INTO ? (key, value) VALUES (?, ?)", c.table, req.Key, bt).Exec()
}
func (c *Cassandra) Ping() error {
return nil
}
func (c *Cassandra) createSession(consistency gocql.Consistency) (*gocql.Session, error) {
session, err := c.cluster.CreateSession()
if err != nil {

View File

@ -265,6 +265,10 @@ func (c *CRDT) Init(metadata state.Metadata) error {
return nil
}
func (c *CRDT) Ping() error {
return nil
}
// Features returns the features available in this state store
func (c *CRDT) Features() []state.Feature {
return c.features

View File

@ -228,6 +228,10 @@ func (cbs *Couchbase) Delete(req *state.DeleteRequest) error {
return nil
}
func (cbs *Couchbase) Ping() error {
return nil
}
// converts string etag sent by the application into a gocb.Cas object, which can then be used for optimistic locking for set and delete operations
func eTagToCas(eTag string) (gocb.Cas, error) {
var cas gocb.Cas = 0

View File

@ -136,6 +136,10 @@ func (f *Firestore) Set(req *state.SetRequest) error {
return state.SetWithOptions(f.setValue, req)
}
func (f *Firestore) Ping() error {
return nil
}
func (f *Firestore) deleteValue(req *state.DeleteRequest) error {
ctx := context.Background()
key := datastore.NameKey(f.entityKind, req.Key, nil)

View File

@ -10,11 +10,10 @@ import (
"fmt"
"github.com/agrea/ptr"
"github.com/hashicorp/consul/api"
"github.com/pkg/errors"
"github.com/dapr/components-contrib/state"
"github.com/dapr/kit/logger"
"github.com/hashicorp/consul/api"
"github.com/pkg/errors"
)
// Consul is a state store implementation for HashiCorp Consul.
@ -138,6 +137,10 @@ func (c *Consul) Set(req *state.SetRequest) error {
return nil
}
func (c *Consul) Ping() error {
return nil
}
// Delete performes a Consul KV delete operation
func (c *Consul) Delete(req *state.DeleteRequest) error {
keyWithPath := fmt.Sprintf("%s/%s", c.keyPrefixPath, req.Key)

View File

@ -123,6 +123,10 @@ func (store *Hazelcast) Get(req *state.GetRequest) (*state.GetResponse, error) {
}, nil
}
func (store *Hazelcast) Ping() error {
return nil
}
// Delete performs a delete operation
func (store *Hazelcast) Delete(req *state.DeleteRequest) error {
err := state.CheckRequestOptions(req.Options)

View File

@ -141,3 +141,7 @@ func (m *Memcached) Get(req *state.GetRequest) (*state.GetResponse, error) {
func (m *Memcached) Set(req *state.SetRequest) error {
return state.SetWithOptions(m.setValue, req)
}
func (m *Memcached) Ping() error {
return nil
}

View File

@ -58,6 +58,7 @@ type MongoDB struct {
client *mongo.Client
collection *mongo.Collection
operationTimeout time.Duration
metadata mongoDBMetadata
features []state.Feature
logger logger.Logger
@ -125,6 +126,7 @@ func (m *MongoDB) Init(metadata state.Metadata) error {
return fmt.Errorf("error in getting read concern object: %s", err)
}
m.metadata = *meta
opts := options.Collection().SetWriteConcern(wc).SetReadConcern(rc)
collection := m.client.Database(meta.databaseName).Collection(meta.collectionName, opts)
@ -151,6 +153,14 @@ func (m *MongoDB) Set(req *state.SetRequest) error {
return nil
}
func (m *MongoDB) Ping() error {
if err := m.client.Ping(context.Background(), nil); err != nil {
return fmt.Errorf("mongoDB store: error connecting to mongoDB at %s: %s", m.metadata.host, err)
}
return nil
}
func (m *MongoDB) setInternal(ctx context.Context, req *state.SetRequest) error {
var vStr string
b, ok := req.Value.([]byte)

View File

@ -149,6 +149,10 @@ func (m *MySQL) Init(metadata state.Metadata) error {
return m.finishInit(db, err)
}
func (m *MySQL) Ping() error {
return nil
}
// Features returns the features available in this state store
func (m *MySQL) Features() []state.Feature {
return m.features

View File

@ -41,6 +41,10 @@ func (p *PostgreSQL) Init(metadata state.Metadata) error {
return p.dbaccess.Init(metadata)
}
func (p *PostgreSQL) Ping() error {
return nil
}
// Features returns the features available in this state store
func (p *PostgreSQL) Features() []state.Feature {
return p.features

View File

@ -130,6 +130,14 @@ func parseRedisMetadata(meta state.Metadata) (metadata, error) {
return m, nil
}
func (r *StateStore) Ping() error {
if _, err := r.client.Ping(context.Background()).Result(); err != nil {
return fmt.Errorf("redis store: error connecting to redis at %s: %s", r.metadata.host, err)
}
return nil
}
// Init does metadata and connection parsing
func (r *StateStore) Init(metadata state.Metadata) error {
m, err := parseRedisMetadata(metadata)

View File

@ -181,6 +181,24 @@ func TestTransactionalDelete(t *testing.T) {
assert.Equal(t, 0, len(vals))
}
func TestPing(t *testing.T) {
s, c := setupMiniredis()
ss := &StateStore{
client: c,
json: jsoniter.ConfigFastest,
logger: logger.NewLogger("test"),
}
err := ss.Ping()
assert.Nil(t, err)
s.Close()
err = ss.Ping()
assert.NotNil(t, err)
}
func TestTransactionalDeleteNoEtag(t *testing.T) {
s, c := setupMiniredis()
defer s.Close()

View File

@ -123,6 +123,10 @@ func (s *RethinkDB) Init(metadata state.Metadata) error {
return nil
}
func (s *RethinkDB) Ping() error {
return nil
}
// Features returns the features available in this state store
func (s *RethinkDB) Features() []state.Feature {
return s.features

View File

@ -253,6 +253,10 @@ func (s *SQLServer) Init(metadata state.Metadata) error {
return nil
}
func (s *SQLServer) Ping() error {
return nil
}
// Features returns the features available in this state store
func (s *SQLServer) Features() []state.Feature {
return s.features

View File

@ -13,6 +13,7 @@ type Store interface {
Delete(req *DeleteRequest) error
Get(req *GetRequest) (*GetResponse, error)
Set(req *SetRequest) error
Ping() error
}
// BulkStore is an interface to perform bulk operations on store

View File

@ -115,6 +115,10 @@ func (s *Store1) Set(req *SetRequest) error {
return nil
}
func (s *Store1) Ping() error {
return nil
}
// example of store which supports bulk method
type Store2 struct {
// DefaultBulkStore
@ -150,6 +154,10 @@ func (s *Store2) Set(req *SetRequest) error {
return nil
}
func (s *Store2) Ping() error {
return nil
}
func (s *Store2) BulkGet(req []GetRequest) (bool, []BulkGetResponse, error) {
if s.supportBulkGet {
s.bulkCount++

View File

@ -295,6 +295,10 @@ func (s *StateStore) BulkSet(reqs []state.SetRequest) error {
}
}
func (s *StateStore) Ping() error {
return nil
}
func (s *StateStore) newCreateRequest(req *zk.SetDataRequest) *zk.CreateRequest {
return &zk.CreateRequest{Path: req.Path, Data: req.Data}
}

View File

@ -196,6 +196,11 @@ func ConformanceTests(t *testing.T, props map[string]string, statestore state.St
assert.Nil(t, err)
})
t.Run("ping", func(t *testing.T) {
err := statestore.Ping()
assert.Nil(t, err)
})
if config.HasOperation("set") {
t.Run("set", func(t *testing.T) {
for _, scenario := range scenarios {