Skip to content

Commit

Permalink
feat: add ping (#249)
Browse files Browse the repository at this point in the history
* feat: adding ping

* add testing

* respect client timeout for pings

* correct error message
  • Loading branch information
pgautier404 authored and cprice404 committed Mar 14, 2023
1 parent 650a65e commit 2121789
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 1 deletion.
1 change: 1 addition & 0 deletions internal/grpcmanagers/data_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ func NewLocalDataGrpcManager(request *models.LocalDataGrpcManagerRequest) (*Data
}
return &DataGrpcManager{Conn: conn}, nil
}

func (dataManager *DataGrpcManager) Close() momentoerrors.MomentoSvcErr {
return momentoerrors.ConvertSvcErr(dataManager.Conn.Close())
}
40 changes: 40 additions & 0 deletions internal/grpcmanagers/ping_manager.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package grpcmanagers

import (
"crypto/tls"
"fmt"

"github.com/momentohq/client-sdk-go/internal/interceptor"
"github.com/momentohq/client-sdk-go/internal/models"
"github.com/momentohq/client-sdk-go/internal/momentoerrors"

"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
)

type PingGrpcManager struct {
Conn *grpc.ClientConn
}

const PingPort = ":443"

func NewPingGrpcManager(request *models.PingGrpcManagerRequest) (*PingGrpcManager, momentoerrors.MomentoSvcErr) {
config := &tls.Config{
InsecureSkipVerify: false,
}
endpoint := fmt.Sprint(request.CredentialProvider.GetCacheEndpoint(), PingPort)
authToken := request.CredentialProvider.GetAuthToken()
conn, err := grpc.Dial(
endpoint,
grpc.WithTransportCredentials(credentials.NewTLS(config)),
grpc.WithUnaryInterceptor(interceptor.AddHeadersInterceptor(authToken)),
)
if err != nil {
return nil, momentoerrors.ConvertSvcErr(err)
}
return &PingGrpcManager{Conn: conn}, nil
}

func (pingManager *PingGrpcManager) Close() momentoerrors.MomentoSvcErr {
return momentoerrors.ConvertSvcErr(pingManager.Conn.Close())
}
9 changes: 9 additions & 0 deletions internal/models/requests.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ type DataStreamGrpcManagerRequest struct {
CredentialProvider auth.CredentialProvider
}

type PingGrpcManagerRequest struct {
CredentialProvider auth.CredentialProvider
}

type LocalDataGrpcManagerRequest struct {
Endpoint string
}
Expand Down Expand Up @@ -54,3 +58,8 @@ type PubSubClientRequest struct {
Configuration config.Configuration
CredentialProvider auth.CredentialProvider
}

type PingClientRequest struct {
Configuration config.Configuration
CredentialProvider auth.CredentialProvider
}
45 changes: 45 additions & 0 deletions internal/services/scs_ping_service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package services

import (
"context"
"time"

"github.com/momentohq/client-sdk-go/internal/grpcmanagers"
"github.com/momentohq/client-sdk-go/internal/models"
"github.com/momentohq/client-sdk-go/internal/momentoerrors"
pb "github.com/momentohq/client-sdk-go/internal/protos"
)

type ScsPingClient struct {
requestTimeout time.Duration
grpcManager *grpcmanagers.PingGrpcManager
grpcClient pb.PingClient
}

func NewScsPingClient(request *models.PingClientRequest) (*ScsPingClient, momentoerrors.MomentoSvcErr) {
pingManager, err := grpcmanagers.NewPingGrpcManager(&models.PingGrpcManagerRequest{
CredentialProvider: request.CredentialProvider,
})
if err != nil {
return nil, err
}
return &ScsPingClient{
requestTimeout: request.Configuration.GetClientSideTimeout(),
grpcManager: pingManager,
grpcClient: pb.NewPingClient(pingManager.Conn),
}, nil
}

