mirror of
https://github.com/temporalio/temporal.git
synced 2026-08-30 18:41:49 -07:00
## What changed? - Applied testifylint, staticcheck, and gofix auto-fixes. - Exact commands that were run: ```sh .bin/golangci-lint-v2.9.0 run --allow-parallel-runners --concurrency 4 --fix --enable-only testifylint --build-tags disable_grpc_modules,test_dep --timeout 20m --config=.github/.golangci.yml .bin/golangci-lint-v2.9.0 run --allow-parallel-runners --concurrency 4 --fix --enable-only staticcheck --build-tags disable_grpc_modules,test_dep --timeout 20m --config=.github/.golangci.yml make fmt-gofix make goimports make fmt git diff --check ``` - No manual or AI changes were made; except where commented on. - Some fixes caused lint errors; those were reverted again. - Changes were all reviewed by me.
424 lines
14 KiB
Go
424 lines
14 KiB
Go
// TODO: move this to chasm_test package
|
|
package chasm
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"sort"
|
|
"strings"
|
|
|
|
commonpb "go.temporal.io/api/common/v1"
|
|
enumspb "go.temporal.io/api/enums/v1"
|
|
persistencespb "go.temporal.io/server/api/persistence/v1"
|
|
"google.golang.org/protobuf/proto"
|
|
)
|
|
|
|
type (
|
|
// TestComponent is a sample CHASM component used in tests.
|
|
// It would be nice to move it another package, but this creates a circular dependency.
|
|
|
|
protoMessageType = persistencespb.WorkflowExecutionState // Random proto message.
|
|
TestComponent struct {
|
|
UnimplementedComponent
|
|
|
|
ComponentData *protoMessageType
|
|
SubComponent1 Field[*TestSubComponent1]
|
|
SubComponent2 Field[*TestSubComponent2]
|
|
SubData1 Field[*protoMessageType]
|
|
SubComponents Map[string, *TestSubComponent1]
|
|
PendingActivities Map[int, *TestSubComponent1]
|
|
SubComponent11Pointer Field[*TestSubComponent11]
|
|
SubComponent11Pointer2 Field[*TestSubComponent11]
|
|
SubComponentInterfacePointer Field[Component]
|
|
|
|
MSPointer MSPointer
|
|
ParentPtr ParentPtr[*TestComponent]
|
|
|
|
Visibility Field[*Visibility]
|
|
}
|
|
|
|
TestSubComponent1 struct {
|
|
UnimplementedComponent
|
|
|
|
SubComponent1Data *protoMessageType
|
|
SubComponent11 Field[*TestSubComponent11]
|
|
SubComponent11_2 Field[*TestSubComponent11]
|
|
SubData11 Field[*protoMessageType] // Random proto message.
|
|
RootPointer Field[*TestComponent]
|
|
|
|
ParentPtr ParentPtr[*TestComponent]
|
|
}
|
|
|
|
TestSubComponent11 struct {
|
|
UnimplementedComponent
|
|
|
|
SubComponent11Data *protoMessageType
|
|
GrandparentPointer Field[*TestComponent]
|
|
ParentComponentPtr Field[*TestSubComponent1]
|
|
|
|
ParentPtr ParentPtr[*TestSubComponent1]
|
|
}
|
|
|
|
TestSubComponent2 struct {
|
|
UnimplementedComponent
|
|
SubComponent2Data *protoMessageType
|
|
}
|
|
|
|
TestSubComponent interface {
|
|
GetData() string
|
|
}
|
|
)
|
|
|
|
const (
|
|
TestComponentStartTimeSAKey = "StartTimeSAKey"
|
|
TestComponentRunIDSAKey = "RunIdSAKey"
|
|
TestComponentStartTimeMemoKey = "StartTimeMemoKey"
|
|
)
|
|
|
|
var (
|
|
TestComponentStartTimeSearchAttribute = NewSearchAttributeDateTime(TestComponentStartTimeSAKey, SearchAttributeFieldDateTime01)
|
|
TestComponentRunIDPredefinedSA = newSearchAttributeKeywordByField(TestComponentRunIDSAKey)
|
|
|
|
_ VisibilitySearchAttributesProvider = (*TestComponent)(nil)
|
|
_ VisibilityMemoProvider = (*TestComponent)(nil)
|
|
_ RootComponent = (*TestComponent)(nil)
|
|
)
|
|
|
|
func (tc *TestComponent) LifecycleState(_ Context) LifecycleState {
|
|
switch tc.ComponentData.GetStatus() {
|
|
case enumspb.WORKFLOW_EXECUTION_STATUS_UNSPECIFIED, enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING:
|
|
return LifecycleStateRunning
|
|
case enumspb.WORKFLOW_EXECUTION_STATUS_TIMED_OUT:
|
|
return LifecycleStatePaused
|
|
case enumspb.WORKFLOW_EXECUTION_STATUS_COMPLETED, enumspb.WORKFLOW_EXECUTION_STATUS_CONTINUED_AS_NEW:
|
|
return LifecycleStateCompleted
|
|
default:
|
|
return LifecycleStateFailed
|
|
}
|
|
}
|
|
|
|
func (tc *TestComponent) Pause(_ MutableContext) {
|
|
tc.ComponentData.Status = enumspb.WORKFLOW_EXECUTION_STATUS_TIMED_OUT
|
|
}
|
|
|
|
func (tc *TestComponent) Unpause(_ MutableContext) {
|
|
tc.ComponentData.Status = enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING
|
|
}
|
|
|
|
func (tc *TestComponent) Terminate(
|
|
mutableContext MutableContext,
|
|
_ TerminateComponentRequest,
|
|
) (TerminateComponentResponse, error) {
|
|
tc.Fail(mutableContext)
|
|
return TerminateComponentResponse{}, nil
|
|
}
|
|
|
|
func (tc *TestComponent) Complete(_ MutableContext) {
|
|
tc.ComponentData.Status = enumspb.WORKFLOW_EXECUTION_STATUS_COMPLETED
|
|
}
|
|
|
|
func (tc *TestComponent) Fail(_ MutableContext) {
|
|
tc.ComponentData.Status = enumspb.WORKFLOW_EXECUTION_STATUS_FAILED
|
|
}
|
|
|
|
func (tc *TestComponent) ContextMetadata(_ Context) map[string]string {
|
|
// TODO: Export context metadata from this test root.
|
|
return nil
|
|
}
|
|
|
|
// SearchAttributes implements VisibilitySearchAttributesProvider interface.
|
|
func (tc *TestComponent) SearchAttributes(_ Context) []SearchAttributeKeyValue {
|
|
return []SearchAttributeKeyValue{
|
|
TestComponentStartTimeSearchAttribute.Value(tc.ComponentData.GetStartTime().AsTime()),
|
|
TestComponentRunIDPredefinedSA.Value(tc.ComponentData.GetRunId()),
|
|
SearchAttributeTemporalScheduledByID.Value(tc.ComponentData.GetRunId()),
|
|
}
|
|
}
|
|
|
|
// Memo implements VisibilityMemoProvider interface.
|
|
func (tc *TestComponent) Memo(_ Context) proto.Message {
|
|
return tc.ComponentData
|
|
}
|
|
|
|
func (tsc1 *TestSubComponent1) LifecycleState(_ Context) LifecycleState {
|
|
switch tsc1.SubComponent1Data.GetStatus() {
|
|
case enumspb.WORKFLOW_EXECUTION_STATUS_UNSPECIFIED, enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING:
|
|
return LifecycleStateRunning
|
|
case enumspb.WORKFLOW_EXECUTION_STATUS_TIMED_OUT:
|
|
return LifecycleStatePaused
|
|
case enumspb.WORKFLOW_EXECUTION_STATUS_COMPLETED, enumspb.WORKFLOW_EXECUTION_STATUS_CONTINUED_AS_NEW:
|
|
return LifecycleStateCompleted
|
|
default:
|
|
return LifecycleStateFailed
|
|
}
|
|
}
|
|
|
|
func (tsc1 *TestSubComponent1) Pause(_ MutableContext) {
|
|
tsc1.SubComponent1Data.Status = enumspb.WORKFLOW_EXECUTION_STATUS_TIMED_OUT
|
|
}
|
|
|
|
func (tsc1 *TestSubComponent1) Unpause(_ MutableContext) {
|
|
tsc1.SubComponent1Data.Status = enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING
|
|
}
|
|
|
|
func (tsc1 *TestSubComponent1) GetData() string {
|
|
return tsc1.SubComponent1Data.GetCreateRequestId()
|
|
}
|
|
|
|
func (tsc11 *TestSubComponent11) LifecycleState(_ Context) LifecycleState {
|
|
switch tsc11.SubComponent11Data.GetStatus() {
|
|
case enumspb.WORKFLOW_EXECUTION_STATUS_UNSPECIFIED, enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING:
|
|
return LifecycleStateRunning
|
|
case enumspb.WORKFLOW_EXECUTION_STATUS_TIMED_OUT:
|
|
return LifecycleStatePaused
|
|
case enumspb.WORKFLOW_EXECUTION_STATUS_COMPLETED, enumspb.WORKFLOW_EXECUTION_STATUS_CONTINUED_AS_NEW:
|
|
return LifecycleStateCompleted
|
|
default:
|
|
return LifecycleStateFailed
|
|
}
|
|
}
|
|
|
|
func (tsc2 *TestSubComponent2) LifecycleState(_ Context) LifecycleState {
|
|
return LifecycleStateRunning
|
|
}
|
|
|
|
func setTestComponentFields(c *TestComponent, backend *MockNodeBackend) {
|
|
c.ComponentData = &protoMessageType{
|
|
CreateRequestId: "component-data",
|
|
}
|
|
c.SubComponent1 = NewComponentField(nil, &TestSubComponent1{
|
|
SubComponent1Data: &protoMessageType{
|
|
CreateRequestId: "sub-component1-data",
|
|
},
|
|
SubComponent11: NewComponentField(nil, &TestSubComponent11{
|
|
SubComponent11Data: &protoMessageType{
|
|
CreateRequestId: "sub-component1-sub-component11-data",
|
|
},
|
|
}),
|
|
SubData11: NewDataField(nil, &protoMessageType{
|
|
CreateRequestId: "sub-component1-sub-data11",
|
|
}),
|
|
})
|
|
c.SubComponent2 = NewEmptyField[*TestSubComponent2]()
|
|
c.SubData1 = NewDataField(nil, &protoMessageType{
|
|
CreateRequestId: "sub-data1",
|
|
})
|
|
c.MSPointer = NewMSPointer(backend)
|
|
}
|
|
|
|
// returns serialized version of TestComponent from above.
|
|
// Generated by generateMapInit function below.
|
|
func testComponentSerializedNodes() map[string]*persistencespb.ChasmNode {
|
|
serializedNodes := map[string]*persistencespb.ChasmNode{
|
|
"": {
|
|
Metadata: &persistencespb.ChasmNodeMetadata{
|
|
InitialVersionedTransition: &persistencespb.VersionedTransition{
|
|
NamespaceFailoverVersion: 1,
|
|
TransitionCount: 1,
|
|
},
|
|
LastUpdateVersionedTransition: &persistencespb.VersionedTransition{
|
|
NamespaceFailoverVersion: 2,
|
|
TransitionCount: 2,
|
|
},
|
|
Attributes: &persistencespb.ChasmNodeMetadata_ComponentAttributes{
|
|
ComponentAttributes: &persistencespb.ChasmComponentAttributes{
|
|
TypeId: testComponentTypeID,
|
|
SideEffectTasks: []*persistencespb.ChasmComponentAttributes_Task(nil),
|
|
PureTasks: []*persistencespb.ChasmComponentAttributes_Task(nil),
|
|
},
|
|
},
|
|
},
|
|
Data: &commonpb.DataBlob{
|
|
EncodingType: 1,
|
|
Data: []byte{0xa, 0xe, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x2d, 0x64, 0x61, 0x74, 0x61},
|
|
},
|
|
},
|
|
"SubComponent1": {
|
|
Metadata: &persistencespb.ChasmNodeMetadata{
|
|
InitialVersionedTransition: &persistencespb.VersionedTransition{
|
|
NamespaceFailoverVersion: 1,
|
|
TransitionCount: 1,
|
|
},
|
|
LastUpdateVersionedTransition: &persistencespb.VersionedTransition{
|
|
NamespaceFailoverVersion: 2,
|
|
TransitionCount: 2,
|
|
},
|
|
Attributes: &persistencespb.ChasmNodeMetadata_ComponentAttributes{
|
|
ComponentAttributes: &persistencespb.ChasmComponentAttributes{
|
|
TypeId: testSubComponent1TypeID,
|
|
SideEffectTasks: []*persistencespb.ChasmComponentAttributes_Task(nil),
|
|
PureTasks: []*persistencespb.ChasmComponentAttributes_Task(nil),
|
|
},
|
|
},
|
|
},
|
|
Data: &commonpb.DataBlob{
|
|
EncodingType: 1,
|
|
Data: []byte{0xa, 0x13, 0x73, 0x75, 0x62, 0x2d, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x31, 0x2d, 0x64, 0x61, 0x74, 0x61},
|
|
},
|
|
},
|
|
"SubComponent1/SubComponent11": {
|
|
Metadata: &persistencespb.ChasmNodeMetadata{
|
|
InitialVersionedTransition: &persistencespb.VersionedTransition{
|
|
NamespaceFailoverVersion: 1,
|
|
TransitionCount: 1,
|
|
},
|
|
LastUpdateVersionedTransition: &persistencespb.VersionedTransition{
|
|
NamespaceFailoverVersion: 2,
|
|
TransitionCount: 2,
|
|
},
|
|
Attributes: &persistencespb.ChasmNodeMetadata_ComponentAttributes{
|
|
ComponentAttributes: &persistencespb.ChasmComponentAttributes{
|
|
TypeId: testSubComponent11TypeID,
|
|
SideEffectTasks: []*persistencespb.ChasmComponentAttributes_Task(nil),
|
|
PureTasks: []*persistencespb.ChasmComponentAttributes_Task(nil),
|
|
},
|
|
},
|
|
},
|
|
Data: &commonpb.DataBlob{
|
|
EncodingType: 1,
|
|
Data: []byte{0xa, 0x23, 0x73, 0x75, 0x62, 0x2d, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x31, 0x2d, 0x73, 0x75, 0x62, 0x2d, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x31, 0x31, 0x2d, 0x64, 0x61, 0x74, 0x61},
|
|
},
|
|
},
|
|
"SubComponent1/SubData11": {
|
|
Metadata: &persistencespb.ChasmNodeMetadata{
|
|
InitialVersionedTransition: &persistencespb.VersionedTransition{
|
|
NamespaceFailoverVersion: 1,
|
|
TransitionCount: 1,
|
|
},
|
|
LastUpdateVersionedTransition: &persistencespb.VersionedTransition{
|
|
NamespaceFailoverVersion: 2,
|
|
TransitionCount: 2,
|
|
},
|
|
Attributes: &persistencespb.ChasmNodeMetadata_DataAttributes{
|
|
DataAttributes: &persistencespb.ChasmDataAttributes{},
|
|
},
|
|
},
|
|
Data: &commonpb.DataBlob{
|
|
EncodingType: 1,
|
|
Data: []byte{0xa, 0x19, 0x73, 0x75, 0x62, 0x2d, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x31, 0x2d, 0x73, 0x75, 0x62, 0x2d, 0x64, 0x61, 0x74, 0x61, 0x31, 0x31},
|
|
},
|
|
},
|
|
"SubData1": {
|
|
Metadata: &persistencespb.ChasmNodeMetadata{
|
|
InitialVersionedTransition: &persistencespb.VersionedTransition{
|
|
NamespaceFailoverVersion: 1,
|
|
TransitionCount: 1,
|
|
},
|
|
LastUpdateVersionedTransition: &persistencespb.VersionedTransition{
|
|
NamespaceFailoverVersion: 2,
|
|
TransitionCount: 2,
|
|
},
|
|
Attributes: &persistencespb.ChasmNodeMetadata_DataAttributes{
|
|
DataAttributes: &persistencespb.ChasmDataAttributes{},
|
|
},
|
|
},
|
|
Data: &commonpb.DataBlob{
|
|
EncodingType: 1,
|
|
Data: []byte{0xa, 0x9, 0x73, 0x75, 0x62, 0x2d, 0x64, 0x61, 0x74, 0x61, 0x31},
|
|
},
|
|
},
|
|
}
|
|
|
|
return serializedNodes
|
|
}
|
|
|
|
// Helper functions to regenerate testComponentSerializedNodes() function body.
|
|
// Use: generateMapInit(serializedNodes, "serializedNodes")
|
|
func generateMapInit(m any, mapName string) {
|
|
val := reflect.ValueOf(m)
|
|
if val.Kind() != reflect.Map {
|
|
fmt.Println("Provided value is not a map")
|
|
return
|
|
}
|
|
|
|
keyType := val.Type().Key()
|
|
elemType := val.Type().Elem()
|
|
|
|
fmt.Printf("%s := map[%s]%s{\n", mapName, keyType, elemType)
|
|
|
|
// Sort string keys for deterministic output
|
|
var keys []reflect.Value
|
|
keys = append(keys, val.MapKeys()...)
|
|
if keyType.Kind() == reflect.String {
|
|
sort.Slice(keys, func(i, j int) bool {
|
|
return keys[i].String() < keys[j].String()
|
|
})
|
|
}
|
|
|
|
for _, key := range keys {
|
|
value := val.MapIndex(key)
|
|
fmt.Printf("\t%#v: %s,\n", key.Interface(), renderProtoPointer(value))
|
|
}
|
|
fmt.Println("}")
|
|
}
|
|
|
|
func renderProtoPointer(v reflect.Value) string {
|
|
if v.IsNil() {
|
|
return "nil"
|
|
}
|
|
|
|
elem := v.Elem() // Dereference the pointer to struct
|
|
t := elem.Type()
|
|
result := fmt.Sprintf("&%s{\n", t.String())
|
|
|
|
for i := 0; i < elem.NumField(); i++ {
|
|
field := t.Field(i)
|
|
|
|
// Skip unexported and known proto internal fields
|
|
if field.PkgPath != "" || isProtoInternalField(field.Name) {
|
|
continue
|
|
}
|
|
|
|
fieldValue := elem.Field(i)
|
|
|
|
// Handle oneof-style interface fields
|
|
if field.Type.Kind() == reflect.Interface && !fieldValue.IsNil() {
|
|
oneofVal := fieldValue.Elem()
|
|
if oneofVal.Kind() == reflect.Pointer {
|
|
oneofVal = oneofVal.Elem()
|
|
}
|
|
|
|
result += fmt.Sprintf("\t\t%s: &%s{\n", field.Name, oneofVal.Type().String())
|
|
for j := 0; j < oneofVal.NumField(); j++ {
|
|
oneofField := oneofVal.Type().Field(j)
|
|
if oneofField.PkgPath != "" || isProtoInternalField(oneofField.Name) {
|
|
continue
|
|
}
|
|
oneofFieldValue := oneofVal.Field(j)
|
|
|
|
// Handle nested proto inside oneof
|
|
if oneofFieldValue.Kind() == reflect.Pointer && oneofFieldValue.Elem().Kind() == reflect.Struct {
|
|
result += fmt.Sprintf("\t\t\t%s: %s,\n", oneofField.Name, renderProtoPointer(oneofFieldValue))
|
|
} else {
|
|
result += fmt.Sprintf("\t\t\t%s: %#v,\n", oneofField.Name, oneofFieldValue.Interface())
|
|
}
|
|
}
|
|
result += "\t\t},\n"
|
|
continue
|
|
}
|
|
|
|
// Recursively handle nested proto messages (pointer to struct)
|
|
if field.Type.Kind() == reflect.Pointer && fieldValue.Kind() == reflect.Pointer && fieldValue.Elem().Kind() == reflect.Struct {
|
|
result += fmt.Sprintf("\t\t%s: %s,\n", field.Name, renderProtoPointer(fieldValue))
|
|
continue
|
|
}
|
|
|
|
// Print normal fields
|
|
result += fmt.Sprintf("\t\t%s: %#v,\n", field.Name, fieldValue.Interface())
|
|
}
|
|
result += "\t}"
|
|
|
|
result = strings.ReplaceAll(result, "persistence.", "persistencespb.")
|
|
|
|
return result
|
|
}
|
|
|
|
func isProtoInternalField(fieldName string) bool {
|
|
switch fieldName {
|
|
case "state", "sizeCache", "unknownFields":
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|