mirror of https://github.com/dapr/go-sdk.git
Compare commits
30 Commits
v1.11.0-rc
...
main
Author | SHA1 | Date |
---|---|---|
|
16374cdb7b | |
|
a3df75f17b | |
|
81312e9da9 | |
|
c81a381811 | |
|
aded0b64d7 | |
|
34fd54eb81 | |
|
c97fd6f30d | |
|
2ab3420adc | |
|
495a389ff0 | |
|
7c63bb9ae1 | |
|
31346f0d54 | |
|
921a6a79c5 | |
|
282a58bc9c | |
|
dce63f1917 | |
|
e52d60c714 | |
|
87659bf63e | |
|
c12c9594c4 | |
|
59acca46a6 | |
|
3fff121af7 | |
|
dd9a2d5a3c | |
|
516684c202 | |
|
e317f06e65 | |
|
4953b123ad | |
|
a074ea7428 | |
|
f9baae2539 | |
|
6c59092f53 | |
|
f87f366fe7 | |
|
2749284a00 | |
|
2cfb6e308e | |
|
d1f04ee738 |
|
@ -49,9 +49,9 @@ func (b *Bot) HandleEvent(ctx context.Context, event Event) (res string, err err
|
|||
switch command {
|
||||
case "/assign":
|
||||
assignee, err := b.AssignIssueToCommenter(event)
|
||||
res = fmt.Sprintf("👍 Issue assigned to %s", assignee)
|
||||
res = "👍 Issue assigned to " + assignee
|
||||
if err == nil {
|
||||
err = b.CreateIssueComment(fmt.Sprintf("🚀 Issue assigned to you @%s", assignee), event)
|
||||
err = b.CreateIssueComment("🚀 Issue assigned to you @"+assignee, event)
|
||||
} else {
|
||||
err = b.CreateIssueComment("⚠️ Unable to assign issue", event)
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
module github.com/dapr/go-sdk/.github/workflows/dapr-bot
|
||||
|
||||
go 1.22
|
||||
|
||||
toolchain go1.22.0
|
||||
go 1.23.3
|
||||
|
||||
require (
|
||||
github.com/google/go-github/v55 v55.0.0
|
||||
|
|
|
@ -38,8 +38,9 @@ jobs:
|
|||
run: |
|
||||
echo "RELEASE_VERSION=$(echo ${GITHUB_REF:10})" >> $GITHUB_ENV
|
||||
|
||||
- name: Release
|
||||
- name: Release Main
|
||||
uses: actions/create-release@v1
|
||||
if: ${{ !contains(github.ref , 'rc') }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
|
@ -49,6 +50,18 @@ jobs:
|
|||
draft: false
|
||||
prerelease: false
|
||||
|
||||
- name: Release RC
|
||||
uses: actions/create-release@v1
|
||||
if: ${{ contains(github.ref, 'rc') }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.ref }}
|
||||
release_name: Release ${{ github.ref }}
|
||||
body: Automatic Go Dapr client release
|
||||
draft: false
|
||||
prerelease: true
|
||||
|
||||
- name: Notify
|
||||
uses: rjstone/discord-webhook-notify@v1
|
||||
with:
|
||||
|
|
|
@ -17,8 +17,7 @@ jobs:
|
|||
name: Test
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
GOVER: ${{ matrix.gover }}
|
||||
GOLANGCILINT_VER: v1.55.2
|
||||
GOLANGCILINT_VER: v1.64.6
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
|
@ -38,7 +37,7 @@ jobs:
|
|||
run: make test
|
||||
|
||||
- name: Lint
|
||||
uses: golangci/golangci-lint-action@v3
|
||||
uses: golangci/golangci-lint-action@v6
|
||||
with:
|
||||
version: ${{ env.GOLANGCILINT_VER }}
|
||||
working-directory: ./.github/workflows/dapr-bot
|
||||
|
|
|
@ -8,17 +8,10 @@ on:
|
|||
|
||||
jobs:
|
||||
build:
|
||||
name: Test on ${{ matrix.gover }}
|
||||
name: Test
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
gover:
|
||||
- "1.21"
|
||||
- "1.22"
|
||||
env:
|
||||
GOVER: ${{ matrix.gover }}
|
||||
GOLANGCILINT_VER: v1.55.2
|
||||
GOLANGCILINT_VER: v1.64.6
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
|
@ -29,7 +22,7 @@ jobs:
|
|||
- name: Setup
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ env.GOVER }}
|
||||
go-version-file: 'go.mod'
|
||||
|
||||
- name: Tidy
|
||||
run: make tidy
|
||||
|
|
|
@ -19,17 +19,13 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
gover:
|
||||
- "1.21"
|
||||
- "1.22"
|
||||
os:
|
||||
- "ubuntu-latest"
|
||||
- "windows-latest"
|
||||
- "macos-latest"
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
GOVER: ${{ matrix.gover }}
|
||||
GOLANGCILINT_VER: v1.55.2 # Make sure to bump /tools/check-lint-version/main_test.go
|
||||
GOLANGCILINT_VER: v1.64.6 # Make sure to bump /tools/check-lint-version/main_test.go
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
|
@ -38,7 +34,7 @@ jobs:
|
|||
- name: Setup
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ env.GOVER }}
|
||||
go-version-file: ./tools/check-lint-version/go.mod
|
||||
|
||||
- name: Tidy
|
||||
working-directory: ./tools/check-lint-version
|
||||
|
|
|
@ -38,9 +38,9 @@ jobs:
|
|||
CHECKOUT_REF: ${{ github.ref }}
|
||||
outputs:
|
||||
DAPR_INSTALL_URL: ${{ env.DAPR_INSTALL_URL }}
|
||||
DAPR_CLI_VER: 1.14.0-rc.6
|
||||
DAPR_CLI_VER: ${{ steps.outputs.outputs.DAPR_CLI_VER }}
|
||||
DAPR_CLI_REF: ${{ steps.outputs.outputs.DAPR_CLI_REF }}
|
||||
DAPR_RUNTIME_VER: 1.14.0-rc.4
|
||||
DAPR_RUNTIME_VER: ${{ steps.outputs.outputs.DAPR_RUNTIME_VER }}
|
||||
CHECKOUT_REPO: ${{ steps.outputs.outputs.CHECKOUT_REPO }}
|
||||
CHECKOUT_REF: ${{ steps.outputs.outputs.CHECKOUT_REF }}
|
||||
DAPR_REF: ${{ steps.outputs.outputs.DAPR_REF }}
|
||||
|
@ -164,6 +164,7 @@ jobs:
|
|||
[
|
||||
"actor",
|
||||
"configuration",
|
||||
"conversation",
|
||||
"crypto",
|
||||
"dist-scheduler",
|
||||
"grpc-service",
|
||||
|
|
120
.golangci.yml
120
.golangci.yml
|
@ -4,7 +4,7 @@ run:
|
|||
concurrency: 4
|
||||
|
||||
# timeout for analysis, e.g. 30s, 5m, default is 1m
|
||||
deadline: 10m
|
||||
timeout: 15m
|
||||
|
||||
# exit code when at least one issue was found, default is 1
|
||||
issues-exit-code: 1
|
||||
|
@ -13,31 +13,35 @@ run:
|
|||
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:
|
||||
# third_party$, testdata$, examples$, Godeps$, builtin$
|
||||
skip-dirs:
|
||||
- ^pkg.*client.*clientset.*versioned.*
|
||||
- ^pkg.*client.*informers.*externalversions.*
|
||||
- ^pkg.*proto.*
|
||||
build-tags:
|
||||
- unit
|
||||
- allcomponents
|
||||
- subtlecrypto
|
||||
|
||||
# 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:
|
||||
# skip-files:
|
||||
# - ".*\\.my\\.go$"
|
||||
# - lib/bad.go
|
||||
|
||||
issues:
|
||||
# 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:
|
||||
# third_party$, testdata$, examples$, Godeps$, builtin$
|
||||
exclude-dirs:
|
||||
- ^pkg.*client.*clientset.*versioned.*
|
||||
- ^pkg.*client.*informers.*externalversions.*
|
||||
- ^pkg.*proto.*
|
||||
|
||||
# output configuration options
|
||||
output:
|
||||
# colored-line-number|line-number|json|tab|checkstyle, default is "colored-line-number"
|
||||
format: tab
|
||||
formats:
|
||||
- format: tab
|
||||
|
||||
# print lines of code with issue, default is true
|
||||
print-issued-lines: true
|
||||
|
@ -57,23 +61,19 @@ linters-settings:
|
|||
# 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.*
|
||||
exclude-functions:
|
||||
- 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:
|
||||
# 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
|
||||
|
@ -86,28 +86,12 @@ linters-settings:
|
|||
# enable or disable analyzers by name
|
||||
enable:
|
||||
- atomicalign
|
||||
enable-all: false
|
||||
disable:
|
||||
- shadow
|
||||
enable-all: false
|
||||
disable-all: false
|
||||
revive:
|
||||
max-open-files: 2048
|
||||
# enable-all-rules: true
|
||||
rules:
|
||||
- name: cyclomatic
|
||||
severity: warning
|
||||
disabled: false
|
||||
arguments: [20]
|
||||
- name: argument-limit
|
||||
severity: warning
|
||||
disabled: false
|
||||
arguments: [8]
|
||||
- name: if-return
|
||||
severity: warning
|
||||
disabled: false
|
||||
- name: unused-parameter
|
||||
severity: warning
|
||||
disabled: true
|
||||
# minimal confidence for issues, default is 0.8
|
||||
confidence: 0.8
|
||||
gofmt:
|
||||
# simplify code: gofmt with `-s` option, true by default
|
||||
simplify: true
|
||||
|
@ -121,9 +105,6 @@ linters-settings:
|
|||
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
|
||||
|
@ -152,10 +133,9 @@ linters-settings:
|
|||
desc: "you must use github.com/cenkalti/backoff/v4"
|
||||
misspell:
|
||||
# Correct spellings using locale preferences for US or UK.
|
||||
# Default is to use a neutral variety of English. (Do not specify a locale value)
|
||||
# Default is to use a neutral variety of English.
|
||||
# Setting locale to US will correct the British spelling of 'colour' to 'color'.
|
||||
# locale:
|
||||
|
||||
# locale: default
|
||||
ignore-words:
|
||||
- someword
|
||||
lll:
|
||||
|
@ -164,12 +144,6 @@ linters-settings:
|
|||
line-length: 120
|
||||
# tab width in spaces. Default to 1.
|
||||
tab-width: 1
|
||||
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
|
||||
|
@ -187,7 +161,7 @@ linters-settings:
|
|||
# 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:
|
||||
# enabled-checks:
|
||||
|
||||
# Which checks should be disabled; can't be combined with 'enabled-checks'; default is empty
|
||||
disabled-checks:
|
||||
|
@ -235,17 +209,20 @@ linters-settings:
|
|||
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.
|
||||
force-case-trailing-whitespace: 0
|
||||
# Allow declarations (var) to be cuddled.
|
||||
allow-cuddle-declarations: false
|
||||
# If the number of lines in a case block is equal to or lager than this number,
|
||||
# the case *must* end white a newline.
|
||||
# https://github.com/bombsimon/wsl/blob/master/doc/configuration.md#force-case-trailing-whitespace
|
||||
# Default: 0
|
||||
force-case-trailing-whitespace: 1
|
||||
|
||||
linters:
|
||||
fast: false
|
||||
enable-all: true
|
||||
disable:
|
||||
# TODO Enforce the below linters later
|
||||
- nosnakecase
|
||||
- musttag
|
||||
- dupl
|
||||
- errcheck
|
||||
- funlen
|
||||
|
@ -254,26 +231,16 @@ linters:
|
|||
- gocyclo
|
||||
- gocognit
|
||||
- godox
|
||||
- interfacer
|
||||
- lll
|
||||
- maligned
|
||||
- scopelint
|
||||
- unparam
|
||||
- wsl
|
||||
- gomnd
|
||||
- testpackage
|
||||
- goerr113
|
||||
- nestif
|
||||
- nlreturn
|
||||
- tagliatelle
|
||||
- ifshort
|
||||
- forbidigo
|
||||
- exhaustive
|
||||
- exhaustruct
|
||||
- exhaustivestruct
|
||||
- noctx
|
||||
- gci
|
||||
- golint
|
||||
- tparallel
|
||||
- paralleltest
|
||||
- wrapcheck
|
||||
|
@ -287,7 +254,6 @@ linters:
|
|||
- varnamelen
|
||||
- errorlint
|
||||
- forcetypeassert
|
||||
- ifshort
|
||||
- maintidx
|
||||
- nilnil
|
||||
- predeclared
|
||||
|
@ -300,14 +266,10 @@ linters:
|
|||
- asasalint
|
||||
- rowserrcheck
|
||||
- sqlclosecheck
|
||||
- structcheck
|
||||
- varcheck
|
||||
- deadcode
|
||||
- golint
|
||||
- inamedparam
|
||||
issues:
|
||||
exclude-rules:
|
||||
- path: .*_test.go
|
||||
linters:
|
||||
- godot
|
||||
|
||||
- tagalign
|
||||
- mnd
|
||||
- canonicalheader
|
||||
- err113
|
||||
- fatcontext
|
||||
- forbidigo # TODO: Re-enable and remove fmt.println
|
6
Makefile
6
Makefile
|
@ -1,6 +1,6 @@
|
|||
RELEASE_VERSION =v1.0.0-rc-3
|
||||
GDOC_PORT =8888
|
||||
GO_COMPAT_VERSION=1.21
|
||||
GO_COMPAT_VERSION=1.22
|
||||
|
||||
.PHONY: all
|
||||
all: help
|
||||
|
@ -33,6 +33,10 @@ cover: ## Displays test coverage in the client and service packages
|
|||
lint: check-lint ## Lints the entire project
|
||||
golangci-lint run --timeout=3m
|
||||
|
||||
.PHONY: lint-fix
|
||||
lint-fix: check-lint ## Lints the entire project
|
||||
golangci-lint run --timeout=3m --fix
|
||||
|
||||
.PHONY: check-lint
|
||||
check-lint: ## Compares the locally installed linter with the workflow version
|
||||
cd ./tools/check-lint-version && \
|
||||
|
|
|
@ -37,11 +37,11 @@ var ignoredActorMethods = []string{"Type"}
|
|||
// init initializes the action method exclusion list with methods from ServerImplBaseCtx and ReminderCallee interfaces.
|
||||
func init() {
|
||||
serverImplBaseCtxType := reflect.TypeOf(&actor.ServerImplBaseCtx{})
|
||||
for i := 0; i < serverImplBaseCtxType.NumMethod(); i++ {
|
||||
for i := range serverImplBaseCtxType.NumMethod() {
|
||||
ignoredActorMethods = append(ignoredActorMethods, serverImplBaseCtxType.Method(i).Name)
|
||||
}
|
||||
ReminderCallType := reflect.TypeOf((*actor.ReminderCallee)(nil)).Elem()
|
||||
for i := 0; i < ReminderCallType.NumMethod(); i++ {
|
||||
for i := range ReminderCallType.NumMethod() {
|
||||
ignoredActorMethods = append(ignoredActorMethods, ReminderCallType.Method(i).Name)
|
||||
}
|
||||
}
|
||||
|
@ -265,7 +265,7 @@ type MethodType struct {
|
|||
// suitableMethods returns suitable Rpc methods of typ.
|
||||
func suitableMethods(typ reflect.Type) map[string]*MethodType {
|
||||
methods := make(map[string]*MethodType)
|
||||
for m := 0; m < typ.NumMethod(); m++ {
|
||||
for m := range typ.NumMethod() {
|
||||
method := typ.Method(m)
|
||||
// skip methods from ServerImplBaseCtx struct and ServerContext and ReminderCallee interfaces.
|
||||
if slices.Contains(ignoredActorMethods, method.Name) {
|
||||
|
|
|
@ -48,6 +48,7 @@ func TestRegisterActorFactoryAndInvokeMethod(t *testing.T) {
|
|||
mockServer.EXPECT().RegisterActorImplFactory(gomock.Any())
|
||||
rt.RegisterActorFactory(actorMock.ActorImplFactory)
|
||||
|
||||
//nolint:usetesting
|
||||
mockServer.EXPECT().InvokeMethod(context.Background(), "mockActorID", "Invoke", []byte("param")).Return([]byte("response"), actorErr.Success)
|
||||
rspData, err := rt.InvokeActorMethod("testActorType", "mockActorID", "Invoke", []byte("param"))
|
||||
|
||||
|
@ -89,6 +90,7 @@ func TestInvokeReminder(t *testing.T) {
|
|||
mockServer.EXPECT().RegisterActorImplFactory(gomock.Any())
|
||||
rt.RegisterActorFactory(actorMock.ActorImplFactory)
|
||||
|
||||
//nolint:usetesting
|
||||
mockServer.EXPECT().InvokeReminder(context.Background(), "mockActorID", "mockReminder", []byte("param")).Return(actorErr.Success)
|
||||
err = rt.InvokeReminder("testActorType", "mockActorID", "mockReminder", []byte("param"))
|
||||
|
||||
|
@ -109,6 +111,7 @@ func TestInvokeTimer(t *testing.T) {
|
|||
mockServer.EXPECT().RegisterActorImplFactory(gomock.Any())
|
||||
rt.RegisterActorFactory(actorMock.ActorImplFactory)
|
||||
|
||||
//nolint:usetesting
|
||||
mockServer.EXPECT().InvokeTimer(context.Background(), "mockActorID", "mockTimer", []byte("param")).Return(actorErr.Success)
|
||||
err = rt.InvokeTimer("testActorType", "mockActorID", "mockTimer", []byte("param"))
|
||||
|
||||
|
|
|
@ -46,7 +46,6 @@ func TestNewActorStateChange(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for name, test := range tests {
|
||||
test := test
|
||||
t.Run(name, func(t *testing.T) {
|
||||
assert.Equal(t, test.want, NewActorStateChange(test.stateName, test.value, test.changeKind, &test.ttl))
|
||||
})
|
||||
|
|
|
@ -289,7 +289,7 @@ func (c *GRPCClient) implActor(actor actor.Client, serializer codec.Codec) {
|
|||
}
|
||||
|
||||
numField := valueOfActor.NumField()
|
||||
for i := 0; i < numField; i++ {
|
||||
for i := range numField {
|
||||
t := typeOfActor.Field(i)
|
||||
methodName := t.Name
|
||||
if methodName == "Type" {
|
||||
|
@ -312,7 +312,7 @@ func (c *GRPCClient) implActor(actor actor.Client, serializer codec.Codec) {
|
|||
}
|
||||
|
||||
funcOuts := make([]reflect.Type, outNum)
|
||||
for i := 0; i < outNum; i++ {
|
||||
for i := range outNum {
|
||||
funcOuts[i] = t.Type.Out(i)
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@ limitations under the License.
|
|||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -25,7 +24,7 @@ import (
|
|||
const testActorType = "test"
|
||||
|
||||
func TestInvokeActor(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
in := &InvokeActorRequest{
|
||||
ActorID: "fn",
|
||||
Method: "mockMethod",
|
||||
|
@ -74,7 +73,7 @@ func TestInvokeActor(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRegisterActorReminder(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
in := &RegisterActorReminderRequest{
|
||||
ActorID: "fn",
|
||||
Data: []byte(`{hello}`),
|
||||
|
@ -137,7 +136,7 @@ func TestRegisterActorReminder(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRegisterActorTimer(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
in := &RegisterActorTimerRequest{
|
||||
ActorID: "fn",
|
||||
Data: []byte(`{hello}`),
|
||||
|
@ -215,7 +214,7 @@ func TestRegisterActorTimer(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestUnregisterActorReminder(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
in := &UnregisterActorReminderRequest{
|
||||
ActorID: "fn",
|
||||
ActorType: testActorType,
|
||||
|
@ -260,7 +259,7 @@ func TestUnregisterActorReminder(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestUnregisterActorTimer(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
in := &UnregisterActorTimerRequest{
|
||||
ActorID: "fn",
|
||||
ActorType: testActorType,
|
||||
|
|
|
@ -14,7 +14,6 @@ limitations under the License.
|
|||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -25,7 +24,7 @@ import (
|
|||
// go test -timeout 30s ./client -count 1 -run ^TestInvokeBinding$
|
||||
|
||||
func TestInvokeBinding(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
in := &InvokeBindingRequest{
|
||||
Name: "test",
|
||||
Operation: "fn",
|
||||
|
|
|
@ -230,24 +230,38 @@ type Client interface {
|
|||
ImplActorClientStub(actorClientStub actor.Client, opt ...config.Option)
|
||||
|
||||
// StartWorkflowBeta1 starts a workflow.
|
||||
// Deprecated: Please use the workflow client (github.com/dapr/go-sdk/workflow).
|
||||
// These methods for managing workflows are no longer supported and will be removed in the 1.16 release.
|
||||
StartWorkflowBeta1(ctx context.Context, req *StartWorkflowRequest) (*StartWorkflowResponse, error)
|
||||
|
||||
// GetWorkflowBeta1 gets a workflow.
|
||||
// Deprecated: Please use the workflow client (github.com/dapr/go-sdk/workflow).
|
||||
// These methods for managing workflows are no longer supported and will be removed in the 1.16 release.
|
||||
GetWorkflowBeta1(ctx context.Context, req *GetWorkflowRequest) (*GetWorkflowResponse, error)
|
||||
|
||||
// PurgeWorkflowBeta1 purges a workflow.
|
||||
// Deprecated: Please use the workflow client (github.com/dapr/go-sdk/workflow).
|
||||
// These methods for managing workflows are no longer supported and will be removed in the 1.16 release.
|
||||
PurgeWorkflowBeta1(ctx context.Context, req *PurgeWorkflowRequest) error
|
||||
|
||||
// TerminateWorkflowBeta1 terminates a workflow.
|
||||
// Deprecated: Please use the workflow client (github.com/dapr/go-sdk/workflow).
|
||||
// These methods for managing workflows are no longer supported and will be removed in the 1.16 release.
|
||||
TerminateWorkflowBeta1(ctx context.Context, req *TerminateWorkflowRequest) error
|
||||
|
||||
// PauseWorkflowBeta1 pauses a workflow.
|
||||
// Deprecated: Please use the workflow client (github.com/dapr/go-sdk/workflow).
|
||||
// These methods for managing workflows are no longer supported and will be removed in the 1.16 release.
|
||||
PauseWorkflowBeta1(ctx context.Context, req *PauseWorkflowRequest) error
|
||||
|
||||
// ResumeWorkflowBeta1 resumes a workflow.
|
||||
// Deprecated: Please use the workflow client (github.com/dapr/go-sdk/workflow).
|
||||
// These methods for managing workflows are no longer supported and will be removed in the 1.16 release.
|
||||
ResumeWorkflowBeta1(ctx context.Context, req *ResumeWorkflowRequest) error
|
||||
|
||||
// RaiseEventWorkflowBeta1 raises an event for a workflow.
|
||||
// Deprecated: Please use the workflow client (github.com/dapr/go-sdk/workflow).
|
||||
// These methods for managing workflows are no longer supported and will be removed in the 1.16 release.
|
||||
RaiseEventWorkflowBeta1(ctx context.Context, req *RaiseEventWorkflowRequest) error
|
||||
|
||||
// ScheduleJobAlpha1 creates and schedules a job.
|
||||
|
@ -259,6 +273,9 @@ type Client interface {
|
|||
// DeleteJobAlpha1 deletes a scheduled job.
|
||||
DeleteJobAlpha1(ctx context.Context, name string) error
|
||||
|
||||
// ConverseAlpha1 interacts with a conversational AI model.
|
||||
ConverseAlpha1(ctx context.Context, request conversationRequest, options ...conversationRequestOption) (*ConversationResponse, error)
|
||||
|
||||
// GrpcClient returns the base grpc client if grpc is used and nil otherwise
|
||||
GrpcClient() pb.DaprClient
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ func TestNewClient(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("new client with trace ID", func(t *testing.T) {
|
||||
_ = testClient.WithTraceID(context.Background(), "test")
|
||||
_ = testClient.WithTraceID(t.Context(), "test")
|
||||
})
|
||||
|
||||
t.Run("new socket client closed with token", func(t *testing.T) {
|
||||
|
@ -120,13 +120,13 @@ func TestNewClient(t *testing.T) {
|
|||
c, err := NewClientWithSocket(testSocket)
|
||||
require.NoError(t, err)
|
||||
defer c.Close()
|
||||
ctx := c.WithTraceID(context.Background(), "")
|
||||
ctx := c.WithTraceID(t.Context(), "")
|
||||
_ = c.WithTraceID(ctx, "test")
|
||||
})
|
||||
}
|
||||
|
||||
func TestShutdown(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
|
||||
t.Run("shutdown", func(t *testing.T) {
|
||||
err := testClient.Shutdown(ctx)
|
||||
|
@ -466,7 +466,7 @@ func (s *testDaprServer) SubscribeConfiguration(in *pb.SubscribeConfigurationReq
|
|||
return err
|
||||
}
|
||||
|
||||
for i := 0; i < 5; i++ {
|
||||
for range 5 {
|
||||
select {
|
||||
case <-stopCh:
|
||||
return nil
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -16,7 +15,7 @@ const (
|
|||
)
|
||||
|
||||
func TestGetConfigurationItem(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
|
||||
t.Run("get configuration item", func(t *testing.T) {
|
||||
resp, err := testClient.GetConfigurationItem(ctx, "example-config", "mykey")
|
||||
|
@ -31,7 +30,7 @@ func TestGetConfigurationItem(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestGetConfigurationItems(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
|
||||
keys := []string{"mykey1", "mykey2", "mykey3"}
|
||||
t.Run("Test get configuration items", func(t *testing.T) {
|
||||
|
@ -44,7 +43,7 @@ func TestGetConfigurationItems(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestSubscribeConfigurationItems(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
|
||||
var counter, totalCounter uint32
|
||||
counter = 0
|
||||
|
@ -67,7 +66,7 @@ func TestSubscribeConfigurationItems(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestUnSubscribeConfigurationItems(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
|
||||
var counter, totalCounter uint32
|
||||
t.Run("Test unsubscribe configuration items", func(t *testing.T) {
|
||||
|
|
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
Copyright 2024 The Dapr Authors
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
|
||||
runtimev1pb "github.com/dapr/dapr/pkg/proto/runtime/v1"
|
||||
)
|
||||
|
||||
// conversationRequest object - currently unexported as used in a functions option pattern
|
||||
type conversationRequest struct {
|
||||
name string
|
||||
inputs []ConversationInput
|
||||
Parameters map[string]*anypb.Any
|
||||
Metadata map[string]string
|
||||
ContextID *string
|
||||
ScrubPII *bool // Scrub PII from the output
|
||||
Temperature *float64
|
||||
}
|
||||
|
||||
// NewConversationRequest defines a request with a component name and one or more inputs as a slice
|
||||
func NewConversationRequest(llmName string, inputs []ConversationInput) conversationRequest {
|
||||
return conversationRequest{
|
||||
name: llmName,
|
||||
inputs: inputs,
|
||||
}
|
||||
}
|
||||
|
||||
type conversationRequestOption func(request *conversationRequest)
|
||||
|
||||
// ConversationInput defines a single input.
|
||||
type ConversationInput struct {
|
||||
// The content to send to the llm.
|
||||
Content string
|
||||
// The role of the message.
|
||||
Role *string
|
||||
// Whether to Scrub PII from the input
|
||||
ScrubPII *bool
|
||||
}
|
||||
|
||||
// ConversationResponse is the basic response from a conversationRequest.
|
||||
type ConversationResponse struct {
|
||||
ContextID string
|
||||
Outputs []ConversationResult
|
||||
}
|
||||
|
||||
// ConversationResult is the individual
|
||||
type ConversationResult struct {
|
||||
Result string
|
||||
Parameters map[string]*anypb.Any
|
||||
}
|
||||
|
||||
// WithParameters should be used to provide parameters for custom fields.
|
||||
func WithParameters(parameters map[string]*anypb.Any) conversationRequestOption {
|
||||
return func(o *conversationRequest) {
|
||||
o.Parameters = parameters
|
||||
}
|
||||
}
|
||||
|
||||
// WithMetadata used to define metadata to be passed to components.
|
||||
func WithMetadata(metadata map[string]string) conversationRequestOption {
|
||||
return func(o *conversationRequest) {
|
||||
o.Metadata = metadata
|
||||
}
|
||||
}
|
||||
|
||||
// WithContextID to provide a new context or continue an existing one.
|
||||
func WithContextID(id string) conversationRequestOption {
|
||||
return func(o *conversationRequest) {
|
||||
o.ContextID = &id
|
||||
}
|
||||
}
|
||||
|
||||
// WithScrubPII to define whether the outputs should have PII removed.
|
||||
func WithScrubPII(scrub bool) conversationRequestOption {
|
||||
return func(o *conversationRequest) {
|
||||
o.ScrubPII = &scrub
|
||||
}
|
||||
}
|
||||
|
||||
// WithTemperature to specify which way the LLM leans.
|
||||
func WithTemperature(temp float64) conversationRequestOption {
|
||||
return func(o *conversationRequest) {
|
||||
o.Temperature = &temp
|
||||
}
|
||||
}
|
||||
|
||||
// ConverseAlpha1 can invoke an LLM given a request created by the NewConversationRequest function.
|
||||
func (c *GRPCClient) ConverseAlpha1(ctx context.Context, req conversationRequest, options ...conversationRequestOption) (*ConversationResponse, error) {
|
||||
cinputs := make([]*runtimev1pb.ConversationInput, len(req.inputs))
|
||||
for i, in := range req.inputs {
|
||||
cinputs[i] = &runtimev1pb.ConversationInput{
|
||||
Content: in.Content,
|
||||
Role: in.Role,
|
||||
ScrubPII: in.ScrubPII,
|
||||
}
|
||||
}
|
||||
|
||||
for _, opt := range options {
|
||||
if opt != nil {
|
||||
opt(&req)
|
||||
}
|
||||
}
|
||||
|
||||
request := runtimev1pb.ConversationRequest{
|
||||
Name: req.name,
|
||||
ContextID: req.ContextID,
|
||||
Inputs: cinputs,
|
||||
Parameters: req.Parameters,
|
||||
Metadata: req.Metadata,
|
||||
ScrubPII: req.ScrubPII,
|
||||
Temperature: req.Temperature,
|
||||
}
|
||||
|
||||
resp, err := c.protoClient.ConverseAlpha1(ctx, &request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
outputs := make([]ConversationResult, len(resp.GetOutputs()))
|
||||
for i, o := range resp.GetOutputs() {
|
||||
outputs[i] = ConversationResult{
|
||||
Result: o.GetResult(),
|
||||
Parameters: o.GetParameters(),
|
||||
}
|
||||
}
|
||||
|
||||
return &ConversationResponse{
|
||||
ContextID: resp.GetContextID(),
|
||||
Outputs: outputs,
|
||||
}, nil
|
||||
}
|
|
@ -30,7 +30,7 @@ import (
|
|||
)
|
||||
|
||||
func TestEncrypt(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
|
||||
t.Run("missing ComponentName", func(t *testing.T) {
|
||||
out, err := testClient.Encrypt(ctx,
|
||||
|
@ -138,7 +138,7 @@ func TestEncrypt(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestDecrypt(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
|
||||
t.Run("missing ComponentName", func(t *testing.T) {
|
||||
out, err := testClient.Decrypt(ctx,
|
||||
|
|
|
@ -27,7 +27,6 @@ type Parsed struct {
|
|||
TLS bool
|
||||
}
|
||||
|
||||
//nolint:revive
|
||||
func ParseGRPCEndpoint(endpoint string) (Parsed, error) {
|
||||
target := endpoint
|
||||
if len(target) == 0 {
|
||||
|
|
|
@ -14,7 +14,6 @@ limitations under the License.
|
|||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -39,7 +38,7 @@ type _testStructwithSlices struct {
|
|||
}
|
||||
|
||||
func TestInvokeMethodWithContent(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
data := "ping"
|
||||
|
||||
t.Run("with content", func(t *testing.T) {
|
||||
|
|
|
@ -14,7 +14,6 @@ limitations under the License.
|
|||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -29,7 +28,7 @@ const (
|
|||
)
|
||||
|
||||
func TestLock(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
|
||||
t.Run("try lock invalid store name", func(t *testing.T) {
|
||||
r, err := testClient.TryLockAlpha1(ctx, "", &LockRequest{})
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -11,7 +10,7 @@ import (
|
|||
|
||||
// Test GetMetadata returns
|
||||
func TestGetMetadata(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
t.Run("get meta", func(t *testing.T) {
|
||||
metadata, err := testClient.GetMetadata(ctx)
|
||||
require.NoError(t, err)
|
||||
|
@ -20,7 +19,7 @@ func TestGetMetadata(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestSetMetadata(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
t.Run("set meta", func(t *testing.T) {
|
||||
err := testClient.SetMetadata(ctx, "test_key", "test_value")
|
||||
require.NoError(t, err)
|
||||
|
|
|
@ -14,7 +14,6 @@ limitations under the License.
|
|||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -39,7 +38,7 @@ type _testCustomContentwithSlices struct {
|
|||
|
||||
// go test -timeout 30s ./client -count 1 -run ^TestPublishEvent$
|
||||
func TestPublishEvent(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
|
||||
t.Run("with data", func(t *testing.T) {
|
||||
err := testClient.PublishEvent(ctx, "messages", "test", []byte("ping"))
|
||||
|
@ -96,7 +95,7 @@ func TestPublishEvent(t *testing.T) {
|
|||
|
||||
// go test -timeout 30s ./client -count 1 -run ^TestPublishEvents$
|
||||
func TestPublishEvents(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
|
||||
t.Run("without pubsub name", func(t *testing.T) {
|
||||
res := testClient.PublishEvents(ctx, "", "test", []interface{}{"ping", "pong"})
|
||||
|
|
|
@ -14,7 +14,6 @@ limitations under the License.
|
|||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -23,7 +22,7 @@ import (
|
|||
)
|
||||
|
||||
func TestSchedulingAlpha1(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
|
||||
t.Run("schedule job - valid", func(t *testing.T) {
|
||||
err := testClient.ScheduleJobAlpha1(ctx, &Job{
|
||||
|
|
|
@ -14,7 +14,6 @@ limitations under the License.
|
|||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -24,7 +23,7 @@ import (
|
|||
|
||||
// go test -timeout 30s ./client -count 1 -run ^TestGetSecret$
|
||||
func TestGetSecret(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
|
||||
t.Run("without store", func(t *testing.T) {
|
||||
out, err := testClient.GetSecret(ctx, "", "key1", nil)
|
||||
|
@ -53,7 +52,7 @@ func TestGetSecret(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestGetBulkSecret(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
|
||||
t.Run("without store", func(t *testing.T) {
|
||||
out, err := testClient.GetBulkSecret(ctx, "", nil)
|
||||
|
|
|
@ -17,6 +17,7 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"google.golang.org/protobuf/types/known/durationpb"
|
||||
|
@ -65,11 +66,11 @@ const (
|
|||
|
||||
type (
|
||||
// StateConsistency is the consistency enum type.
|
||||
StateConsistency int
|
||||
StateConsistency int32
|
||||
// StateConcurrency is the concurrency enum type.
|
||||
StateConcurrency int
|
||||
StateConcurrency int32
|
||||
// OperationType is the operation enum type.
|
||||
OperationType int
|
||||
OperationType int32
|
||||
)
|
||||
|
||||
// GetPBConsistency get consistency pb value.
|
||||
|
@ -252,9 +253,15 @@ func toProtoDuration(d time.Duration) *durationpb.Duration {
|
|||
nanos := d.Nanoseconds()
|
||||
secs := nanos / 1e9
|
||||
nanos -= secs * 1e9
|
||||
|
||||
// conversion check - gosec ignored below for conversion
|
||||
if nanos <= int64(math.MinInt32) && nanos >= int64(math.MaxInt32) {
|
||||
panic("integer overflow converting duration to proto")
|
||||
}
|
||||
|
||||
return &durationpb.Duration{
|
||||
Seconds: secs,
|
||||
Nanos: int32(nanos),
|
||||
Nanos: int32(nanos), //nolint:gosec
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -484,7 +491,7 @@ func (c *GRPCClient) DeleteBulkState(ctx context.Context, storeName string, keys
|
|||
}
|
||||
|
||||
items := make([]*DeleteStateItem, 0, len(keys))
|
||||
for i := 0; i < len(keys); i++ {
|
||||
for i := range keys {
|
||||
item := &DeleteStateItem{
|
||||
Key: keys[i],
|
||||
Metadata: meta,
|
||||
|
@ -502,7 +509,7 @@ func (c *GRPCClient) DeleteBulkStateItems(ctx context.Context, storeName string,
|
|||
}
|
||||
|
||||
states := make([]*v1.StateItem, 0, len(items))
|
||||
for i := 0; i < len(items); i++ {
|
||||
for i := range items {
|
||||
item := items[i]
|
||||
if err := hasRequiredStateArgs(storeName, item.Key); err != nil {
|
||||
return fmt.Errorf("missing required arguments: %w", err)
|
||||
|
|
|
@ -14,7 +14,6 @@ limitations under the License.
|
|||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -77,7 +76,7 @@ func TestStateOptionsConverter(t *testing.T) {
|
|||
|
||||
// go test -timeout 30s ./client -count 1 -run ^TestSaveState$
|
||||
func TestSaveState(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
data := testData
|
||||
store := testStore
|
||||
key := "key1"
|
||||
|
@ -118,7 +117,7 @@ func TestSaveState(t *testing.T) {
|
|||
|
||||
// go test -timeout 30s ./client -count 1 -run ^TestDeleteState$
|
||||
func TestDeleteState(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
data := testData
|
||||
store := testStore
|
||||
key := "key1"
|
||||
|
@ -189,7 +188,7 @@ func TestDeleteState(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestDeleteBulkState(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
data := testData
|
||||
store := testStore
|
||||
keys := []string{"key1", "key2", "key3"}
|
||||
|
@ -337,7 +336,7 @@ func TestDeleteBulkState(t *testing.T) {
|
|||
|
||||
// go test -timeout 30s ./client -count 1 -run ^TestStateTransactions$
|
||||
func TestStateTransactions(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
data := `{ "message": "test" }`
|
||||
store := testStore
|
||||
meta := map[string]string{}
|
||||
|
@ -410,7 +409,7 @@ func TestStateTransactions(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestQueryState(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
data := testData
|
||||
store := testStore
|
||||
key1 := "key1"
|
||||
|
|
|
@ -23,6 +23,9 @@ import (
|
|||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
pb "github.com/dapr/dapr/pkg/proto/runtime/v1"
|
||||
"github.com/dapr/go-sdk/service/common"
|
||||
)
|
||||
|
@ -37,10 +40,15 @@ type SubscriptionOptions struct {
|
|||
}
|
||||
|
||||
type Subscription struct {
|
||||
ctx context.Context
|
||||
stream pb.Dapr_SubscribeTopicEventsAlpha1Client
|
||||
|
||||
// lock locks concurrent writes to subscription stream.
|
||||
lock sync.Mutex
|
||||
closed atomic.Bool
|
||||
|
||||
createStream func(ctx context.Context, opts SubscriptionOptions) (pb.Dapr_SubscribeTopicEventsAlpha1Client, error)
|
||||
opts SubscriptionOptions
|
||||
}
|
||||
|
||||
type SubscriptionMessage struct {
|
||||
|
@ -55,7 +63,10 @@ func (c *GRPCClient) Subscribe(ctx context.Context, opts SubscriptionOptions) (*
|
|||
}
|
||||
|
||||
s := &Subscription{
|
||||
stream: stream,
|
||||
ctx: ctx,
|
||||
stream: stream,
|
||||
createStream: c.subscribeInitialRequest,
|
||||
opts: opts,
|
||||
}
|
||||
|
||||
return s, nil
|
||||
|
@ -101,52 +112,96 @@ func (s *Subscription) Close() error {
|
|||
}
|
||||
|
||||
func (s *Subscription) Receive() (*SubscriptionMessage, error) {
|
||||
resp, err := s.stream.Recv()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
event := resp.GetEventMessage()
|
||||
|
||||
data := any(event.GetData())
|
||||
if len(event.GetData()) > 0 {
|
||||
mediaType, _, err := mime.ParseMediaType(event.GetDataContentType())
|
||||
if err == nil {
|
||||
var v interface{}
|
||||
switch mediaType {
|
||||
case "application/json":
|
||||
if err := json.Unmarshal(event.GetData(), &v); err == nil {
|
||||
data = v
|
||||
}
|
||||
case "text/plain":
|
||||
// Assume UTF-8 encoded string.
|
||||
data = string(event.GetData())
|
||||
for {
|
||||
resp, err := s.stream.Recv()
|
||||
if err != nil {
|
||||
select {
|
||||
case <-s.ctx.Done():
|
||||
return nil, errors.New("subscription context closed")
|
||||
default:
|
||||
if strings.HasPrefix(mediaType, "application/") &&
|
||||
strings.HasSuffix(mediaType, "+json") {
|
||||
// proceed to check the gRPC status error
|
||||
}
|
||||
|
||||
st, ok := status.FromError(err)
|
||||
if !ok {
|
||||
// not a grpc status error
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch st.Code() {
|
||||
case codes.Unavailable, codes.Unknown:
|
||||
logger.Printf("gRPC error while reading from stream: %s (code=%v)",
|
||||
st.Message(), st.Code())
|
||||
// close the current stream and reconnect
|
||||
if s.closed.Load() {
|
||||
return nil, errors.New("subscription is permanently closed; cannot reconnect")
|
||||
}
|
||||
if err := s.closeStreamOnly(); err != nil {
|
||||
logger.Printf("error closing current stream: %v", err)
|
||||
}
|
||||
|
||||
newStream, nerr := s.createStream(s.ctx, s.opts)
|
||||
if nerr != nil {
|
||||
return nil, errors.New("re-subscribe failed")
|
||||
}
|
||||
|
||||
s.lock.Lock()
|
||||
s.stream = newStream
|
||||
s.lock.Unlock()
|
||||
|
||||
// try receiving again
|
||||
continue
|
||||
|
||||
case codes.Canceled:
|
||||
return nil, errors.New("stream canceled")
|
||||
|
||||
default:
|
||||
return nil, errors.New("subscription recv error")
|
||||
}
|
||||
}
|
||||
|
||||
event := resp.GetEventMessage()
|
||||
data := any(event.GetData())
|
||||
if len(event.GetData()) > 0 {
|
||||
mediaType, _, err := mime.ParseMediaType(event.GetDataContentType())
|
||||
if err == nil {
|
||||
var v interface{}
|
||||
switch mediaType {
|
||||
case "application/json":
|
||||
if err := json.Unmarshal(event.GetData(), &v); err == nil {
|
||||
data = v
|
||||
}
|
||||
case "text/plain":
|
||||
// Assume UTF-8 encoded string.
|
||||
data = string(event.GetData())
|
||||
default:
|
||||
if strings.HasPrefix(mediaType, "application/") &&
|
||||
strings.HasSuffix(mediaType, "+json") {
|
||||
if err := json.Unmarshal(event.GetData(), &v); err == nil {
|
||||
data = v
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
topicEvent := &common.TopicEvent{
|
||||
ID: event.GetId(),
|
||||
Source: event.GetSource(),
|
||||
Type: event.GetType(),
|
||||
SpecVersion: event.GetSpecVersion(),
|
||||
DataContentType: event.GetDataContentType(),
|
||||
Data: data,
|
||||
RawData: event.GetData(),
|
||||
Topic: event.GetTopic(),
|
||||
PubsubName: event.GetPubsubName(),
|
||||
}
|
||||
topicEvent := &common.TopicEvent{
|
||||
ID: event.GetId(),
|
||||
Source: event.GetSource(),
|
||||
Type: event.GetType(),
|
||||
SpecVersion: event.GetSpecVersion(),
|
||||
DataContentType: event.GetDataContentType(),
|
||||
Data: data,
|
||||
RawData: event.GetData(),
|
||||
Topic: event.GetTopic(),
|
||||
PubsubName: event.GetPubsubName(),
|
||||
}
|
||||
|
||||
return &SubscriptionMessage{
|
||||
sub: s,
|
||||
TopicEvent: topicEvent,
|
||||
}, nil
|
||||
return &SubscriptionMessage{
|
||||
sub: s,
|
||||
TopicEvent: topicEvent,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SubscriptionMessage) Success() error {
|
||||
|
@ -232,3 +287,13 @@ func (c *GRPCClient) subscribeInitialRequest(ctx context.Context, opts Subscript
|
|||
|
||||
return stream, nil
|
||||
}
|
||||
|
||||
func (s *Subscription) closeStreamOnly() error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
if s.stream != nil {
|
||||
return s.stream.CloseSend()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -116,14 +116,14 @@ func createNonBlockingClient(ctx context.Context, serverAddr string) (client Cli
|
|||
}
|
||||
|
||||
func TestGrpcWaitHappyCase(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
|
||||
err := testClient.Wait(ctx, waitTimeout)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestGrpcWaitUnresponsiveTcpServer(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
|
||||
server, err := createUnresponsiveTCPServer()
|
||||
require.NoError(t, err)
|
||||
|
@ -141,7 +141,7 @@ func TestGrpcWaitUnresponsiveTcpServer(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestGrpcWaitUnresponsiveUnixServer(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
|
||||
server, err := createUnresponsiveUnixServer()
|
||||
require.NoError(t, err)
|
||||
|
|
|
@ -15,7 +15,6 @@ limitations under the License.
|
|||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
|
@ -35,7 +34,7 @@ func TestMarshalInput(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestWorkflowBeta1(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
|
||||
// 1: StartWorkflow
|
||||
t.Run("start workflow - valid (without id)", func(t *testing.T) {
|
||||
|
|
|
@ -88,6 +88,91 @@ resp, err = client.InvokeMethodWithContent(ctx, "app-id", "method-name", "post",
|
|||
|
||||
For a full guide on service invocation, visit [How-To: Invoke a service]({{< ref howto-invoke-discover-services.md >}}).
|
||||
|
||||
### Workflows
|
||||
|
||||
Workflows and their activities can be authored and managed using the Dapr Go SDK like so:
|
||||
|
||||
```go
|
||||
import (
|
||||
...
|
||||
"github.com/dapr/go-sdk/workflow"
|
||||
...
|
||||
)
|
||||
|
||||
func ExampleWorkflow(ctx *workflow.WorkflowContext) (any, error) {
|
||||
var output string
|
||||
input := "world"
|
||||
|
||||
if err := ctx.CallActivity(ExampleActivity, workflow.ActivityInput(input)).Await(&output); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Print output - "hello world"
|
||||
fmt.Println(output)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func ExampleActivity(ctx workflow.ActivityContext) (any, error) {
|
||||
var input int
|
||||
if err := ctx.GetInput(&input); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return fmt.Sprintf("hello %s", input), nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Create a workflow worker
|
||||
w, err := workflow.NewWorker()
|
||||
if err != nil {
|
||||
log.Fatalf("error creating worker: %v", err)
|
||||
}
|
||||
|
||||
// Register the workflow
|
||||
w.RegisterWorkflow(ExampleWorkflow)
|
||||
|
||||
// Register the activity
|
||||
w.RegisterActivity(ExampleActivity)
|
||||
|
||||
// Start workflow runner
|
||||
if err := w.Start(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Create a workflow client
|
||||
wfClient, err := workflow.NewClient()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Start a new workflow
|
||||
id, err := wfClient.ScheduleNewWorkflow(context.Background(), "ExampleWorkflow")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Wait for the workflow to complete
|
||||
metadata, err := wfClient.WaitForWorkflowCompletion(ctx, id)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Print workflow status post-completion
|
||||
fmt.Println(metadata.RuntimeStatus)
|
||||
|
||||
// Shutdown Worker
|
||||
w.Shutdown()
|
||||
}
|
||||
```
|
||||
|
||||
- For a more comprehensive guide on workflows visit these How-To guides:
|
||||
- [How-To: Author a workflow]({{< ref howto-author-workflow.md >}}).
|
||||
- [How-To: Manage a workflow]({{< ref howto-manage-workflow.md >}}).
|
||||
- Visit the Go SDK Examples to jump into complete examples:
|
||||
- [Workflow Example](https://github.com/dapr/go-sdk/tree/main/examples/workflow)
|
||||
- [Workflow - Parallelised](https://github.com/dapr/go-sdk/tree/main/examples/workflow-parallel)
|
||||
|
||||
### State Management
|
||||
|
||||
For simple use-cases, Dapr client provides easy to use `Save`, `Get`, `Delete` methods:
|
||||
|
@ -245,6 +330,49 @@ if res.Error != nil {
|
|||
|
||||
For a full guide on pub/sub, visit [How-To: Publish & subscribe]({{< ref howto-publish-subscribe.md >}}).
|
||||
|
||||
### Workflow
|
||||
|
||||
You can create [workflows]({{< ref workflow-overview.md >}}) using the Go SDK. For example, start with a simple workflow activity:
|
||||
|
||||
```go
|
||||
func TestActivity(ctx workflow.ActivityContext) (any, error) {
|
||||
var input int
|
||||
if err := ctx.GetInput(&input); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Do something here
|
||||
return "result", nil
|
||||
}
|
||||
```
|
||||
|
||||
Write a simple workflow function:
|
||||
|
||||
```go
|
||||
func TestWorkflow(ctx *workflow.WorkflowContext) (any, error) {
|
||||
var input int
|
||||
if err := ctx.GetInput(&input); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var output string
|
||||
if err := ctx.CallActivity(TestActivity, workflow.ActivityInput(input)).Await(&output); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := ctx.WaitForExternalEvent("testEvent", time.Second*60).Await(&output); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := ctx.CreateTimer(time.Second).Await(nil); err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
return output, nil
|
||||
}
|
||||
```
|
||||
|
||||
Then compose your application that will use the workflow you've created. [Refer to the How-To: Author workflows guide]({{< ref howto-author-workflow.md >}}) for a full walk-through.
|
||||
|
||||
Try out the [Go SDK workflow example.](https://github.com/dapr/go-sdk/blob/main/examples/workflow)
|
||||
|
||||
### Output Bindings
|
||||
|
||||
|
||||
|
|
|
@ -83,6 +83,35 @@ if err != nil {
|
|||
}
|
||||
```
|
||||
|
||||
You can also create a custom type that implements the `TopicEventSubscriber` interface to handle your events:
|
||||
|
||||
```go
|
||||
type EventHandler struct {
|
||||
// any data or references that your event handler needs.
|
||||
}
|
||||
|
||||
func (h *EventHandler) Handle(ctx context.Context, e *common.TopicEvent) (retry bool, err error) {
|
||||
log.Printf("event - PubsubName:%s, Topic:%s, ID:%s, Data: %v", e.PubsubName, e.Topic, e.ID, e.Data)
|
||||
// do something with the event
|
||||
return true, nil
|
||||
}
|
||||
```
|
||||
|
||||
The `EventHandler` can then be added using the `AddTopicEventSubscriber` method:
|
||||
|
||||
```go
|
||||
sub := &common.Subscription{
|
||||
PubsubName: "messages",
|
||||
Topic: "topic1",
|
||||
}
|
||||
eventHandler := &EventHandler{
|
||||
// initialize any fields
|
||||
}
|
||||
if err := s.AddTopicEventSubscriber(sub, eventHandler); err != nil {
|
||||
log.Fatalf("error adding topic subscription: %v", err)
|
||||
}
|
||||
```
|
||||
|
||||
### Service Invocation Handler
|
||||
To handle service invocations you will need to add at least one service invocation handler before starting the service:
|
||||
|
||||
|
|
|
@ -78,6 +78,35 @@ if err != nil {
|
|||
}
|
||||
```
|
||||
|
||||
You can also create a custom type that implements the `TopicEventSubscriber` interface to handle your events:
|
||||
|
||||
```go
|
||||
type EventHandler struct {
|
||||
// any data or references that your event handler needs.
|
||||
}
|
||||
|
||||
func (h *EventHandler) Handle(ctx context.Context, e *common.TopicEvent) (retry bool, err error) {
|
||||
log.Printf("event - PubsubName:%s, Topic:%s, ID:%s, Data: %v", e.PubsubName, e.Topic, e.ID, e.Data)
|
||||
// do something with the event
|
||||
return true, nil
|
||||
}
|
||||
```
|
||||
|
||||
The `EventHandler` can then be added using the `AddTopicEventSubscriber` method:
|
||||
|
||||
```go
|
||||
sub := &common.Subscription{
|
||||
PubsubName: "messages",
|
||||
Topic: "topic1",
|
||||
}
|
||||
eventHandler := &EventHandler{
|
||||
// initialize any fields
|
||||
}
|
||||
if err := s.AddTopicEventSubscriber(sub, eventHandler); err != nil {
|
||||
log.Fatalf("error adding topic subscription: %v", err)
|
||||
}
|
||||
```
|
||||
|
||||
### Service Invocation Handler
|
||||
To handle service invocations you will need to add at least one service invocation handler before starting the service:
|
||||
|
||||
|
|
|
@ -17,8 +17,8 @@ expected_stdout_lines:
|
|||
- '== APP == get post request = laurence'
|
||||
- '== APP == get req = hello'
|
||||
- '== APP == get req = hello'
|
||||
- '== APP == receive reminder = testReminderName state = "hello" duetime = 5s period = 5s'
|
||||
- '== APP == receive reminder = testReminderName state = "hello" duetime = 5s period = 5s'
|
||||
- '== APP == receive reminder = testReminderName state = "hello"'
|
||||
- '== APP == receive reminder = testReminderName state = "hello"'
|
||||
background: true
|
||||
sleep: 30
|
||||
timeout_seconds: 60
|
||||
|
@ -99,6 +99,6 @@ dapr stop --app-id actor-serving
|
|||
== APP == get post request = laurence
|
||||
== APP == get req = hello
|
||||
== APP == get req = hello
|
||||
== APP == receive reminder = testReminderName state = "hello" duetime = 5s period = 5s
|
||||
== APP == receive reminder = testReminderName state = "hello" duetime = 5s period = 5s
|
||||
== APP == receive reminder = testReminderName state = "hello"
|
||||
== APP == receive reminder = testReminderName state = "hello"
|
||||
```
|
||||
|
|
|
@ -124,7 +124,7 @@ func (t *TestActor) IncrementAndGet(ctx context.Context, stateKey string) (*api.
|
|||
}
|
||||
|
||||
func (t *TestActor) ReminderCall(reminderName string, state []byte, dueTime string, period string) {
|
||||
fmt.Println("receive reminder = ", reminderName, " state = ", string(state), "duetime = ", dueTime, "period = ", period)
|
||||
fmt.Println("receive reminder = ", reminderName, " state = ", string(state))
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
# Dapr Conversation Example with go-sdk
|
||||
|
||||
## Step
|
||||
|
||||
### Prepare
|
||||
|
||||
- Dapr installed
|
||||
|
||||
### Run Conversation Example
|
||||
|
||||
<!-- STEP
|
||||
name: Run Conversation
|
||||
output_match_mode: substring
|
||||
expected_stdout_lines:
|
||||
- '== APP == conversation output: hello world'
|
||||
|
||||
background: true
|
||||
sleep: 60
|
||||
timeout_seconds: 60
|
||||
-->
|
||||
|
||||
```bash
|
||||
dapr run --app-id conversation \
|
||||
--dapr-grpc-port 50001 \
|
||||
--log-level debug \
|
||||
--resources-path ./config \
|
||||
-- go run ./main.go
|
||||
```
|
||||
|
||||
<!-- END_STEP -->
|
||||
|
||||
## Result
|
||||
|
||||
```
|
||||
- '== APP == conversation output: hello world'
|
||||
```
|
|
@ -0,0 +1,7 @@
|
|||
apiVersion: dapr.io/v1alpha1
|
||||
kind: Component
|
||||
metadata:
|
||||
name: echo
|
||||
spec:
|
||||
type: conversation.echo
|
||||
version: v1
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
Copyright 2024 The Dapr Authors
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
dapr "github.com/dapr/go-sdk/client"
|
||||
)
|
||||
|
||||
func main() {
|
||||
client, err := dapr.NewClient()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
input := dapr.ConversationInput{
|
||||
Content: "hello world",
|
||||
// Role: nil, // Optional
|
||||
// ScrubPII: nil, // Optional
|
||||
}
|
||||
|
||||
fmt.Printf("conversation input: %s\n", input.Content)
|
||||
|
||||
var conversationComponent = "echo"
|
||||
|
||||
request := dapr.NewConversationRequest(conversationComponent, []dapr.ConversationInput{input})
|
||||
|
||||
resp, err := client.ConverseAlpha1(context.Background(), request)
|
||||
if err != nil {
|
||||
log.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("conversation output: %s\n", resp.Outputs[0].Result)
|
||||
}
|
|
@ -15,11 +15,11 @@ expected_stdout_lines:
|
|||
- 'Scheduler stream connected'
|
||||
- 'schedulejob - success'
|
||||
- 'job 0 received'
|
||||
- 'extracted payload: {db-backup {my-prod-db /backup-dir}}'
|
||||
- 'payload: {db-backup {my-prod-db /backup-dir}}'
|
||||
- 'job 1 received'
|
||||
- 'extracted payload: {db-backup {my-prod-db /backup-dir}}'
|
||||
- 'payload: {db-backup {my-prod-db /backup-dir}}'
|
||||
- 'job 2 received'
|
||||
- 'extracted payload: {db-backup {my-prod-db /backup-dir}}'
|
||||
- 'payload: {db-backup {my-prod-db /backup-dir}}'
|
||||
- 'getjob - resp: &{prod-db-backup @every 1s 10 value:"{\"task\":\"db-backup\",\"metadata\":{\"db_name\":\"my-prod-db\",\"backup_location\":\"/backup-dir\"}}"}'
|
||||
- 'deletejob - success'
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ package main
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
|
@ -96,19 +95,11 @@ func main() {
|
|||
var jobCount = 0
|
||||
|
||||
func prodDBBackupHandler(ctx context.Context, job *common.JobEvent) error {
|
||||
var jobData common.Job
|
||||
if err := json.Unmarshal(job.Data, &jobData); err != nil {
|
||||
return fmt.Errorf("failed to unmarshal job: %v", err)
|
||||
}
|
||||
decodedPayload, err := base64.StdEncoding.DecodeString(jobData.Value)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to decode job payload: %v", err)
|
||||
}
|
||||
var jobPayload api.DBBackup
|
||||
if err := json.Unmarshal(decodedPayload, &jobPayload); err != nil {
|
||||
if err := json.Unmarshal(job.Data, &jobPayload); err != nil {
|
||||
return fmt.Errorf("failed to unmarshal payload: %v", err)
|
||||
}
|
||||
fmt.Printf("job %d received:\n type: %v \n typeurl: %v\n value: %v\n extracted payload: %v\n", jobCount, job.JobType, jobData.TypeURL, jobData.Value, jobPayload)
|
||||
fmt.Printf("job %d received:\n type: %v \n payload: %v\n", jobCount, job.JobType, jobPayload)
|
||||
jobCount++
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module github.com/dapr/go-sdk/examples
|
||||
|
||||
go 1.22.5
|
||||
go 1.24.2
|
||||
|
||||
replace github.com/dapr/go-sdk => ../
|
||||
|
||||
|
@ -9,31 +9,32 @@ require (
|
|||
github.com/dapr/go-sdk v0.0.0-00010101000000-000000000000
|
||||
github.com/go-redis/redis/v8 v8.11.5
|
||||
github.com/google/uuid v1.6.0
|
||||
google.golang.org/grpc v1.65.0
|
||||
google.golang.org/grpc v1.72.0
|
||||
google.golang.org/grpc/examples v0.0.0-20240516203910-e22436abb809
|
||||
google.golang.org/protobuf v1.34.2
|
||||
google.golang.org/protobuf v1.36.6
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/dapr/dapr v1.14.0-rc.5 // indirect
|
||||
github.com/dapr/dapr v1.15.5 // indirect
|
||||
github.com/dapr/durabletask-go v0.6.5 // indirect
|
||||
github.com/dapr/kit v0.15.2 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/go-chi/chi/v5 v5.1.0 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/marusama/semaphore/v2 v2.5.0 // indirect
|
||||
github.com/microsoft/durabletask-go v0.5.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
|
||||
go.opentelemetry.io/otel v1.27.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.27.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.27.0 // indirect
|
||||
golang.org/x/net v0.26.0 // indirect
|
||||
golang.org/x/sys v0.21.0 // indirect
|
||||
golang.org/x/text v0.16.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240624140628-dc46fd24d27d // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/otel v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.35.0 // indirect
|
||||
golang.org/x/net v0.40.0 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
golang.org/x/text v0.25.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250505200425-f936aa4a68b2 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e // indirect
|
||||
)
|
||||
|
|
|
@ -6,16 +6,20 @@ github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK3
|
|||
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/dapr/dapr v1.14.0-rc.5 h1:oTZPcT5fwda6bCMxrfenem6tOyeqW1nastxTwWInBCY=
|
||||
github.com/dapr/dapr v1.14.0-rc.5/go.mod h1:IQWNthXF/I+qqlW4I0T+F4hCu74eKon4vjhpNvoBl8A=
|
||||
github.com/dapr/dapr v1.15.5 h1:bkCmcQQfaQ5C49P3l0elCzDr4/Oja5kitM3jStY+2RY=
|
||||
github.com/dapr/dapr v1.15.5/go.mod h1:wwopO8AD9CZOgVj4bsdXNmeQujMo0v3MLAqeaX+gb00=
|
||||
github.com/dapr/durabletask-go v0.6.5 h1:aWcxMfYudojpgRjJRdUr7yyZ7rGcvLtWXUuA4cGHBR0=
|
||||
github.com/dapr/durabletask-go v0.6.5/go.mod h1:nTZ5fCbJLnZbVdi6Z2YxdDF1OgQZL3LroogGuetrwuA=
|
||||
github.com/dapr/kit v0.15.2 h1:5H9IhKScU/SpE2Hxvr5vUlmYN1e2MJN15RoT8/KSziU=
|
||||
github.com/dapr/kit v0.15.2/go.mod h1:HwFsBKEbcyLanWlDZE7u/jnaDCD/tU+n3pkFNUctQNw=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
|
||||
github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
|
@ -29,58 +33,63 @@ github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
|||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/marusama/semaphore/v2 v2.5.0 h1:o/1QJD9DBYOWRnDhPwDVAXQn6mQYD0gZaS1Tpx6DJGM=
|
||||
github.com/marusama/semaphore/v2 v2.5.0/go.mod h1:z9nMiNUekt/LTpTUQdpp+4sJeYqUGpwMHfW0Z8V8fnQ=
|
||||
github.com/microsoft/durabletask-go v0.5.0 h1:4DWBgg05wnkV/VwakaiPqZ4cARvATP74ZQJFcXVMC18=
|
||||
github.com/microsoft/durabletask-go v0.5.0/go.mod h1:goe2gmMgLptCijMDQ7JsekaR86KjPUG64V9JDXvKBhE=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
|
||||
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc=
|
||||
github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
|
||||
go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg=
|
||||
go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ=
|
||||
go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik=
|
||||
go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak=
|
||||
go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw=
|
||||
go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4=
|
||||
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY=
|
||||
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI=
|
||||
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
|
||||
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
|
||||
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240624140628-dc46fd24d27d h1:k3zyW3BYYR30e8v3x0bTDdE9vpYFjZHK+HcyqkrppWk=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240624140628-dc46fd24d27d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
|
||||
google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
|
||||
google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
|
||||
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
|
||||
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
|
||||
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
|
||||
go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
|
||||
go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
|
||||
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
|
||||
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM=
|
||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8=
|
||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250505200425-f936aa4a68b2 h1:IqsN8hx+lWLqlN+Sc3DoMy/watjofWiU8sRFgQ8fhKM=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250505200425-f936aa4a68b2/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||
google.golang.org/grpc v1.72.0 h1:S7UkcVa60b5AAQTaO6ZKamFp1zMZSU0fGDK2WZLbBnM=
|
||||
google.golang.org/grpc v1.72.0/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
|
||||
google.golang.org/grpc/examples v0.0.0-20240516203910-e22436abb809 h1:f96Rv5C5Y2CWlbKK6KhKDdyFgGOjPHPEMsdyaxE9k0c=
|
||||
google.golang.org/grpc/examples v0.0.0-20240516203910-e22436abb809/go.mod h1:uaPEAc5V00jjG3DPhGFLXGT290RUV3+aNQigs1W50/8=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
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=
|
||||
|
@ -89,5 +98,8 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD
|
|||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
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=
|
||||
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e h1:KqK5c/ghOm8xkHYhlodbp6i6+r+ChV2vuAuVRdFbLro=
|
||||
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
|
|
|
@ -16,7 +16,7 @@ output_match_mode: substring
|
|||
expected_stdout_lines:
|
||||
- "ContentType:text/plain, Verb:POST, QueryString:, hellow"
|
||||
background: true
|
||||
sleep: 15
|
||||
sleep: 30
|
||||
timeout_seconds: 60
|
||||
-->
|
||||
|
||||
|
@ -91,7 +91,7 @@ expected_stdout_lines:
|
|||
```bash
|
||||
dapr run --app-id custom-grpc-client \
|
||||
-d ./config \
|
||||
--dapr-http-max-request-size 41 \
|
||||
--max-body-size 41Mi \
|
||||
--log-level debug \
|
||||
go run ./custom-grpc-client/main.go
|
||||
```
|
||||
|
|
|
@ -95,7 +95,7 @@ func main() {
|
|||
|
||||
in := &dapr.InvokeBindingRequest{
|
||||
Name: "example-http-binding",
|
||||
Operation: "create",
|
||||
Operation: "get",
|
||||
}
|
||||
if err := client.InvokeOutputBinding(ctx, in); err != nil {
|
||||
panic(err)
|
||||
|
|
|
@ -7,6 +7,6 @@ spec:
|
|||
version: v1
|
||||
metadata:
|
||||
- name: url
|
||||
value: https://http2.pro/api/v1
|
||||
value: https://sandbox.api.service.nhs.uk/hello-world/hello/world
|
||||
- name: method
|
||||
value: GET
|
||||
|
|
|
@ -15,6 +15,7 @@ expected_stdout_lines:
|
|||
- '== APP == Worker initialized'
|
||||
- '== APP == TestWorkflow registered'
|
||||
- '== APP == TestActivity registered'
|
||||
- '== APP == FailActivity registered'
|
||||
- '== APP == runner started'
|
||||
- '== APP == workflow started with id: a7a4168d-3a1c-41da-8a4f-e7f6d9c718d9'
|
||||
- '== APP == workflow paused'
|
||||
|
@ -22,20 +23,14 @@ expected_stdout_lines:
|
|||
- '== APP == stage: 1'
|
||||
- '== APP == workflow event raised'
|
||||
- '== APP == stage: 2'
|
||||
- '== APP == fail activity executions: 3'
|
||||
- '== APP == workflow status: COMPLETED'
|
||||
- '== APP == workflow purged'
|
||||
- '== APP == stage: 2'
|
||||
- '== APP == workflow started with id: a7a4168d-3a1c-41da-8a4f-e7f6d9c718d9'
|
||||
- '== APP == workflow status: RUNNING'
|
||||
- '== APP == workflow terminated'
|
||||
- '== APP == workflow purged'
|
||||
- '== APP == workflow client test'
|
||||
- '== APP == [wfclient] started workflow with id: a7a4168d-3a1c-41da-8a4f-e7f6d9c718d9'
|
||||
- '== APP == [wfclient] workflow status: RUNNING'
|
||||
- '== APP == [wfclient] stage: 1'
|
||||
- '== APP == [wfclient] event raised'
|
||||
- '== APP == [wfclient] stage: 2'
|
||||
- '== APP == [wfclient] workflow terminated'
|
||||
- '== APP == [wfclient] workflow purged'
|
||||
- '== APP == workflow worker successfully shutdown'
|
||||
|
||||
background: true
|
||||
|
|
|
@ -16,19 +16,16 @@ package main
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/dapr/go-sdk/client"
|
||||
"github.com/dapr/go-sdk/workflow"
|
||||
)
|
||||
|
||||
var stage = 0
|
||||
|
||||
const (
|
||||
workflowComponent = "dapr"
|
||||
)
|
||||
var failActivityTries = 0
|
||||
|
||||
func main() {
|
||||
w, err := workflow.NewWorker()
|
||||
|
@ -48,76 +45,60 @@ func main() {
|
|||
}
|
||||
fmt.Println("TestActivity registered")
|
||||
|
||||
if err := w.RegisterActivity(FailActivity); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println("FailActivity registered")
|
||||
|
||||
// Start workflow runner
|
||||
if err := w.Start(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println("runner started")
|
||||
|
||||
daprClient, err := client.NewClient()
|
||||
wfClient, err := workflow.NewClient()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to intialise client: %v", err)
|
||||
}
|
||||
defer daprClient.Close()
|
||||
defer wfClient.Close()
|
||||
ctx := context.Background()
|
||||
|
||||
// Start workflow test
|
||||
respStart, err := daprClient.StartWorkflowBeta1(ctx, &client.StartWorkflowRequest{
|
||||
InstanceID: "a7a4168d-3a1c-41da-8a4f-e7f6d9c718d9",
|
||||
WorkflowComponent: workflowComponent,
|
||||
WorkflowName: "TestWorkflow",
|
||||
Options: nil,
|
||||
Input: 1,
|
||||
SendRawInput: false,
|
||||
})
|
||||
instanceID, err := wfClient.ScheduleNewWorkflow(ctx, "TestWorkflow", workflow.WithInstanceID("a7a4168d-3a1c-41da-8a4f-e7f6d9c718d9"), workflow.WithInput(1))
|
||||
if err != nil {
|
||||
log.Fatalf("failed to start workflow: %v", err)
|
||||
}
|
||||
fmt.Printf("workflow started with id: %v\n", respStart.InstanceID)
|
||||
fmt.Printf("workflow started with id: %v\n", instanceID)
|
||||
|
||||
// Pause workflow test
|
||||
err = daprClient.PauseWorkflowBeta1(ctx, &client.PauseWorkflowRequest{
|
||||
InstanceID: "a7a4168d-3a1c-41da-8a4f-e7f6d9c718d9",
|
||||
WorkflowComponent: workflowComponent,
|
||||
})
|
||||
|
||||
err = wfClient.SuspendWorkflow(ctx, instanceID, "")
|
||||
if err != nil {
|
||||
log.Fatalf("failed to pause workflow: %v", err)
|
||||
}
|
||||
|
||||
respGet, err := daprClient.GetWorkflowBeta1(ctx, &client.GetWorkflowRequest{
|
||||
InstanceID: "a7a4168d-3a1c-41da-8a4f-e7f6d9c718d9",
|
||||
WorkflowComponent: workflowComponent,
|
||||
})
|
||||
respFetch, err := wfClient.FetchWorkflowMetadata(ctx, instanceID, workflow.WithFetchPayloads(true))
|
||||
if err != nil {
|
||||
log.Fatalf("failed to get workflow: %v", err)
|
||||
log.Fatalf("failed to fetch workflow: %v", err)
|
||||
}
|
||||
|
||||
if respGet.RuntimeStatus != workflow.StatusSuspended.String() {
|
||||
log.Fatalf("workflow not paused: %v", respGet.RuntimeStatus)
|
||||
if respFetch.RuntimeStatus != workflow.StatusSuspended {
|
||||
log.Fatalf("workflow not paused: %v", respFetch.RuntimeStatus)
|
||||
}
|
||||
|
||||
fmt.Printf("workflow paused\n")
|
||||
|
||||
// Resume workflow test
|
||||
err = daprClient.ResumeWorkflowBeta1(ctx, &client.ResumeWorkflowRequest{
|
||||
InstanceID: "a7a4168d-3a1c-41da-8a4f-e7f6d9c718d9",
|
||||
WorkflowComponent: workflowComponent,
|
||||
})
|
||||
|
||||
err = wfClient.ResumeWorkflow(ctx, instanceID, "")
|
||||
if err != nil {
|
||||
log.Fatalf("failed to resume workflow: %v", err)
|
||||
}
|
||||
|
||||
respGet, err = daprClient.GetWorkflowBeta1(ctx, &client.GetWorkflowRequest{
|
||||
InstanceID: "a7a4168d-3a1c-41da-8a4f-e7f6d9c718d9",
|
||||
WorkflowComponent: workflowComponent,
|
||||
})
|
||||
respFetch, err = wfClient.FetchWorkflowMetadata(ctx, instanceID, workflow.WithFetchPayloads(true))
|
||||
if err != nil {
|
||||
log.Fatalf("failed to get workflow: %v", err)
|
||||
}
|
||||
|
||||
if respGet.RuntimeStatus != workflow.StatusRunning.String() {
|
||||
if respFetch.RuntimeStatus != workflow.StatusRunning {
|
||||
log.Fatalf("workflow not running")
|
||||
}
|
||||
|
||||
|
@ -127,14 +108,7 @@ func main() {
|
|||
|
||||
// Raise Event Test
|
||||
|
||||
err = daprClient.RaiseEventWorkflowBeta1(ctx, &client.RaiseEventWorkflowRequest{
|
||||
InstanceID: "a7a4168d-3a1c-41da-8a4f-e7f6d9c718d9",
|
||||
WorkflowComponent: workflowComponent,
|
||||
EventName: "testEvent",
|
||||
EventData: "testData",
|
||||
SendRawData: false,
|
||||
})
|
||||
|
||||
err = wfClient.RaiseEvent(ctx, instanceID, "testEvent", workflow.WithEventPayload("testData"))
|
||||
if err != nil {
|
||||
fmt.Printf("failed to raise event: %v", err)
|
||||
}
|
||||
|
@ -145,31 +119,31 @@ func main() {
|
|||
|
||||
fmt.Printf("stage: %d\n", stage)
|
||||
|
||||
respGet, err = daprClient.GetWorkflowBeta1(ctx, &client.GetWorkflowRequest{
|
||||
InstanceID: "a7a4168d-3a1c-41da-8a4f-e7f6d9c718d9",
|
||||
WorkflowComponent: workflowComponent,
|
||||
})
|
||||
waitCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||
_, err = wfClient.WaitForWorkflowCompletion(waitCtx, instanceID)
|
||||
cancel()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to wait for workflow: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("fail activity executions: %d\n", failActivityTries)
|
||||
|
||||
respFetch, err = wfClient.FetchWorkflowMetadata(ctx, instanceID, workflow.WithFetchPayloads(true))
|
||||
if err != nil {
|
||||
log.Fatalf("failed to get workflow: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("workflow status: %v\n", respGet.RuntimeStatus)
|
||||
fmt.Printf("workflow status: %v\n", respFetch.RuntimeStatus)
|
||||
|
||||
// Purge workflow test
|
||||
err = daprClient.PurgeWorkflowBeta1(ctx, &client.PurgeWorkflowRequest{
|
||||
InstanceID: "a7a4168d-3a1c-41da-8a4f-e7f6d9c718d9",
|
||||
WorkflowComponent: workflowComponent,
|
||||
})
|
||||
err = wfClient.PurgeWorkflow(ctx, instanceID)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to purge workflow: %v", err)
|
||||
}
|
||||
|
||||
respGet, err = daprClient.GetWorkflowBeta1(ctx, &client.GetWorkflowRequest{
|
||||
InstanceID: "a7a4168d-3a1c-41da-8a4f-e7f6d9c718d9",
|
||||
WorkflowComponent: workflowComponent,
|
||||
})
|
||||
if err != nil && respGet != nil {
|
||||
log.Fatal("failed to purge workflow")
|
||||
respFetch, err = wfClient.FetchWorkflowMetadata(ctx, instanceID, workflow.WithFetchPayloads(true))
|
||||
if err == nil || respFetch != nil {
|
||||
log.Fatalf("failed to purge workflow: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println("workflow purged")
|
||||
|
@ -177,120 +151,30 @@ func main() {
|
|||
fmt.Printf("stage: %d\n", stage)
|
||||
|
||||
// Terminate workflow test
|
||||
respStart, err = daprClient.StartWorkflowBeta1(ctx, &client.StartWorkflowRequest{
|
||||
InstanceID: "a7a4168d-3a1c-41da-8a4f-e7f6d9c718d9",
|
||||
WorkflowComponent: workflowComponent,
|
||||
WorkflowName: "TestWorkflow",
|
||||
Options: nil,
|
||||
Input: 1,
|
||||
SendRawInput: false,
|
||||
})
|
||||
id, err := wfClient.ScheduleNewWorkflow(ctx, "TestWorkflow", workflow.WithInstanceID("a7a4168d-3a1c-41da-8a4f-e7f6d9c718d9"), workflow.WithInput(1))
|
||||
if err != nil {
|
||||
log.Fatalf("failed to start workflow: %v", err)
|
||||
}
|
||||
fmt.Printf("workflow started with id: %v\n", instanceID)
|
||||
|
||||
fmt.Printf("workflow started with id: %s\n", respStart.InstanceID)
|
||||
|
||||
err = daprClient.TerminateWorkflowBeta1(ctx, &client.TerminateWorkflowRequest{
|
||||
InstanceID: "a7a4168d-3a1c-41da-8a4f-e7f6d9c718d9",
|
||||
WorkflowComponent: workflowComponent,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("failed to terminate workflow: %v", err)
|
||||
}
|
||||
|
||||
respGet, err = daprClient.GetWorkflowBeta1(ctx, &client.GetWorkflowRequest{
|
||||
InstanceID: "a7a4168d-3a1c-41da-8a4f-e7f6d9c718d9",
|
||||
WorkflowComponent: workflowComponent,
|
||||
})
|
||||
metadata, err := wfClient.WaitForWorkflowStart(ctx, id)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to get workflow: %v", err)
|
||||
}
|
||||
if respGet.RuntimeStatus != workflow.StatusTerminated.String() {
|
||||
log.Fatal("failed to terminate workflow")
|
||||
}
|
||||
fmt.Printf("workflow status: %s\n", metadata.RuntimeStatus.String())
|
||||
|
||||
err = wfClient.TerminateWorkflow(ctx, id)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to terminate workflow: %v", err)
|
||||
}
|
||||
fmt.Println("workflow terminated")
|
||||
|
||||
err = daprClient.PurgeWorkflowBeta1(ctx, &client.PurgeWorkflowRequest{
|
||||
InstanceID: "a7a4168d-3a1c-41da-8a4f-e7f6d9c718d9",
|
||||
WorkflowComponent: workflowComponent,
|
||||
})
|
||||
|
||||
respGet, err = daprClient.GetWorkflowBeta1(ctx, &client.GetWorkflowRequest{
|
||||
InstanceID: "a7a4168d-3a1c-41da-8a4f-e7f6d9c718d9",
|
||||
WorkflowComponent: workflowComponent,
|
||||
})
|
||||
if err == nil || respGet != nil {
|
||||
err = wfClient.PurgeWorkflow(ctx, id)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to purge workflow: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println("workflow purged")
|
||||
|
||||
// WFClient
|
||||
// TODO: Expand client validation
|
||||
|
||||
stage = 0
|
||||
fmt.Println("workflow client test")
|
||||
|
||||
wfClient, err := workflow.NewClient()
|
||||
if err != nil {
|
||||
log.Fatalf("[wfclient] faield to initialize: %v", err)
|
||||
}
|
||||
|
||||
id, err := wfClient.ScheduleNewWorkflow(ctx, "TestWorkflow", workflow.WithInstanceID("a7a4168d-3a1c-41da-8a4f-e7f6d9c718d9"), workflow.WithInput(1))
|
||||
if err != nil {
|
||||
log.Fatalf("[wfclient] failed to start workflow: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("[wfclient] started workflow with id: %s\n", id)
|
||||
|
||||
metadata, err := wfClient.FetchWorkflowMetadata(ctx, id)
|
||||
if err != nil {
|
||||
log.Fatalf("[wfclient] failed to get worfklow: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("[wfclient] workflow status: %v\n", metadata.RuntimeStatus.String())
|
||||
|
||||
if stage != 1 {
|
||||
log.Fatalf("Workflow assertion failed while validating the wfclient. Stage 1 expected, current: %d", stage)
|
||||
}
|
||||
|
||||
fmt.Printf("[wfclient] stage: %d\n", stage)
|
||||
|
||||
// TODO: WaitForWorkflowStart
|
||||
// TODO: WaitForWorkflowCompletion
|
||||
|
||||
// raise event
|
||||
|
||||
if err := wfClient.RaiseEvent(ctx, id, "testEvent", workflow.WithEventPayload("testData")); err != nil {
|
||||
log.Fatalf("[wfclient] failed to raise event: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println("[wfclient] event raised")
|
||||
|
||||
// Sleep to allow the workflow to advance
|
||||
time.Sleep(time.Second)
|
||||
|
||||
if stage != 2 {
|
||||
log.Fatalf("Workflow assertion failed while validating the wfclient. Stage 2 expected, current: %d", stage)
|
||||
}
|
||||
|
||||
fmt.Printf("[wfclient] stage: %d\n", stage)
|
||||
|
||||
// stop workflow
|
||||
if err := wfClient.TerminateWorkflow(ctx, id); err != nil {
|
||||
log.Fatalf("[wfclient] failed to terminate workflow: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println("[wfclient] workflow terminated")
|
||||
|
||||
if err := wfClient.PurgeWorkflow(ctx, id); err != nil {
|
||||
log.Fatalf("[wfclient] failed to purge workflow: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println("[wfclient] workflow purged")
|
||||
|
||||
// stop workflow runtime
|
||||
if err := w.Shutdown(); err != nil {
|
||||
log.Fatalf("failed to shutdown runtime: %v", err)
|
||||
|
@ -318,6 +202,15 @@ func TestWorkflow(ctx *workflow.WorkflowContext) (any, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if err := ctx.CallActivity(FailActivity, workflow.ActivityRetryPolicy(workflow.RetryPolicy{
|
||||
MaxAttempts: 3,
|
||||
InitialRetryInterval: 100 * time.Millisecond,
|
||||
BackoffCoefficient: 2,
|
||||
MaxRetryInterval: 1 * time.Second,
|
||||
})).Await(nil); err == nil {
|
||||
return nil, fmt.Errorf("unexpected no error executing fail activity")
|
||||
}
|
||||
|
||||
return output, nil
|
||||
}
|
||||
|
||||
|
@ -331,3 +224,8 @@ func TestActivity(ctx workflow.ActivityContext) (any, error) {
|
|||
|
||||
return fmt.Sprintf("Stage: %d", stage), nil
|
||||
}
|
||||
|
||||
func FailActivity(ctx workflow.ActivityContext) (any, error) {
|
||||
failActivityTries += 1
|
||||
return nil, errors.New("dummy activity error")
|
||||
}
|
||||
|
|
34
go.mod
34
go.mod
|
@ -1,34 +1,34 @@
|
|||
module github.com/dapr/go-sdk
|
||||
|
||||
go 1.22.5
|
||||
go 1.24.2
|
||||
|
||||
require (
|
||||
github.com/dapr/dapr v1.14.0-rc.5
|
||||
github.com/dapr/dapr v1.15.5
|
||||
github.com/dapr/durabletask-go v0.6.5
|
||||
github.com/go-chi/chi/v5 v5.1.0
|
||||
github.com/golang/mock v1.6.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/microsoft/durabletask-go v0.5.0
|
||||
github.com/stretchr/testify v1.9.0
|
||||
google.golang.org/grpc v1.65.0
|
||||
google.golang.org/protobuf v1.34.2
|
||||
github.com/stretchr/testify v1.10.0
|
||||
google.golang.org/grpc v1.72.0
|
||||
google.golang.org/protobuf v1.36.6
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
github.com/dapr/kit v0.15.2 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/marusama/semaphore/v2 v2.5.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
go.opentelemetry.io/otel v1.27.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.27.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.27.0 // indirect
|
||||
golang.org/x/net v0.26.0 // indirect
|
||||
golang.org/x/sys v0.21.0 // indirect
|
||||
golang.org/x/text v0.16.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240624140628-dc46fd24d27d // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/otel v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.35.0 // indirect
|
||||
golang.org/x/net v0.40.0 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
golang.org/x/text v0.25.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250505200425-f936aa4a68b2 // indirect
|
||||
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e // indirect
|
||||
)
|
||||
|
|
86
go.sum
86
go.sum
|
@ -1,8 +1,13 @@
|
|||
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/dapr/dapr v1.14.0-rc.5 h1:oTZPcT5fwda6bCMxrfenem6tOyeqW1nastxTwWInBCY=
|
||||
github.com/dapr/dapr v1.14.0-rc.5/go.mod h1:IQWNthXF/I+qqlW4I0T+F4hCu74eKon4vjhpNvoBl8A=
|
||||
github.com/dapr/dapr v1.15.5 h1:bkCmcQQfaQ5C49P3l0elCzDr4/Oja5kitM3jStY+2RY=
|
||||
github.com/dapr/dapr v1.15.5/go.mod h1:wwopO8AD9CZOgVj4bsdXNmeQujMo0v3MLAqeaX+gb00=
|
||||
github.com/dapr/durabletask-go v0.6.5 h1:aWcxMfYudojpgRjJRdUr7yyZ7rGcvLtWXUuA4cGHBR0=
|
||||
github.com/dapr/durabletask-go v0.6.5/go.mod h1:nTZ5fCbJLnZbVdi6Z2YxdDF1OgQZL3LroogGuetrwuA=
|
||||
github.com/dapr/kit v0.15.2 h1:5H9IhKScU/SpE2Hxvr5vUlmYN1e2MJN15RoT8/KSziU=
|
||||
github.com/dapr/kit v0.15.2/go.mod h1:HwFsBKEbcyLanWlDZE7u/jnaDCD/tU+n3pkFNUctQNw=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
|
||||
|
@ -16,41 +21,48 @@ github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
|||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
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/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/marusama/semaphore/v2 v2.5.0 h1:o/1QJD9DBYOWRnDhPwDVAXQn6mQYD0gZaS1Tpx6DJGM=
|
||||
github.com/marusama/semaphore/v2 v2.5.0/go.mod h1:z9nMiNUekt/LTpTUQdpp+4sJeYqUGpwMHfW0Z8V8fnQ=
|
||||
github.com/microsoft/durabletask-go v0.5.0 h1:4DWBgg05wnkV/VwakaiPqZ4cARvATP74ZQJFcXVMC18=
|
||||
github.com/microsoft/durabletask-go v0.5.0/go.mod h1:goe2gmMgLptCijMDQ7JsekaR86KjPUG64V9JDXvKBhE=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg=
|
||||
go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ=
|
||||
go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik=
|
||||
go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak=
|
||||
go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw=
|
||||
go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
|
||||
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
|
||||
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
|
||||
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
|
||||
go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
|
||||
go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
|
||||
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
|
||||
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY=
|
||||
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI=
|
||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM=
|
||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
|
||||
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
|
||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
@ -58,27 +70,31 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240624140628-dc46fd24d27d h1:k3zyW3BYYR30e8v3x0bTDdE9vpYFjZHK+HcyqkrppWk=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240624140628-dc46fd24d27d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
|
||||
google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
|
||||
google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250505200425-f936aa4a68b2 h1:IqsN8hx+lWLqlN+Sc3DoMy/watjofWiU8sRFgQ8fhKM=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250505200425-f936aa4a68b2/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||
google.golang.org/grpc v1.72.0 h1:S7UkcVa60b5AAQTaO6ZKamFp1zMZSU0fGDK2WZLbBnM=
|
||||
google.golang.org/grpc v1.72.0/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
|
||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
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=
|
||||
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e h1:KqK5c/ghOm8xkHYhlodbp6i6+r+ChV2vuAuVRdFbLro=
|
||||
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
|
|
|
@ -27,18 +27,23 @@ const (
|
|||
)
|
||||
|
||||
// Service represents Dapr callback service.
|
||||
//
|
||||
//nolint:interfacebloat
|
||||
type Service interface {
|
||||
// AddHealthCheckHandler sets a health check handler, name: http (router) and grpc (invalid).
|
||||
AddHealthCheckHandler(name string, fn HealthCheckHandler) error
|
||||
// AddServiceInvocationHandler appends provided service invocation handler with its name to the service.
|
||||
AddServiceInvocationHandler(name string, fn ServiceInvocationHandler) error
|
||||
// AddTopicEventHandler appends provided event handler with its topic and optional metadata to the service.
|
||||
// Note, retries are only considered when there is an error. Lack of error is considered as a success
|
||||
// Note, retries are only considered when there is an error. Lack of error is considered as a success.
|
||||
AddTopicEventHandler(sub *Subscription, fn TopicEventHandler) error
|
||||
// AddTopicEventSubscriber appends the provided subscriber with its topic and optional metadata to the service.
|
||||
// Note, retries are only considered when there is an error. Lack of error is considered as a success.
|
||||
AddTopicEventSubscriber(sub *Subscription, subscriber TopicEventSubscriber) error
|
||||
// AddBindingInvocationHandler appends provided binding invocation handler with its name to the service.
|
||||
AddBindingInvocationHandler(name string, fn BindingInvocationHandler) error
|
||||
// RegisterActorImplFactory Register a new actor to actor runtime of go sdk
|
||||
// Deprecated: use RegisterActorImplFactoryContext instead
|
||||
// Deprecated: use RegisterActorImplFactoryContext instead.
|
||||
RegisterActorImplFactory(f actor.Factory, opts ...config.Option)
|
||||
// RegisterActorImplFactoryContext Register a new actor to actor runtime of go sdk
|
||||
RegisterActorImplFactoryContext(f actor.FactoryContext, opts ...config.Option)
|
||||
|
@ -49,7 +54,7 @@ type Service interface {
|
|||
Start() error
|
||||
// Stop stops the previously started service.
|
||||
Stop() error
|
||||
// Gracefully stops the previous started service
|
||||
// Gracefully stops the previous started service.
|
||||
GracefulStop() error
|
||||
}
|
||||
|
||||
|
@ -60,3 +65,13 @@ type (
|
|||
JobEventHandler func(ctx context.Context, in *JobEvent) error
|
||||
HealthCheckHandler func(context.Context) error
|
||||
)
|
||||
|
||||
type TopicEventSubscriber interface {
|
||||
Handle(ctx context.Context, e *TopicEvent) (retry bool, err error)
|
||||
}
|
||||
|
||||
// Handle converts TopicEventHandler into an adapter that implements
|
||||
// TopicEventSubscriber.
|
||||
func (h TopicEventHandler) Handle(ctx context.Context, e *TopicEvent) (retry bool, err error) {
|
||||
return h(ctx, e)
|
||||
}
|
||||
|
|
|
@ -47,6 +47,10 @@ type TopicEvent struct {
|
|||
PubsubName string `json:"pubsubname"`
|
||||
// Metadata is the custom metadata attached to the event.
|
||||
Metadata map[string]string `json:"metadata,omitempty"`
|
||||
// TraceID is the tracing header identifier for the incoming event
|
||||
TraceID string `json:"traceid"`
|
||||
// TraceParent is name of the parent trace identifier for the incoming event
|
||||
TraceParent string `json:"traceparent"`
|
||||
}
|
||||
|
||||
func (e *TopicEvent) Struct(target interface{}) error {
|
||||
|
@ -103,6 +107,8 @@ type Subscription struct {
|
|||
Priority int `json:"priority"`
|
||||
// DisableTopicValidation allows to receive events from publisher topics that differ from the subscribed topic.
|
||||
DisableTopicValidation bool `json:"disableTopicValidation"`
|
||||
// DeadLetterTopic is the name of the deadletter topic.
|
||||
DeadLetterTopic string `json:"deadLetterTopic"`
|
||||
}
|
||||
|
||||
type SubscriptionResponseStatus string
|
||||
|
|
|
@ -27,10 +27,10 @@ import (
|
|||
// AddBindingInvocationHandler appends provided binding invocation handler with its name to the service.
|
||||
func (s *Server) AddBindingInvocationHandler(name string, fn common.BindingInvocationHandler) error {
|
||||
if name == "" {
|
||||
return fmt.Errorf("binding name required")
|
||||
return errors.New("binding name required")
|
||||
}
|
||||
if fn == nil {
|
||||
return fmt.Errorf("binding handler required")
|
||||
return errors.New("binding handler required")
|
||||
}
|
||||
s.bindingHandlers[name] = fn
|
||||
return nil
|
||||
|
|
|
@ -40,7 +40,7 @@ func TestListInputBindings(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
err = server.AddBindingInvocationHandler("test2", testBindingHandler)
|
||||
require.NoError(t, err)
|
||||
resp, err := server.ListInputBindings(context.Background(), &emptypb.Empty{})
|
||||
resp, err := server.ListInputBindings(t.Context(), &emptypb.Empty{})
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
assert.Lenf(t, resp.GetBindings(), 2, "expected 2 handlers")
|
||||
|
@ -57,7 +57,7 @@ func TestBindingForErrors(t *testing.T) {
|
|||
|
||||
// go test -timeout 30s ./service/grpc -count 1 -run ^TestBinding$
|
||||
func TestBinding(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
methodName := "test"
|
||||
|
||||
server := getTestServer()
|
||||
|
|
|
@ -15,7 +15,7 @@ package grpc
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"errors"
|
||||
|
||||
pb "github.com/dapr/dapr/pkg/proto/runtime/v1"
|
||||
"github.com/dapr/go-sdk/service/common"
|
||||
|
@ -26,7 +26,7 @@ import (
|
|||
// AddHealthCheckHandler appends provided app health check handler.
|
||||
func (s *Server) AddHealthCheckHandler(_ string, fn common.HealthCheckHandler) error {
|
||||
if fn == nil {
|
||||
return fmt.Errorf("health check handler required")
|
||||
return errors.New("health check handler required")
|
||||
}
|
||||
|
||||
s.healthCheckHandler = fn
|
||||
|
@ -44,5 +44,5 @@ func (s *Server) HealthCheck(ctx context.Context, _ *emptypb.Empty) (*pb.HealthC
|
|||
return &pb.HealthCheckResponse{}, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("health check handler not implemented")
|
||||
return nil, errors.New("health check handler not implemented")
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ func TestHealthCheckHandlerForErrors(t *testing.T) {
|
|||
|
||||
// go test -timeout 30s ./service/grpc -count 1 -run ^TestHealthCheck$
|
||||
func TestHealthCheck(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
|
||||
server := getTestServer()
|
||||
startTestServer(server)
|
||||
|
|
|
@ -28,7 +28,7 @@ import (
|
|||
// AddServiceInvocationHandler appends provided service invocation handler with its method to the service.
|
||||
func (s *Server) AddServiceInvocationHandler(method string, fn cc.ServiceInvocationHandler) error {
|
||||
if method == "" || method == "/" {
|
||||
return fmt.Errorf("servie name required")
|
||||
return errors.New("service name required")
|
||||
}
|
||||
|
||||
if method[0] == '/' {
|
||||
|
@ -36,7 +36,7 @@ func (s *Server) AddServiceInvocationHandler(method string, fn cc.ServiceInvocat
|
|||
}
|
||||
|
||||
if fn == nil {
|
||||
return fmt.Errorf("invocation handler required")
|
||||
return errors.New("invocation handler required")
|
||||
}
|
||||
s.invokeHandlers[method] = fn
|
||||
return nil
|
||||
|
|
|
@ -67,21 +67,21 @@ func TestInvokeWithToken(t *testing.T) {
|
|||
grpcMetadata := metadata.New(map[string]string{
|
||||
cc.APITokenKey: os.Getenv(cc.AppAPITokenEnvVar),
|
||||
})
|
||||
ctx := metadata.NewIncomingContext(context.Background(), grpcMetadata)
|
||||
ctx := metadata.NewIncomingContext(t.Context(), grpcMetadata)
|
||||
in := &common.InvokeRequest{Method: methodName}
|
||||
_, err := server.OnInvoke(ctx, in)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
t.Run("invoke with empty token, return failed", func(t *testing.T) {
|
||||
in := &common.InvokeRequest{Method: methodName}
|
||||
_, err := server.OnInvoke(context.Background(), in)
|
||||
_, err := server.OnInvoke(t.Context(), in)
|
||||
require.Error(t, err)
|
||||
})
|
||||
t.Run("invoke with mismatch token, return failed", func(t *testing.T) {
|
||||
grpcMetadata := metadata.New(map[string]string{
|
||||
cc.APITokenKey: "mismatch-token",
|
||||
})
|
||||
ctx := metadata.NewOutgoingContext(context.Background(), grpcMetadata)
|
||||
ctx := metadata.NewOutgoingContext(t.Context(), grpcMetadata)
|
||||
in := &common.InvokeRequest{Method: methodName}
|
||||
_, err := server.OnInvoke(ctx, in)
|
||||
require.Error(t, err)
|
||||
|
@ -93,7 +93,7 @@ func TestInvokeWithToken(t *testing.T) {
|
|||
func TestInvoke(t *testing.T) {
|
||||
methodName := "test"
|
||||
methodNameWithError := "error"
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
|
||||
server := getTestServer()
|
||||
err := server.AddServiceInvocationHandler("/"+methodName, testInvokeHandler)
|
||||
|
|
|
@ -31,11 +31,20 @@ import (
|
|||
|
||||
// AddTopicEventHandler appends provided event handler with topic name to the service.
|
||||
func (s *Server) AddTopicEventHandler(sub *common.Subscription, fn common.TopicEventHandler) error {
|
||||
if fn == nil {
|
||||
return errors.New("topic handler required")
|
||||
}
|
||||
|
||||
return s.AddTopicEventSubscriber(sub, fn)
|
||||
}
|
||||
|
||||
// AddTopicEventSubscriber appends the provided subscriber to the service.
|
||||
func (s *Server) AddTopicEventSubscriber(sub *common.Subscription, subscriber common.TopicEventSubscriber) error {
|
||||
if sub == nil {
|
||||
return errors.New("subscription required")
|
||||
}
|
||||
|
||||
return s.topicRegistrar.AddSubscription(sub, fn)
|
||||
return s.topicRegistrar.AddSubscription(sub, subscriber)
|
||||
}
|
||||
|
||||
// ListTopicSubscriptions is called by Dapr to get the list of topics in a pubsub component the app wants to subscribe to.
|
||||
|
@ -44,10 +53,11 @@ func (s *Server) ListTopicSubscriptions(ctx context.Context, in *emptypb.Empty)
|
|||
for _, v := range s.topicRegistrar {
|
||||
s := v.Subscription
|
||||
sub := &runtimev1pb.TopicSubscription{
|
||||
PubsubName: s.PubsubName,
|
||||
Topic: s.Topic,
|
||||
Metadata: s.Metadata,
|
||||
Routes: convertRoutes(s.Routes),
|
||||
PubsubName: s.PubsubName,
|
||||
Topic: s.Topic,
|
||||
Metadata: s.Metadata,
|
||||
Routes: convertRoutes(s.Routes),
|
||||
DeadLetterTopic: s.DeadLetterTopic,
|
||||
}
|
||||
subs = append(subs, sub)
|
||||
}
|
||||
|
@ -142,7 +152,7 @@ func (s *Server) OnTopicEvent(ctx context.Context, in *runtimev1pb.TopicEventReq
|
|||
in.GetPath(), in.GetPubsubName(), in.GetTopic(),
|
||||
)
|
||||
}
|
||||
retry, err := h(ctx, e)
|
||||
retry, err := h.Handle(ctx, e)
|
||||
if err == nil {
|
||||
return &runtimev1pb.TopicEventResponse{Status: runtimev1pb.TopicEventResponse_SUCCESS}, nil
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ func TestTopicSubscriptionList(t *testing.T) {
|
|||
}
|
||||
err := server.AddTopicEventHandler(sub1, eventHandler)
|
||||
require.NoError(t, err)
|
||||
resp, err := server.ListTopicSubscriptions(context.Background(), &emptypb.Empty{})
|
||||
resp, err := server.ListTopicSubscriptions(t.Context(), &emptypb.Empty{})
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
if assert.Lenf(t, resp.GetSubscriptions(), 1, "expected 1 handlers") {
|
||||
|
@ -76,7 +76,7 @@ func TestTopicSubscriptionList(t *testing.T) {
|
|||
}
|
||||
err = server.AddTopicEventHandler(sub2, eventHandler)
|
||||
require.NoError(t, err)
|
||||
resp, err = server.ListTopicSubscriptions(context.Background(), &emptypb.Empty{})
|
||||
resp, err = server.ListTopicSubscriptions(t.Context(), &emptypb.Empty{})
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
if assert.Lenf(t, resp.GetSubscriptions(), 1, "expected 1 handlers") {
|
||||
|
@ -96,7 +96,7 @@ func TestTopicSubscriptionList(t *testing.T) {
|
|||
|
||||
// go test -timeout 30s ./service/grpc -count 1 -run ^TestTopic$
|
||||
func TestTopic(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
|
||||
sub := &common.Subscription{
|
||||
PubsubName: "messages",
|
||||
|
@ -158,7 +158,7 @@ func TestTopic(t *testing.T) {
|
|||
Topic: sub2.Topic,
|
||||
PubsubName: sub2.PubsubName,
|
||||
}
|
||||
ctx := metadata.NewIncomingContext(context.Background(), metadata.New(map[string]string{"Metadata.key1": "value1"}))
|
||||
ctx := metadata.NewIncomingContext(t.Context(), metadata.New(map[string]string{"Metadata.key1": "value1"}))
|
||||
_, err = server.OnTopicEvent(ctx, in)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
@ -167,7 +167,7 @@ func TestTopic(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestTopicWithValidationDisabled(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
|
||||
sub := &common.Subscription{
|
||||
PubsubName: "messages",
|
||||
|
@ -197,7 +197,7 @@ func TestTopicWithValidationDisabled(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestTopicWithErrors(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
|
||||
sub1 := &common.Subscription{
|
||||
PubsubName: "messages",
|
||||
|
@ -269,7 +269,7 @@ func eventHandlerWithError(ctx context.Context, event *common.TopicEvent) (retry
|
|||
}
|
||||
|
||||
func TestEventDataHandling(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
|
||||
tests := map[string]struct {
|
||||
contentType string
|
||||
|
|
|
@ -14,7 +14,7 @@ limitations under the License.
|
|||
package http
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
@ -25,14 +25,14 @@ import (
|
|||
// AddBindingInvocationHandler appends provided binding invocation handler with its route to the service.
|
||||
func (s *Server) AddBindingInvocationHandler(route string, fn common.BindingInvocationHandler) error {
|
||||
if route == "" {
|
||||
return fmt.Errorf("binding route required")
|
||||
return errors.New("binding route required")
|
||||
}
|
||||
if fn == nil {
|
||||
return fmt.Errorf("binding handler required")
|
||||
return errors.New("binding handler required")
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(route, "/") {
|
||||
route = fmt.Sprintf("/%s", route)
|
||||
route = "/" + route
|
||||
}
|
||||
|
||||
s.mux.Handle(route, optionsHandler(http.HandlerFunc(
|
||||
|
|
|
@ -14,7 +14,7 @@ limitations under the License.
|
|||
package http
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
|
@ -24,11 +24,11 @@ import (
|
|||
// AddHealthCheckHandler appends provided app health check handler.
|
||||
func (s *Server) AddHealthCheckHandler(route string, fn common.HealthCheckHandler) error {
|
||||
if fn == nil {
|
||||
return fmt.Errorf("health check handler required")
|
||||
return errors.New("health check handler required")
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(route, "/") {
|
||||
route = fmt.Sprintf("/%s", route)
|
||||
route = "/" + route
|
||||
}
|
||||
|
||||
s.mux.Handle(route, optionsHandler(http.HandlerFunc(
|
||||
|
|
|
@ -14,7 +14,7 @@ limitations under the License.
|
|||
package http
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
@ -27,11 +27,11 @@ import (
|
|||
// AddServiceInvocationHandler appends provided service invocation handler with its route to the service.
|
||||
func (s *Server) AddServiceInvocationHandler(route string, fn common.ServiceInvocationHandler) error {
|
||||
if route == "" || route == "/" {
|
||||
return fmt.Errorf("service route required")
|
||||
return errors.New("service route required")
|
||||
}
|
||||
|
||||
if fn == nil {
|
||||
return fmt.Errorf("invocation handler required")
|
||||
return errors.New("invocation handler required")
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(route, "/") {
|
||||
|
|
|
@ -2,17 +2,16 @@ package http
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/dapr/go-sdk/service/common"
|
||||
)
|
||||
|
||||
func (s *Server) AddJobEventHandler(name string, fn common.JobEventHandler) error {
|
||||
if name == "" {
|
||||
return fmt.Errorf("job event name required")
|
||||
return errors.New("job event name required")
|
||||
}
|
||||
if fn == nil {
|
||||
return fmt.Errorf("job event handler required")
|
||||
return errors.New("job event handler required")
|
||||
}
|
||||
|
||||
return errors.New("handling http scheduling requests has not been implemented in this sdk")
|
||||
|
|
|
@ -69,6 +69,10 @@ type topicEventJSON struct {
|
|||
Topic string `json:"topic"`
|
||||
// PubsubName is name of the pub/sub this message came from
|
||||
PubsubName string `json:"pubsubname"`
|
||||
// TraceID is the tracing header identifier for the incoming event
|
||||
TraceID string `json:"traceid"`
|
||||
// TraceParent is name of the parent trace identifier for the incoming event
|
||||
TraceParent string `json:"traceparent"`
|
||||
}
|
||||
|
||||
func (in topicEventJSON) getData() (data any, rawData []byte) {
|
||||
|
@ -190,9 +194,11 @@ func (s *Server) registerBaseHandler() {
|
|||
err := runtime.GetActorRuntimeInstanceContext().Deactivate(r.Context(), actorType, actorID)
|
||||
if err == actorErr.ErrActorTypeNotFound || err == actorErr.ErrActorIDNotFound {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
if err != actorErr.Success {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
@ -207,9 +213,11 @@ func (s *Server) registerBaseHandler() {
|
|||
err := runtime.GetActorRuntimeInstanceContext().InvokeReminder(r.Context(), actorType, actorID, reminderName, reqData)
|
||||
if err == actorErr.ErrActorTypeNotFound {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
if err != actorErr.Success {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
@ -224,9 +232,11 @@ func (s *Server) registerBaseHandler() {
|
|||
err := runtime.GetActorRuntimeInstanceContext().InvokeTimer(r.Context(), actorType, actorID, timerName, reqData)
|
||||
if err == actorErr.ErrActorTypeNotFound {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
if err != actorErr.Success {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
@ -235,6 +245,15 @@ func (s *Server) registerBaseHandler() {
|
|||
|
||||
// AddTopicEventHandler appends provided event handler with it's name to the service.
|
||||
func (s *Server) AddTopicEventHandler(sub *common.Subscription, fn common.TopicEventHandler) error {
|
||||
if fn == nil {
|
||||
return errors.New("topic handler required")
|
||||
}
|
||||
|
||||
return s.AddTopicEventSubscriber(sub, fn)
|
||||
}
|
||||
|
||||
// AddTopicEventSubscriber appends the provided subscriber to the service.
|
||||
func (s *Server) AddTopicEventSubscriber(sub *common.Subscription, subscriber common.TopicEventSubscriber) error {
|
||||
if sub == nil {
|
||||
return errors.New("subscription required")
|
||||
}
|
||||
|
@ -243,7 +262,7 @@ func (s *Server) AddTopicEventHandler(sub *common.Subscription, fn common.TopicE
|
|||
if sub.Route == "" {
|
||||
return errors.New("handler route name")
|
||||
}
|
||||
if err := s.topicRegistrar.AddSubscription(sub, fn); err != nil {
|
||||
if err := s.topicRegistrar.AddSubscription(sub, subscriber); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -294,13 +313,15 @@ func (s *Server) AddTopicEventHandler(sub *common.Subscription, fn common.TopicE
|
|||
PubsubName: in.PubsubName,
|
||||
Topic: in.Topic,
|
||||
Metadata: getCustomMetdataFromHeaders(r),
|
||||
TraceID: in.TraceID,
|
||||
TraceParent: in.TraceParent,
|
||||
}
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
// execute user handler
|
||||
retry, err := fn(r.Context(), &te)
|
||||
retry, err := subscriber.Handle(r.Context(), &te)
|
||||
if err == nil {
|
||||
writeStatus(w, common.SubscriptionResponseStatusSuccess)
|
||||
return
|
||||
|
|
|
@ -71,7 +71,9 @@ func TestEventHandler(t *testing.T) {
|
|||
"comexampleextension1" : "value",
|
||||
"comexampleothervalue" : 5,
|
||||
"datacontenttype" : "application/json",
|
||||
"data" : "eyJtZXNzYWdlIjoiaGVsbG8ifQ=="
|
||||
"data" : "eyJtZXNzYWdlIjoiaGVsbG8ifQ==",
|
||||
"traceid": "aaa",
|
||||
"traceparent": "bbb"
|
||||
}`
|
||||
|
||||
s := newServer("", nil)
|
||||
|
|
|
@ -2,7 +2,6 @@ package internal
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/dapr/go-sdk/service/common"
|
||||
)
|
||||
|
@ -15,11 +14,11 @@ type TopicRegistrar map[string]*TopicRegistration
|
|||
// TopicRegistration encapsulates the subscription and handlers.
|
||||
type TopicRegistration struct {
|
||||
Subscription *TopicSubscription
|
||||
DefaultHandler common.TopicEventHandler
|
||||
RouteHandlers map[string]common.TopicEventHandler
|
||||
DefaultHandler common.TopicEventSubscriber
|
||||
RouteHandlers map[string]common.TopicEventSubscriber
|
||||
}
|
||||
|
||||
func (m TopicRegistrar) AddSubscription(sub *common.Subscription, fn common.TopicEventHandler) error {
|
||||
func (m TopicRegistrar) AddSubscription(sub *common.Subscription, fn common.TopicEventSubscriber) error {
|
||||
if sub.Topic == "" {
|
||||
return errors.New("topic name required")
|
||||
}
|
||||
|
@ -27,7 +26,7 @@ func (m TopicRegistrar) AddSubscription(sub *common.Subscription, fn common.Topi
|
|||
return errors.New("pub/sub name required")
|
||||
}
|
||||
if fn == nil {
|
||||
return fmt.Errorf("topic handler required")
|
||||
return errors.New("topic handler required")
|
||||
}
|
||||
|
||||
var key string
|
||||
|
@ -40,8 +39,8 @@ func (m TopicRegistrar) AddSubscription(sub *common.Subscription, fn common.Topi
|
|||
ts, ok := m[key]
|
||||
if !ok {
|
||||
ts = &TopicRegistration{
|
||||
Subscription: NewTopicSubscription(sub.PubsubName, sub.Topic),
|
||||
RouteHandlers: make(map[string]common.TopicEventHandler),
|
||||
Subscription: NewTopicSubscription(sub.PubsubName, sub.Topic, sub.DeadLetterTopic),
|
||||
RouteHandlers: make(map[string]common.TopicEventSubscriber),
|
||||
DefaultHandler: nil,
|
||||
}
|
||||
ts.Subscription.SetMetadata(sub.Metadata)
|
||||
|
|
|
@ -13,12 +13,12 @@ import (
|
|||
)
|
||||
|
||||
func TestTopicRegistrarValidation(t *testing.T) {
|
||||
fn := func(ctx context.Context, e *common.TopicEvent) (retry bool, err error) {
|
||||
fn := common.TopicEventHandler(func(ctx context.Context, e *common.TopicEvent) (retry bool, err error) {
|
||||
return false, nil
|
||||
}
|
||||
})
|
||||
tests := map[string]struct {
|
||||
sub common.Subscription
|
||||
fn common.TopicEventHandler
|
||||
fn common.TopicEventSubscriber
|
||||
err string
|
||||
}{
|
||||
"pubsub required": {
|
||||
|
@ -63,7 +63,6 @@ func TestTopicRegistrarValidation(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for name, tt := range tests {
|
||||
tt := tt // dereference loop var
|
||||
t.Run(name, func(t *testing.T) {
|
||||
m := internal.TopicRegistrar{}
|
||||
if tt.err != "" {
|
||||
|
@ -76,9 +75,9 @@ func TestTopicRegistrarValidation(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestTopicAddSubscriptionMetadata(t *testing.T) {
|
||||
handler := func(ctx context.Context, e *common.TopicEvent) (retry bool, err error) {
|
||||
handler := common.TopicEventHandler(func(ctx context.Context, e *common.TopicEvent) (retry bool, err error) {
|
||||
return false, nil
|
||||
}
|
||||
})
|
||||
topicRegistrar := internal.TopicRegistrar{}
|
||||
sub := &common.Subscription{
|
||||
PubsubName: "pubsubname",
|
||||
|
|
|
@ -18,6 +18,8 @@ type TopicSubscription struct {
|
|||
Routes *TopicRoutes `json:"routes,omitempty"`
|
||||
// Metadata is the subscription metadata.
|
||||
Metadata map[string]string `json:"metadata,omitempty"`
|
||||
// DeadLetterTopic is the name of the deadletter topic.
|
||||
DeadLetterTopic string `json:"deadLetterTopic"`
|
||||
}
|
||||
|
||||
// TopicRoutes encapsulates the default route and multiple routing rules.
|
||||
|
@ -42,10 +44,11 @@ type TopicRule struct {
|
|||
}
|
||||
|
||||
// NewTopicSubscription creates a new `TopicSubscription`.
|
||||
func NewTopicSubscription(pubsubName, topic string) *TopicSubscription {
|
||||
func NewTopicSubscription(pubsubName, topic, deadLetterTopic string) *TopicSubscription {
|
||||
return &TopicSubscription{ //nolint:exhaustivestruct
|
||||
PubsubName: pubsubName,
|
||||
Topic: topic,
|
||||
PubsubName: pubsubName,
|
||||
Topic: topic,
|
||||
DeadLetterTopic: deadLetterTopic,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
|
||||
func TestTopicSubscripiton(t *testing.T) {
|
||||
t.Run("duplicate metadata", func(t *testing.T) {
|
||||
sub := internal.NewTopicSubscription("test", "mytopic")
|
||||
sub := internal.NewTopicSubscription("test", "mytopic", "")
|
||||
require.NoError(t, sub.SetMetadata(map[string]string{
|
||||
"test": "test",
|
||||
}))
|
||||
|
@ -22,7 +22,7 @@ func TestTopicSubscripiton(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("duplicate route", func(t *testing.T) {
|
||||
sub := internal.NewTopicSubscription("test", "mytopic")
|
||||
sub := internal.NewTopicSubscription("test", "mytopic", "")
|
||||
require.NoError(t, sub.SetDefaultRoute("/test"))
|
||||
assert.Equal(t, "/test", sub.Route)
|
||||
require.EqualError(t, sub.SetDefaultRoute("/test"),
|
||||
|
@ -30,7 +30,7 @@ func TestTopicSubscripiton(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("duplicate route after routing rule", func(t *testing.T) {
|
||||
sub := internal.NewTopicSubscription("test", "mytopic")
|
||||
sub := internal.NewTopicSubscription("test", "mytopic", "")
|
||||
require.NoError(t, sub.AddRoutingRule("/other", `event.type == "test"`, 0))
|
||||
require.NoError(t, sub.SetDefaultRoute("/test"))
|
||||
require.EqualError(t, sub.SetDefaultRoute("/test"),
|
||||
|
@ -38,7 +38,7 @@ func TestTopicSubscripiton(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("default route after routing rule", func(t *testing.T) {
|
||||
sub := internal.NewTopicSubscription("test", "mytopic")
|
||||
sub := internal.NewTopicSubscription("test", "mytopic", "")
|
||||
require.NoError(t, sub.SetDefaultRoute("/test"))
|
||||
assert.Equal(t, "/test", sub.Route)
|
||||
require.NoError(t, sub.AddRoutingRule("/other", `event.type == "test"`, 0))
|
||||
|
@ -49,14 +49,14 @@ func TestTopicSubscripiton(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("duplicate routing rule priority", func(t *testing.T) {
|
||||
sub := internal.NewTopicSubscription("test", "mytopic")
|
||||
sub := internal.NewTopicSubscription("test", "mytopic", "")
|
||||
require.NoError(t, sub.AddRoutingRule("/other", `event.type == "other"`, 1))
|
||||
require.EqualError(t, sub.AddRoutingRule("/test", `event.type == "test"`, 1),
|
||||
"subscription for topic mytopic on pubsub test already has a routing rule with priority 1")
|
||||
})
|
||||
|
||||
t.Run("priority ordering", func(t *testing.T) {
|
||||
sub := internal.NewTopicSubscription("test", "mytopic")
|
||||
sub := internal.NewTopicSubscription("test", "mytopic", "")
|
||||
require.NoError(t, sub.AddRoutingRule("/100", `event.type == "100"`, 100))
|
||||
require.NoError(t, sub.AddRoutingRule("/1", `event.type == "1"`, 1))
|
||||
require.NoError(t, sub.AddRoutingRule("/50", `event.type == "50"`, 50))
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
module github.com/dapr/go-sdk/tools/check-lint-version
|
||||
|
||||
go 1.21
|
||||
|
||||
toolchain go1.21.6
|
||||
go 1.23.3
|
||||
|
||||
require (
|
||||
github.com/stretchr/testify v1.8.4
|
||||
|
|
|
@ -51,7 +51,7 @@ func getCurrentVersion() (string, error) {
|
|||
if matches == nil {
|
||||
return "", fmt.Errorf("no version found: %v", string(out))
|
||||
}
|
||||
return fmt.Sprintf("v%s", matches[1]), err
|
||||
return "v" + matches[1], err
|
||||
}
|
||||
|
||||
func isVersionValid(workflowVersion, currentVersion string) bool {
|
||||
|
@ -72,7 +72,7 @@ func compareVersions(path string) string {
|
|||
if !validVersion {
|
||||
return fmt.Sprintf("Invalid version, expected: %s, current: %s - See: https://golangci-lint.run/usage/install/ for instructions to update", workflowVersion, currentVersion)
|
||||
}
|
||||
return fmt.Sprintf("Linter version is valid (MajorMinor): %s", currentVersion)
|
||||
return "Linter version is valid (MajorMinor): " + currentVersion
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
|
|
@ -28,7 +28,7 @@ func TestParseWorkflow(t *testing.T) {
|
|||
|
||||
t.Run("parse testing workflow file", func(t *testing.T) {
|
||||
parsedVersion, err := parseWorkflowVersionFromFile("../../.github/workflows/test-tooling.yml")
|
||||
assert.Equal(t, "v1.55.2", parsedVersion)
|
||||
assert.Equal(t, "v1.64.6", parsedVersion)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ func TestParseWorkflow(t *testing.T) {
|
|||
func TestGetCurrentVersion(t *testing.T) {
|
||||
t.Run("get current version from system", func(t *testing.T) {
|
||||
currentVersion, err := getCurrentVersion()
|
||||
assert.Equal(t, "v1.55.2", currentVersion)
|
||||
assert.Equal(t, "v1.64.6", currentVersion)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
|
@ -49,23 +49,23 @@ func TestGetCurrentVersion(t *testing.T) {
|
|||
|
||||
func TestIsVersionValid(t *testing.T) {
|
||||
t.Run("compare versions - exactly equal to", func(t *testing.T) {
|
||||
assert.True(t, true, isVersionValid("v1.54.2", "v1.54.2"))
|
||||
assert.True(t, isVersionValid("v1.54.2", "v1.54.2"))
|
||||
})
|
||||
|
||||
t.Run("compare versions - patch version greater (workflow)", func(t *testing.T) {
|
||||
assert.True(t, true, isVersionValid("v1.54.3", "v1.54.2"))
|
||||
assert.True(t, isVersionValid("v1.54.3", "v1.54.2"))
|
||||
})
|
||||
|
||||
t.Run("compare versions - patch version greater (installed)", func(t *testing.T) {
|
||||
assert.True(t, true, isVersionValid("v1.54.2", "v1.54.3"))
|
||||
assert.True(t, isVersionValid("v1.54.2", "v1.54.3"))
|
||||
})
|
||||
|
||||
t.Run("compare versions - invalid (installed)", func(t *testing.T) {
|
||||
assert.False(t, false, isVersionValid("v1.54.2", "v1.52.2"))
|
||||
assert.False(t, isVersionValid("v1.54.2", "v1.52.2"))
|
||||
})
|
||||
|
||||
t.Run("compare versions - invalid (workflow)", func(t *testing.T) {
|
||||
assert.False(t, false, isVersionValid("v1.52.2", "v1.54.2"))
|
||||
assert.False(t, isVersionValid("v1.52.2", "v1.54.2"))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
v1.11.0
|
||||
v1.12.0
|
|
@ -17,10 +17,11 @@ package workflow
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
|
||||
"github.com/microsoft/durabletask-go/task"
|
||||
"github.com/dapr/durabletask-go/task"
|
||||
)
|
||||
|
||||
type ActivityContext struct {
|
||||
|
@ -38,7 +39,16 @@ func (wfac *ActivityContext) Context() context.Context {
|
|||
type callActivityOption func(*callActivityOptions) error
|
||||
|
||||
type callActivityOptions struct {
|
||||
rawInput *wrapperspb.StringValue
|
||||
rawInput *wrapperspb.StringValue
|
||||
retryPolicy *RetryPolicy
|
||||
}
|
||||
|
||||
type RetryPolicy struct {
|
||||
MaxAttempts int
|
||||
InitialRetryInterval time.Duration
|
||||
BackoffCoefficient float64
|
||||
MaxRetryInterval time.Duration
|
||||
RetryTimeout time.Duration
|
||||
}
|
||||
|
||||
// ActivityInput is an option to pass a JSON-serializable input
|
||||
|
@ -61,6 +71,26 @@ func ActivityRawInput(input string) callActivityOption {
|
|||
}
|
||||
}
|
||||
|
||||
func ActivityRetryPolicy(policy RetryPolicy) callActivityOption {
|
||||
return func(opts *callActivityOptions) error {
|
||||
opts.retryPolicy = &policy
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (opts *callActivityOptions) getRetryPolicy() *task.RetryPolicy {
|
||||
if opts.retryPolicy == nil {
|
||||
return nil
|
||||
}
|
||||
return &task.RetryPolicy{
|
||||
MaxAttempts: opts.retryPolicy.MaxAttempts,
|
||||
InitialRetryInterval: opts.retryPolicy.InitialRetryInterval,
|
||||
BackoffCoefficient: opts.retryPolicy.BackoffCoefficient,
|
||||
MaxRetryInterval: opts.retryPolicy.MaxRetryInterval,
|
||||
RetryTimeout: opts.retryPolicy.RetryTimeout,
|
||||
}
|
||||
}
|
||||
|
||||
func marshalData(input any) ([]byte, error) {
|
||||
if input == nil {
|
||||
return nil, nil
|
||||
|
|
|
@ -19,13 +19,17 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/dapr/durabletask-go/task"
|
||||
)
|
||||
|
||||
type testingTaskActivityContext struct {
|
||||
inputBytes []byte
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
func (t *testingTaskActivityContext) GetInput(v any) error {
|
||||
|
@ -33,7 +37,7 @@ func (t *testingTaskActivityContext) GetInput(v any) error {
|
|||
}
|
||||
|
||||
func (t *testingTaskActivityContext) Context() context.Context {
|
||||
return context.TODO()
|
||||
return t.ctx
|
||||
}
|
||||
|
||||
func TestActivityContext(t *testing.T) {
|
||||
|
@ -41,7 +45,7 @@ func TestActivityContext(t *testing.T) {
|
|||
inputBytes, err := json.Marshal(inputString)
|
||||
require.NoErrorf(t, err, "required no error, but got %v", err)
|
||||
|
||||
ac := ActivityContext{ctx: &testingTaskActivityContext{inputBytes: inputBytes}}
|
||||
ac := ActivityContext{ctx: &testingTaskActivityContext{inputBytes: inputBytes, ctx: t.Context()}}
|
||||
t.Run("test getinput", func(t *testing.T) {
|
||||
var inputReturn string
|
||||
err := ac.GetInput(&inputReturn)
|
||||
|
@ -50,7 +54,7 @@ func TestActivityContext(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("test context", func(t *testing.T) {
|
||||
assert.Equal(t, context.TODO(), ac.Context())
|
||||
assert.Equal(t, t.Context(), ac.Context())
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -69,6 +73,26 @@ func TestCallActivityOptions(t *testing.T) {
|
|||
opts := returnCallActivityOptions(ActivityRawInput("test"))
|
||||
assert.Equal(t, "test", opts.rawInput.GetValue())
|
||||
})
|
||||
|
||||
t.Run("activity retry policy - set", func(t *testing.T) {
|
||||
opts := returnCallActivityOptions(ActivityRetryPolicy(RetryPolicy{
|
||||
MaxAttempts: 3,
|
||||
InitialRetryInterval: 100 * time.Millisecond,
|
||||
BackoffCoefficient: 2,
|
||||
MaxRetryInterval: 2 * time.Second,
|
||||
}))
|
||||
assert.Equal(t, &task.RetryPolicy{
|
||||
MaxAttempts: 3,
|
||||
InitialRetryInterval: 100 * time.Millisecond,
|
||||
BackoffCoefficient: 2,
|
||||
MaxRetryInterval: 2 * time.Second,
|
||||
}, opts.getRetryPolicy())
|
||||
})
|
||||
|
||||
t.Run("activity retry policy - empty", func(t *testing.T) {
|
||||
opts := returnCallActivityOptions()
|
||||
assert.Empty(t, opts.getRetryPolicy())
|
||||
})
|
||||
}
|
||||
|
||||
func returnCallActivityOptions(opts ...callActivityOption) callActivityOptions {
|
||||
|
|
|
@ -20,17 +20,34 @@ import (
|
|||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/microsoft/durabletask-go/api"
|
||||
"github.com/microsoft/durabletask-go/backend"
|
||||
durabletaskclient "github.com/microsoft/durabletask-go/client"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
|
||||
"github.com/dapr/durabletask-go/api"
|
||||
"github.com/dapr/durabletask-go/backend"
|
||||
durabletaskclient "github.com/dapr/durabletask-go/client"
|
||||
|
||||
dapr "github.com/dapr/go-sdk/client"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
conn *grpc.ClientConn
|
||||
taskHubClient *durabletaskclient.TaskHubGrpcClient
|
||||
}
|
||||
|
||||
type WorkflowIDReusePolicy struct {
|
||||
OperationStatus []Status
|
||||
Action CreateWorkflowAction
|
||||
}
|
||||
|
||||
type CreateWorkflowAction = api.CreateOrchestrationAction
|
||||
|
||||
const (
|
||||
ReuseIDActionError CreateWorkflowAction = api.REUSE_ID_ACTION_ERROR
|
||||
ReuseIDActionIgnore CreateWorkflowAction = api.REUSE_ID_ACTION_IGNORE
|
||||
ReuseIDActionTerminate CreateWorkflowAction = api.REUSE_ID_ACTION_TERMINATE
|
||||
)
|
||||
|
||||
// WithInstanceID is an option to set an InstanceID when scheduling a new workflow.
|
||||
func WithInstanceID(id string) api.NewOrchestrationOptions {
|
||||
return api.WithInstanceID(api.InstanceID(id))
|
||||
|
@ -45,7 +62,7 @@ func WithInput(input any) api.NewOrchestrationOptions {
|
|||
|
||||
// WithRawInput is an option to pass a byte slice as an input when scheduling a new workflow.
|
||||
func WithRawInput(input string) api.NewOrchestrationOptions {
|
||||
return api.WithRawInput(input)
|
||||
return api.WithRawInput(wrapperspb.String(input))
|
||||
}
|
||||
|
||||
// WithStartTime is an option to set the start time when scheduling a new workflow.
|
||||
|
@ -53,6 +70,13 @@ func WithStartTime(time time.Time) api.NewOrchestrationOptions {
|
|||
return api.WithStartTime(time)
|
||||
}
|
||||
|
||||
func WithReuseIDPolicy(policy WorkflowIDReusePolicy) api.NewOrchestrationOptions {
|
||||
return api.WithOrchestrationIdReusePolicy(&api.OrchestrationIdReusePolicy{
|
||||
OperationStatus: convertStatusSlice(policy.OperationStatus),
|
||||
Action: policy.Action,
|
||||
})
|
||||
}
|
||||
|
||||
// WithFetchPayloads is an option to return the payload from a workflow.
|
||||
func WithFetchPayloads(fetchPayloads bool) api.FetchOrchestrationMetadataOptions {
|
||||
return api.WithFetchPayloads(fetchPayloads)
|
||||
|
@ -65,7 +89,7 @@ func WithEventPayload(data any) api.RaiseEventOptions {
|
|||
|
||||
// WithRawEventData is an option to send a byte slice with an event to a workflow.
|
||||
func WithRawEventData(data string) api.RaiseEventOptions {
|
||||
return api.WithRawEventData(data)
|
||||
return api.WithRawEventData(wrapperspb.String(data))
|
||||
}
|
||||
|
||||
// WithOutput is an option to define an output when terminating a workflow.
|
||||
|
@ -75,7 +99,17 @@ func WithOutput(data any) api.TerminateOptions {
|
|||
|
||||
// WithRawOutput is an option to define a byte slice to output when terminating a workflow.
|
||||
func WithRawOutput(data string) api.TerminateOptions {
|
||||
return api.WithRawOutput(data)
|
||||
return api.WithRawOutput(wrapperspb.String(data))
|
||||
}
|
||||
|
||||
// WithRecursiveTerminate configures whether to terminate all sub-workflows created by the target workflow.
|
||||
func WithRecursiveTerminate(recursive bool) api.TerminateOptions {
|
||||
return api.WithRecursiveTerminate(recursive)
|
||||
}
|
||||
|
||||
// WithRecursivePurge configures whether to purge all sub-workflows created by the target workflow.
|
||||
func WithRecursivePurge(recursive bool) api.PurgeOptions {
|
||||
return api.WithRecursivePurge(recursive)
|
||||
}
|
||||
|
||||
type clientOption func(*clientOptions) error
|
||||
|
@ -113,9 +147,11 @@ func NewClient(opts ...clientOption) (*Client, error) {
|
|||
return &Client{}, fmt.Errorf("failed to initialise dapr.Client: %v", err)
|
||||
}
|
||||
|
||||
taskHubClient := durabletaskclient.NewTaskHubGrpcClient(daprClient.GrpcClientConn(), backend.DefaultLogger())
|
||||
conn := daprClient.GrpcClientConn()
|
||||
taskHubClient := durabletaskclient.NewTaskHubGrpcClient(conn, backend.DefaultLogger())
|
||||
|
||||
return &Client{
|
||||
conn: conn,
|
||||
taskHubClient: taskHubClient,
|
||||
}, nil
|
||||
}
|
||||
|
@ -205,9 +241,13 @@ func (c *Client) ResumeWorkflow(ctx context.Context, id, reason string) error {
|
|||
|
||||
// PurgeWorkflow will purge a given workflow and return an error output.
|
||||
// NOTE: The workflow must be in a terminated or completed state.
|
||||
func (c *Client) PurgeWorkflow(ctx context.Context, id string) error {
|
||||
func (c *Client) PurgeWorkflow(ctx context.Context, id string, opts ...api.PurgeOptions) error {
|
||||
if id == "" {
|
||||
return errors.New("no workflow id specified")
|
||||
}
|
||||
return c.taskHubClient.PurgeOrchestrationState(ctx, api.InstanceID(id))
|
||||
return c.taskHubClient.PurgeOrchestrationState(ctx, api.InstanceID(id), opts...)
|
||||
}
|
||||
|
||||
func (c *Client) Close() {
|
||||
_ = c.conn.Close()
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@ limitations under the License.
|
|||
package workflow
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -52,9 +51,12 @@ func TestClientMethods(t *testing.T) {
|
|||
testClient := Client{
|
||||
taskHubClient: nil,
|
||||
}
|
||||
ctx := context.Background()
|
||||
ctx := t.Context()
|
||||
t.Run("ScheduleNewWorkflow - empty wf name", func(t *testing.T) {
|
||||
id, err := testClient.ScheduleNewWorkflow(ctx, "", nil)
|
||||
id, err := testClient.ScheduleNewWorkflow(ctx, "", WithReuseIDPolicy(WorkflowIDReusePolicy{
|
||||
OperationStatus: []Status{StatusCompleted},
|
||||
Action: ReuseIDActionIgnore,
|
||||
}))
|
||||
require.Error(t, err)
|
||||
assert.Empty(t, id)
|
||||
})
|
||||
|
|
|
@ -18,7 +18,7 @@ import (
|
|||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/microsoft/durabletask-go/task"
|
||||
"github.com/dapr/durabletask-go/task"
|
||||
)
|
||||
|
||||
type WorkflowContext struct {
|
||||
|
@ -50,6 +50,11 @@ func (wfc *WorkflowContext) IsReplaying() bool {
|
|||
return wfc.orchestrationContext.IsReplaying
|
||||
}
|
||||
|
||||
// SetCustomStatus sets custom status to the workflow context
|
||||
func (wfc *WorkflowContext) SetCustomStatus(cs string) {
|
||||
wfc.orchestrationContext.SetCustomStatus(cs)
|
||||
}
|
||||
|
||||
// CallActivity returns a completable task for a given activity.
|
||||
// You must call Await(output any) on the returned Task to block the workflow and wait for the task to complete.
|
||||
// The value passed to the Await method must be a pointer or can be nil to ignore the returned value.
|
||||
|
@ -63,7 +68,7 @@ func (wfc *WorkflowContext) CallActivity(activity interface{}, opts ...callActiv
|
|||
}
|
||||
}
|
||||
|
||||
return wfc.orchestrationContext.CallActivity(activity, task.WithRawActivityInput(options.rawInput.GetValue()))
|
||||
return wfc.orchestrationContext.CallActivity(activity, task.WithRawActivityInput(options.rawInput), task.WithActivityRetryPolicy(options.getRetryPolicy()))
|
||||
}
|
||||
|
||||
// CallChildWorkflow returns a completable task for a given workflow.
|
||||
|
@ -79,9 +84,9 @@ func (wfc *WorkflowContext) CallChildWorkflow(workflow interface{}, opts ...call
|
|||
}
|
||||
}
|
||||
if options.instanceID != "" {
|
||||
return wfc.orchestrationContext.CallSubOrchestrator(workflow, task.WithRawSubOrchestratorInput(options.rawInput.GetValue()), task.WithSubOrchestrationInstanceID(options.instanceID))
|
||||
return wfc.orchestrationContext.CallSubOrchestrator(workflow, task.WithRawSubOrchestratorInput(options.rawInput), task.WithSubOrchestrationInstanceID(options.instanceID), task.WithSubOrchestrationRetryPolicy(options.getRetryPolicy()))
|
||||
}
|
||||
return wfc.orchestrationContext.CallSubOrchestrator(workflow, task.WithRawSubOrchestratorInput(options.rawInput.GetValue()))
|
||||
return wfc.orchestrationContext.CallSubOrchestrator(workflow, task.WithRawSubOrchestratorInput(options.rawInput), task.WithSubOrchestrationRetryPolicy(options.getRetryPolicy()))
|
||||
}
|
||||
|
||||
// CreateTimer returns a completable task that blocks for a given duration.
|
||||
|
|
|
@ -18,9 +18,10 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/microsoft/durabletask-go/task"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/dapr/durabletask-go/task"
|
||||
)
|
||||
|
||||
func TestContext(t *testing.T) {
|
||||
|
|
|
@ -14,7 +14,10 @@ limitations under the License.
|
|||
*/
|
||||
package workflow
|
||||
|
||||
import "github.com/microsoft/durabletask-go/api"
|
||||
import (
|
||||
"github.com/dapr/durabletask-go/api"
|
||||
"github.com/dapr/durabletask-go/api/protos"
|
||||
)
|
||||
|
||||
type Status int
|
||||
|
||||
|
@ -48,12 +51,42 @@ func (s Status) String() string {
|
|||
return status[s]
|
||||
}
|
||||
|
||||
func (s Status) RuntimeStatus() api.OrchestrationStatus {
|
||||
switch s {
|
||||
case StatusRunning:
|
||||
return api.RUNTIME_STATUS_RUNNING
|
||||
case StatusCompleted:
|
||||
return api.RUNTIME_STATUS_COMPLETED
|
||||
case StatusContinuedAsNew:
|
||||
return api.RUNTIME_STATUS_CONTINUED_AS_NEW
|
||||
case StatusFailed:
|
||||
return api.RUNTIME_STATUS_FAILED
|
||||
case StatusCanceled:
|
||||
return api.RUNTIME_STATUS_CANCELED
|
||||
case StatusTerminated:
|
||||
return api.RUNTIME_STATUS_TERMINATED
|
||||
case StatusPending:
|
||||
return api.RUNTIME_STATUS_PENDING
|
||||
case StatusSuspended:
|
||||
return api.RUNTIME_STATUS_SUSPENDED
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
type WorkflowState struct {
|
||||
Metadata api.OrchestrationMetadata
|
||||
Metadata protos.OrchestrationMetadata
|
||||
}
|
||||
|
||||
// RuntimeStatus returns the status from a workflow state.
|
||||
func (wfs *WorkflowState) RuntimeStatus() Status {
|
||||
s := Status(wfs.Metadata.RuntimeStatus.Number())
|
||||
s := Status(wfs.Metadata.GetRuntimeStatus().Number())
|
||||
return s
|
||||
}
|
||||
|
||||
func convertStatusSlice(ss []Status) []api.OrchestrationStatus {
|
||||
out := []api.OrchestrationStatus{}
|
||||
for _, s := range ss {
|
||||
out = append(out, s.RuntimeStatus())
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
|
|
@ -17,12 +17,13 @@ package workflow
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/microsoft/durabletask-go/api"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/dapr/durabletask-go/api/protos"
|
||||
)
|
||||
|
||||
func TestString(t *testing.T) {
|
||||
wfState := WorkflowState{Metadata: api.OrchestrationMetadata{RuntimeStatus: 0}}
|
||||
wfState := WorkflowState{Metadata: protos.OrchestrationMetadata{RuntimeStatus: 0}}
|
||||
|
||||
t.Run("test running", func(t *testing.T) {
|
||||
s := wfState.RuntimeStatus()
|
||||
|
|
|
@ -25,9 +25,9 @@ import (
|
|||
|
||||
dapr "github.com/dapr/go-sdk/client"
|
||||
|
||||
"github.com/microsoft/durabletask-go/backend"
|
||||
durabletaskclient "github.com/microsoft/durabletask-go/client"
|
||||
"github.com/microsoft/durabletask-go/task"
|
||||
"github.com/dapr/durabletask-go/backend"
|
||||
durabletaskclient "github.com/dapr/durabletask-go/client"
|
||||
"github.com/dapr/durabletask-go/task"
|
||||
)
|
||||
|
||||
type WorkflowWorker struct {
|
||||
|
@ -125,7 +125,13 @@ func wrapActivity(a Activity) task.Activity {
|
|||
return func(ctx task.ActivityContext) (any, error) {
|
||||
aCtx := ActivityContext{ctx: ctx}
|
||||
|
||||
return a(aCtx)
|
||||
result, err := a(aCtx)
|
||||
if err != nil {
|
||||
activityName, _ := getFunctionName(a) // Get the activity name for context
|
||||
return nil, fmt.Errorf("activity %s failed: %w", activityName, err)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ import (
|
|||
|
||||
daprClient "github.com/dapr/go-sdk/client"
|
||||
|
||||
"github.com/microsoft/durabletask-go/task"
|
||||
"github.com/dapr/durabletask-go/task"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
|
|
@ -18,9 +18,10 @@ import (
|
|||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/microsoft/durabletask-go/api"
|
||||
"github.com/microsoft/durabletask-go/task"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
|
||||
"github.com/dapr/durabletask-go/api/protos"
|
||||
"github.com/dapr/durabletask-go/task"
|
||||
)
|
||||
|
||||
type Metadata struct {
|
||||
|
@ -43,29 +44,29 @@ type FailureDetails struct {
|
|||
IsNonRetriable bool `json:"IsNonRetriable"`
|
||||
}
|
||||
|
||||
func convertMetadata(orchestrationMetadata *api.OrchestrationMetadata) *Metadata {
|
||||
func convertMetadata(orchestrationMetadata *protos.OrchestrationMetadata) *Metadata {
|
||||
metadata := Metadata{
|
||||
InstanceID: string(orchestrationMetadata.InstanceID),
|
||||
Name: orchestrationMetadata.Name,
|
||||
RuntimeStatus: Status(orchestrationMetadata.RuntimeStatus.Number()),
|
||||
CreatedAt: orchestrationMetadata.CreatedAt,
|
||||
LastUpdatedAt: orchestrationMetadata.LastUpdatedAt,
|
||||
SerializedInput: orchestrationMetadata.SerializedInput,
|
||||
SerializedOutput: orchestrationMetadata.SerializedOutput,
|
||||
SerializedCustomStatus: orchestrationMetadata.SerializedCustomStatus,
|
||||
InstanceID: orchestrationMetadata.GetInstanceId(),
|
||||
Name: orchestrationMetadata.GetName(),
|
||||
RuntimeStatus: Status(orchestrationMetadata.GetRuntimeStatus().Number()),
|
||||
CreatedAt: orchestrationMetadata.GetCreatedAt().AsTime(),
|
||||
LastUpdatedAt: orchestrationMetadata.GetLastUpdatedAt().AsTime(),
|
||||
SerializedInput: orchestrationMetadata.GetInput().GetValue(),
|
||||
SerializedOutput: orchestrationMetadata.GetOutput().GetValue(),
|
||||
SerializedCustomStatus: orchestrationMetadata.GetCustomStatus().GetValue(),
|
||||
}
|
||||
if orchestrationMetadata.FailureDetails != nil {
|
||||
if orchestrationMetadata.GetFailureDetails() != nil {
|
||||
metadata.FailureDetails = &FailureDetails{
|
||||
Type: orchestrationMetadata.FailureDetails.GetErrorType(),
|
||||
Message: orchestrationMetadata.FailureDetails.GetErrorMessage(),
|
||||
StackTrace: orchestrationMetadata.FailureDetails.GetStackTrace().GetValue(),
|
||||
IsNonRetriable: orchestrationMetadata.FailureDetails.GetIsNonRetriable(),
|
||||
Type: orchestrationMetadata.GetFailureDetails().GetErrorType(),
|
||||
Message: orchestrationMetadata.GetFailureDetails().GetErrorMessage(),
|
||||
StackTrace: orchestrationMetadata.GetFailureDetails().GetStackTrace().GetValue(),
|
||||
IsNonRetriable: orchestrationMetadata.GetFailureDetails().GetIsNonRetriable(),
|
||||
}
|
||||
|
||||
if orchestrationMetadata.FailureDetails.GetInnerFailure() != nil {
|
||||
if orchestrationMetadata.GetFailureDetails().GetInnerFailure() != nil {
|
||||
var root *FailureDetails
|
||||
current := root
|
||||
failure := orchestrationMetadata.FailureDetails.GetInnerFailure()
|
||||
failure := orchestrationMetadata.GetFailureDetails().GetInnerFailure()
|
||||
for {
|
||||
current.Type = failure.GetErrorType()
|
||||
current.Message = failure.GetErrorMessage()
|
||||
|
@ -87,8 +88,9 @@ func convertMetadata(orchestrationMetadata *api.OrchestrationMetadata) *Metadata
|
|||
}
|
||||
|
||||
type callChildWorkflowOptions struct {
|
||||
instanceID string
|
||||
rawInput *wrapperspb.StringValue
|
||||
instanceID string
|
||||
rawInput *wrapperspb.StringValue
|
||||
retryPolicy *RetryPolicy
|
||||
}
|
||||
|
||||
type callChildWorkflowOption func(*callChildWorkflowOptions) error
|
||||
|
@ -121,6 +123,26 @@ func ChildWorkflowInstanceID(instanceID string) callChildWorkflowOption {
|
|||
}
|
||||
}
|
||||
|
||||
func ChildWorkflowRetryPolicy(policy RetryPolicy) callChildWorkflowOption {
|
||||
return func(opts *callChildWorkflowOptions) error {
|
||||
opts.retryPolicy = &policy
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (opts *callChildWorkflowOptions) getRetryPolicy() *task.RetryPolicy {
|
||||
if opts.retryPolicy == nil {
|
||||
return nil
|
||||
}
|
||||
return &task.RetryPolicy{
|
||||
MaxAttempts: opts.retryPolicy.MaxAttempts,
|
||||
InitialRetryInterval: opts.retryPolicy.InitialRetryInterval,
|
||||
BackoffCoefficient: opts.retryPolicy.BackoffCoefficient,
|
||||
MaxRetryInterval: opts.retryPolicy.MaxRetryInterval,
|
||||
RetryTimeout: opts.retryPolicy.RetryTimeout,
|
||||
}
|
||||
}
|
||||
|
||||
// NewTaskSlice returns a slice of tasks which can be executed in parallel
|
||||
func NewTaskSlice(length int) []task.Task {
|
||||
taskSlice := make([]task.Task, length)
|
||||
|
|
|
@ -2,15 +2,18 @@ package workflow
|
|||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/microsoft/durabletask-go/api"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/dapr/durabletask-go/api/protos"
|
||||
"github.com/dapr/durabletask-go/task"
|
||||
)
|
||||
|
||||
func TestConvertMetadata(t *testing.T) {
|
||||
t.Run("convert metadata", func(t *testing.T) {
|
||||
rawMetadata := &api.OrchestrationMetadata{
|
||||
InstanceID: api.InstanceID("test"),
|
||||
rawMetadata := &protos.OrchestrationMetadata{
|
||||
InstanceId: "test",
|
||||
}
|
||||
metadata := convertMetadata(rawMetadata)
|
||||
assert.NotEmpty(t, metadata)
|
||||
|
@ -37,6 +40,26 @@ func TestCallChildWorkflowOptions(t *testing.T) {
|
|||
opts := returnCallChildWorkflowOptions(ChildWorkflowInput(make(chan int)))
|
||||
assert.Empty(t, opts.rawInput.GetValue())
|
||||
})
|
||||
|
||||
t.Run("child workflow retry policy - set", func(t *testing.T) {
|
||||
opts := returnCallChildWorkflowOptions(ChildWorkflowRetryPolicy(RetryPolicy{
|
||||
MaxAttempts: 3,
|
||||
InitialRetryInterval: 100 * time.Millisecond,
|
||||
BackoffCoefficient: 2,
|
||||
MaxRetryInterval: 2 * time.Second,
|
||||
}))
|
||||
assert.Equal(t, &task.RetryPolicy{
|
||||
MaxAttempts: 3,
|
||||
InitialRetryInterval: 100 * time.Millisecond,
|
||||
BackoffCoefficient: 2,
|
||||
MaxRetryInterval: 2 * time.Second,
|
||||
}, opts.getRetryPolicy())
|
||||
})
|
||||
|
||||
t.Run("child workflow retry policy - empty", func(t *testing.T) {
|
||||
opts := returnCallChildWorkflowOptions()
|
||||
assert.Empty(t, opts.getRetryPolicy())
|
||||
})
|
||||
}
|
||||
|
||||
func returnCallChildWorkflowOptions(opts ...callChildWorkflowOption) callChildWorkflowOptions {
|
||||
|
|
Loading…
Reference in New Issue