func (client *ScsPingClient) Close() momentoerrors.MomentoSvcErr {
return client.grpcManager.Close()
}

func (client *ScsPingClient) Ping(ctx context.Context) momentoerrors.MomentoSvcErr {
ctx, cancel := context.WithTimeout(ctx, client.requestTimeout)
defer cancel()
_, err := client.grpcClient.Ping(ctx, &pb.XPingRequest{})
if err != nil {
return momentoerrors.ConvertSvcErr(err)
}
return nil
}
21 changes: 20 additions & 1 deletion momento/cache_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ type CacheClient interface {
DictionaryRemoveField(ctx context.Context, r *DictionaryRemoveFieldRequest) (responses.DictionaryRemoveFieldResponse, error)
DictionaryRemoveFields(ctx context.Context, r *DictionaryRemoveFieldsRequest) (responses.DictionaryRemoveFieldsResponse, error)

Ping(ctx context.Context) (responses.PingResponse, error)

Close()
}

Expand All @@ -66,6 +68,7 @@ type defaultScsClient struct {
credentialProvider auth.CredentialProvider
controlClient *services.ScsControlClient
dataClient *scsDataClient
pingClient *services.ScsPingClient
}

type CacheClientProps struct {
Expand All @@ -82,7 +85,7 @@ func NewCacheClient(configuration config.Configuration, credentialProvider auth.
DefaultTtl: defaultTtl,
}
if props.Configuration.GetClientSideTimeout() < 1 {
return nil, momentoerrors.NewMomentoSvcErr(momentoerrors.InvalidArgumentError, "request timeout must not be 0", nil)
return nil, momentoerrors.NewMomentoSvcErr(momentoerrors.InvalidArgumentError, "request timeout must be greater than 0", nil)
}
client := &defaultScsClient{
credentialProvider: props.CredentialProvider,
Expand Down Expand Up @@ -113,8 +116,17 @@ func NewCacheClient(configuration config.Configuration, credentialProvider auth.
return nil, convertMomentoSvcErrorToCustomerError(momentoerrors.ConvertSvcErr(err))
}

pingClient, err := services.NewScsPingClient(&models.PingClientRequest{
Configuration: props.Configuration,
CredentialProvider: props.CredentialProvider,
})
if err != nil {
return nil, convertMomentoSvcErrorToCustomerError(momentoerrors.ConvertSvcErr(err))
}

client.dataClient = dataClient
client.controlClient = controlClient
client.pingClient = pingClient

return client, nil
}
Expand Down Expand Up @@ -453,6 +465,13 @@ func (c defaultScsClient) DictionaryRemoveFields(ctx context.Context, r *Diction
return r.response, nil
}

func (c defaultScsClient) Ping(ctx context.Context) (responses.PingResponse, error) {
if err := c.pingClient.Ping(ctx); err != nil {
return nil, err
}
return &responses.PingSuccess{}, nil
}

func (c defaultScsClient) Close() {
defer c.controlClient.Close()
defer c.dataClient.Close()
Expand Down
29 changes: 29 additions & 0 deletions momento/ping_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package momento_test

import (
. "github.com/momentohq/client-sdk-go/momento/test_helpers"
. "github.com/momentohq/client-sdk-go/responses"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

var _ = Describe("ping", func() {
var sharedContext SharedContext

BeforeEach(func() {
sharedContext = NewSharedContext()
sharedContext.CreateDefaultCache()
DeferCleanup(func() {
sharedContext.Close()
})
})

It("receives successful ping responses", func() {
for i := 0; i < 25; i++ {
Expect(
sharedContext.Client.Ping(sharedContext.Ctx),
).To(BeAssignableToTypeOf(&PingSuccess{}))
}
})

})
9 changes: 9 additions & 0 deletions responses/ping.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package responses

type PingResponse interface {
isPingResponse()
}

type PingSuccess struct{}

func (PingSuccess) isPingResponse() {}

0 comments on commit 2121789

Please sign in to comment.