diff --git a/.golangci.yaml b/.golangci.yaml index 6dbf6f9..2e2fe06 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -19,6 +19,7 @@ linters: - gci - funlen - maintidx + - containedctx linters-settings: goimports: local-prefixes: github.com/diagridio diff --git a/api.go b/api.go index f661e1b..981080b 100644 --- a/api.go +++ b/api.go @@ -99,7 +99,7 @@ func (c *cron) Delete(ctx context.Context, name string) error { return err } - return c.queue.Dequeue(c.key.JobKey(name)) + return nil } // validateName validates the name of a job. diff --git a/api_test.go b/api_test.go index 2a155d9..ce1ac0f 100644 --- a/api_test.go +++ b/api_test.go @@ -495,7 +495,8 @@ func Test_validateName(t *testing.T) { } for _, test := range tests { - test := test + name := test.name + expErr := test.expErr t.Run(test.name, func(t *testing.T) { t.Parallel() c, err := New(Options{ @@ -506,8 +507,8 @@ func Test_validateName(t *testing.T) { TriggerFn: func(context.Context, *api.TriggerRequest) bool { return true }, }) require.NoError(t, err) - err = c.(*cron).validateName(test.name) - assert.Equal(t, test.expErr, err != nil, "%v", err) + err = c.(*cron).validateName(name) + assert.Equal(t, expErr, err != nil, "%v", err) }) } } diff --git a/cron.go b/cron.go index 8071a1c..4b19154 100644 --- a/cron.go +++ b/cron.go @@ -107,7 +107,7 @@ type cron struct { wg sync.WaitGroup // queueLock prevents an informed schedule from overwriting a job as it is // being triggered, i.e. prevent a PUT and mid-trigger race condition. - queueLock sync.RWMutex + queueLock concurrency.MutexMap[string] } // New creates a new cron instance. @@ -178,6 +178,7 @@ func New(opts Options) (Interface, error) { readyCh: make(chan struct{}), closeCh: make(chan struct{}), errCh: make(chan error), + queueLock: concurrency.NewMutexMap[string](), }, nil } @@ -190,12 +191,20 @@ func (c *cron) Run(ctx context.Context) error { c.queue = queue.NewProcessor[string, *counter.Counter]( func(counter *counter.Counter) { - c.queueLock.RLock() + c.queueLock.Lock(counter.Key()) + if ctx.Err() != nil { + c.queueLock.Unlock(counter.Key()) + return + } + c.wg.Add(1) go func() { - defer c.queueLock.RUnlock() defer c.wg.Done() - c.handleTrigger(ctx, counter) + if c.handleTrigger(ctx, counter) { + c.queueLock.Unlock(counter.Key()) + } else { + c.queueLock.DeleteUnlock(counter.Key()) + } }() }, ).WithClock(c.clock) @@ -259,7 +268,8 @@ func (c *cron) Run(ctx context.Context) error { } // handleTrigger handles triggering a schedule job. -func (c *cron) handleTrigger(ctx context.Context, counter *counter.Counter) { +// Returns true if the job is being re-enqueued, false otherwise. +func (c *cron) handleTrigger(ctx context.Context, counter *counter.Counter) bool { if !c.triggerFn(ctx, counter.TriggerRequest()) { // If the trigger function returns false, i.e. failed client side, // re-enqueue the job immediately. @@ -269,7 +279,7 @@ func (c *cron) handleTrigger(ctx context.Context, counter *counter.Counter) { case c.errCh <- err: } } - return + return true } ok, err := counter.Trigger(ctx) @@ -283,29 +293,26 @@ func (c *cron) handleTrigger(ctx context.Context, counter *counter.Counter) { case c.errCh <- err: } } + + return true } + + return false } // handleInformerEvent handles an etcd informed event. -// TODO: @joshvanl: add a safe per key read lock to prevent locking all -// triggers and an unrelated write. Must be able to handle a key being -// de-queued and unlocked (deleted) whilst an Add schedule is waiting on the -// lock, and visa versa. I don't think there is much if any we gain though as -// we _always_ hack to lock somewhere.. func (c *cron) handleInformerEvent(ctx context.Context, e *informer.Event) error { - c.queueLock.Lock() - defer c.queueLock.Unlock() - - select { - case <-ctx.Done(): + if ctx.Err() != nil { return ctx.Err() - default: } + c.queueLock.Lock(string(e.Key)) if e.IsPut { + defer c.queueLock.Unlock(string(e.Key)) return c.schedule(ctx, c.key.JobName(e.Key), e.Job) } + defer c.queueLock.DeleteUnlock(string(e.Key)) return c.queue.Dequeue(string(e.Key)) } diff --git a/cron_test.go b/cron_test.go index 8a6494e..db5f942 100644 --- a/cron_test.go +++ b/cron_test.go @@ -23,83 +23,41 @@ import ( "google.golang.org/protobuf/types/known/wrapperspb" "github.com/diagridio/go-etcd-cron/api" + "github.com/diagridio/go-etcd-cron/internal/client" "github.com/diagridio/go-etcd-cron/internal/tests" ) func Test_retry(t *testing.T) { t.Parallel() - client := tests.EmbeddedETCDBareClient(t) - var triggerd atomic.Int64 - cron, err := New(Options{ - Log: logr.Discard(), - Client: client, - Namespace: "abc", - PartitionID: 0, - PartitionTotal: 1, - TriggerFn: func(context.Context, *api.TriggerRequest) bool { - triggerd.Add(1) - return triggerd.Load() != 1 - }, + var ok atomic.Bool + helper := testCronWithOptions(t, testCronOptions{ + total: 1, + returnOk: &ok, }) - require.NoError(t, err) - - errCh := make(chan error) - ctx, cancel := context.WithCancel(context.Background()) - t.Cleanup(func() { - cancel() - select { - case err := <-errCh: - require.NoError(t, err) - case <-time.After(5 * time.Second): - t.Fatal("timeout waiting for cron to stop") - } - }) - go func() { - errCh <- cron.Run(ctx) - }() job := &api.Job{ DueTime: ptr.Of(time.Now().Format(time.RFC3339)), } - require.NoError(t, cron.Add(ctx, "yoyo", job)) + require.NoError(t, helper.cron.Add(helper.ctx, "yoyo", job)) + assert.EventuallyWithT(t, func(c *assert.CollectT) { + assert.Greater(c, helper.triggered.Load(), int64(2)) + }, 5*time.Second, 10*time.Millisecond) + ok.Store(true) + triggered := helper.triggered.Load() <-time.After(3 * time.Second) - assert.Equal(t, int64(2), triggerd.Load()) + assert.Equal(t, triggered+1, helper.triggered.Load()) } func Test_payload(t *testing.T) { t.Parallel() - client := tests.EmbeddedETCDBareClient(t) gotCh := make(chan *api.TriggerRequest, 1) - cron, err := New(Options{ - Log: logr.Discard(), - Client: client, - Namespace: "abc", - PartitionID: 0, - PartitionTotal: 1, - TriggerFn: func(_ context.Context, api *api.TriggerRequest) bool { - gotCh <- api - return true - }, - }) - require.NoError(t, err) - - errCh := make(chan error) - ctx, cancel := context.WithCancel(context.Background()) - t.Cleanup(func() { - cancel() - select { - case err := <-errCh: - require.NoError(t, err) - case <-time.After(5 * time.Second): - t.Fatal("timeout waiting for cron to stop") - } + helper := testCronWithOptions(t, testCronOptions{ + total: 1, + gotCh: gotCh, }) - go func() { - errCh <- cron.Run(ctx) - }() payload, err := anypb.New(wrapperspb.String("hello")) require.NoError(t, err) @@ -110,7 +68,7 @@ func Test_payload(t *testing.T) { Payload: payload, Metadata: meta, } - require.NoError(t, cron.Add(ctx, "yoyo", job)) + require.NoError(t, helper.cron.Add(helper.ctx, "yoyo", job)) select { case got := <-gotCh: @@ -129,95 +87,38 @@ func Test_payload(t *testing.T) { func Test_remove(t *testing.T) { t.Parallel() - client := tests.EmbeddedETCDBareClient(t) - var triggered atomic.Int64 - cron, err := New(Options{ - Log: logr.Discard(), - Client: client, - Namespace: "abc", - PartitionID: 0, - PartitionTotal: 1, - TriggerFn: func(context.Context, *api.TriggerRequest) bool { - triggered.Add(1) - return true - }, - }) - require.NoError(t, err) - - errCh := make(chan error) - ctx, cancel := context.WithCancel(context.Background()) - t.Cleanup(func() { - cancel() - select { - case err := <-errCh: - require.NoError(t, err) - case <-time.After(5 * time.Second): - t.Fatal("timeout waiting for cron to stop") - } - }) - go func() { - errCh <- cron.Run(ctx) - }() + helper := testCron(t, 1) job := &api.Job{ DueTime: ptr.Of(time.Now().Add(time.Second * 2).Format(time.RFC3339)), } - require.NoError(t, cron.Add(ctx, "def", job)) - require.NoError(t, cron.Delete(ctx, "def")) + require.NoError(t, helper.cron.Add(helper.ctx, "def", job)) + require.NoError(t, helper.cron.Delete(helper.ctx, "def")) <-time.After(3 * time.Second) - assert.Equal(t, int64(0), triggered.Load()) + assert.Equal(t, int64(0), helper.triggered.Load()) } func Test_upsert(t *testing.T) { t.Parallel() - client := tests.EmbeddedETCDBareClient(t) - var triggered atomic.Int64 - cron, err := New(Options{ - Log: logr.Discard(), - Client: client, - Namespace: "abc", - PartitionID: 0, - PartitionTotal: 1, - TriggerFn: func(context.Context, *api.TriggerRequest) bool { - triggered.Add(1) - - return true - }, - }) - require.NoError(t, err) - - errCh := make(chan error) - ctx, cancel := context.WithCancel(context.Background()) - t.Cleanup(func() { - cancel() - select { - case err := <-errCh: - require.NoError(t, err) - case <-time.After(5 * time.Second): - t.Fatal("timeout waiting for cron to stop") - } - }) - go func() { - errCh <- cron.Run(ctx) - }() + helper := testCron(t, 1) job := &api.Job{ DueTime: ptr.Of(time.Now().Add(time.Hour).Format(time.RFC3339)), } - require.NoError(t, cron.Add(ctx, "def", job)) + require.NoError(t, helper.cron.Add(helper.ctx, "def", job)) job = &api.Job{ DueTime: ptr.Of(time.Now().Add(time.Second).Format(time.RFC3339)), } - require.NoError(t, cron.Add(ctx, "def", job)) + require.NoError(t, helper.cron.Add(helper.ctx, "def", job)) assert.Eventually(t, func() bool { - return triggered.Load() == 1 + return helper.triggered.Load() == 1 }, 5*time.Second, 1*time.Second) - resp, err := client.Get(context.Background(), "abc/jobs/def") + resp, err := helper.client.Get(context.Background(), "abc/jobs/def") require.NoError(t, err) assert.Empty(t, resp.Kvs) } @@ -225,57 +126,20 @@ func Test_upsert(t *testing.T) { func Test_patition(t *testing.T) { t.Parallel() - client := tests.EmbeddedETCDBareClient(t) - var triggered atomic.Int64 - - crons := make([]Interface, 100) - for i := 0; i < 100; i++ { - cron, err := New(Options{ - Log: logr.Discard(), - Client: client, - Namespace: "abc", - PartitionID: uint32(i), - PartitionTotal: 100, - TriggerFn: func(context.Context, *api.TriggerRequest) bool { - triggered.Add(1) - return true - }, - }) - require.NoError(t, err) - crons[i] = cron - } - - errCh := make(chan error) - ctx, cancel := context.WithCancel(context.Background()) - t.Cleanup(func() { - cancel() - for i := 0; i < 100; i++ { - select { - case err := <-errCh: - require.NoError(t, err) - case <-time.After(5 * time.Second): - t.Fatal("timeout waiting for cron to stop") - } - } - }) - for i := 0; i < 100; i++ { - go func(i int) { - errCh <- crons[i].Run(ctx) - }(i) - } + helper := testCron(t, 100) for i := 0; i < 100; i++ { job := &api.Job{ DueTime: ptr.Of(time.Now().Add(time.Second).Format(time.RFC3339)), } - require.NoError(t, crons[0].Add(ctx, "test-"+strconv.Itoa(i), job)) + require.NoError(t, helper.allCrons[i].Add(helper.ctx, "test-"+strconv.Itoa(i), job)) } assert.Eventually(t, func() bool { - return triggered.Load() == 100 + return helper.triggered.Load() == 100 }, 5*time.Second, 1*time.Second) - resp, err := client.Get(context.Background(), "abc/jobs", clientv3.WithPrefix()) + resp, err := helper.client.Get(context.Background(), "abc/jobs", clientv3.WithPrefix()) require.NoError(t, err) assert.Empty(t, resp.Kvs) } @@ -283,47 +147,19 @@ func Test_patition(t *testing.T) { func Test_oneshot(t *testing.T) { t.Parallel() - client := tests.EmbeddedETCDBareClient(t) - var triggered atomic.Int64 - cron, err := New(Options{ - Log: logr.Discard(), - Client: client, - Namespace: "abc", - PartitionID: 0, - PartitionTotal: 1, - TriggerFn: func(context.Context, *api.TriggerRequest) bool { - triggered.Add(1) - return true - }, - }) - require.NoError(t, err) - - errCh := make(chan error) - ctx, cancel := context.WithCancel(context.Background()) - t.Cleanup(func() { - cancel() - select { - case err := <-errCh: - require.NoError(t, err) - case <-time.After(5 * time.Second): - t.Fatal("timeout waiting for cron to stop") - } - }) - go func() { - errCh <- cron.Run(ctx) - }() + helper := testCron(t, 1) job := &api.Job{ DueTime: ptr.Of(time.Now().Add(time.Second).Format(time.RFC3339)), } - require.NoError(t, cron.Add(ctx, "def", job)) + require.NoError(t, helper.cron.Add(helper.ctx, "def", job)) assert.Eventually(t, func() bool { - return triggered.Load() == 1 + return helper.triggered.Load() == 1 }, 5*time.Second, 1*time.Second) - resp, err := client.Get(context.Background(), "abc/jobs/def") + resp, err := helper.client.Get(context.Background(), "abc/jobs/def") require.NoError(t, err) assert.Empty(t, resp.Kvs) } @@ -331,48 +167,20 @@ func Test_oneshot(t *testing.T) { func Test_repeat(t *testing.T) { t.Parallel() - client := tests.EmbeddedETCDBareClient(t) - var triggered atomic.Int64 - cron, err := New(Options{ - Log: logr.Discard(), - Client: client, - Namespace: "abc", - PartitionID: 0, - PartitionTotal: 1, - TriggerFn: func(context.Context, *api.TriggerRequest) bool { - triggered.Add(1) - return true - }, - }) - require.NoError(t, err) - - errCh := make(chan error) - ctx, cancel := context.WithCancel(context.Background()) - t.Cleanup(func() { - cancel() - select { - case err := <-errCh: - require.NoError(t, err) - case <-time.After(5 * time.Second): - t.Fatal("timeout waiting for cron to stop") - } - }) - go func() { - errCh <- cron.Run(ctx) - }() + helper := testCron(t, 1) job := &api.Job{ Schedule: ptr.Of("@every 1s"), Repeats: ptr.Of(uint32(3)), } - require.NoError(t, cron.Add(ctx, "def", job)) + require.NoError(t, helper.cron.Add(helper.ctx, "def", job)) - assert.Eventually(t, func() bool { - return triggered.Load() == 3 + assert.EventuallyWithT(t, func(c *assert.CollectT) { + assert.Equal(c, int64(3), helper.triggered.Load()) }, 5*time.Second, 1*time.Second) - resp, err := client.Get(context.Background(), "abc/jobs/def") + resp, err := helper.client.Get(context.Background(), "abc/jobs/def") require.NoError(t, err) assert.Empty(t, resp.Kvs) } @@ -671,55 +479,155 @@ func Test_schedule(t *testing.T) { func Test_zeroDueTime(t *testing.T) { t.Parallel() - client := tests.EmbeddedETCDBareClient(t) - var triggerd atomic.Int64 - cron, err := New(Options{ - Log: logr.Discard(), - Client: client, - Namespace: "abc", - PartitionID: 0, - PartitionTotal: 1, - TriggerFn: func(context.Context, *api.TriggerRequest) bool { - triggerd.Add(1) - return true - }, - }) - require.NoError(t, err) + helper := testCron(t, 1) - errCh := make(chan error) - ctx, cancel := context.WithCancel(context.Background()) - t.Cleanup(func() { - cancel() - select { - case err := <-errCh: - require.NoError(t, err) - case <-time.After(5 * time.Second): - t.Fatal("timeout waiting for cron to stop") - } - }) - go func() { - errCh <- cron.Run(ctx) - }() - - require.NoError(t, cron.Add(ctx, "yoyo", &api.Job{ + require.NoError(t, helper.cron.Add(helper.ctx, "yoyo", &api.Job{ Schedule: ptr.Of("@every 1h"), DueTime: ptr.Of("0s"), })) assert.Eventually(t, func() bool { - return triggerd.Load() == 1 + return helper.triggered.Load() == 1 }, 3*time.Second, time.Millisecond*10) - require.NoError(t, cron.Add(ctx, "yoyo2", &api.Job{ + require.NoError(t, helper.cron.Add(helper.ctx, "yoyo2", &api.Job{ Schedule: ptr.Of("@every 1h"), DueTime: ptr.Of("1s"), })) assert.Eventually(t, func() bool { - return triggerd.Load() == 2 + return helper.triggered.Load() == 2 }, 3*time.Second, time.Millisecond*10) - require.NoError(t, cron.Add(ctx, "yoyo3", &api.Job{ + require.NoError(t, helper.cron.Add(helper.ctx, "yoyo3", &api.Job{ Schedule: ptr.Of("@every 1h"), })) <-time.After(2 * time.Second) - assert.Equal(t, int64(2), triggerd.Load()) + assert.Equal(t, int64(2), helper.triggered.Load()) +} + +func Test_parallel(t *testing.T) { + t.Parallel() + + for _, test := range []struct { + name string + total uint32 + }{ + {"1 queue", 1}, + {"multi queue", 50}, + } { + total := test.total + t.Run(test.name, func(t *testing.T) { + t.Parallel() + + releaseCh := make(chan struct{}) + var waiting atomic.Int32 + var done atomic.Int32 + helper := testCronWithOptions(t, testCronOptions{ + total: total, + triggerFn: func() { + waiting.Add(1) + <-releaseCh + done.Add(1) + }, + }) + + for i := 0; i < 100; i++ { + require.NoError(t, helper.cron.Add(helper.ctx, strconv.Itoa(i), &api.Job{ + DueTime: ptr.Of("0s"), + })) + } + + assert.EventuallyWithT(t, func(c *assert.CollectT) { + assert.Equal(c, int32(100), waiting.Load()) + }, 5*time.Second, 10*time.Millisecond) + close(releaseCh) + assert.EventuallyWithT(t, func(c *assert.CollectT) { + assert.Equal(c, int32(100), done.Load()) + }, 5*time.Second, 10*time.Millisecond) + }) + } +} + +type testCronOptions struct { + total uint32 + returnOk *atomic.Bool + gotCh chan *api.TriggerRequest + triggerFn func() +} + +type helper struct { + ctx context.Context + client client.Interface + cron Interface + allCrons []Interface + triggered *atomic.Int64 +} + +func testCron(t *testing.T, total uint32) *helper { + t.Helper() + return testCronWithOptions(t, testCronOptions{ + total: total, + }) +} + +func testCronWithOptions(t *testing.T, opts testCronOptions) *helper { + t.Helper() + + require.Greater(t, opts.total, uint32(0)) + cl := tests.EmbeddedETCDBareClient(t) + + var triggered atomic.Int64 + var cron Interface + allCrns := make([]Interface, opts.total) + for i := 0; i < int(opts.total); i++ { + c, err := New(Options{ + Log: logr.Discard(), + Client: cl, + Namespace: "abc", + PartitionID: uint32(i), + PartitionTotal: opts.total, + TriggerFn: func(_ context.Context, req *api.TriggerRequest) bool { + ok := opts.returnOk == nil || opts.returnOk.Load() + triggered.Add(1) + if opts.gotCh != nil { + opts.gotCh <- req + } + if opts.triggerFn != nil { + opts.triggerFn() + } + return ok + }, + }) + require.NoError(t, err) + allCrns[i] = c + if i == 0 { + cron = c + } + } + + errCh := make(chan error, opts.total) + ctx, cancel := context.WithCancel(context.Background()) + t.Cleanup(func() { + cancel() + for i := 0; i < int(opts.total); i++ { + select { + case err := <-errCh: + require.NoError(t, err) + case <-time.After(5 * time.Second): + t.Fatal("timeout waiting for cron to stop") + } + } + }) + for i := uint32(0); i < opts.total; i++ { + go func(i uint32) { + errCh <- allCrns[i].Run(ctx) + }(i) + } + + return &helper{ + ctx: ctx, + client: client.New(cl), + cron: cron, + allCrons: allCrns, + triggered: &triggered, + } } diff --git a/go.mod b/go.mod index 0743451..e963da1 100644 --- a/go.mod +++ b/go.mod @@ -1,12 +1,12 @@ module github.com/diagridio/go-etcd-cron -go 1.21.9 +go 1.22.5 require ( - github.com/dapr/kit v0.13.0 + github.com/dapr/kit v0.13.1-0.20240722163453-58c6d9df14d3 github.com/go-logr/logr v1.3.0 github.com/go-logr/zapr v1.3.0 - github.com/stretchr/testify v1.8.4 + github.com/stretchr/testify v1.9.0 go.etcd.io/etcd/api/v3 v3.5.13 go.etcd.io/etcd/client/pkg/v3 v3.5.13 go.etcd.io/etcd/client/v3 v3.5.13 @@ -63,15 +63,16 @@ require ( go.opentelemetry.io/otel/trace v1.20.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.uber.org/multierr v1.10.0 // indirect - golang.org/x/crypto v0.21.0 // indirect - golang.org/x/net v0.23.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/crypto v0.24.0 // indirect + golang.org/x/exp v0.0.0-20231006140011-7918f672742d // 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 golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect - google.golang.org/grpc v1.59.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect + google.golang.org/grpc v1.64.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 6b956a2..ea6c2ef 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.110.7 h1:rJyC7nWRg2jWGZ4wSJ5nY65GTdYJkg0cd/uXb+ACI6o= -cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY= -cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute v1.25.1 h1:ZRpHJedLtTpKgr3RV1Fx23NuaAEN1Zfx9hw1u4aJdjU= +cloud.google.com/go/compute v1.25.1/go.mod h1:oopOIR53ly6viBYxaDhBfJwzUAxf1zE//uf3IB011ls= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= @@ -25,16 +25,16 @@ github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50 h1:DBmgJDC9dTfkVyGgipamEh2BpGYxScCH1TOF1LL1cXc= +github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50/go.mod h1:5e1+Vvlzido69INQaVO6d87Qn543Xr6nooe9Kz7oBFM= github.com/cockroachdb/datadriven v1.0.2 h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD93PBm/jA= github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/dapr/kit v0.13.0 h1:4S+5QqDCreva+MBONtIgxeg6B2b1W89bB8F5lqKgTa0= -github.com/dapr/kit v0.13.0/go.mod h1:VyHrelNXPbtS/VcQX0Y/uzW0lfEVuveJ+1E5bDys8mo= +github.com/dapr/kit v0.13.1-0.20240722163453-58c6d9df14d3 h1:+HZd67sGtxQq7UoEXpby0x0pE0XcZwTY03UuZc48P/M= +github.com/dapr/kit v0.13.1-0.20240722163453-58c6d9df14d3/go.mod h1:Hz1W2LmWfA4UX/12MdA+brsf+np6f/1dJt6C6F63cjI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -44,8 +44,8 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= -github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= +github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= +github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -68,8 +68,8 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69 github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs= github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= -github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= +github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= +github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -182,8 +182,8 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +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/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= @@ -235,8 +235,8 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf 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/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= @@ -259,13 +259,13 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +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/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU= -golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk= +golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= +golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -273,8 +273,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -289,13 +289,13 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +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.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +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/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -312,26 +312,26 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d h1:VBu5YqKPv6XiJ199exd8Br+Aetz+o08F+PLMnwJQHAY= google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= -google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d h1:DoPTO70H+bcDXcd39vOqb2viZxgqeBeSGtZ55yZU4/Q= -google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= +google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 h1:RFiFrvy37/mpSpdySBDrUdipW/dHwsRwh3J3+A9VgT4= +google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237/go.mod h1:Z5Iiy3jtmioajWHDGFk7CeugTyHtPvMHA4UTmUkyalE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 h1:NnYq6UN9ReLM9/Y01KWNOWyI5xQ9kbIms5GGJVwS/Yc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= -google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= +google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= +google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/internal/client/client_test.go b/internal/client/client_test.go index 28e11af..363debe 100644 --- a/internal/client/client_test.go +++ b/internal/client/client_test.go @@ -83,8 +83,7 @@ func Test_Delete(t *testing.T) { } for name, test := range tests { - name, test := name, test - + testInLoop := test t.Run(name, func(t *testing.T) { t.Parallel() @@ -92,7 +91,7 @@ func Test_Delete(t *testing.T) { t.Parallel() kv := new(mock) - require.NoError(t, test(&client{kv: kv})) + require.NoError(t, testInLoop(&client{kv: kv})) assert.Equal(t, uint32(1), kv.calls.Load()) }) @@ -101,7 +100,7 @@ func Test_Delete(t *testing.T) { kv := new(mock) kv.err = errors.New("this is an error") - require.Error(t, test(&client{kv: kv})) + require.Error(t, testInLoop(&client{kv: kv})) assert.Equal(t, uint32(1), kv.calls.Load()) }) @@ -122,7 +121,7 @@ func Test_Delete(t *testing.T) { }) go func() { - errCh <- test(&client{kv: kv, clock: clock}) + errCh <- testInLoop(&client{kv: kv, clock: clock}) }() assert.Eventually(t, clock.HasWaiters, time.Second, time.Millisecond*10) @@ -151,7 +150,7 @@ func Test_Delete(t *testing.T) { }) go func() { - errCh <- test(&client{kv: kv, clock: clock}) + errCh <- testInLoop(&client{kv: kv, clock: clock}) }() assert.Eventually(t, clock.HasWaiters, time.Second, time.Millisecond*10) diff --git a/internal/counter/counter_test.go b/internal/counter/counter_test.go index 03acb25..568c30d 100644 --- a/internal/counter/counter_test.go +++ b/internal/counter/counter_test.go @@ -880,12 +880,13 @@ func Test_updateNext(t *testing.T) { } for name, test := range tests { - test := test + counter := test.counter + exp := test.exp + expNext := test.expNext t.Run(name, func(t *testing.T) { t.Parallel() - c := test.counter - assert.Equal(t, test.exp, c.updateNext()) - assert.Equal(t, test.expNext, c.next) + assert.Equal(t, exp, counter.updateNext()) + assert.Equal(t, expNext, counter.next) }) } } diff --git a/internal/grave/yard_test.go b/internal/grave/yard_test.go index c32d63a..4d5d7c5 100644 --- a/internal/grave/yard_test.go +++ b/internal/grave/yard_test.go @@ -120,17 +120,17 @@ func Test_HasJustDeleted(t *testing.T) { } for name, test := range tests { - test := test + testInLoop := test t.Run(name, func(t *testing.T) { t.Parallel() yard := New() - for _, key := range test.deletes { + for _, key := range testInLoop.deletes { yard.Deleted(key) } - assert.Equal(t, test.expBool, yard.HasJustDeleted(test.key)) - assert.Equal(t, test.expMap, yard.deletesMap) + assert.Equal(t, testInLoop.expBool, yard.HasJustDeleted(testInLoop.key)) + assert.Equal(t, testInLoop.expMap, yard.deletesMap) }) } } diff --git a/internal/informer/informer_test.go b/internal/informer/informer_test.go index 18975f9..0268d5f 100644 --- a/internal/informer/informer_test.go +++ b/internal/informer/informer_test.go @@ -333,7 +333,7 @@ func Test_handleEvent(t *testing.T) { } for name, test := range tests { - test := test + testInLoop := test t.Run(name, func(t *testing.T) { t.Parallel() part, err := partitioner.New(partitioner.Options{ @@ -345,8 +345,8 @@ func Test_handleEvent(t *testing.T) { collector := fake.New() yard := grave.New() - if test.yardDelete != nil { - yard.Deleted(*test.yardDelete) + if testInLoop.yardDelete != nil { + yard.Deleted(*testInLoop.yardDelete) } i := New(Options{ @@ -358,10 +358,10 @@ func Test_handleEvent(t *testing.T) { PartitionID: 0, }), }) - gotEvent, err := i.handleEvent(test.ev) - assert.Equal(t, test.expEvent, gotEvent) - assert.Equal(t, test.expErr, err != nil, "%v", err) - assert.Equal(t, test.expCollectorPops, collector.HasPoped()) + gotEvent, err := i.handleEvent(testInLoop.ev) + assert.Equal(t, testInLoop.expEvent, gotEvent) + assert.Equal(t, testInLoop.expErr, err != nil, "%v", err) + assert.Equal(t, testInLoop.expCollectorPops, collector.HasPoped()) }) } } diff --git a/internal/key/key_test.go b/internal/key/key_test.go index 34f9ff2..34e947d 100644 --- a/internal/key/key_test.go +++ b/internal/key/key_test.go @@ -42,14 +42,14 @@ func Test_JobKey(t *testing.T) { } for _, test := range tests { - test := test + testInLoop := test t.Run(test.namespace+"/"+test.jobName, func(t *testing.T) { t.Parallel() key := New(Options{ - Namespace: test.namespace, - PartitionID: test.partitionID, + Namespace: testInLoop.namespace, + PartitionID: testInLoop.partitionID, }) - assert.Equal(t, test.expJobKey, key.JobKey(test.jobName)) + assert.Equal(t, testInLoop.expJobKey, key.JobKey(testInLoop.jobName)) }) } } @@ -84,14 +84,14 @@ func Test_CounterKey(t *testing.T) { } for _, test := range tests { - test := test + testInLoop := test t.Run(test.namespace+"/"+test.jobName, func(t *testing.T) { t.Parallel() key := New(Options{ - Namespace: test.namespace, - PartitionID: test.partitionID, + Namespace: testInLoop.namespace, + PartitionID: testInLoop.partitionID, }) - assert.Equal(t, test.expCounterKey, key.CounterKey(test.jobName)) + assert.Equal(t, testInLoop.expCounterKey, key.CounterKey(testInLoop.jobName)) }) } } @@ -118,14 +118,14 @@ func Test_LeadershipNamespace(t *testing.T) { } for _, test := range tests { - test := test + testInLoop := test t.Run(test.namespace, func(t *testing.T) { t.Parallel() key := New(Options{ - Namespace: test.namespace, + Namespace: testInLoop.namespace, PartitionID: 123, }) - assert.Equal(t, test.expLeadershipNS, key.LeadershipNamespace()) + assert.Equal(t, testInLoop.expLeadershipNS, key.LeadershipNamespace()) }) } } @@ -156,14 +156,14 @@ func Test_LeadershipKey(t *testing.T) { } for _, test := range tests { - test := test + testInLoop := test t.Run(fmt.Sprintf("%s/%d", test.namespace, test.partitionID), func(t *testing.T) { t.Parallel() key := New(Options{ - Namespace: test.namespace, - PartitionID: test.partitionID, + Namespace: testInLoop.namespace, + PartitionID: testInLoop.partitionID, }) - assert.Equal(t, test.expLeadershipKey, key.LeadershipKey()) + assert.Equal(t, testInLoop.expLeadershipKey, key.LeadershipKey()) }) } } @@ -190,14 +190,14 @@ func Test_JobNamespace(t *testing.T) { } for _, test := range tests { - test := test + testInLoop := test t.Run(test.namespace, func(t *testing.T) { t.Parallel() key := New(Options{ - Namespace: test.namespace, + Namespace: testInLoop.namespace, PartitionID: 123, }) - assert.Equal(t, test.expJobNS, key.JobNamespace()) + assert.Equal(t, testInLoop.expJobNS, key.JobNamespace()) }) } } @@ -224,14 +224,14 @@ func Test_JobName(t *testing.T) { } for _, test := range tests { - test := test + testInLoop := test t.Run(test.key, func(t *testing.T) { t.Parallel() key := New(Options{ Namespace: "/123", PartitionID: 123, }) - assert.Equal(t, test.expJobName, key.JobName([]byte(test.key))) + assert.Equal(t, testInLoop.expJobName, key.JobName([]byte(testInLoop.key))) }) } } diff --git a/internal/partitioner/partitioner_test.go b/internal/partitioner/partitioner_test.go index 0d5694f..dac10bf 100644 --- a/internal/partitioner/partitioner_test.go +++ b/internal/partitioner/partitioner_test.go @@ -53,15 +53,15 @@ func Test_New(t *testing.T) { } for name, test := range tests { - test := test + testInLoop := test t.Run(name, func(t *testing.T) { t.Parallel() parter, err := New(Options{ - ID: test.id, - Total: test.total, + ID: testInLoop.id, + Total: testInLoop.total, }) - assert.Equal(t, test.exp, parter) - assert.Equal(t, test.expErr, err != nil, "%v", err) + assert.Equal(t, testInLoop.exp, parter) + assert.Equal(t, testInLoop.expErr, err != nil, "%v", err) }) } } diff --git a/internal/scheduler/builder_test.go b/internal/scheduler/builder_test.go index 4eb7bae..245bf51 100644 --- a/internal/scheduler/builder_test.go +++ b/internal/scheduler/builder_test.go @@ -97,13 +97,13 @@ func Test_Scheduler(t *testing.T) { } for name, test := range tests { - test := test + testInLoop := test t.Run(name, func(t *testing.T) { t.Parallel() builder := &Builder{clock: clock} - gotScheduler, gotErr := builder.Scheduler(test.job) - assert.Equal(t, test.expScheduler, gotScheduler) - assert.Equal(t, test.expErr, gotErr != nil, "%v", gotErr) + gotScheduler, gotErr := builder.Scheduler(testInLoop.job) + assert.Equal(t, testInLoop.expScheduler, gotScheduler) + assert.Equal(t, testInLoop.expErr, gotErr != nil, "%v", gotErr) }) } } @@ -294,17 +294,17 @@ func Test_Parse(t *testing.T) { } for name, test := range tests { - test := test + testInLoop := test t.Run(name, func(t *testing.T) { t.Parallel() builder := &Builder{clock: clock} - gotStored, gotErr := builder.Parse(test.job) + gotStored, gotErr := builder.Parse(testInLoop.job) if gotStored != nil { assert.NotEqual(t, uint32(0), gotStored.GetPartitionId()) gotStored.PartitionId = 0 } - assert.Equal(t, test.expStored, gotStored) - assert.Equal(t, test.expErr, gotErr != nil, "%v", gotErr) + assert.Equal(t, testInLoop.expStored, gotStored) + assert.Equal(t, testInLoop.expErr, gotErr != nil, "%v", gotErr) }) } } @@ -352,12 +352,12 @@ func Test_parsePointInTime(t *testing.T) { } for name, test := range tests { - test := test + testInLoop := test t.Run(name, func(t *testing.T) { t.Parallel() - gotTime, gotErr := parsePointInTime(test.str, now) - assert.Equal(t, test.expTime, gotTime) - assert.Equal(t, test.expErr, gotErr != nil, "%v", gotErr) + gotTime, gotErr := parsePointInTime(testInLoop.str, now) + assert.Equal(t, testInLoop.expTime, gotTime) + assert.Equal(t, testInLoop.expErr, gotErr != nil, "%v", gotErr) }) } } diff --git a/internal/scheduler/oneshot_test.go b/internal/scheduler/oneshot_test.go index eafad4e..d88a595 100644 --- a/internal/scheduler/oneshot_test.go +++ b/internal/scheduler/oneshot_test.go @@ -37,11 +37,11 @@ func Test_oneshot(t *testing.T) { } for _, test := range tests { - test := test + testInLoop := test t.Run(strconv.Itoa(int(test.count)), func(t *testing.T) { t.Parallel() oneshot := &oneshot{dueTime: dueTime} - assert.Equal(t, test.expNext, oneshot.Next(test.count, nil)) + assert.Equal(t, testInLoop.expNext, oneshot.Next(testInLoop.count, nil)) }) } } diff --git a/internal/scheduler/repeats_test.go b/internal/scheduler/repeats_test.go index fd68695..34e2b1c 100644 --- a/internal/scheduler/repeats_test.go +++ b/internal/scheduler/repeats_test.go @@ -133,21 +133,21 @@ func Test_repeats(t *testing.T) { } for name, test := range tests { - test := test + testInLoop := test t.Run(name, func(t *testing.T) { t.Parallel() - cron, err := cron.ParseStandard(test.schedule) + cron, err := cron.ParseStandard(testInLoop.schedule) require.NoError(t, err) repeats := &repeats{ - start: test.start, - dueTime: test.dueTime, - exp: test.exp, + start: testInLoop.start, + dueTime: testInLoop.dueTime, + exp: testInLoop.exp, cron: cron, - total: test.total, + total: testInLoop.total, } - assert.Equal(t, test.expNext, repeats.Next(test.count, test.last)) + assert.Equal(t, testInLoop.expNext, repeats.Next(testInLoop.count, testInLoop.last)) }) } }