go.temporal.io/server@v1.23.0/common/persistence/sql/sqlplugin/tests/history_current_execution.go (about)

     1  // The MIT License
     2  //
     3  // Copyright (c) 2020 Temporal Technologies Inc.  All rights reserved.
     4  //
     5  // Copyright (c) 2020 Uber Technologies, Inc.
     6  //
     7  // Permission is hereby granted, free of charge, to any person obtaining a copy
     8  // of this software and associated documentation files (the "Software"), to deal
     9  // in the Software without restriction, including without limitation the rights
    10  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    11  // copies of the Software, and to permit persons to whom the Software is
    12  // furnished to do so, subject to the following conditions:
    13  //
    14  // The above copyright notice and this permission notice shall be included in
    15  // all copies or substantial portions of the Software.
    16  //
    17  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    18  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    19  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    20  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    21  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    22  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    23  // THE SOFTWARE.
    24  
    25  package tests
    26  
    27  import (
    28  	"math/rand"
    29  	"testing"
    30  
    31  	"github.com/stretchr/testify/require"
    32  	"github.com/stretchr/testify/suite"
    33  	enumspb "go.temporal.io/api/enums/v1"
    34  
    35  	enumsspb "go.temporal.io/server/api/enums/v1"
    36  	"go.temporal.io/server/common/persistence/sql/sqlplugin"
    37  	"go.temporal.io/server/common/primitives"
    38  	"go.temporal.io/server/common/shuffle"
    39  )
    40  
    41  type (
    42  	historyCurrentExecutionSuite struct {
    43  		suite.Suite
    44  		*require.Assertions
    45  
    46  		store sqlplugin.HistoryExecution
    47  	}
    48  )
    49  
    50  var (
    51  	testHistoryExecutionStates = []enumsspb.WorkflowExecutionState{
    52  		enumsspb.WORKFLOW_EXECUTION_STATE_CREATED,
    53  		enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING,
    54  		enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED,
    55  		enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE,
    56  	}
    57  	testHistoryExecutionStatus = map[enumsspb.WorkflowExecutionState][]enumspb.WorkflowExecutionStatus{
    58  		enumsspb.WORKFLOW_EXECUTION_STATE_CREATED: {enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING},
    59  		enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING: {enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING},
    60  		enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED: {
    61  			enumspb.WORKFLOW_EXECUTION_STATUS_COMPLETED,
    62  			enumspb.WORKFLOW_EXECUTION_STATUS_FAILED,
    63  			enumspb.WORKFLOW_EXECUTION_STATUS_CANCELED,
    64  			enumspb.WORKFLOW_EXECUTION_STATUS_TERMINATED,
    65  			enumspb.WORKFLOW_EXECUTION_STATUS_CONTINUED_AS_NEW,
    66  			enumspb.WORKFLOW_EXECUTION_STATUS_TIMED_OUT,
    67  		},
    68  		enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE: {enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING},
    69  	}
    70  )
    71  
    72  func NewHistoryCurrentExecutionSuite(
    73  	t *testing.T,
    74  	store sqlplugin.HistoryExecution,
    75  ) *historyCurrentExecutionSuite {
    76  	return &historyCurrentExecutionSuite{
    77  		Assertions: require.New(t),
    78  		store:      store,
    79  	}
    80  }
    81  
    82  func (s *historyCurrentExecutionSuite) SetupSuite() {
    83  
    84  }
    85  
    86  func (s *historyCurrentExecutionSuite) TearDownSuite() {
    87  
    88  }
    89  
    90  func (s *historyCurrentExecutionSuite) SetupTest() {
    91  	s.Assertions = require.New(s.T())
    92  }
    93  
    94  func (s *historyCurrentExecutionSuite) TearDownTest() {
    95  
    96  }
    97  
    98  func (s *historyCurrentExecutionSuite) TestInsert_Success() {
    99  	shardID := rand.Int31()
   100  	namespaceID := primitives.NewUUID()
   101  	workflowID := shuffle.String(testHistoryExecutionWorkflowID)
   102  	runID := primitives.NewUUID()
   103  	requestID := primitives.NewUUID().String()
   104  	lastWriteVersion := rand.Int63()
   105  
   106  	currentExecution := s.newRandomCurrentExecutionRow(shardID, namespaceID, workflowID, runID, requestID, lastWriteVersion)
   107  	result, err := s.store.InsertIntoCurrentExecutions(newExecutionContext(), &currentExecution)
   108  	s.NoError(err)
   109  	rowsAffected, err := result.RowsAffected()
   110  	s.NoError(err)
   111  	s.Equal(1, int(rowsAffected))
   112  }
   113  
   114  func (s *historyCurrentExecutionSuite) TestInsert_Fail_Duplicate() {
   115  	shardID := rand.Int31()
   116  	namespaceID := primitives.NewUUID()
   117  	workflowID := shuffle.String(testHistoryExecutionWorkflowID)
   118  	runID := primitives.NewUUID()
   119  	requestID := primitives.NewUUID().String()
   120  	lastWriteVersion := rand.Int63()
   121  
   122  	currentExecution := s.newRandomCurrentExecutionRow(shardID, namespaceID, workflowID, runID, requestID, lastWriteVersion)
   123  	result, err := s.store.InsertIntoCurrentExecutions(newExecutionContext(), &currentExecution)
   124  	s.NoError(err)
   125  	rowsAffected, err := result.RowsAffected()
   126  	s.NoError(err)
   127  	s.Equal(1, int(rowsAffected))
   128  
   129  	currentExecution = s.newRandomCurrentExecutionRow(shardID, namespaceID, workflowID, runID, requestID, lastWriteVersion)
   130  	_, err = s.store.InsertIntoCurrentExecutions(newExecutionContext(), &currentExecution)
   131  	s.Error(err) // TODO persistence layer should do proper error translation
   132  }
   133  
   134  func (s *historyCurrentExecutionSuite) TestInsertSelect() {
   135  	shardID := rand.Int31()
   136  	namespaceID := primitives.NewUUID()
   137  	workflowID := shuffle.String(testHistoryExecutionWorkflowID)
   138  	runID := primitives.NewUUID()
   139  	requestID := primitives.NewUUID().String()
   140  	lastWriteVersion := rand.Int63()
   141  
   142  	currentExecution := s.newRandomCurrentExecutionRow(shardID, namespaceID, workflowID, runID, requestID, lastWriteVersion)
   143  	result, err := s.store.InsertIntoCurrentExecutions(newExecutionContext(), &currentExecution)
   144  	s.NoError(err)
   145  	rowsAffected, err := result.RowsAffected()
   146  	s.NoError(err)
   147  	s.Equal(1, int(rowsAffected))
   148  
   149  	filter := sqlplugin.CurrentExecutionsFilter{
   150  		ShardID:     shardID,
   151  		NamespaceID: namespaceID,
   152  		WorkflowID:  workflowID,
   153  		RunID:       nil,
   154  	}
   155  	row, err := s.store.SelectFromCurrentExecutions(newExecutionContext(), filter)
   156  	s.NoError(err)
   157  	s.Equal(&currentExecution, row)
   158  }
   159  
   160  func (s *historyCurrentExecutionSuite) TestInsertUpdate_Success() {
   161  	shardID := rand.Int31()
   162  	namespaceID := primitives.NewUUID()
   163  	workflowID := shuffle.String(testHistoryExecutionWorkflowID)
   164  	runID := primitives.NewUUID()
   165  	requestID := primitives.NewUUID().String()
   166  	lastWriteVersion := rand.Int63()
   167  
   168  	currentExecution := s.newRandomCurrentExecutionRow(shardID, namespaceID, workflowID, runID, requestID, lastWriteVersion)
   169  	result, err := s.store.InsertIntoCurrentExecutions(newExecutionContext(), &currentExecution)
   170  	s.NoError(err)
   171  	rowsAffected, err := result.RowsAffected()
   172  	s.NoError(err)
   173  	s.Equal(1, int(rowsAffected))
   174  
   175  	currentExecution = s.newRandomCurrentExecutionRow(shardID, namespaceID, workflowID, runID, primitives.NewUUID().String(), rand.Int63())
   176  	result, err = s.store.UpdateCurrentExecutions(newExecutionContext(), &currentExecution)
   177  	s.NoError(err)
   178  	rowsAffected, err = result.RowsAffected()
   179  	s.NoError(err)
   180  	s.Equal(1, int(rowsAffected))
   181  }
   182  
   183  func (s *historyCurrentExecutionSuite) TestUpdate_Fail() {
   184  	shardID := rand.Int31()
   185  	namespaceID := primitives.NewUUID()
   186  	workflowID := shuffle.String(testHistoryExecutionWorkflowID)
   187  	runID := primitives.NewUUID()
   188  	requestID := primitives.NewUUID().String()
   189  	lastWriteVersion := rand.Int63()
   190  
   191  	currentExecution := s.newRandomCurrentExecutionRow(shardID, namespaceID, workflowID, runID, requestID, lastWriteVersion)
   192  	result, err := s.store.UpdateCurrentExecutions(newExecutionContext(), &currentExecution)
   193  	s.NoError(err)
   194  	rowsAffected, err := result.RowsAffected()
   195  	s.NoError(err)
   196  	s.Equal(0, int(rowsAffected))
   197  }
   198  
   199  func (s *historyCurrentExecutionSuite) TestInsertUpdateSelect() {
   200  	shardID := rand.Int31()
   201  	namespaceID := primitives.NewUUID()
   202  	workflowID := shuffle.String(testHistoryExecutionWorkflowID)
   203  	runID := primitives.NewUUID()
   204  	requestID := primitives.NewUUID().String()
   205  	lastWriteVersion := rand.Int63()
   206  
   207  	currentExecution := s.newRandomCurrentExecutionRow(shardID, namespaceID, workflowID, runID, requestID, lastWriteVersion)
   208  	result, err := s.store.InsertIntoCurrentExecutions(newExecutionContext(), &currentExecution)
   209  	s.NoError(err)
   210  	rowsAffected, err := result.RowsAffected()
   211  	s.NoError(err)
   212  	s.Equal(1, int(rowsAffected))
   213  
   214  	currentExecution = s.newRandomCurrentExecutionRow(shardID, namespaceID, workflowID, runID, primitives.NewUUID().String(), rand.Int63())
   215  	result, err = s.store.UpdateCurrentExecutions(newExecutionContext(), &currentExecution)
   216  	s.NoError(err)
   217  	rowsAffected, err = result.RowsAffected()
   218  	s.NoError(err)
   219  	s.Equal(1, int(rowsAffected))
   220  
   221  	filter := sqlplugin.CurrentExecutionsFilter{
   222  		ShardID:     shardID,
   223  		NamespaceID: namespaceID,
   224  		WorkflowID:  workflowID,
   225  		RunID:       nil,
   226  	}
   227  	row, err := s.store.SelectFromCurrentExecutions(newExecutionContext(), filter)
   228  	s.NoError(err)
   229  	s.Equal(&currentExecution, row)
   230  }
   231  
   232  func (s *historyCurrentExecutionSuite) TestInsertDeleteSelect_Success() {
   233  	shardID := rand.Int31()
   234  	namespaceID := primitives.NewUUID()
   235  	workflowID := shuffle.String(testHistoryExecutionWorkflowID)
   236  	runID := primitives.NewUUID()
   237  	requestID := primitives.NewUUID().String()
   238  	lastWriteVersion := rand.Int63()
   239  
   240  	currentExecution := s.newRandomCurrentExecutionRow(shardID, namespaceID, workflowID, runID, requestID, lastWriteVersion)
   241  	result, err := s.store.InsertIntoCurrentExecutions(newExecutionContext(), &currentExecution)
   242  	s.NoError(err)
   243  	rowsAffected, err := result.RowsAffected()
   244  	s.NoError(err)
   245  	s.Equal(1, int(rowsAffected))
   246  
   247  	filter := sqlplugin.CurrentExecutionsFilter{
   248  		ShardID:     shardID,
   249  		NamespaceID: namespaceID,
   250  		WorkflowID:  workflowID,
   251  		RunID:       runID,
   252  	}
   253  	result, err = s.store.DeleteFromCurrentExecutions(newExecutionContext(), filter)
   254  	s.NoError(err)
   255  	rowsAffected, err = result.RowsAffected()
   256  	s.NoError(err)
   257  	s.Equal(1, int(rowsAffected))
   258  
   259  	filter.RunID = nil
   260  	_, err = s.store.SelectFromCurrentExecutions(newExecutionContext(), filter)
   261  	s.Error(err) // TODO persistence layer should do proper error translation
   262  }
   263  
   264  func (s *historyCurrentExecutionSuite) TestInsertDeleteSelect_Fail() {
   265  	shardID := rand.Int31()
   266  	namespaceID := primitives.NewUUID()
   267  	workflowID := shuffle.String(testHistoryExecutionWorkflowID)
   268  	runID := primitives.NewUUID()
   269  	requestID := primitives.NewUUID().String()
   270  	lastWriteVersion := rand.Int63()
   271  
   272  	currentExecution := s.newRandomCurrentExecutionRow(shardID, namespaceID, workflowID, runID, requestID, lastWriteVersion)
   273  	result, err := s.store.InsertIntoCurrentExecutions(newExecutionContext(), &currentExecution)
   274  	s.NoError(err)
   275  	rowsAffected, err := result.RowsAffected()
   276  	s.NoError(err)
   277  	s.Equal(1, int(rowsAffected))
   278  
   279  	filter := sqlplugin.CurrentExecutionsFilter{
   280  		ShardID:     shardID,
   281  		NamespaceID: namespaceID,
   282  		WorkflowID:  workflowID,
   283  		RunID:       primitives.NewUUID(),
   284  	}
   285  	result, err = s.store.DeleteFromCurrentExecutions(newExecutionContext(), filter)
   286  	s.NoError(err)
   287  	rowsAffected, err = result.RowsAffected()
   288  	s.NoError(err)
   289  	s.Equal(0, int(rowsAffected))
   290  
   291  	filter.RunID = nil
   292  	row, err := s.store.SelectFromCurrentExecutions(newExecutionContext(), filter)
   293  	s.NoError(err)
   294  	s.Equal(&currentExecution, row)
   295  }
   296  
   297  func (s *historyCurrentExecutionSuite) TestLock() {
   298  	shardID := rand.Int31()
   299  	namespaceID := primitives.NewUUID()
   300  	workflowID := shuffle.String(testHistoryExecutionWorkflowID)
   301  	runID := primitives.NewUUID()
   302  	requestID := primitives.NewUUID().String()
   303  	lastWriteVersion := rand.Int63()
   304  
   305  	currentExecution := s.newRandomCurrentExecutionRow(shardID, namespaceID, workflowID, runID, requestID, lastWriteVersion)
   306  	result, err := s.store.InsertIntoCurrentExecutions(newExecutionContext(), &currentExecution)
   307  	s.NoError(err)
   308  	rowsAffected, err := result.RowsAffected()
   309  	s.NoError(err)
   310  	s.Equal(1, int(rowsAffected))
   311  
   312  	// NOTE: lock without transaction is equivalent to select
   313  	//  this test only test the select functionality
   314  	filter := sqlplugin.CurrentExecutionsFilter{
   315  		ShardID:     shardID,
   316  		NamespaceID: namespaceID,
   317  		WorkflowID:  workflowID,
   318  		RunID:       nil,
   319  	}
   320  	row, err := s.store.LockCurrentExecutions(newExecutionContext(), filter)
   321  	s.NoError(err)
   322  	s.Equal(&currentExecution, row)
   323  }
   324  
   325  func (s *historyCurrentExecutionSuite) newRandomCurrentExecutionRow(
   326  	shardID int32,
   327  	namespaceID primitives.UUID,
   328  	workflowID string,
   329  	runID primitives.UUID,
   330  	requestID string,
   331  	lastWriteVersion int64,
   332  ) sqlplugin.CurrentExecutionsRow {
   333  	state := testHistoryExecutionStates[rand.Intn(len(testHistoryExecutionStates))]
   334  	status := testHistoryExecutionStatus[state][rand.Intn(len(testHistoryExecutionStatus[state]))]
   335  	return sqlplugin.CurrentExecutionsRow{
   336  		ShardID:          shardID,
   337  		NamespaceID:      namespaceID,
   338  		WorkflowID:       workflowID,
   339  		RunID:            runID,
   340  		CreateRequestID:  requestID,
   341  		LastWriteVersion: lastWriteVersion,
   342  		State:            state,
   343  		Status:           status,
   344  	}
   345  }