Bläddra i källkod

完成状态的增删查

yjp 3 år sedan
förälder
incheckning
0c30928b5e
8 ändrade filer med 341 tillägg och 0 borttagningar
  1. 13 0
      components/statestore.yaml
  2. 3 0
      dapr_run.sh
  3. 14 0
      go.mod
  4. 32 0
      go.sum
  5. 20 0
      state/dto.go
  6. 119 0
      state/state.go
  7. 96 0
      test/state_test.go
  8. 44 0
      utils/utils.go

+ 13 - 0
components/statestore.yaml

@@ -0,0 +1,13 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+  name: dapr_api
+  namespace: default
+spec:
+  type: state.redis
+  version: v1
+  metadata:
+    - name: redisHost
+      value: localhost:30379
+    - name: redisPassword
+      value: mtyzxhc

+ 3 - 0
dapr_run.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+dapr run --app-id dapr_api --dapr-http-port 10080 --components-path ./components
+

+ 14 - 0
go.mod

@@ -1,3 +1,17 @@
 module git.sxidc.com/service-supports/dapr_api
 
 go 1.19
+
+require (
+	github.com/go-resty/resty/v2 v2.7.0
+	github.com/satori/go.uuid v1.2.0
+	github.com/stretchr/testify v1.8.0
+)
+
+require (
+	github.com/davecgh/go-spew v1.1.1 // indirect
+	github.com/pmezard/go-difflib v1.0.0 // indirect
+	golang.org/x/net v0.0.0-20211029224645-99673261e6eb // indirect
+	gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
+)

+ 32 - 0
go.sum

@@ -0,0 +1,32 @@
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY=
+github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I=
+github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
+github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
+github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+golang.org/x/net v0.0.0-20211029224645-99673261e6eb h1:pirldcYWx7rx7kE5r+9WsOXPXK0+WH5+uZ7uPmJ44uM=
+golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

+ 20 - 0
state/dto.go

@@ -0,0 +1,20 @@
+package state
+
+type SaveStateRequest struct {
+	Key      string            `json:"key"`
+	Value    string            `json:"value"`
+	Etag     string            `json:"etag,omitempty"`
+	MetaData map[string]string `json:"metadata,omitempty"`
+	Options  map[string]string `json:"options,omitempty"`
+}
+
+type GetStateBulkRequest struct {
+	Keys        []string `json:"keys"`
+	Parallelism int      `json:"parallelism,omitempty"`
+}
+
+type GetStateBulkItem struct {
+	Key  string `json:"key"`
+	Data string `json:"data"`
+	Etag string `json:"etag"`
+}

+ 119 - 0
state/state.go

