Merge branch 'master' into state-fix
This commit is contained in:
commit
e48d4bca90
|
|
@ -0,0 +1,61 @@
|
|||
# ------------------------------------------------------------
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
# ------------------------------------------------------------
|
||||
|
||||
name: components-contrib
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- release-*
|
||||
tags:
|
||||
- v*
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- release-*
|
||||
jobs:
|
||||
build:
|
||||
name: Build ${{ matrix.target_os }}_${{ matrix.target_arch }} binaries
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
GOVER: 1.13.3
|
||||
GOOS: ${{ matrix.target_os }}
|
||||
GOARCH: ${{ matrix.target_arch }}
|
||||
GOPROXY: https://proxy.golang.org
|
||||
GOLANGCI_LINT_VER: v1.21.0
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
target_arch: [arm, amd64]
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
target_os: linux
|
||||
- os: windows-latest
|
||||
target_os: windows
|
||||
- os: macOS-latest
|
||||
target_os: darwin
|
||||
exclude:
|
||||
- os: windows-latest
|
||||
target_arch: arm
|
||||
- os: macOS-latest
|
||||
target_arch: arm
|
||||
steps:
|
||||
- name: Set up Go ${{ env.GOVER }}
|
||||
uses: actions/setup-go@v1
|
||||
with:
|
||||
go-version: ${{ env.GOVER }}
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v1
|
||||
- name: Install golangci-lint ${{ env.GOLANGCI_LINT_VER }}
|
||||
if: matrix.target_arch != 'arm'
|
||||
run: |
|
||||
curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b "${{ env.GOROOT }}/bin" "${{ env.GOLANGCI_LINT_VER }}"
|
||||
- name: Run make lint
|
||||
if: matrix.target_arch != 'arm'
|
||||
run: make lint
|
||||
- name: Run make test
|
||||
if: matrix.target_arch != 'arm'
|
||||
run: make test
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
/dist
|
||||
.idea
|
||||
|
|
@ -0,0 +1,228 @@
|
|||
# options for analysis running
|
||||
run:
|
||||
# default concurrency is a available CPU number
|
||||
concurrency: 4
|
||||
|
||||
# timeout for analysis, e.g. 30s, 5m, default is 1m
|
||||
deadline: 5m
|
||||
|
||||
# exit code when at least one issue was found, default is 1
|
||||
issues-exit-code: 1
|
||||
|
||||
# include test files or not, default is true
|
||||
tests: true
|
||||
|
||||
# list of build tags, all linters use it. Default is empty list.
|
||||
#build-tags:
|
||||
# - mytag
|
||||
|
||||
# which dirs to skip: they won't be analyzed;
|
||||
# can use regexp here: generated.*, regexp is applied on full path;
|
||||
# default value is empty list, but next dirs are always skipped independently
|
||||
# from this option's value:
|
||||
# vendor$, third_party$, testdata$, examples$, Godeps$, builtin$
|
||||
skip-dirs:
|
||||
- ^vendor$
|
||||
|
||||
# which files to skip: they will be analyzed, but issues from them
|
||||
# won't be reported. Default value is empty list, but there is
|
||||
# no need to include all autogenerated files, we confidently recognize
|
||||
# autogenerated files. If it's not please let us know.
|
||||
skip-files:
|
||||
# - ".*\\.my\\.go$"
|
||||
# - lib/bad.go
|
||||
|
||||
# output configuration options
|
||||
output:
|
||||
# colored-line-number|line-number|json|tab|checkstyle, default is "colored-line-number"
|
||||
format: tab
|
||||
|
||||
# print lines of code with issue, default is true
|
||||
print-issued-lines: true
|
||||
|
||||
# print linter name in the end of issue text, default is true
|
||||
print-linter-name: true
|
||||
|
||||
|
||||
# all available settings of specific linters
|
||||
linters-settings:
|
||||
errcheck:
|
||||
# report about not checking of errors in type assetions: `a := b.(MyStruct)`;
|
||||
# default is false: such cases aren't reported by default.
|
||||
check-type-assertions: false
|
||||
|
||||
# report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`;
|
||||
# default is false: such cases aren't reported by default.
|
||||
check-blank: false
|
||||
|
||||
# [deprecated] comma-separated list of pairs of the form pkg:regex
|
||||
# the regex is used to ignore names within pkg. (default "fmt:.*").
|
||||
# see https://github.com/kisielk/errcheck#the-deprecated-method for details
|
||||
ignore: fmt:.*,io/ioutil:^Read.*
|
||||
|
||||
# path to a file containing a list of functions to exclude from checking
|
||||
# see https://github.com/kisielk/errcheck#excluding-functions for details
|
||||
exclude:
|
||||
|
||||
funlen:
|
||||
lines: 60
|
||||
statements: 40
|
||||
|
||||
govet:
|
||||
# report about shadowed variables
|
||||
check-shadowing: true
|
||||
|
||||
# settings per analyzer
|
||||
settings:
|
||||
printf: # analyzer name, run `go tool vet help` to see all analyzers
|
||||
funcs: # run `go tool vet help printf` to see available settings for `printf` analyzer
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf
|
||||
|
||||
# enable or disable analyzers by name
|
||||
enable:
|
||||
- atomicalign
|
||||
enable-all: false
|
||||
disable:
|
||||
- shadow
|
||||
disable-all: false
|
||||
golint:
|
||||
# minimal confidence for issues, default is 0.8
|
||||
min-confidence: 0.8
|
||||
gofmt:
|
||||
# simplify code: gofmt with `-s` option, true by default
|
||||
simplify: true
|
||||
goimports:
|
||||
# put imports beginning with prefix after 3rd-party packages;
|
||||
# it's a comma-separated list of prefixes
|
||||
local-prefixes:
|
||||
gocyclo:
|
||||
# minimal code complexity to report, 30 by default (but we recommend 10-20)
|
||||
min-complexity: 10
|
||||
gocognit:
|
||||
# minimal code complexity to report, 30 by default (but we recommend 10-20)
|
||||
min-complexity: 10
|
||||
maligned:
|
||||
# print struct with more effective memory layout or not, false by default
|
||||
suggest-new: true
|
||||
dupl:
|
||||
# tokens count to trigger issue, 150 by default
|
||||
threshold: 100
|
||||
goconst:
|
||||
# minimal length of string constant, 3 by default
|
||||
min-len: 3
|
||||
# minimal occurrences count to trigger, 3 by default
|
||||
min-occurrences: 3
|
||||
depguard:
|
||||
list-type: blacklist
|
||||
include-go-root: false
|
||||
packages:
|
||||
- github.com/sirupsen/logrus
|
||||
packages-with-error-messages:
|
||||
# specify an error message to output when a blacklisted package is used
|
||||
github.com/sirupsen/logrus: "logging is allowed only by logutils.Log"
|
||||
misspell:
|
||||
# Correct spellings using locale preferences for US or UK.
|
||||
# Default is to use a neutral variety of English.
|
||||
# Setting locale to US will correct the British spelling of 'colour' to 'color'.
|
||||
locale: default
|
||||
ignore-words:
|
||||
- someword
|
||||
lll:
|
||||
# max line length, lines longer will be reported. Default is 120.
|
||||
# '\t' is counted as 1 character by default, and can be changed with the tab-width option
|
||||
line-length: 120
|
||||
# tab width in spaces. Default to 1.
|
||||
tab-width: 1
|
||||
unused:
|
||||
# treat code as a program (not a library) and report unused exported identifiers; default is false.
|
||||
# XXX: if you enable this setting, unused will report a lot of false-positives in text editors:
|
||||
# if it's called for subdir of a project it can't find funcs usages. All text editor integrations
|
||||
# with golangci-lint call it on a directory with the changed file.
|
||||
check-exported: false
|
||||
unparam:
|
||||
# Inspect exported functions, default is false. Set to true if no external program/library imports your code.
|
||||
# XXX: if you enable this setting, unparam will report a lot of false-positives in text editors:
|
||||
# if it's called for subdir of a project it can't find external interfaces. All text editor integrations
|
||||
# with golangci-lint call it on a directory with the changed file.
|
||||
check-exported: false
|
||||
nakedret:
|
||||
# make an issue if func has more lines of code than this setting and it has naked returns; default is 30
|
||||
max-func-lines: 30
|
||||
prealloc:
|
||||
# XXX: we don't recommend using this linter before doing performance profiling.
|
||||
# For most programs usage of prealloc will be a premature optimization.
|
||||
|
||||
# Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.
|
||||
# True by default.
|
||||
simple: true
|
||||
range-loops: true # Report preallocation suggestions on range loops, true by default
|
||||
for-loops: false # Report preallocation suggestions on for loops, false by default
|
||||
gocritic:
|
||||
# Which checks should be enabled; can't be combined with 'disabled-checks';
|
||||
# See https://go-critic.github.io/overview#checks-overview
|
||||
# To check which checks are enabled run `GL_DEBUG=gocritic golangci-lint run`
|
||||
# By default list of stable checks is used.
|
||||
enabled-checks:
|
||||
|
||||
# Which checks should be disabled; can't be combined with 'enabled-checks'; default is empty
|
||||
disabled-checks:
|
||||
- regexpMust
|
||||
- rangeValCopy
|
||||
- hugeParam
|
||||
- ifElseChain
|
||||
- singleCaseSwitch
|
||||
|
||||
# Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.
|
||||
# Empty list by default. See https://github.com/go-critic/go-critic#usage -> section "Tags".
|
||||
enabled-tags:
|
||||
- performance
|
||||
|
||||
settings: # settings passed to gocritic
|
||||
captLocal: # must be valid enabled check name
|
||||
paramsOnly: true
|
||||
godox:
|
||||
# report any comments starting with keywords, this is useful for TODO or FIXME comments that
|
||||
# might be left in the code accidentally and should be resolved before merging
|
||||
keywords: # default keywords are TODO, BUG, and FIXME, these can be overwritten by this setting
|
||||
- NOTE
|
||||
- OPTIMIZE # marks code that should be optimized before merging
|
||||
- HACK # marks hack-arounds that should be removed before merging
|
||||
dogsled:
|
||||
# checks assignments with too many blank identifiers; default is 2
|
||||
max-blank-identifiers: 2
|
||||
|
||||
whitespace:
|
||||
multi-if: false # Enforces newlines (or comments) after every multi-line if statement
|
||||
multi-func: false # Enforces newlines (or comments) after every multi-line function signature
|
||||
|
||||
wsl:
|
||||
# If true append is only allowed to be cuddled if appending value is
|
||||
# matching variables, fields or types on line above. Default is true.
|
||||
strict-append: true
|
||||
# Allow calls and assignments to be cuddled as long as the lines have any
|
||||
# matching variables, fields or types. Default is true.
|
||||
allow-assign-and-call: true
|
||||
# Allow multiline assignments to be cuddled. Default is true.
|
||||
allow-multiline-assign: true
|
||||
# Allow case blocks to end with a whitespace.
|
||||
allow-case-traling-whitespace: true
|
||||
# Allow declarations (var) to be cuddled.
|
||||
allow-cuddle-declarations: false
|
||||
|
||||
linters:
|
||||
fast: false
|
||||
enable-all: true
|
||||
disable:
|
||||
# TODO Enforce the below linters later
|
||||
- dupl
|
||||
- errcheck
|
||||
- funlen
|
||||
- gocyclo
|
||||
- gocognit
|
||||
- lll
|
||||
- scopelint
|
||||
- unparam
|
||||
- wsl
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
# ------------------------------------------------------------
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
# ------------------------------------------------------------
|
||||
|
||||
################################################################################
|
||||
# Variables #
|
||||
################################################################################
|
||||
|
||||
export GO111MODULE ?= on
|
||||
export GOPROXY ?= https://proxy.golang.org
|
||||
export GOSUMDB ?= sum.golang.org
|
||||
|
||||
GIT_COMMIT = $(shell git rev-list -1 HEAD)
|
||||
GIT_VERSION = $(shell git describe --always --abbrev=7 --dirty)
|
||||
# By default, disable CGO_ENABLED. See the details on https://golang.org/cmd/cgo
|
||||
CGO ?= 0
|
||||
|
||||
LOCAL_ARCH := $(shell uname -m)
|
||||
ifeq ($(LOCAL_ARCH),x86_64)
|
||||
TARGET_ARCH_LOCAL=amd64
|
||||
else ifeq ($(shell echo $(LOCAL_ARCH) | head -c 5),armv8)
|
||||
TARGET_ARCH_LOCAL=arm64
|
||||
else ifeq ($(shell echo $(LOCAL_ARCH) | head -c 4),armv)
|
||||
TARGET_ARCH_LOCAL=arm
|
||||
else
|
||||
TARGET_ARCH_LOCAL=amd64
|
||||
endif
|
||||
export GOARCH ?= $(TARGET_ARCH_LOCAL)
|
||||
|
||||
LOCAL_OS := $(shell uname)
|
||||
ifeq ($(LOCAL_OS),Linux)
|
||||
TARGET_OS_LOCAL = linux
|
||||
else ifeq ($(LOCAL_OS),Darwin)
|
||||
TARGET_OS_LOCAL = darwin
|
||||
else
|
||||
TARGET_OS_LOCAL ?= windows
|
||||
endif
|
||||
export GOOS ?= $(TARGET_OS_LOCAL)
|
||||
|
||||
ifeq ($(GOOS),windows)
|
||||
BINARY_EXT_LOCAL:=.exe
|
||||
GOLANGCI_LINT:=golangci-lint.exe
|
||||
else
|
||||
BINARY_EXT_LOCAL:=
|
||||
GOLANGCI_LINT:=golangci-lint
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
# Target: test #
|
||||
################################################################################
|
||||
.PHONY: test
|
||||
test:
|
||||
go test ./... -mod=vendor
|
||||
|
||||
################################################################################
|
||||
# Target: lint #
|
||||
################################################################################
|
||||
.PHONY: lint
|
||||
lint:
|
||||
# Due to https://github.com/golangci/golangci-lint/issues/580, we need to add --fix for windows
|
||||
$(GOLANGCI_LINT) run --fix
|
||||
15
Readme.md
15
Readme.md
|
|
@ -1,5 +1,11 @@
|
|||
# Components Contrib
|
||||
|
||||
[](https://goreportcard.com/report/github.com/dapr/components-contrib)
|
||||
[](https://github.com/dapr/components-contrib/actions?workflow=components-contrib)
|
||||
[](https://gitter.im/Dapr/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
[](https://opensource.org/licenses/MIT)
|
||||
|
||||
|
||||
The purpose of Components Contrib is to provide open, community driven reusable components for building distributed applications.
|
||||
These components are being used by the [Dapr](https://github.com/dapr/dapr) project, but are separate and decoupled from it.
|
||||
|
||||
|
|
@ -11,6 +17,7 @@ Available component types:
|
|||
* [Pub Sub](pubsub/Readme.md)
|
||||
* [State Stores](state/Readme.md)
|
||||
* [Secret Stores](secretstores/Readme.md)
|
||||
* [Tracing Exporters](exporters/Readme.md)
|
||||
|
||||
For documentation on how components are being used in Dapr in a language/platform agnostic way, visit [Dapr Docs](https://github.com/dapr/docs).
|
||||
|
||||
|
|
@ -36,5 +43,11 @@ git clone https://github.com/dapr/components-contrib.git github.com/dapr/compone
|
|||
### Running tests
|
||||
|
||||
```bash
|
||||
go test ./...
|
||||
make test
|
||||
```
|
||||
|
||||
### Running linting
|
||||
|
||||
```bash
|
||||
make lint
|
||||
```
|
||||
|
|
@ -49,7 +49,7 @@ func (a *AzureBlobStorage) Init(metadata bindings.Metadata) error {
|
|||
a.metadata = m
|
||||
credential, err := azblob.NewSharedKeyCredential(m.StorageAccount, m.StorageAccessKey)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Invalid credentials with error: %s", err.Error())
|
||||
return fmt.Errorf("invalid credentials with error: %s", err.Error())
|
||||
}
|
||||
p := azblob.NewPipeline(credential, azblob.PipelineOptions{})
|
||||
|
||||
|
|
|
|||
|
|
@ -49,22 +49,28 @@ func (c *CosmosDB) Init(metadata bindings.Metadata) error {
|
|||
})
|
||||
|
||||
dbs, err := client.QueryDatabases(&documentdb.Query{
|
||||
Query: fmt.Sprintf("SELECT * FROM ROOT r WHERE r.id='%s'", m.Database),
|
||||
Query: "SELECT * FROM ROOT r WHERE r.id=@id",
|
||||
Parameters: []documentdb.Parameter{
|
||||
{Name: "@id", Value: m.Database},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
} else if len(dbs) == 0 {
|
||||
return fmt.Errorf("Database %s for CosmosDB state store not found", m.Database)
|
||||
return fmt.Errorf("database %s for CosmosDB state store not found", m.Database)
|
||||
}
|
||||
|
||||
c.db = &dbs[0]
|
||||
colls, err := client.QueryCollections(c.db.Self, &documentdb.Query{
|
||||
Query: fmt.Sprintf("SELECT * FROM ROOT r WHERE r.id='%s'", m.Collection),
|
||||
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 fmt.Errorf("collection %s for CosmosDB state store not found", m.Collection)
|
||||
}
|
||||
|
||||
c.collection = &colls[0]
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
"encoding/json"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
eventhub "github.com/Azure/azure-event-hubs-go"
|
||||
|
|
@ -111,7 +112,6 @@ func (a *AzureEventHubs) Read(handler func(*bindings.ReadResponse) error) error
|
|||
if a.metadata.ConsumerGroup != "" {
|
||||
log.Infof("eventhubs: using consumer group %s", a.metadata.ConsumerGroup)
|
||||
ops = append(ops, eventhub.ReceiveWithConsumerGroup(a.metadata.ConsumerGroup))
|
||||
|
||||
}
|
||||
|
||||
for _, partitionID := range runtimeInfo.PartitionIDs {
|
||||
|
|
@ -122,7 +122,7 @@ func (a *AzureEventHubs) Read(handler func(*bindings.ReadResponse) error) error
|
|||
}
|
||||
|
||||
signalChan := make(chan os.Signal, 1)
|
||||
signal.Notify(signalChan, os.Interrupt, os.Kill)
|
||||
signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM)
|
||||
<-signalChan
|
||||
|
||||
a.hub.Close(context.Background())
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import (
|
|||
)
|
||||
|
||||
// HTTPSource is a binding for an http url endpoint invocation
|
||||
// nolint:golint
|
||||
type HTTPSource struct {
|
||||
metadata httpMetadata
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,5 +20,4 @@ func TestInit(t *testing.T) {
|
|||
assert.Nil(t, err)
|
||||
assert.Equal(t, "a", hs.metadata.URL)
|
||||
assert.Equal(t, "a", hs.metadata.Method)
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ func (k *Kafka) Read(handler func(*bindings.ReadResponse) error) error {
|
|||
config := sarama.NewConfig()
|
||||
config.Version = sarama.V1_0_0_0
|
||||
|
||||
consumer := consumer{
|
||||
c := consumer{
|
||||
callback: handler,
|
||||
ready: make(chan bool),
|
||||
}
|
||||
|
|
@ -144,18 +144,18 @@ func (k *Kafka) Read(handler func(*bindings.ReadResponse) error) error {
|
|||
go func() {
|
||||
defer wg.Done()
|
||||
for {
|
||||
if err = client.Consume(ctx, k.topics, &consumer); err != nil {
|
||||
log.Errorf("error from consumer: %s", err)
|
||||
if err = client.Consume(ctx, k.topics, &c); err != nil {
|
||||
log.Errorf("error from c: %s", err)
|
||||
}
|
||||
// check if context was cancelled, signaling that the consumer should stop
|
||||
// check if context was cancelled, signaling that the c should stop
|
||||
if ctx.Err() != nil {
|
||||
return
|
||||
}
|
||||
consumer.ready = make(chan bool)
|
||||
c.ready = make(chan bool)
|
||||
}
|
||||
}()
|
||||
|
||||
<-consumer.ready
|
||||
<-c.ready
|
||||
|
||||
sigterm := make(chan os.Signal, 1)
|
||||
signal.Notify(sigterm, syscall.SIGINT, syscall.SIGTERM)
|
||||
|
|
|
|||
|
|
@ -17,8 +17,6 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func makerFn() interface{} { return &client.V1Namespace{} }
|
||||
|
||||
type staticHandler struct {
|
||||
Code int
|
||||
Body string
|
||||
|
|
@ -64,7 +62,7 @@ func TestReadItem(t *testing.T) {
|
|||
}
|
||||
count := 0
|
||||
i.Read(func(res *bindings.ReadResponse) error {
|
||||
count = count + 1
|
||||
count++
|
||||
|
||||
result := client.Result{}
|
||||
json.Unmarshal(res.Data, &result)
|
||||
|
|
|
|||
|
|
@ -72,12 +72,12 @@ func (m *MQTT) getMQTTMetadata(metadata bindings.Metadata) (*mqttMetadata, error
|
|||
return nil, err
|
||||
}
|
||||
|
||||
var mqttMetadata mqttMetadata
|
||||
err = json.Unmarshal(b, &mqttMetadata)
|
||||
var mMetadata mqttMetadata
|
||||
err = json.Unmarshal(b, &mMetadata)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &mqttMetadata, nil
|
||||
return &mMetadata, nil
|
||||
}
|
||||
|
||||
func (m *MQTT) Write(req *bindings.WriteRequest) error {
|
||||
|
|
|
|||
|
|
@ -22,5 +22,4 @@ func TestParseMetadata(t *testing.T) {
|
|||
assert.Equal(t, "a", rm.Host)
|
||||
assert.Equal(t, true, rm.DeleteWhenUnused)
|
||||
assert.Equal(t, true, rm.Durable)
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import (
|
|||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/dapr/components-contrib/bindings"
|
||||
|
||||
|
|
@ -70,7 +69,7 @@ func (r *Redis) parseMetadata(metadata bindings.Metadata) (*redisMetadata, error
|
|||
|
||||
func (r *Redis) Write(req *bindings.WriteRequest) error {
|
||||
if val, ok := req.Metadata["key"]; ok && val != "" {
|
||||
key := fmt.Sprintf(val)
|
||||
key := val
|
||||
res := r.client.Do(context.Background(), "SET", key, req.Data)
|
||||
if err := redis.AsError(res); err != nil {
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
package exporters
|
||||
|
||||
// Exporter is the interface for tracing exporter wrappers
|
||||
type Exporter interface {
|
||||
Init(daprID string, hostAddress string, metadata Metadata) error
|
||||
}
|
||||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
package exporters
|
||||
|
||||
// Exporter is the interface for tracing exporter wrappers
|
||||
type Exporter interface {
|
||||
Init(daprID string, hostAddress string, metadata Metadata) error
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
package exporters
|
||||
|
||||
// Metadata represents a set of exporter specific properties
|
||||
type Metadata struct {
|
||||
Properties map[string]string `json:"properties"`
|
||||
Buffer *string `json:"-"`
|
||||
}
|
||||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
package exporters
|
||||
|
||||
// Metadata represents a set of exporter specific properties
|
||||
type Metadata struct {
|
||||
Properties map[string]string `json:"properties"`
|
||||
Buffer *string `json:"-"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,66 +1,66 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
package native
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
|
||||
"contrib.go.opencensus.io/exporter/ocagent"
|
||||
"github.com/dapr/components-contrib/exporters"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// Metadata is the native exporter config
|
||||
type nativeExporterMetadata struct {
|
||||
AgentEndpoint string `json:"agentEndpoint"`
|
||||
Enabled string `json:"enabled"`
|
||||
}
|
||||
|
||||
// NewNativeExporter returns a new native exporter instance
|
||||
func NewNativeExporter() *Exporter {
|
||||
return &Exporter{}
|
||||
}
|
||||
|
||||
// Exporter is an OpenCensus native exporter
|
||||
type Exporter struct {
|
||||
}
|
||||
|
||||
// Init creates a new native endpoint and reporter
|
||||
func (l *Exporter) Init(daprID string, hostAddress string, metadata exporters.Metadata) error {
|
||||
meta, err := l.getNativeMetadata(metadata)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
enabled, _ := strconv.ParseBool(meta.Enabled)
|
||||
if !enabled {
|
||||
return nil
|
||||
}
|
||||
|
||||
exporter, err := ocagent.NewExporter(ocagent.WithInsecure(), ocagent.WithServiceName(daprID), ocagent.WithAddress(meta.AgentEndpoint))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
trace.RegisterExporter(exporter)
|
||||
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *Exporter) getNativeMetadata(metadata exporters.Metadata) (*nativeExporterMetadata, error) {
|
||||
b, err := json.Marshal(metadata.Properties)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var nativeExporterMetadata nativeExporterMetadata
|
||||
err = json.Unmarshal(b, &nativeExporterMetadata)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &nativeExporterMetadata, nil
|
||||
}
|
||||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
package native
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
|
||||
"contrib.go.opencensus.io/exporter/ocagent"
|
||||
"github.com/dapr/components-contrib/exporters"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// Metadata is the native exporter config
|
||||
type nativeExporterMetadata struct {
|
||||
AgentEndpoint string `json:"agentEndpoint"`
|
||||
Enabled string `json:"enabled"`
|
||||
}
|
||||
|
||||
// NewNativeExporter returns a new native exporter instance
|
||||
func NewNativeExporter() *Exporter {
|
||||
return &Exporter{}
|
||||
}
|
||||
|
||||
// Exporter is an OpenCensus native exporter
|
||||
type Exporter struct {
|
||||
}
|
||||
|
||||
// Init creates a new native endpoint and reporter
|
||||
func (l *Exporter) Init(daprID string, hostAddress string, metadata exporters.Metadata) error {
|
||||
meta, err := l.getNativeMetadata(metadata)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
enabled, _ := strconv.ParseBool(meta.Enabled)
|
||||
if !enabled {
|
||||
return nil
|
||||
}
|
||||
|
||||
exporter, err := ocagent.NewExporter(ocagent.WithInsecure(), ocagent.WithServiceName(daprID), ocagent.WithAddress(meta.AgentEndpoint))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
trace.RegisterExporter(exporter)
|
||||
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *Exporter) getNativeMetadata(metadata exporters.Metadata) (*nativeExporterMetadata, error) {
|
||||
b, err := json.Marshal(metadata.Properties)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var nExporterMetadata nativeExporterMetadata
|
||||
err = json.Unmarshal(b, &nExporterMetadata)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &nExporterMetadata, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,22 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
package native
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/dapr/components-contrib/exporters"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestParseMetadata(t *testing.T) {
|
||||
m := exporters.Metadata{}
|
||||
m.Properties = map[string]string{"agentEndpoint": "c"}
|
||||
exporter := NewNativeExporter()
|
||||
metadata, err := exporter.getNativeMetadata(m)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "c", metadata.AgentEndpoint)
|
||||
}
|
||||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
package native
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/dapr/components-contrib/exporters"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestParseMetadata(t *testing.T) {
|
||||
m := exporters.Metadata{}
|
||||
m.Properties = map[string]string{"agentEndpoint": "c"}
|
||||
exporter := NewNativeExporter()
|
||||
metadata, err := exporter.getNativeMetadata(m)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "c", metadata.AgentEndpoint)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,41 +1,41 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
package stringexporter
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/dapr/components-contrib/exporters"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// Metadata is the string exporter config
|
||||
type stringExporterMetadata struct {
|
||||
Buffer *string
|
||||
}
|
||||
|
||||
// NewStringExporter returns a new string exporter instance
|
||||
func NewStringExporter() *Exporter {
|
||||
return &Exporter{}
|
||||
}
|
||||
|
||||
// Exporter is an OpenCensus string exporter
|
||||
type Exporter struct {
|
||||
Buffer *string
|
||||
}
|
||||
|
||||
// ExportSpan exports span content to the buffer
|
||||
func (se *Exporter) ExportSpan(sd *trace.SpanData) {
|
||||
*se.Buffer = strconv.Itoa(int(sd.Status.Code))
|
||||
}
|
||||
|
||||
// Init creates a new string exporter endpoint and reporter
|
||||
func (se *Exporter) Init(daprID string, hostAddress string, metadata exporters.Metadata) error {
|
||||
se.Buffer = metadata.Buffer
|
||||
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
|
||||
trace.RegisterExporter(se)
|
||||
return nil
|
||||
}
|
||||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
package stringexporter
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/dapr/components-contrib/exporters"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// Metadata is the string exporter config
|
||||
type Metadata struct {
|
||||
Buffer *string
|
||||
}
|
||||
|
||||
// NewStringExporter returns a new string exporter instance
|
||||
func NewStringExporter() *Exporter {
|
||||
return &Exporter{}
|
||||
}
|
||||
|
||||
// Exporter is an OpenCensus string exporter
|
||||
type Exporter struct {
|
||||
Buffer *string
|
||||
}
|
||||
|
||||
// ExportSpan exports span content to the buffer
|
||||
func (se *Exporter) ExportSpan(sd *trace.SpanData) {
|
||||
*se.Buffer = strconv.Itoa(int(sd.Status.Code))
|
||||
}
|
||||
|
||||
// Init creates a new string exporter endpoint and reporter
|
||||
func (se *Exporter) Init(daprID string, hostAddress string, metadata exporters.Metadata) error {
|
||||
se.Buffer = metadata.Buffer
|
||||
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
|
||||
trace.RegisterExporter(se)
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,70 +1,69 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
package zipkin
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
|
||||
"contrib.go.opencensus.io/exporter/zipkin"
|
||||
"github.com/dapr/components-contrib/exporters"
|
||||
openzipkin "github.com/openzipkin/zipkin-go"
|
||||
zipkinHTTP "github.com/openzipkin/zipkin-go/reporter/http"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// Metadata is the zipkin config
|
||||
type zipkinMetadata struct {
|
||||
ExporterAddress string `json:"exporterAddress"`
|
||||
Enabled string `json:"enabled"`
|
||||
}
|
||||
|
||||
// NewZipkinExporter returns a new zipkin exporter instance
|
||||
func NewZipkinExporter() *Exporter {
|
||||
return &Exporter{}
|
||||
}
|
||||
|
||||
// Exporter is an OpenCensus zipkin exporter
|
||||
type Exporter struct {
|
||||
}
|
||||
|
||||
// Init creates a new zipkin endpoint and reporter
|
||||
func (z *Exporter) Init(daprID string, hostAddress string, metadata exporters.Metadata) error {
|
||||
|
||||
meta, err := z.getZipkinMetadata(metadata)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
enabled, _ := strconv.ParseBool(meta.Enabled)
|
||||
if !enabled {
|
||||
return nil
|
||||
}
|
||||
|
||||
localEndpoint, err := openzipkin.NewEndpoint(daprID, hostAddress)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
reporter := zipkinHTTP.NewReporter(meta.ExporterAddress)
|
||||
ze := zipkin.NewExporter(reporter, localEndpoint)
|
||||
trace.RegisterExporter(ze)
|
||||
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (z *Exporter) getZipkinMetadata(metadata exporters.Metadata) (*zipkinMetadata, error) {
|
||||
b, err := json.Marshal(metadata.Properties)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var zipkinMeta zipkinMetadata
|
||||
err = json.Unmarshal(b, &zipkinMeta)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &zipkinMeta, nil
|
||||
}
|
||||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
package zipkin
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
|
||||
"contrib.go.opencensus.io/exporter/zipkin"
|
||||
"github.com/dapr/components-contrib/exporters"
|
||||
openzipkin "github.com/openzipkin/zipkin-go"
|
||||
zipkinHTTP "github.com/openzipkin/zipkin-go/reporter/http"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// Metadata is the zipkin config
|
||||
type zipkinMetadata struct {
|
||||
ExporterAddress string `json:"exporterAddress"`
|
||||
Enabled string `json:"enabled"`
|
||||
}
|
||||
|
||||
// NewZipkinExporter returns a new zipkin exporter instance
|
||||
func NewZipkinExporter() *Exporter {
|
||||
return &Exporter{}
|
||||
}
|
||||
|
||||
// Exporter is an OpenCensus zipkin exporter
|
||||
type Exporter struct {
|
||||
}
|
||||
|
||||
// Init creates a new zipkin endpoint and reporter
|
||||
func (z *Exporter) Init(daprID string, hostAddress string, metadata exporters.Metadata) error {
|
||||
meta, err := z.getZipkinMetadata(metadata)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
enabled, _ := strconv.ParseBool(meta.Enabled)
|
||||
if !enabled {
|
||||
return nil
|
||||
}
|
||||
|
||||
localEndpoint, err := openzipkin.NewEndpoint(daprID, hostAddress)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
reporter := zipkinHTTP.NewReporter(meta.ExporterAddress)
|
||||
ze := zipkin.NewExporter(reporter, localEndpoint)
|
||||
trace.RegisterExporter(ze)
|
||||
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (z *Exporter) getZipkinMetadata(metadata exporters.Metadata) (*zipkinMetadata, error) {
|
||||
b, err := json.Marshal(metadata.Properties)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var zipkinMeta zipkinMetadata
|
||||
err = json.Unmarshal(b, &zipkinMeta)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &zipkinMeta, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,22 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
package zipkin
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/dapr/components-contrib/exporters"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestParseMetadata(t *testing.T) {
|
||||
m := exporters.Metadata{}
|
||||
m.Properties = map[string]string{"exporterAddress": "c"}
|
||||
exporter := NewZipkinExporter()
|
||||
metadata, err := exporter.getZipkinMetadata(m)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "c", metadata.ExporterAddress)
|
||||
}
|
||||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
package zipkin
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/dapr/components-contrib/exporters"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestParseMetadata(t *testing.T) {
|
||||
m := exporters.Metadata{}
|
||||
m.Properties = map[string]string{"exporterAddress": "c"}
|
||||
exporter := NewZipkinExporter()
|
||||
metadata, err := exporter.getZipkinMetadata(m)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "c", metadata.ExporterAddress)
|
||||
}
|
||||
|
|
|
|||
14
go.mod
14
go.mod
|
|
@ -1,6 +1,6 @@
|
|||
module github.com/dapr/components-contrib
|
||||
|
||||
go 1.12
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
cloud.google.com/go/pubsub v1.0.1
|
||||
|
|
@ -22,7 +22,9 @@ require (
|
|||
github.com/Sirupsen/logrus v1.0.6
|
||||
github.com/a8m/documentdb v1.2.0
|
||||
github.com/aws/aws-sdk-go v1.25.0
|
||||
github.com/coreos/bbolt v1.3.3 // indirect
|
||||
github.com/coreos/etcd v3.3.17+incompatible // indirect
|
||||
github.com/coreos/go-semver v0.3.0 // indirect
|
||||
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect
|
||||
github.com/creack/pty v1.1.9 // indirect
|
||||
|
|
@ -34,10 +36,14 @@ require (
|
|||
github.com/gocql/gocql v0.0.0-20191018090344-07ace3bab0f8
|
||||
github.com/google/pprof v0.0.0-20190908185732-236ed259b199 // indirect
|
||||
github.com/google/uuid v1.1.1
|
||||
github.com/gorilla/websocket v1.4.1 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.1.0 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.11.2 // indirect
|
||||
github.com/hashicorp/consul/api v1.2.0
|
||||
github.com/hashicorp/golang-lru v0.5.3 // indirect
|
||||
github.com/jcmturner/gofork v1.0.0 // indirect
|
||||
github.com/jonboulle/clockwork v0.1.0 // indirect
|
||||
github.com/joomcode/errorx v1.0.0 // indirect
|
||||
github.com/joomcode/redispipe v0.9.0
|
||||
github.com/json-iterator/go v1.1.7
|
||||
|
|
@ -52,13 +58,15 @@ require (
|
|||
github.com/rogpeppe/fastuuid v1.2.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.4.0 // indirect
|
||||
github.com/satori/go.uuid v1.2.0
|
||||
github.com/soheilhy/cmux v0.1.4 // indirect
|
||||
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271
|
||||
github.com/stretchr/testify v1.4.0
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 // indirect
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect
|
||||
go.etcd.io/bbolt v1.3.3 // indirect
|
||||
go.etcd.io/etcd v3.3.17+incompatible
|
||||
go.opencensus.io v0.22.1
|
||||
go.uber.org/atomic v1.4.0 // indirect
|
||||
go.uber.org/multierr v1.2.0 // indirect
|
||||
go.uber.org/zap v1.10.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad
|
||||
golang.org/x/exp v0.0.0-20190927203820-447a159532ef // indirect
|
||||
golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a // indirect
|
||||
|
|
|
|||
19
go.sum
19
go.sum
|
|
@ -103,8 +103,10 @@ github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA
|
|||
github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.17+incompatible h1:f/Z3EoDSx1yjaIjLQGo1diYUlQYSBrrAQ5vP8NjwXwo=
|
||||
github.com/coreos/etcd v3.3.17+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c=
|
||||
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg=
|
||||
|
|
@ -156,6 +158,8 @@ github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415 h1:WSBJMqJbLxsn+bTCP
|
|||
github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.0 h1:xU6/SpYbvkNYiptHJYEDRseDLvYE7wSqhYYNy0QSUzI=
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
|
|
@ -201,7 +205,10 @@ github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:
|
|||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk=
|
||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.2/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
|
|
@ -249,6 +256,7 @@ github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5i
|
|||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
|
||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/joomcode/errorx v1.0.0 h1:RJAKLTy1Sv2Tszhu14m5RZP4VGRlhXutG/XlL1En5VM=
|
||||
github.com/joomcode/errorx v1.0.0/go.mod h1:kgco15ekB6cs+4Xjzo7SPeXzx38PbJzBwbnu9qfVNHQ=
|
||||
github.com/joomcode/redispipe v0.9.0 h1:NukwwIvxhg6r2lVxa1RJhEZXYPZZF/OX9WZJk+2cK1Q=
|
||||
|
|
@ -261,8 +269,10 @@ github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62F
|
|||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024 h1:rBMNdlhTLzJjJSDIjNEXX1Pz3Hmwmz91v+zycvx9PJc=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f2633dfe/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
|
|
@ -305,6 +315,7 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
|
|||
github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3 h1:EooPXg51Tn+xmWPXJUGCnJhJSpeuMlBmfJVcqIRmmv8=
|
||||
github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/openzipkin/zipkin-go v0.1.1 h1:A/ADD6HaPnAKj3yS7HjGHRK77qi41Hi0DirOOIQAeIw=
|
||||
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
||||
github.com/openzipkin/zipkin-go v0.1.6 h1:yXiysv1CSK7Q5yjGy1710zZGnsbMUIjluWBxtLXHPBo=
|
||||
|
|
@ -339,6 +350,8 @@ github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdh
|
|||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/sirupsen/logrus v1.1.1 h1:VzGj7lhU7KEB9e9gMpAV/v5XT2NVSvLJhJLCWbnkgXg=
|
||||
github.com/sirupsen/logrus v1.1.1/go.mod h1:zrgwTnHtNr00buQ1vSptGe8m1f/BbgsPukg8qsT7A+A=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4=
|
||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271 h1:WhxRHzgeVGETMlmVfqhRn8RIeeNoPr2Czh33I4Zdccw=
|
||||
|
|
@ -352,8 +365,11 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
|||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
|
||||
github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/etcd v3.3.17+incompatible h1:g8iRku1SID8QAW8cDlV0L/PkZlw63LSiYEHYHoE6j/s=
|
||||
go.etcd.io/etcd v3.3.17+incompatible/go.mod h1:yaeTdrJi5lOmYerz05bd8+V7KubZs8YSFZfzsF9A6aI=
|
||||
go.opencensus.io v0.15.0/go.mod h1:UffZAU+4sDEINUGP/B7UfBBkq4fqLu9zXAX7ke6CHW0=
|
||||
|
|
@ -364,6 +380,7 @@ go.opencensus.io v0.22.1 h1:8dP3SGL7MPB94crU3bEPplMPe83FI4EouesJUeFHv50=
|
|||
go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA=
|
||||
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/multierr v1.2.0 h1:6I+W7f5VwC5SV9dNrZ3qXrDB9mD0dyGOi/ZJmYw03T4=
|
||||
go.uber.org/multierr v1.2.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
|
||||
|
|
@ -449,6 +466,7 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
|
|||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
|
@ -470,6 +488,7 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZe
|
|||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0 h1:xQwXv67TxFo9nC1GJFyab5eq/5B590r6RlnL/G8Sz7w=
|
||||
golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
|
|
|||
|
|
@ -194,8 +194,7 @@ func getCassandraMetadata(metadata state.Metadata) (*cassandraMetadata, error) {
|
|||
|
||||
// Delete performs a delete operation
|
||||
func (c *Cassandra) Delete(req *state.DeleteRequest) error {
|
||||
query := fmt.Sprintf("DELETE FROM %s WHERE key='%s'", c.table, req.Key)
|
||||
return c.session.Query(query).Exec()
|
||||
return c.session.Query("DELETE FROM ? WHERE key = ?", c.table, req.Key).Exec()
|
||||
}
|
||||
|
||||
// BulkDelete performs a bulk delete operation
|
||||
|
|
@ -212,8 +211,6 @@ func (c *Cassandra) BulkDelete(req []state.DeleteRequest) error {
|
|||
|
||||
// Get retrieves state from cassandra with a key
|
||||
func (c *Cassandra) Get(req *state.GetRequest) (*state.GetResponse, error) {
|
||||
query := fmt.Sprintf("SELECT value FROM %s WHERE key='%s'", c.table, req.Key)
|
||||
|
||||
session := c.session
|
||||
|
||||
if req.Options.Consistency == state.Strong {
|
||||
|
|
@ -232,7 +229,7 @@ func (c *Cassandra) Get(req *state.GetRequest) (*state.GetResponse, error) {
|
|||
session = sess
|
||||
}
|
||||
|
||||
results, err := session.Query(query).Iter().SliceMap()
|
||||
results, err := session.Query("SELECT value FROM ? WHERE key = ?", c.table, req.Key).Iter().SliceMap()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -255,8 +252,6 @@ func (c *Cassandra) Set(req *state.SetRequest) error {
|
|||
bt, _ = jsoniter.ConfigFastest.Marshal(req.Value)
|
||||
}
|
||||
|
||||
query := fmt.Sprintf("INSERT INTO %s (key, value) VALUES (?, ?)", c.table)
|
||||
|
||||
session := c.session
|
||||
|
||||
if req.Options.Consistency == state.Strong {
|
||||
|
|
@ -275,7 +270,7 @@ func (c *Cassandra) Set(req *state.SetRequest) error {
|
|||
session = sess
|
||||
}
|
||||
|
||||
return session.Query(query, req.Key, bt).Exec()
|
||||
return session.Query("INSERT INTO ? (key, value) VALUES (?, ?)", c.table, req.Key, bt).Exec()
|
||||
}
|
||||
|
||||
func (c *Cassandra) createSession(consistency gocql.Consistency) (*gocql.Session, error) {
|
||||
|
|
|
|||
|
|
@ -63,22 +63,28 @@ func (c *StateStore) Init(metadata state.Metadata) error {
|
|||
})
|
||||
|
||||
dbs, err := client.QueryDatabases(&documentdb.Query{
|
||||
Query: fmt.Sprintf("SELECT * FROM ROOT r WHERE r.id='%s'", creds.Database),
|
||||
Query: "SELECT * FROM ROOT r WHERE r.id=@id",
|
||||
Parameters: []documentdb.Parameter{
|
||||
{Name: "@id", Value: creds.Database},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
} else if len(dbs) == 0 {
|
||||
return fmt.Errorf("Database %s for CosmosDB state store not found", creds.Database)
|
||||
return fmt.Errorf("database %s for CosmosDB state store not found", creds.Database)
|
||||
}
|
||||
|
||||
c.db = &dbs[0]
|
||||
colls, err := client.QueryCollections(c.db.Self, &documentdb.Query{
|
||||
Query: fmt.Sprintf("SELECT * FROM ROOT r WHERE r.id='%s'", creds.Collection),
|
||||
Query: "SELECT * FROM ROOT r WHERE r.id=@id",
|
||||
Parameters: []documentdb.Parameter{
|
||||
{Name: "@id", Value: creds.Collection},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
} else if len(colls) == 0 {
|
||||
return fmt.Errorf("Collection %s for CosmosDB state store not found", creds.Collection)
|
||||
return fmt.Errorf("collection %s for CosmosDB state store not found", creds.Collection)
|
||||
}
|
||||
|
||||
c.collection = &colls[0]
|
||||
|
|
@ -102,7 +108,7 @@ func (c *StateStore) Get(req *state.GetRequest) (*state.GetResponse, error) {
|
|||
|
||||
_, err := c.client.QueryDocuments(
|
||||
c.collection.Self,
|
||||
documentdb.NewQuery("SELECT * FROM ROOT r WHERE r.id=@id", documentdb.P{"@id", key}),
|
||||
documentdb.NewQuery("SELECT * FROM ROOT r WHERE r.id=@id", documentdb.P{Name: "@id", Value: key}),
|
||||
&items,
|
||||
options...,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@ import (
|
|||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
const defaultOperationTimeout = time.Duration(10 * time.Second)
|
||||
const defaultOperationTimeout = 10 * time.Second
|
||||
const defaultSeparator = ","
|
||||
|
||||
var errMissingEndpoints = errors.New("Endpoints are required")
|
||||
var errMissingEndpoints = errors.New("endpoints are required")
|
||||
var errInvalidDialTimeout = errors.New("DialTimeout is invalid")
|
||||
|
||||
// ETCD is a state store
|
||||
|
|
@ -126,7 +126,8 @@ func validateRequired(configProps *configProperties) error {
|
|||
|
||||
// Get retrieves state from ETCD with a key
|
||||
func (r *ETCD) Get(req *state.GetRequest) (*state.GetResponse, error) {
|
||||
ctx, _ := context.WithTimeout(context.Background(), r.operationTimeout)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), r.operationTimeout)
|
||||
defer cancel()
|
||||
resp, err := r.client.Get(ctx, req.Key, clientv3.WithSort(clientv3.SortByVersion, clientv3.SortDescend))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -144,7 +145,8 @@ func (r *ETCD) Get(req *state.GetRequest) (*state.GetResponse, error) {
|
|||
|
||||
// Delete performs a delete operation
|
||||
func (r *ETCD) Delete(req *state.DeleteRequest) error {
|
||||
ctx, _ := context.WithTimeout(context.Background(), r.operationTimeout)
|
||||
ctx, cancelFn := context.WithTimeout(context.Background(), r.operationTimeout)
|
||||
defer cancelFn()
|
||||
_, err := r.client.Delete(ctx, req.Key)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -167,8 +169,8 @@ func (r *ETCD) BulkDelete(req []state.DeleteRequest) error {
|
|||
|
||||
// Set saves state into ETCD
|
||||
func (r *ETCD) Set(req *state.SetRequest) error {
|
||||
ctx, _ := context.WithTimeout(context.Background(), r.operationTimeout)
|
||||
|
||||
ctx, cancelFn := context.WithTimeout(context.Background(), r.operationTimeout)
|
||||
defer cancelFn()
|
||||
var vStr string
|
||||
b, ok := req.Value.([]byte)
|
||||
if ok {
|
||||
|
|
|
|||
|
|
@ -97,13 +97,12 @@ func (r *StateStore) getConnectedSlaves() (int, error) {
|
|||
}
|
||||
|
||||
return r.parseConnectedSlaves(s), nil
|
||||
|
||||
}
|
||||
|
||||
func (r *StateStore) parseConnectedSlaves(res string) int {
|
||||
infos := strings.Split(res, infoReplicationDelimiter)
|
||||
for _, info := range infos {
|
||||
if strings.Index(info, connectedSlavesReplicas) >= 0 {
|
||||
if strings.Contains(info, connectedSlavesReplicas) {
|
||||
parsedReplicas, _ := strconv.ParseUint(info[len(connectedSlavesReplicas):], 10, 32)
|
||||
return int(parsedReplicas)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,86 +1,86 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
package redis
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestGetKeyVersion(t *testing.T) {
|
||||
store := NewRedisStateStore()
|
||||
t.Run("With all required fields", func(t *testing.T) {
|
||||
key, ver, err := store.getKeyVersion([]interface{}{"data", "TEST_KEY", "version", "TEST_VER"})
|
||||
assert.Equal(t, nil, err, "failed to read all fields")
|
||||
assert.Equal(t, "TEST_KEY", key, "failed to read key")
|
||||
assert.Equal(t, "TEST_VER", ver, "failed to read version")
|
||||
})
|
||||
t.Run("With missing data", func(t *testing.T) {
|
||||
_, _, err := store.getKeyVersion([]interface{}{"version", "TEST_VER"})
|
||||
assert.NotNil(t, err, "failed to respond to missing data field")
|
||||
})
|
||||
t.Run("With missing version", func(t *testing.T) {
|
||||
_, _, err := store.getKeyVersion([]interface{}{"data", "TEST_KEY"})
|
||||
assert.NotNil(t, err, "failed to respond to missing version field")
|
||||
})
|
||||
t.Run("With all required fields - out of order", func(t *testing.T) {
|
||||
key, ver, err := store.getKeyVersion([]interface{}{"version", "TEST_VER", "dragon", "TEST_DRAGON", "data", "TEST_KEY"})
|
||||
assert.Equal(t, nil, err, "failed to read all fields")
|
||||
assert.Equal(t, "TEST_KEY", key, "failed to read key")
|
||||
assert.Equal(t, "TEST_VER", ver, "failed to read version")
|
||||
})
|
||||
t.Run("With no fields", func(t *testing.T) {
|
||||
_, _, err := store.getKeyVersion([]interface{}{})
|
||||
assert.NotNil(t, err, "failed to respond to missing fields")
|
||||
})
|
||||
t.Run("With wrong fields", func(t *testing.T) {
|
||||
_, _, err := store.getKeyVersion([]interface{}{"dragon", "TEST_DRAGON"})
|
||||
assert.NotNil(t, err, "failed to respond to missing fields")
|
||||
})
|
||||
}
|
||||
|
||||
func TestParseEtag(t *testing.T) {
|
||||
store := NewRedisStateStore()
|
||||
t.Run("Empty ETag", func(t *testing.T) {
|
||||
ver, err := store.parseETag("")
|
||||
assert.Equal(t, nil, err, "failed to parse ETag")
|
||||
assert.Equal(t, 0, ver, "default version should be 0")
|
||||
})
|
||||
t.Run("Number ETag", func(t *testing.T) {
|
||||
ver, err := store.parseETag("354")
|
||||
assert.Equal(t, nil, err, "failed to parse ETag")
|
||||
assert.Equal(t, 354, ver, "version should be 254")
|
||||
})
|
||||
t.Run("String ETag", func(t *testing.T) {
|
||||
_, err := store.parseETag("dragon")
|
||||
assert.NotNil(t, err, "shouldn't recognize string ETag")
|
||||
})
|
||||
}
|
||||
|
||||
func TestParseConnectedSlavs(t *testing.T) {
|
||||
store := NewRedisStateStore()
|
||||
|
||||
t.Run("Empty info", func(t *testing.T) {
|
||||
slaves := store.parseConnectedSlaves("")
|
||||
assert.Equal(t, 0, slaves, "connected slaves must be 0")
|
||||
})
|
||||
|
||||
t.Run("connectedSlaves property is not included", func(t *testing.T) {
|
||||
slaves := store.parseConnectedSlaves("# Replication\r\nrole:master\r\n")
|
||||
assert.Equal(t, 0, slaves, "connected slaves must be 0")
|
||||
})
|
||||
|
||||
t.Run("connectedSlaves is 2", func(t *testing.T) {
|
||||
slaves := store.parseConnectedSlaves("# Replication\r\nrole:master\r\nconnected_slaves:2\r\n")
|
||||
assert.Equal(t, 2, slaves, "connected slaves must be 2")
|
||||
})
|
||||
|
||||
t.Run("connectedSlaves is 1", func(t *testing.T) {
|
||||
slaves := store.parseConnectedSlaves("# Replication\r\nrole:master\r\nconnected_slaves:1")
|
||||
assert.Equal(t, 1, slaves, "connected slaves must be 1")
|
||||
})
|
||||
}
|
||||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
package redis
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestGetKeyVersion(t *testing.T) {
|
||||
store := NewRedisStateStore()
|
||||
t.Run("With all required fields", func(t *testing.T) {
|
||||
key, ver, err := store.getKeyVersion([]interface{}{"data", "TEST_KEY", "version", "TEST_VER"})
|
||||
assert.Equal(t, nil, err, "failed to read all fields")
|
||||
assert.Equal(t, "TEST_KEY", key, "failed to read key")
|
||||
assert.Equal(t, "TEST_VER", ver, "failed to read version")
|
||||
})
|
||||
t.Run("With missing data", func(t *testing.T) {
|
||||
_, _, err := store.getKeyVersion([]interface{}{"version", "TEST_VER"})
|
||||
assert.NotNil(t, err, "failed to respond to missing data field")
|
||||
})
|
||||
t.Run("With missing version", func(t *testing.T) {
|
||||
_, _, err := store.getKeyVersion([]interface{}{"data", "TEST_KEY"})
|
||||
assert.NotNil(t, err, "failed to respond to missing version field")
|
||||
})
|
||||
t.Run("With all required fields - out of order", func(t *testing.T) {
|
||||
key, ver, err := store.getKeyVersion([]interface{}{"version", "TEST_VER", "dragon", "TEST_DRAGON", "data", "TEST_KEY"})
|
||||
assert.Equal(t, nil, err, "failed to read all fields")
|
||||
assert.Equal(t, "TEST_KEY", key, "failed to read key")
|
||||
assert.Equal(t, "TEST_VER", ver, "failed to read version")
|
||||
})
|
||||
t.Run("With no fields", func(t *testing.T) {
|
||||
_, _, err := store.getKeyVersion([]interface{}{})
|
||||
assert.NotNil(t, err, "failed to respond to missing fields")
|
||||
})
|
||||
t.Run("With wrong fields", func(t *testing.T) {
|
||||
_, _, err := store.getKeyVersion([]interface{}{"dragon", "TEST_DRAGON"})
|
||||
assert.NotNil(t, err, "failed to respond to missing fields")
|
||||
})
|
||||
}
|
||||
|
||||
func TestParseEtag(t *testing.T) {
|
||||
store := NewRedisStateStore()
|
||||
t.Run("Empty ETag", func(t *testing.T) {
|
||||
ver, err := store.parseETag("")
|
||||
assert.Equal(t, nil, err, "failed to parse ETag")
|
||||
assert.Equal(t, 0, ver, "default version should be 0")
|
||||
})
|
||||
t.Run("Number ETag", func(t *testing.T) {
|
||||
ver, err := store.parseETag("354")
|
||||
assert.Equal(t, nil, err, "failed to parse ETag")
|
||||
assert.Equal(t, 354, ver, "version should be 254")
|
||||
})
|
||||
t.Run("String ETag", func(t *testing.T) {
|
||||
_, err := store.parseETag("dragon")
|
||||
assert.NotNil(t, err, "shouldn't recognize string ETag")
|
||||
})
|
||||
}
|
||||
|
||||
func TestParseConnectedSlavs(t *testing.T) {
|
||||
store := NewRedisStateStore()
|
||||
|
||||
t.Run("Empty info", func(t *testing.T) {
|
||||
slaves := store.parseConnectedSlaves("")
|
||||
assert.Equal(t, 0, slaves, "connected slaves must be 0")
|
||||
})
|
||||
|
||||
t.Run("connectedSlaves property is not included", func(t *testing.T) {
|
||||
slaves := store.parseConnectedSlaves("# Replication\r\nrole:master\r\n")
|
||||
assert.Equal(t, 0, slaves, "connected slaves must be 0")
|
||||
})
|
||||
|
||||
t.Run("connectedSlaves is 2", func(t *testing.T) {
|
||||
slaves := store.parseConnectedSlaves("# Replication\r\nrole:master\r\nconnected_slaves:2\r\n")
|
||||
assert.Equal(t, 2, slaves, "connected slaves must be 2")
|
||||
})
|
||||
|
||||
t.Run("connectedSlaves is 1", func(t *testing.T) {
|
||||
slaves := store.parseConnectedSlaves("# Replication\r\nrole:master\r\nconnected_slaves:1")
|
||||
assert.Equal(t, 1, slaves, "connected slaves must be 1")
|
||||
})
|
||||
}
|
||||
|
|
|
|||
196
state/retry.go
196
state/retry.go
|
|
@ -1,98 +1,98 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
package state
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
FirstWrite = "first-write"
|
||||
LastWrite = "last-write"
|
||||
Strong = "strong"
|
||||
Eventual = "eventual"
|
||||
Exponential = "exponential"
|
||||
Linear = "linear"
|
||||
)
|
||||
|
||||
// CheckSetRequestOptions checks if set request options use supported keywords
|
||||
func CheckSetRequestOptions(req *SetRequest) error {
|
||||
if req.Options.Concurrency != "" && req.Options.Concurrency != FirstWrite && req.Options.Concurrency != LastWrite {
|
||||
return fmt.Errorf("unrecognized concurrency model '%s'", req.Options.Concurrency)
|
||||
}
|
||||
if req.Options.Consistency != "" && req.Options.Consistency != Strong && req.Options.Consistency != Eventual {
|
||||
return fmt.Errorf("unrecognized consistency model '%s'", req.Options.Consistency)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckDeleteRequestOptions checks if delete request options use supported keywords
|
||||
func CheckDeleteRequestOptions(req *DeleteRequest) error {
|
||||
if req.Options.Concurrency != "" && req.Options.Concurrency != FirstWrite && req.Options.Concurrency != LastWrite {
|
||||
return fmt.Errorf("unrecognized concurrency model '%s'", req.Options.Concurrency)
|
||||
}
|
||||
if req.Options.Consistency != "" && req.Options.Consistency != Strong && req.Options.Consistency != Eventual {
|
||||
return fmt.Errorf("unrecognized consistency model '%s'", req.Options.Consistency)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetWithRetries handles SetRequest with retries
|
||||
func SetWithRetries(method func(req *SetRequest) error, req *SetRequest) error {
|
||||
switch req.Options.RetryPolicy.Pattern {
|
||||
case "":
|
||||
fallthrough
|
||||
case Linear:
|
||||
fallthrough
|
||||
case Exponential:
|
||||
if req.Options.RetryPolicy.Threshold > 0 {
|
||||
duration := req.Options.RetryPolicy.Interval
|
||||
for i := 0; i < req.Options.RetryPolicy.Threshold; i++ {
|
||||
err := method(req)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
time.Sleep(duration)
|
||||
if req.Options.RetryPolicy.Pattern == Exponential {
|
||||
duration *= 2
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("failed to set value after %d retries", req.Options.RetryPolicy.Threshold)
|
||||
}
|
||||
return method(req)
|
||||
default:
|
||||
return fmt.Errorf("unrecognized retry patter '%s'", req.Options.RetryPolicy.Pattern)
|
||||
}
|
||||
}
|
||||
|
||||
// DeleteWithRetries handles SetRequest with retries
|
||||
func DeleteWithRetries(method func(req *DeleteRequest) error, req *DeleteRequest) error {
|
||||
switch req.Options.RetryPolicy.Pattern {
|
||||
case "":
|
||||
fallthrough
|
||||
case Linear:
|
||||
fallthrough
|
||||
case Exponential:
|
||||
if req.Options.RetryPolicy.Threshold > 0 {
|
||||
duration := req.Options.RetryPolicy.Interval
|
||||
for i := 0; i < req.Options.RetryPolicy.Threshold; i++ {
|
||||
err := method(req)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
time.Sleep(duration)
|
||||
if req.Options.RetryPolicy.Pattern == Exponential {
|
||||
duration *= 2
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("failed to set value after %d retries", req.Options.RetryPolicy.Threshold)
|
||||
}
|
||||
return method(req)
|
||||
default:
|
||||
return fmt.Errorf("unrecognized retry patter '%s'", req.Options.RetryPolicy.Pattern)
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
package state
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
FirstWrite = "first-write"
|
||||
LastWrite = "last-write"
|
||||
Strong = "strong"
|
||||
Eventual = "eventual"
|
||||
Exponential = "exponential"
|
||||
Linear = "linear"
|
||||
)
|
||||
|
||||
// CheckSetRequestOptions checks if set request options use supported keywords
|
||||
func CheckSetRequestOptions(req *SetRequest) error {
|
||||
if req.Options.Concurrency != "" && req.Options.Concurrency != FirstWrite && req.Options.Concurrency != LastWrite {
|
||||
return fmt.Errorf("unrecognized concurrency model '%s'", req.Options.Concurrency)
|
||||
}
|
||||
if req.Options.Consistency != "" && req.Options.Consistency != Strong && req.Options.Consistency != Eventual {
|
||||
return fmt.Errorf("unrecognized consistency model '%s'", req.Options.Consistency)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckDeleteRequestOptions checks if delete request options use supported keywords
|
||||
func CheckDeleteRequestOptions(req *DeleteRequest) error {
|
||||
if req.Options.Concurrency != "" && req.Options.Concurrency != FirstWrite && req.Options.Concurrency != LastWrite {
|
||||
return fmt.Errorf("unrecognized concurrency model '%s'", req.Options.Concurrency)
|
||||
}
|
||||
if req.Options.Consistency != "" && req.Options.Consistency != Strong && req.Options.Consistency != Eventual {
|
||||
return fmt.Errorf("unrecognized consistency model '%s'", req.Options.Consistency)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetWithRetries handles SetRequest with retries
|
||||
func SetWithRetries(method func(req *SetRequest) error, req *SetRequest) error {
|
||||
switch req.Options.RetryPolicy.Pattern {
|
||||
case "":
|
||||
fallthrough
|
||||
case Linear:
|
||||
fallthrough
|
||||
case Exponential:
|
||||
if req.Options.RetryPolicy.Threshold > 0 {
|
||||
duration := req.Options.RetryPolicy.Interval
|
||||
for i := 0; i < req.Options.RetryPolicy.Threshold; i++ {
|
||||
err := method(req)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
time.Sleep(duration)
|
||||
if req.Options.RetryPolicy.Pattern == Exponential {
|
||||
duration *= 2
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("failed to set value after %d retries", req.Options.RetryPolicy.Threshold)
|
||||
}
|
||||
return method(req)
|
||||
default:
|
||||
return fmt.Errorf("unrecognized retry patter '%s'", req.Options.RetryPolicy.Pattern)
|
||||
}
|
||||
}
|
||||
|
||||
// DeleteWithRetries handles SetRequest with retries
|
||||
func DeleteWithRetries(method func(req *DeleteRequest) error, req *DeleteRequest) error {
|
||||
switch req.Options.RetryPolicy.Pattern {
|
||||
case "":
|
||||
fallthrough
|
||||
case Linear:
|
||||
fallthrough
|
||||
case Exponential:
|
||||
if req.Options.RetryPolicy.Threshold > 0 {
|
||||
duration := req.Options.RetryPolicy.Interval
|
||||
for i := 0; i < req.Options.RetryPolicy.Threshold; i++ {
|
||||
err := method(req)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
time.Sleep(duration)
|
||||
if req.Options.RetryPolicy.Pattern == Exponential {
|
||||
duration *= 2
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("failed to set value after %d retries", req.Options.RetryPolicy.Threshold)
|
||||
}
|
||||
return method(req)
|
||||
default:
|
||||
return fmt.Errorf("unrecognized retry patter '%s'", req.Options.RetryPolicy.Pattern)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,89 +1,88 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
package state
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// TestRetryPolicies is used to test retry policies
|
||||
func TestRetryPolicies(t *testing.T) {
|
||||
t.Run("set with no options", func(t *testing.T) {
|
||||
counter := 0
|
||||
SetWithRetries(func(req *SetRequest) error {
|
||||
counter++
|
||||
return nil
|
||||
}, &SetRequest{})
|
||||
assert.Equal(t, 1, counter, "should execute only once")
|
||||
})
|
||||
|
||||
t.Run("set with no retry policies", func(t *testing.T) {
|
||||
counter := 0
|
||||
SetWithRetries(func(req *SetRequest) error {
|
||||
counter++
|
||||
return nil
|
||||
}, &SetRequest{
|
||||
Options: SetStateOption{},
|
||||
})
|
||||
assert.Equal(t, 1, counter, "should execute only once")
|
||||
})
|
||||
|
||||
t.Run("set with empty retry policies", func(t *testing.T) {
|
||||
counter := 0
|
||||
SetWithRetries(func(req *SetRequest) error {
|
||||
counter++
|
||||
return nil
|
||||
}, &SetRequest{
|
||||
Options: SetStateOption{
|
||||
RetryPolicy: RetryPolicy{
|
||||
Interval: 0,
|
||||
Threshold: 0,
|
||||
Pattern: "",
|
||||
},
|
||||
},
|
||||
})
|
||||
assert.Equal(t, 1, counter, "should execute only once")
|
||||
})
|
||||
|
||||
t.Run("bad policy", func(t *testing.T) {
|
||||
ret := SetWithRetries(func(req *SetRequest) error {
|
||||
return nil
|
||||
}, &SetRequest{
|
||||
Options: SetStateOption{
|
||||
RetryPolicy: RetryPolicy{
|
||||
Interval: 100,
|
||||
Threshold: 3,
|
||||
Pattern: "dummy",
|
||||
},
|
||||
},
|
||||
})
|
||||
assert.NotNil(t, ret, "should reject policy")
|
||||
})
|
||||
|
||||
t.Run("liner retry 3 times", func(t *testing.T) {
|
||||
counter := 0
|
||||
SetWithRetries(func(req *SetRequest) error {
|
||||
counter++
|
||||
if counter < 3 {
|
||||
return fmt.Errorf("BAD")
|
||||
}
|
||||
return nil
|
||||
}, &SetRequest{
|
||||
Options: SetStateOption{
|
||||
RetryPolicy: RetryPolicy{
|
||||
Interval: 100,
|
||||
Threshold: 3,
|
||||
Pattern: "linear",
|
||||
},
|
||||
},
|
||||
})
|
||||
assert.Equal(t, 3, counter, "should execute 3 times")
|
||||
})
|
||||
|
||||
}
|
||||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
package state
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// TestRetryPolicies is used to test retry policies
|
||||
func TestRetryPolicies(t *testing.T) {
|
||||
t.Run("set with no options", func(t *testing.T) {
|
||||
counter := 0
|
||||
SetWithRetries(func(req *SetRequest) error {
|
||||
counter++
|
||||
return nil
|
||||
}, &SetRequest{})
|
||||
assert.Equal(t, 1, counter, "should execute only once")
|
||||
})
|
||||
|
||||
t.Run("set with no retry policies", func(t *testing.T) {
|
||||
counter := 0
|
||||
SetWithRetries(func(req *SetRequest) error {
|
||||
counter++
|
||||
return nil
|
||||
}, &SetRequest{
|
||||
Options: SetStateOption{},
|
||||
})
|
||||
assert.Equal(t, 1, counter, "should execute only once")
|
||||
})
|
||||
|
||||
t.Run("set with empty retry policies", func(t *testing.T) {
|
||||
counter := 0
|
||||
SetWithRetries(func(req *SetRequest) error {
|
||||
counter++
|
||||
return nil
|
||||
}, &SetRequest{
|
||||
Options: SetStateOption{
|
||||
RetryPolicy: RetryPolicy{
|
||||
Interval: 0,
|
||||
Threshold: 0,
|
||||
Pattern: "",
|
||||
},
|
||||
},
|
||||
})
|
||||
assert.Equal(t, 1, counter, "should execute only once")
|
||||
})
|
||||
|
||||
t.Run("bad policy", func(t *testing.T) {
|
||||
ret := SetWithRetries(func(req *SetRequest) error {
|
||||
return nil
|
||||
}, &SetRequest{
|
||||
Options: SetStateOption{
|
||||
RetryPolicy: RetryPolicy{
|
||||
Interval: 100,
|
||||
Threshold: 3,
|
||||
Pattern: "dummy",
|
||||
},
|
||||
},
|
||||
})
|
||||
assert.NotNil(t, ret, "should reject policy")
|
||||
})
|
||||
|
||||
t.Run("liner retry 3 times", func(t *testing.T) {
|
||||
counter := 0
|
||||
SetWithRetries(func(req *SetRequest) error {
|
||||
counter++
|
||||
if counter < 3 {
|
||||
return fmt.Errorf("BAD")
|
||||
}
|
||||
return nil
|
||||
}, &SetRequest{
|
||||
Options: SetStateOption{
|
||||
RetryPolicy: RetryPolicy{
|
||||
Interval: 100,
|
||||
Threshold: 3,
|
||||
Pattern: "linear",
|
||||
},
|
||||
},
|
||||
})
|
||||
assert.Equal(t, 3, counter, "should execute 3 times")
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
package state
|
||||
|
||||
// StateStore is an interface to perform operations on store
|
||||
// nolint:golint
|
||||
type StateStore interface {
|
||||
Init(metadata Metadata) error
|
||||
Delete(req *DeleteRequest) error
|
||||
|
|
|
|||
Loading…
Reference in New Issue