Files
tasks/service/worker/batcher/workflow_test.go
ShivamandGitHub 76ed53a9be [Refactoring]: Move a subset of validators to the frontend (#8727)
## What changed?
- Move some of the validator functions to the frontend, where some
pre-existing validations are already present.
- Quite specifically, move the function ValidateVersioningOverride to
the frontend. The detailed reasoning is present below.
- Additionally, move some of the validator functions that internally
call the function ValidateVersioningOverride to the frontend.

## Why?
- The reasons I have moved the validators to the frontend are as
follows:
1. ValidateVersioningOverride will soon be making an RPC call. To make
this RPC call, the function would require _workerdeployment.Client_. The
frontend handler, currently, has this already present as a member. Note
- I thought of embedding this directly in the history handler itself but
chose against it since the _workerdeployment.Client_ internally has a
dependency on history, which would have then caused circular
dependencies.
2. Additionally, failed validations would unnecessary make a RPC
roundtrip to history (in some cases). Instead, we should be validating
user inputs in the frontend only and quickly returning an error whenever
the inputs don't match what we expect.


**NOTE**: This is part 1 of a change that I am working on. Part 2
involves actually adding that RPC call that I mentioned above. The
reason why I have a separate PR open for this is because this touches
parts of the codebase worked on by many different folks. Thus, for the
sole purpose of iterating faster, I decided to make refactoring into
it's own PR.

## How did you test it?
- [ ] built
- [ ] run locally and tested manually
- [ ] covered by existing tests
- [ ] added new unit test(s)
- [ ] added new functional test(s)

## Potential risks
This should not be a risky change.


---

> [!NOTE]
> Shift versioning-override and related input validations from history
to frontend handlers, add reset post-op validation, and simplify batch
workflow by validating at API layer.
> 
> - **Frontend**:
> - Validate `VersioningOverride` in `StartWorkflowExecution`,
`SignalWithStartWorkflowExecution`, `ResetWorkflowExecution` (via new
`validatePostResetOperationInputs`), and
`UpdateWorkflowExecutionOptions`.
> - Adjust `StartBatchOperation` flow: ensure `EnableBatcher` check
precedes `ValidateBatchOperation`.
> - Minor: fetch `namespaceID` before validating options in
`UpdateWorkflowExecutionOptions`.
> - **History**:
> - Remove `VersioningOverride` validations from
`create_workflow_util.go`, `resetworkflow/api.go` (and delete its local
post-reset validator), and `updateworkflowoptions/api.go` (also pass
`req.GetWorkflowExecutionOptions()` directly to `MergeAndApply`).
> - **Worker/Batcher**:
> - Drop in-workflow `ValidateBatchOperation` call; rely on frontend
validation. Update tests accordingly (remove missing-params test).
> 
> <sup>Written by [Cursor
Bugbot]() for commit
d1e90031ff0a6dae30c8bdf972ade522a3a5b823. This will update automatically
on new commits. Configure
[here]().</sup>
2025-12-01 22:57:39 +00:00

108 lines
3.1 KiB
Go

package batcher
import (
"testing"
"github.com/google/uuid"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/suite"
batchpb "go.temporal.io/api/batch/v1"
commonpb "go.temporal.io/api/common/v1"
enumspb "go.temporal.io/api/enums/v1"
"go.temporal.io/api/workflowservice/v1"
"go.temporal.io/sdk/testsuite"
batchspb "go.temporal.io/server/api/batch/v1"
"go.uber.org/mock/gomock"
)
type batcherSuite struct {
suite.Suite
testsuite.WorkflowTestSuite
controller *gomock.Controller
env *testsuite.TestWorkflowEnvironment
}
func TestBatcherSuite(t *testing.T) {
suite.Run(t, new(batcherSuite))
}
func (s *batcherSuite) SetupTest() {
s.controller = gomock.NewController(s.T())
s.env = s.WorkflowTestSuite.NewTestWorkflowEnvironment()
s.env.RegisterWorkflow(BatchWorkflowProtobuf)
}
func (s *batcherSuite) TearDownTest() {
s.controller.Finish()
s.env.AssertExpectations(s.T())
}
func (s *batcherSuite) TestBatchWorkflow_ValidParams_Query_Protobuf() {
var ac *activities
s.env.OnActivity(ac.BatchActivityWithProtobuf, mock.Anything, mock.Anything).Return(HeartBeatDetails{
SuccessCount: 42,
ErrorCount: 27,
}, nil)
s.env.OnUpsertMemo(mock.Anything).Run(func(args mock.Arguments) {
memo, ok := args.Get(0).(map[string]interface{})
s.Require().True(ok)
s.Equal(map[string]interface{}{
"batch_operation_stats": BatchOperationStats{
NumSuccess: 42,
NumFailure: 27,
},
}, memo)
}).Once()
s.env.ExecuteWorkflow(BatchWorkflowProtobuf, &batchspb.BatchOperationInput{
Request: &workflowservice.StartBatchOperationRequest{
JobId: uuid.NewString(),
Operation: &workflowservice.StartBatchOperationRequest_TerminationOperation{
TerminationOperation: &batchpb.BatchOperationTermination{},
},
Namespace: "test-namespace",
Reason: "test-reason",
VisibilityQuery: "test-query",
},
BatchType: enumspb.BATCH_OPERATION_TYPE_TERMINATE,
})
err := s.env.GetWorkflowError()
s.Require().NoError(err)
}
func (s *batcherSuite) TestBatchWorkflow_ValidParams_Executions_Protobuf() {
var ac *activities
s.env.OnActivity(ac.BatchActivityWithProtobuf, mock.Anything, mock.Anything).Return(HeartBeatDetails{
SuccessCount: 42,
ErrorCount: 27,
}, nil)
s.env.OnUpsertMemo(mock.Anything).Run(func(args mock.Arguments) {
memo, ok := args.Get(0).(map[string]interface{})
s.Require().True(ok)
s.Equal(map[string]interface{}{
"batch_operation_stats": BatchOperationStats{
NumSuccess: 42,
NumFailure: 27,
},
}, memo)
}).Once()
s.env.ExecuteWorkflow(BatchWorkflowProtobuf, &batchspb.BatchOperationInput{
Request: &workflowservice.StartBatchOperationRequest{
JobId: uuid.NewString(),
Operation: &workflowservice.StartBatchOperationRequest_TerminationOperation{
TerminationOperation: &batchpb.BatchOperationTermination{},
},
Executions: []*commonpb.WorkflowExecution{
{
WorkflowId: uuid.NewString(),
RunId: uuid.NewString(),
},
},
Reason: "test-reason",
Namespace: "test-namespace",
},
BatchType: enumspb.BATCH_OPERATION_TYPE_TERMINATE,
})
err := s.env.GetWorkflowError()
s.Require().NoError(err)
}