@@ -0,0 +1,119 @@
+package state
+
+import (
+	"encoding/json"
+	"fmt"
+	resty "github.com/go-resty/resty/v2"
+	"time"
+)
+
+const (
+	saveUrlFormat    = "http://localhost:%d/v1.0/state/%s"
+	getUrlFormat     = "http://localhost:%d/v1.0/state/%s/%s"
+	getBulkUrlFormat = "http://localhost:%d/v1.0/state/%s/bulk"
+	deleteUrlFormat  = "http://localhost:%d/v1.0/state/%s/%s"
+)
+
+type API struct {
+	port   int
+	client *resty.Client
+}
+
+func NewAPI(port int, timeout time.Duration) *API {
+	return &API{
+		port:   port,
+		client: resty.New().SetTimeout(timeout),
+	}
+}
+
+func DestroyAPI(api *API) {
+	if api == nil {
+		return
+	}
+
+	api.port = 0
+	api.client = nil
+}
+
+func (api *API) SaveState(storeName string, request []SaveStateRequest) error {
+	saveUrl := fmt.Sprintf(saveUrlFormat, api.port, storeName)
+
+	resp, err := api.client.R().
+		SetHeader("Content-Type", "application/json").
+		SetBody(request).
+		Post(saveUrl)
+	if err != nil {
+		return err
+	}
+
+	if resp.IsError() {
+		return fmt.Errorf("Status %d: %s\n", resp.StatusCode(), resp.Body())
+	}
+
+	return nil
+}
+
+func (api *API) GetState(storeName string, key string, queryParams map[string]string, result interface{}) (string, error) {
+	getUrl := fmt.Sprintf(getUrlFormat, api.port, storeName, key)
+
+	resp, err := api.client.R().
+		SetQueryParams(queryParams).
+		SetResult(result).
+		Get(getUrl)
+	if err != nil {
+		return "", err
+	}
+
+	if resp.IsError() {
+		return "", fmt.Errorf("Status %d: %s\n", resp.StatusCode(), resp.Body())
+	}
+
+	return resp.Header().Get("Etag"), nil
+}
+
+func (api *API) GetStateBulk(storeName string, queryParams map[string]string, request GetStateBulkRequest) ([]GetStateBulkItem, error) {
+	getBulkUrl := fmt.Sprintf(getBulkUrlFormat, api.port, storeName)
+
+	resp, err := api.client.R().
+		SetQueryParams(queryParams).
+		SetBody(request).
+		Post(getBulkUrl)
+	if err != nil {
+		return nil, err
+	}
+
+	if resp.IsError() {
+		return nil, fmt.Errorf("Status %d: %s\n", resp.StatusCode(), resp.Body())
+	}
+
+	items := make([]GetStateBulkItem, 0)
+	if resp.Body() != nil && len(resp.Body()) != 0 {
+		err = json.Unmarshal(resp.Body(), &items)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	return items, nil
+}
+
+func (api *API) DeleteState(storeName string, key string, queryParams map[string]string) error {
+	deleteUrl := fmt.Sprintf(deleteUrlFormat, api.port, storeName, key)
+
+	resp, err := api.client.R().
+		SetQueryParams(queryParams).
+		Delete(deleteUrl)
+	if err != nil {
+		return err
+	}
+
+	if resp.IsError() {
+		return fmt.Errorf("Status %d: %s\n", resp.StatusCode(), resp.Body())
+	}
+
+	return nil
+}
+
+func (api *API) Transaction() {
+
+}

+ 96 - 0
test/state_test.go

@@ -0,0 +1,96 @@
+package test
+
+import (
+	"git.sxidc.com/service-supports/dapr_api/state"
+	"git.sxidc.com/service-supports/dapr_api/utils"
+	"github.com/stretchr/testify/assert"
+	"testing"
+	"time"
+)
+
+const (
+	httpPort       = 10080
+	stateStoreName = "dapr_api"
+)
+
+func TestState(t *testing.T) {
+	api := state.NewAPI(httpPort, 10*time.Second)
+	defer state.DestroyAPI(api)
+
+	key1 := utils.SimpleUUID()
+	value1 := utils.SimpleUUID()
+	key2 := utils.SimpleUUID()
+	value2 := utils.SimpleUUID()
+
+	err := api.SaveState(stateStoreName, []state.SaveStateRequest{
+		{
+			Key:   key1,
+			Value: value1,
+		},
+		{
+			Key:   key2,
+			Value: value2,
+		},
+	})
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	var getValue string
+	etag, err := api.GetState(stateStoreName, key1, nil, &getValue)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	assert.NotEmpty(t, etag, "etag为空")
+	assert.Equal(t, value1, getValue, "value不一致")
+
+	getStateBulkItems, err := api.GetStateBulk(stateStoreName, nil, state.GetStateBulkRequest{
+		Keys:        []string{key1, key2},
+		Parallelism: 1,
+	})
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	assert.Equal(t, 2, len(getStateBulkItems), "获取到的state数量不正确")
+
+	for _, getStateBulkItem := range getStateBulkItems {
+		assert.NotEmpty(t, getStateBulkItem.Etag, "etag为空")
+
+		if getStateBulkItem.Key != key1 && getStateBulkItem.Key != key2 {
+			t.Fatal("批量获取到的key错误")
+		}
+
+		if getStateBulkItem.Key == key1 {
+			assert.Equal(t, value1, getStateBulkItem.Data, "value不一致")
+		}
+
+		if getStateBulkItem.Key == key2 {
+			assert.Equal(t, value2, getStateBulkItem.Data, "value不一致")
+		}
+	}
+
+	err = api.DeleteState(stateStoreName, key2, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	err = api.DeleteState(stateStoreName, key1, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	getStateBulkItems, err = api.GetStateBulk(stateStoreName, nil, state.GetStateBulkRequest{
+		Keys:        []string{key1, key2},
+		Parallelism: 1,
+	})
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	for _, getStateBulkItem := range getStateBulkItems {
+		assert.Empty(t, getStateBulkItem.Etag, "获取到的etag不为空")
+		assert.Empty(t, getStateBulkItem.Data, "获取到的data不为空")
+	}
+}

+ 44 - 0
utils/utils.go

@@ -0,0 +1,44 @@
+package utils
+
+import (
+	uuid "github.com/satori/go.uuid"
+	"strings"
+)
+
+func AllBlank(str ...string) bool {
+	for _, s := range str {
+		if !HasBlank(s) {
+			return false
+		}
+	}
+
+	return true
+}
+
+func HasBlank(str ...string) bool {
+	for _, s := range str {
+		if strings.Trim(s, " ") == "" {
+			return true
+		}
+	}
+
+	return false
+}
+
+func HasText(str ...string) bool {
+	for _, s := range str {
+		if strings.Trim(s, " ") != "" {
+			return true
+		}
+	}
+
+	return false
+}
+
+func GetUUID() string {
+	return uuid.NewV4().String()
+}
+
+func SimpleUUID() string {
+	return strings.ReplaceAll(GetUUID(), "-", "")
+}