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(), ¤tExecution) 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(), ¤tExecution) 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(), ¤tExecution) 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(), ¤tExecution) 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(¤tExecution, 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(), ¤tExecution) 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(), ¤tExecution) 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(), ¤tExecution) 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(), ¤tExecution) 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(), ¤tExecution) 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(¤tExecution, 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(), ¤tExecution) 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(), ¤tExecution) 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(¤tExecution, 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(), ¤tExecution) 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(¤tExecution, 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 }