mirror of
https://github.com/hanzoai/tasks.git
synced 2026-10-04 02:04:03 +00:00
## What changed? - The initial current version of a worker deployment is now `"__unversioned__"` instead of `""` - When the ramping version of a worker deployment becomes unversioned, the deployment tells all the task queues in the current version that they now have an unversioned ramp. - If the unversioned ramp is promoted to current version, or if the unversioned ramping version is unset, the deployment tells all the task queues of the previous current version that they no longer have an unversioned ramp. ## Why? <!-- Tell your future self why have you made these changes --> ## How did you test it? - Made sure all existing WorkerDeploymentSuite and DeploymentVersionSuite tests pass - Wrote new tests in WorkerDeploymentSuite for the specific edge cases that this code handles: - `TestSetCurrentVersion_Unversioned_NoRamp`: Test that when current version changes from versioned -> unversioned, the task queues become unversioned - `TestSetCurrentVersion_Unversioned_PromoteUnversionedRamp`: Test that when the current version changes from versioned -> unversioned and unversioned was previously ramping, the task queues become unversioned with no more unversioned ramp - `TestSetRampingVersion_Unversioned_UnversionedCurrent`: Test that this fails with "Ramping version __unversioned__ is already current" error - `TestSetRampingVersion_Unversioned_VersionedCurrent`: Test that the ramping version of the current version's task queues becomes unversioned ## Potential risks <!-- Assuming the worst case, what can be broken when deploying this change to production? --> ## Documentation <!-- Have you made sure this change doesn't falsify anything currently stated in `docs/`? If significant new behavior is added, have you described that in `docs/`? --> ## Is hotfix candidate? <!-- Is this PR a hotfix candidate or does it require a notification to be sent to the broader community? (Yes/No) --> --------- Co-authored-by: Shivam <[email protected]> Co-authored-by: Shahab Tajik <[email protected]> Co-authored-by: Shivam Saraf <[email protected]> Co-authored-by: ShahabT <[email protected]>
183 lines
7.3 KiB
Go
183 lines
7.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 worker_versioning
|
|
|
|
import (
|
|
"strconv"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
deploymentspb "go.temporal.io/server/api/deployment/v1"
|
|
persistencespb "go.temporal.io/server/api/persistence/v1"
|
|
"go.temporal.io/server/common/primitives/timestamp"
|
|
)
|
|
|
|
var (
|
|
v1 = &deploymentspb.WorkerDeploymentVersion{
|
|
BuildId: "v1",
|
|
DeploymentName: "foo",
|
|
}
|
|
v2 = &deploymentspb.WorkerDeploymentVersion{
|
|
BuildId: "v2",
|
|
DeploymentName: "foo",
|
|
}
|
|
v3 = &deploymentspb.WorkerDeploymentVersion{
|
|
BuildId: "v3",
|
|
DeploymentName: "foo",
|
|
}
|
|
)
|
|
|
|
func TestCalculateTaskQueueVersioningInfo(t *testing.T) {
|
|
t1 := timestamp.TimePtr(time.Now().Add(-2 * time.Hour))
|
|
t2 := timestamp.TimePtr(time.Now().Add(-time.Hour))
|
|
t3 := timestamp.TimePtr(time.Now())
|
|
|
|
tests := []struct {
|
|
name string
|
|
wantCurrent *deploymentspb.DeploymentVersionData
|
|
wantRamping *deploymentspb.DeploymentVersionData
|
|
data *persistencespb.DeploymentData
|
|
}{
|
|
{name: "nil data"},
|
|
{name: "empty data", data: &persistencespb.DeploymentData{}},
|
|
{name: "old data", wantCurrent: &deploymentspb.DeploymentVersionData{Version: v1, RoutingUpdateTime: t1},
|
|
data: &persistencespb.DeploymentData{
|
|
Deployments: []*persistencespb.DeploymentData_DeploymentDataItem{
|
|
{Deployment: DeploymentFromDeploymentVersion(v1), Data: &deploymentspb.TaskQueueData{LastBecameCurrentTime: t1}},
|
|
}},
|
|
},
|
|
{name: "old and new data", wantCurrent: &deploymentspb.DeploymentVersionData{Version: v2, RoutingUpdateTime: t2, CurrentSinceTime: t2},
|
|
data: &persistencespb.DeploymentData{
|
|
Deployments: []*persistencespb.DeploymentData_DeploymentDataItem{
|
|
{Deployment: DeploymentFromDeploymentVersion(v1), Data: &deploymentspb.TaskQueueData{LastBecameCurrentTime: t1}},
|
|
},
|
|
Versions: []*deploymentspb.DeploymentVersionData{
|
|
{Version: v2, CurrentSinceTime: t2, RoutingUpdateTime: t2},
|
|
},
|
|
},
|
|
},
|
|
{name: "two current + two ramping",
|
|
wantCurrent: &deploymentspb.DeploymentVersionData{Version: v2, RoutingUpdateTime: t2, CurrentSinceTime: t2},
|
|
wantRamping: &deploymentspb.DeploymentVersionData{Version: v3, RoutingUpdateTime: t3, RampPercentage: 20, RampingSinceTime: t1},
|
|
data: &persistencespb.DeploymentData{
|
|
Versions: []*deploymentspb.DeploymentVersionData{
|
|
{Version: v1, CurrentSinceTime: t1, RoutingUpdateTime: t1},
|
|
{Version: v2, CurrentSinceTime: t2, RoutingUpdateTime: t2},
|
|
{Version: v1, RampPercentage: 50, RoutingUpdateTime: t2, RampingSinceTime: t2},
|
|
{Version: v3, RampPercentage: 20, RoutingUpdateTime: t3, RampingSinceTime: t1},
|
|
},
|
|
},
|
|
},
|
|
{name: "ramp without current", wantRamping: &deploymentspb.DeploymentVersionData{Version: v3, RoutingUpdateTime: t3, RampPercentage: 20, RampingSinceTime: t3},
|
|
data: &persistencespb.DeploymentData{
|
|
Versions: []*deploymentspb.DeploymentVersionData{
|
|
{Version: v1, RampPercentage: 50, RoutingUpdateTime: t2, RampingSinceTime: t2},
|
|
{Version: v3, RampPercentage: 20, RoutingUpdateTime: t3, RampingSinceTime: t3},
|
|
},
|
|
},
|
|
},
|
|
{name: "ramp to unversioned",
|
|
wantRamping: &deploymentspb.DeploymentVersionData{Version: nil, RoutingUpdateTime: t2, RampPercentage: 20, RampingSinceTime: t2},
|
|
data: &persistencespb.DeploymentData{
|
|
Versions: []*deploymentspb.DeploymentVersionData{
|
|
{Version: v1, RampPercentage: 50, RoutingUpdateTime: t1, RampingSinceTime: t1},
|
|
// Passing only deployment name without version
|
|
{Version: nil, RampPercentage: 20, RoutingUpdateTime: t2, RampingSinceTime: t2},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
current, ramping := CalculateTaskQueueVersioningInfo(tt.data)
|
|
if !current.Equal(tt.wantCurrent) {
|
|
t.Errorf("got current = %v, want %v", current, tt.wantCurrent)
|
|
}
|
|
if !ramping.Equal(tt.wantRamping) {
|
|
t.Errorf("got ramping = %v, want %v", ramping, tt.wantRamping)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestFindDeploymentVersionForWorkflowID(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
current *deploymentspb.DeploymentVersionData
|
|
ramping *deploymentspb.DeploymentVersionData
|
|
want *deploymentspb.WorkerDeploymentVersion
|
|
}{
|
|
{name: "nil current and ramping info", want: nil},
|
|
{name: "with current version", current: &deploymentspb.DeploymentVersionData{Version: v1}, want: v1},
|
|
{name: "with full ramp", current: &deploymentspb.DeploymentVersionData{Version: v1}, ramping: &deploymentspb.DeploymentVersionData{Version: v2, RampPercentage: 100}, want: v2},
|
|
{name: "with full ramp to unversioned", current: &deploymentspb.DeploymentVersionData{Version: v1}, ramping: &deploymentspb.DeploymentVersionData{RampPercentage: 100}, want: nil},
|
|
{name: "with full ramp from unversioned", ramping: &deploymentspb.DeploymentVersionData{Version: v1, RampPercentage: 100}, want: v1},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := FindDeploymentVersionForWorkflowID(tt.current, tt.ramping, "my-wf-id"); !got.Equal(tt.want) {
|
|
t.Errorf("FindDeploymentVersionForWorkflowID() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestFindDeploymentVersionForWorkflowID_PartialRamp(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
from *deploymentspb.WorkerDeploymentVersion
|
|
to *deploymentspb.WorkerDeploymentVersion
|
|
}{
|
|
{name: "from v1 to v2", from: v1, to: v2},
|
|
{name: "from v1 to unversioned", from: v1},
|
|
{name: "from unversioned to v2", to: v2},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
var current *deploymentspb.DeploymentVersionData
|
|
var ramping *deploymentspb.DeploymentVersionData
|
|
if tt.from != nil {
|
|
current = &deploymentspb.DeploymentVersionData{
|
|
Version: tt.from,
|
|
}
|
|
}
|
|
ramping = &deploymentspb.DeploymentVersionData{
|
|
Version: tt.to,
|
|
RampPercentage: 30,
|
|
}
|
|
histogram := make(map[string]int)
|
|
runs := 1000000
|
|
for i := 0; i < runs; i++ {
|
|
v := FindDeploymentVersionForWorkflowID(current, ramping, "wf-"+strconv.Itoa(i))
|
|
histogram[v.GetBuildId()]++
|
|
}
|
|
|
|
assert.InEpsilon(t, .7*float64(runs), histogram[tt.from.GetBuildId()], .02)
|
|
assert.InEpsilon(t, .3*float64(runs), histogram[tt.to.GetBuildId()], .02)
|
|
})
|
|
}
|
|
}
|