func ValidateConflictResolveWorkflowModeState()

in common/persistence/operationModeValidator.go [170:328]


func ValidateConflictResolveWorkflowModeState(
	mode ConflictResolveWorkflowMode,
	resetWorkflowSnapshot InternalWorkflowSnapshot,
	newWorkflowSnapshot *InternalWorkflowSnapshot,
	currentWorkflowMutation *InternalWorkflowMutation,
) error {

	resetWorkflowState := resetWorkflowSnapshot.ExecutionInfo.State
	if err := checkWorkflowState(resetWorkflowState); err != nil {
		return err
	}
	var newWorkflowState *int
	if newWorkflowSnapshot != nil {
		newWorkflowState = &newWorkflowSnapshot.ExecutionInfo.State
		if err := checkWorkflowState(*newWorkflowState); err != nil {
			return err
		}
	}
	var currentWorkflowState *int
	if currentWorkflowMutation != nil {
		currentWorkflowState = &currentWorkflowMutation.ExecutionInfo.State
		if err := checkWorkflowState(*currentWorkflowState); err != nil {
			return err
		}
	}

	switch mode {
	case ConflictResolveWorkflowModeUpdateCurrent:
		// update current record
		// 1. reset workflow only ->
		//  reset workflow cannot be zombie
		// 2. reset workflow & new workflow ->
		//  reset workflow cannot be created / running / zombie,
		//  new workflow cannot be zombie / completed
		// 3. current workflow & reset workflow ->
		//  current workflow cannot be created / running,
		//  reset workflow cannot be zombie
		// 4. current workflow & reset workflow & new workflow ->
		//  current workflow cannot be created / running,
		//  reset workflow cannot be created / running / zombie,
		//  new workflow cannot be zombie / completed

		// TODO remove case 1 & 2 support once 2DC is deprecated
		// it is ok that currentWorkflowMutation is null, only for 2 DC case
		// NDC should always require current workflow for CAS
		// Note: current workflow mutation can be in zombie state, for the update

		// case 1 & 2
		if currentWorkflowState == nil {
			// case 1
			if newWorkflowState == nil {
				if resetWorkflowState == WorkflowStateZombie {
					return newInvalidConflictResolveWorkflowMode(
						mode,
						resetWorkflowState,
					)
				}
				return nil
			}

			// case 2
			if resetWorkflowState == WorkflowStateCreated ||
				resetWorkflowState == WorkflowStateRunning ||
				resetWorkflowState == WorkflowStateZombie ||
				*newWorkflowState == WorkflowStateZombie ||
				*newWorkflowState == WorkflowStateCompleted {
				return newInvalidConflictResolveWorkflowWithNewMode(
					mode,
					resetWorkflowState,
					*newWorkflowState,
				)
			}
			return nil
		}

		// case 3 & 4
		// case 3
		if newWorkflowState == nil {
			if *currentWorkflowState == WorkflowStateCreated ||
				*currentWorkflowState == WorkflowStateRunning ||
				resetWorkflowState == WorkflowStateZombie {
				return newInvalidConflictResolveWorkflowWithCurrentMode(
					mode,
					resetWorkflowState,
					*currentWorkflowState,
				)
			}
			return nil
		}

		// case 4
		if *currentWorkflowState == WorkflowStateCreated ||
			*currentWorkflowState == WorkflowStateRunning ||
			resetWorkflowState == WorkflowStateCreated ||
			resetWorkflowState == WorkflowStateRunning ||
			resetWorkflowState == WorkflowStateZombie ||
			*newWorkflowState == WorkflowStateZombie ||
			*newWorkflowState == WorkflowStateCompleted {
			return newInvalidConflictResolveWorkflowWithCurrentWithNewMode(
				mode,
				resetWorkflowState,
				*newWorkflowState,
				*currentWorkflowState,
			)
		}
		return nil

	case ConflictResolveWorkflowModeBypassCurrent:
		// bypass current record
		// * current workflow cannot be set
		// 1. reset workflow only ->
		//  reset workflow cannot be created / running
		// 2. reset workflow & new workflow ->
		//  reset workflow cannot be created / running / zombie,
		//  new workflow cannot be created / running / completed

		// precondition
		if currentWorkflowMutation != nil {
			return &types.InternalServiceError{
				Message: fmt.Sprintf(
					"Invalid workflow conflict resolve mode %v, encounter current workflow",
					mode,
				),
			}
		}

		// case 1
		if newWorkflowState == nil {
			if resetWorkflowState == WorkflowStateCreated ||
				resetWorkflowState == WorkflowStateRunning {
				return newInvalidConflictResolveWorkflowMode(
					mode,
					resetWorkflowState,
				)
			}
			return nil
		}

		// case 2
		if resetWorkflowState == WorkflowStateCreated ||
			resetWorkflowState == WorkflowStateRunning ||
			resetWorkflowState == WorkflowStateZombie ||
			*newWorkflowState == WorkflowStateCreated ||
			*newWorkflowState == WorkflowStateRunning ||
			*newWorkflowState == WorkflowStateCompleted {
			return newInvalidConflictResolveWorkflowWithNewMode(
				mode,
				resetWorkflowState,
				*newWorkflowState,
			)
		}
		return nil

	default:
		return &types.InternalServiceError{
			Message: fmt.Sprintf("unknown mode: %v", mode),
		}
	}
}