mirror of
https://github.com/hanzoai/tasks.git
synced 2026-10-04 02:04:03 +00:00
278 lines
9.3 KiB
Go
278 lines
9.3 KiB
Go
// The MIT License
|
|
//
|
|
// Copyright (c) 2020 Temporal Technologies Inc. All rights reserved.
|
|
//
|
|
// Copyright (c) 2020 Uber Technologies, Inc.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
// in the Software without restriction, including without limitation the rights
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
// THE SOFTWARE.
|
|
|
|
package host
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
|
|
"go.temporal.io/server/service/matching"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
"github.com/stretchr/testify/suite"
|
|
|
|
"go.temporal.io/api/serviceerror"
|
|
taskqueuepb "go.temporal.io/api/taskqueue/v1"
|
|
"go.temporal.io/api/workflowservice/v1"
|
|
sdkclient "go.temporal.io/sdk/client"
|
|
"go.temporal.io/sdk/worker"
|
|
"go.temporal.io/sdk/workflow"
|
|
"go.temporal.io/server/common/dynamicconfig"
|
|
"go.temporal.io/server/common/log/tag"
|
|
)
|
|
|
|
type versioningIntegSuite struct {
|
|
// override suite.Suite.Assertions with require.Assertions; this means that s.NotNil(nil) will stop the test,
|
|
// not merely log an error
|
|
*require.Assertions
|
|
IntegrationBase
|
|
sdkClient sdkclient.Client
|
|
}
|
|
|
|
func (s *versioningIntegSuite) SetupSuite() {
|
|
s.dynamicConfigOverrides = make(map[dynamicconfig.Key]interface{})
|
|
s.dynamicConfigOverrides[dynamicconfig.MatchingUpdateAckInterval] = 1 * time.Second
|
|
s.setupSuite("testdata/integration_test_cluster.yaml")
|
|
}
|
|
|
|
func (s *versioningIntegSuite) TearDownSuite() {
|
|
s.tearDownSuite()
|
|
}
|
|
|
|
func (s *versioningIntegSuite) SetupTest() {
|
|
// Have to define our overridden assertions in the test setup. If we did it earlier, s.T() will return nil
|
|
s.Assertions = require.New(s.T())
|
|
|
|
clientAddr := "127.0.0.1:7134"
|
|
if TestFlags.FrontendAddr != "" {
|
|
clientAddr = TestFlags.FrontendAddr
|
|
}
|
|
sdkClient, err := sdkclient.Dial(sdkclient.Options{
|
|
HostPort: clientAddr,
|
|
Namespace: s.namespace,
|
|
})
|
|
if err != nil {
|
|
s.Logger.Fatal("Error when creating SDK client", tag.Error(err))
|
|
}
|
|
s.sdkClient = sdkClient
|
|
}
|
|
|
|
func (s *versioningIntegSuite) TearDownTest() {
|
|
s.sdkClient.Close()
|
|
}
|
|
|
|
func TestVersioningIntegrationSuite(t *testing.T) {
|
|
flag.Parse()
|
|
suite.Run(t, new(versioningIntegSuite))
|
|
}
|
|
|
|
func (s *versioningIntegSuite) TestBasicVersionUpdate() {
|
|
ctx := NewContext()
|
|
tq := "integration-versioning-basic"
|
|
|
|
res, err := s.engine.UpdateWorkerBuildIdOrdering(ctx, &workflowservice.UpdateWorkerBuildIdOrderingRequest{
|
|
Namespace: s.namespace,
|
|
TaskQueue: tq,
|
|
VersionId: &taskqueuepb.VersionId{WorkerBuildId: "foo"},
|
|
PreviousCompatible: nil,
|
|
BecomeDefault: true,
|
|
})
|
|
s.NoError(err)
|
|
s.NotNil(res)
|
|
|
|
res2, err := s.engine.GetWorkerBuildIdOrdering(ctx, &workflowservice.GetWorkerBuildIdOrderingRequest{
|
|
Namespace: s.namespace,
|
|
TaskQueue: tq,
|
|
})
|
|
s.NoError(err)
|
|
s.NotNil(res2)
|
|
s.Equal("foo", res2.CurrentDefault.GetVersion().GetWorkerBuildId())
|
|
}
|
|
|
|
func (s *versioningIntegSuite) TestSeriesOfUpdates() {
|
|
ctx := NewContext()
|
|
tq := "integration-versioning-series"
|
|
|
|
for i := 0; i < 10; i++ {
|
|
res, err := s.engine.UpdateWorkerBuildIdOrdering(ctx, &workflowservice.UpdateWorkerBuildIdOrderingRequest{
|
|
Namespace: s.namespace,
|
|
TaskQueue: tq,
|
|
VersionId: &taskqueuepb.VersionId{WorkerBuildId: fmt.Sprintf("foo-%d", i)},
|
|
PreviousCompatible: nil,
|
|
BecomeDefault: true,
|
|
})
|
|
s.NoError(err)
|
|
s.NotNil(res)
|
|
}
|
|
res, err := s.engine.UpdateWorkerBuildIdOrdering(ctx, &workflowservice.UpdateWorkerBuildIdOrderingRequest{
|
|
Namespace: s.namespace,
|
|
TaskQueue: tq,
|
|
VersionId: &taskqueuepb.VersionId{WorkerBuildId: "foo-2.1"},
|
|
PreviousCompatible: &taskqueuepb.VersionId{WorkerBuildId: "foo-2"},
|
|
BecomeDefault: false,
|
|
})
|
|
s.NoError(err)
|
|
s.NotNil(res)
|
|
|
|
res2, err := s.engine.GetWorkerBuildIdOrdering(ctx, &workflowservice.GetWorkerBuildIdOrderingRequest{
|
|
Namespace: s.namespace,
|
|
TaskQueue: tq,
|
|
})
|
|
s.NoError(err)
|
|
s.NotNil(res2)
|
|
s.Equal("foo-9", res2.CurrentDefault.GetVersion().GetWorkerBuildId())
|
|
s.Equal(1, len(res2.CompatibleLeaves))
|
|
s.Equal("foo-2.1", res2.CompatibleLeaves[0].GetVersion().GetWorkerBuildId())
|
|
s.Equal("foo-2", res2.CompatibleLeaves[0].GetPreviousCompatible().GetVersion().GetWorkerBuildId())
|
|
}
|
|
|
|
func (s *versioningIntegSuite) TestLinkToNonexistentCompatibleVersionReturnsNotFound() {
|
|
ctx := NewContext()
|
|
tq := "integration-versioning-compat-not-found"
|
|
|
|
res, err := s.engine.UpdateWorkerBuildIdOrdering(ctx, &workflowservice.UpdateWorkerBuildIdOrderingRequest{
|
|
Namespace: s.namespace,
|
|
TaskQueue: tq,
|
|
VersionId: &taskqueuepb.VersionId{WorkerBuildId: "foo"},
|
|
PreviousCompatible: &taskqueuepb.VersionId{WorkerBuildId: "i don't exist yo"},
|
|
})
|
|
s.Error(err)
|
|
s.Nil(res)
|
|
s.IsType(&serviceerror.NotFound{}, err)
|
|
}
|
|
|
|
// This test verifies that the lease renewal of a task queue does not destroy the versioning data - as it updates the
|
|
// task queue info. We need to make sure that update preserves the versioning data.
|
|
func (s *versioningIntegSuite) TestVersioningStateNotDestroyedByOtherUpdates() {
|
|
ctx := NewContext()
|
|
tq := "integration-versioning-not-destroyed"
|
|
|
|
res, err := s.engine.UpdateWorkerBuildIdOrdering(ctx, &workflowservice.UpdateWorkerBuildIdOrderingRequest{
|
|
Namespace: s.namespace,
|
|
TaskQueue: tq,
|
|
VersionId: &taskqueuepb.VersionId{WorkerBuildId: "foo"},
|
|
PreviousCompatible: nil,
|
|
BecomeDefault: true,
|
|
})
|
|
s.NoError(err)
|
|
s.NotNil(res)
|
|
|
|
sdkWorker := worker.New(s.sdkClient, tq, worker.Options{})
|
|
if err := sdkWorker.Start(); err != nil {
|
|
s.Logger.Fatal("Error starting worker", tag.Error(err))
|
|
}
|
|
|
|
wfFunc := func(ctx workflow.Context) error {
|
|
// This timer exists to ensure the lease-renewal on the task queue happens, to verify that doesn't blow up data.
|
|
// The renewal interval has been lowered in this suite.
|
|
_ = workflow.Sleep(ctx, 3*time.Second)
|
|
return nil
|
|
}
|
|
sdkWorker.RegisterWorkflow(wfFunc)
|
|
id := "integration-test-unhandled-command-new-task"
|
|
workflowOptions := sdkclient.StartWorkflowOptions{ID: id, TaskQueue: tq}
|
|
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
|
defer cancel()
|
|
workflowRun, err := s.sdkClient.ExecuteWorkflow(ctx, workflowOptions, wfFunc)
|
|
s.NoError(err)
|
|
err = workflowRun.Get(ctx, nil)
|
|
s.NoError(err)
|
|
sdkWorker.Stop()
|
|
|
|
res2, err := s.engine.GetWorkerBuildIdOrdering(ctx, &workflowservice.GetWorkerBuildIdOrderingRequest{
|
|
Namespace: s.namespace,
|
|
TaskQueue: tq,
|
|
})
|
|
s.NoError(err)
|
|
s.NotNil(res2)
|
|
s.Equal("foo", res2.CurrentDefault.GetVersion().GetWorkerBuildId())
|
|
}
|
|
|
|
func (s *versioningIntegSuite) TestVersioningChangesPropagatedToSubPartitions() {
|
|
ctx := NewContext()
|
|
tq := "integration-versioning-sub-partitions"
|
|
|
|
res, err := s.engine.UpdateWorkerBuildIdOrdering(ctx, &workflowservice.UpdateWorkerBuildIdOrderingRequest{
|
|
Namespace: s.namespace,
|
|
TaskQueue: tq,
|
|
VersionId: &taskqueuepb.VersionId{WorkerBuildId: "foo"},
|
|
BecomeDefault: true,
|
|
})
|
|
s.NoError(err)
|
|
s.NotNil(res)
|
|
|
|
res2, err := s.engine.GetWorkerBuildIdOrdering(ctx, &workflowservice.GetWorkerBuildIdOrderingRequest{
|
|
Namespace: s.namespace,
|
|
TaskQueue: tq,
|
|
})
|
|
s.NoError(err)
|
|
s.NotNil(res2)
|
|
s.Equal("foo", res2.CurrentDefault.GetVersion().GetWorkerBuildId())
|
|
|
|
// Verify partitions have data
|
|
dcCol := dynamicconfig.NewCollection(s.testCluster.GetHost().dcClient, s.Logger)
|
|
partCount := dcCol.GetTaskQueuePartitionsProperty(dynamicconfig.MatchingNumTaskqueueReadPartitions)(s.namespace, tq, 0)
|
|
if partCount <= 1 {
|
|
s.T().Skip("This test makes no sense unless there are >1 partitions")
|
|
}
|
|
|
|
for i := 1; i < partCount; i++ {
|
|
subPartName, err := matching.NewTaskQueueNameWithPartition(tq, i)
|
|
s.NoError(err)
|
|
res, err := s.engine.GetWorkerBuildIdOrdering(ctx, &workflowservice.GetWorkerBuildIdOrderingRequest{
|
|
Namespace: s.namespace,
|
|
TaskQueue: subPartName.String(),
|
|
})
|
|
s.NoError(err)
|
|
s.NotNil(res)
|
|
s.Equal("foo", res.CurrentDefault.GetVersion().GetWorkerBuildId())
|
|
}
|
|
|
|
// Make a modification, verify it propagates to partitions
|
|
res, err = s.engine.UpdateWorkerBuildIdOrdering(ctx, &workflowservice.UpdateWorkerBuildIdOrderingRequest{
|
|
Namespace: s.namespace,
|
|
TaskQueue: tq,
|
|
VersionId: &taskqueuepb.VersionId{WorkerBuildId: "foo-2"},
|
|
BecomeDefault: true,
|
|
})
|
|
s.NoError(err)
|
|
s.NotNil(res)
|
|
|
|
for i := 1; i < partCount; i++ {
|
|
subPartName, err := matching.NewTaskQueueNameWithPartition(tq, i)
|
|
s.NoError(err)
|
|
res, err := s.engine.GetWorkerBuildIdOrdering(ctx, &workflowservice.GetWorkerBuildIdOrderingRequest{
|
|
Namespace: s.namespace,
|
|
TaskQueue: subPartName.String(),
|
|
})
|
|
s.NoError(err)
|
|
s.NotNil(res)
|
|
s.Equal("foo-2", res.CurrentDefault.GetVersion().GetWorkerBuildId())
|
|
}
|
|
}
|