Pub, service invocation methods support structs without serialization (#104)

* added PublishEventfromStruct to client

* PublishEventfromStruct refactor

* updated PublishEventfromStruct description

* fixed unit tests for PublicEventfromStruct

* added InvokeServiceWithCustomContent service invocation method supporting structs

* renamed PublishEventfromStruct to PublishEventfromCustomContent

Co-authored-by: Mark Chmarny <mchmarny@users.noreply.github.com>
This commit is contained in:
Juan Carlos Zamora 2020-12-09 19:48:14 +01:00 committed by GitHub
parent 32dbe98dc7
commit bd7d126b4f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 174 additions and 0 deletions

17
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,17 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Launch",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${fileDirname}",
"env": {},
"args": []
}
]
}

View File

@ -45,9 +45,15 @@ type Client interface {
// InvokeServiceWithContent invokes service with content
InvokeServiceWithContent(ctx context.Context, serviceID, method string, content *DataContent) (out []byte, err error)
// InvokeServiceWithCustomContent invokes service with custom content (struct + content type).
InvokeServiceWithCustomContent(ctx context.Context, serviceID, method string, contentType string, content interface{}) (out []byte, err error)
// PublishEvent pubishes data onto topic in specific pubsub component.
PublishEvent(ctx context.Context, component, topic string, in []byte) error
// PublishEventfromCustomContent serializes an struct and pubishes its contents as data (JSON) onto topic in specific pubsub component.
PublishEventfromCustomContent(ctx context.Context, component, topic string, in interface{}) error
// GetSecret retreaves preconfigred secret from specified store using key.
GetSecret(ctx context.Context, store, key string, meta map[string]string) (out map[string]string, err error)

View File

@ -2,6 +2,7 @@ package client
import (
"context"
"encoding/json"
v1 "github.com/dapr/go-sdk/dapr/proto/common/v1"
pb "github.com/dapr/go-sdk/dapr/proto/runtime/v1"
@ -83,3 +84,39 @@ func (c *GRPCClient) InvokeServiceWithContent(ctx context.Context, serviceID, me
return c.invokeServiceWithRequest(ctx, req)
}
// InvokeServiceWithCustomContent invokes service with custom content (struct + content type).
func (c *GRPCClient) InvokeServiceWithCustomContent(ctx context.Context, serviceID, method string, contentType string, content interface{}) (out []byte, err error) {
if serviceID == "" {
return nil, errors.New("serviceID is required")
}
if method == "" {
return nil, errors.New("method name is required")
}
if contentType == "" {
return nil, errors.New("content type required")
}
if content == nil {
return nil, errors.New("content required")
}
contentData, err := json.Marshal(content)
if err != nil {
return nil, errors.WithMessage(err, "error serializing input struct")
}
req := &pb.InvokeServiceRequest{
Id: serviceID,
Message: &v1.InvokeRequest{
Method: method,
Data: &anypb.Any{Value: contentData},
ContentType: contentType,
HttpExtension: &v1.HTTPExtension{
Verb: v1.HTTPExtension_POST,
},
},
}
return c.invokeServiceWithRequest(ctx, req)
}

View File

@ -7,6 +7,20 @@ import (
"github.com/stretchr/testify/assert"
)
type _testStructwithText struct {
Key1, Key2 string
}
type _testStructwithTextandNumbers struct {
Key1 string
Key2 int
}
type _testStructwithSlices struct {
Key1 []string
Key2 []int
}
// go test -timeout 30s ./client -count 1 -run ^TestInvokeServiceWithContent$
func TestInvokeServiceWithContent(t *testing.T) {
@ -31,4 +45,31 @@ func TestInvokeServiceWithContent(t *testing.T) {
assert.Nil(t, resp)
})
t.Run("from struct with text", func(t *testing.T) {
testdata := _testCustomContentwithText{
Key1: "value1",
Key2: "value2",
}
_, err := testClient.InvokeServiceWithCustomContent(ctx, "test", "fn", "text/plain", testdata)
assert.Nil(t, err)
})
t.Run("from struct with text and numbers", func(t *testing.T) {
testdata := _testCustomContentwithTextandNumbers{
Key1: "value1",
Key2: 2500,
}
_, err := testClient.InvokeServiceWithCustomContent(ctx, "test", "fn", "text/plain", testdata)
assert.Nil(t, err)
})
t.Run("from struct with slices", func(t *testing.T) {
testdata := _testCustomContentwithSlices{
Key1: []string{"value1", "value2", "value3"},
Key2: []int{25, 40, 600},
}
_, err := testClient.InvokeServiceWithCustomContent(ctx, "test", "fn", "text/plain", testdata)
assert.Nil(t, err)
})
}

View File

@ -2,6 +2,7 @@ package client
import (
"context"
"encoding/json"
pb "github.com/dapr/go-sdk/dapr/proto/runtime/v1"
"github.com/pkg/errors"
@ -29,3 +30,34 @@ func (c *GRPCClient) PublishEvent(ctx context.Context, component, topic string,
return nil
}
// PublishEventfromCustomContent serializes an struct and pubishes its contents as data (JSON) onto topic in specific pubsub component.
func (c *GRPCClient) PublishEventfromCustomContent(ctx context.Context, component, topic string, in interface{}) error {
if topic == "" {
return errors.New("topic name required")
}
if component == "" {
return errors.New("component name required")
}
bytes, err := json.Marshal(in)
if err != nil {
return errors.WithMessage(err, "error serializing input struct")
}
envelop := &pb.PublishEventRequest{
PubsubName: component,
Topic: topic,
Data: bytes,
}
_, err = c.protoClient.PublishEvent(c.withAuthToken(ctx), envelop)
if err != nil {
return errors.Wrapf(err, "error publishing event unto %s topic", topic)
}
return nil
}

View File

@ -7,6 +7,20 @@ import (
"github.com/stretchr/testify/assert"
)
type _testCustomContentwithText struct {
Key1, Key2 string
}
type _testCustomContentwithTextandNumbers struct {
Key1 string
Key2 int
}
type _testCustomContentwithSlices struct {
Key1 []string
Key2 []int
}
// go test -timeout 30s ./client -count 1 -run ^TestPublishEvent$
func TestPublishEvent(t *testing.T) {
ctx := context.Background()
@ -25,4 +39,31 @@ func TestPublishEvent(t *testing.T) {
err := testClient.PublishEvent(ctx, "messagebus", "", []byte("ping"))
assert.NotNil(t, err)
})
t.Run("from struct with text", func(t *testing.T) {
testdata := _testStructwithText{
Key1: "value1",
Key2: "value2",
}
err := testClient.PublishEventfromCustomContent(ctx, "messagebus", "test", testdata)
assert.Nil(t, err)
})
t.Run("from struct with text and numbers", func(t *testing.T) {
testdata := _testStructwithTextandNumbers{
Key1: "value1",
Key2: 2500,
}
err := testClient.PublishEventfromCustomContent(ctx, "messagebus", "test", testdata)
assert.Nil(t, err)
})
t.Run("from struct with slices", func(t *testing.T) {
testdata := _testStructwithSlices{
Key1: []string{"value1", "value2", "value3"},
Key2: []int{25, 40, 600},
}
err := testClient.PublishEventfromCustomContent(ctx, "messagebus", "test", testdata)
assert.Nil(t, err)
})
}