go.temporal.io/server@v1.23.0/common/persistence/sql/sqlplugin/tests/history_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 34 "go.temporal.io/server/common/persistence/sql/sqlplugin" 35 "go.temporal.io/server/common/primitives" 36 "go.temporal.io/server/common/shuffle" 37 ) 38 39 type ( 40 historyExecutionSuite struct { 41 suite.Suite 42 *require.Assertions 43 44 store sqlplugin.HistoryExecution 45 } 46 ) 47 48 const ( 49 testHistoryExecutionWorkflowID = "random workflow ID" 50 51 testHistoryExecutionEncoding = "random encoding" 52 testHistoryExecutionStateEncoding = "random encoding" 53 ) 54 55 var ( 56 testHistoryExecutionData = []byte("random history execution data") 57 testHistoryExecutionStateData = []byte("random history execution state data") 58 ) 59 60 func NewHistoryExecutionSuite( 61 t *testing.T, 62 store sqlplugin.HistoryExecution, 63 ) *historyExecutionSuite { 64 return &historyExecutionSuite{ 65 Assertions: require.New(t), 66 store: store, 67 } 68 } 69 70 func (s *historyExecutionSuite) SetupSuite() { 71 72 } 73 74 func (s *historyExecutionSuite) TearDownSuite() { 75 76 } 77 78 func (s *historyExecutionSuite) SetupTest() { 79 s.Assertions = require.New(s.T()) 80 } 81 82 func (s *historyExecutionSuite) TearDownTest() { 83 84 } 85 86 func (s *historyExecutionSuite) TestInsert_Success() { 87 shardID := rand.Int31() 88 namespaceID := primitives.NewUUID() 89 workflowID := shuffle.String(testHistoryExecutionWorkflowID) 90 runID := primitives.NewUUID() 91 nextEventID := rand.Int63() 92 lastWriteVersion := rand.Int63() 93 94 execution := s.newRandomExecutionRow(shardID, namespaceID, workflowID, runID, nextEventID, lastWriteVersion) 95 result, err := s.store.InsertIntoExecutions(newExecutionContext(), &execution) 96 s.NoError(err) 97 rowsAffected, err := result.RowsAffected() 98 s.NoError(err) 99 s.Equal(1, int(rowsAffected)) 100 } 101 102 func (s *historyExecutionSuite) TestInsert_Fail_Duplicate() { 103 shardID := rand.Int31() 104 namespaceID := primitives.NewUUID() 105 workflowID := shuffle.String(testHistoryExecutionWorkflowID) 106 runID := primitives.NewUUID() 107 nextEventID := rand.Int63() 108 lastWriteVersion := rand.Int63() 109 110 execution := s.newRandomExecutionRow(shardID, namespaceID, workflowID, runID, nextEventID, lastWriteVersion) 111 result, err := s.store.InsertIntoExecutions(newExecutionContext(), &execution) 112 s.NoError(err) 113 rowsAffected, err := result.RowsAffected() 114 s.NoError(err) 115 s.Equal(1, int(rowsAffected)) 116 117 execution = s.newRandomExecutionRow(shardID, namespaceID, workflowID, runID, nextEventID, lastWriteVersion) 118 _, err = s.store.InsertIntoExecutions(newExecutionContext(), &execution) 119 s.Error(err) // TODO persistence layer should do proper error translation 120 } 121 122 func (s *historyExecutionSuite) TestInsertSelect() { 123 shardID := rand.Int31() 124 namespaceID := primitives.NewUUID() 125 workflowID := shuffle.String(testHistoryExecutionWorkflowID) 126 runID := primitives.NewUUID() 127 nextEventID := rand.Int63() 128 lastWriteVersion := rand.Int63() 129 130 execution := s.newRandomExecutionRow(shardID, namespaceID, workflowID, runID, nextEventID, lastWriteVersion) 131 result, err := s.store.InsertIntoExecutions(newExecutionContext(), &execution) 132 s.NoError(err) 133 rowsAffected, err := result.RowsAffected() 134 s.NoError(err) 135 s.Equal(1, int(rowsAffected)) 136 137 filter := sqlplugin.ExecutionsFilter{ 138 ShardID: shardID, 139 NamespaceID: namespaceID, 140 WorkflowID: workflowID, 141 RunID: runID, 142 } 143 row, err := s.store.SelectFromExecutions(newExecutionContext(), filter) 144 s.NoError(err) 145 s.Equal(&execution, row) 146 } 147 148 func (s *historyExecutionSuite) TestInsertUpdate_Success() { 149 shardID := rand.Int31() 150 namespaceID := primitives.NewUUID() 151 workflowID := shuffle.String(testHistoryExecutionWorkflowID) 152 runID := primitives.NewUUID() 153 nextEventID := rand.Int63() 154 lastWriteVersion := rand.Int63() 155 156 execution := s.newRandomExecutionRow(shardID, namespaceID, workflowID, runID, nextEventID, lastWriteVersion) 157 result, err := s.store.InsertIntoExecutions(newExecutionContext(), &execution) 158 s.NoError(err) 159 rowsAffected, err := result.RowsAffected() 160 s.NoError(err) 161 s.Equal(1, int(rowsAffected)) 162 163 execution = s.newRandomExecutionRow(shardID, namespaceID, workflowID, runID, rand.Int63(), rand.Int63()) 164 result, err = s.store.UpdateExecutions(newExecutionContext(), &execution) 165 s.NoError(err) 166 rowsAffected, err = result.RowsAffected() 167 s.NoError(err) 168 s.Equal(1, int(rowsAffected)) 169 } 170 171 func (s *historyExecutionSuite) TestUpdate_Fail() { 172 shardID := rand.Int31() 173 namespaceID := primitives.NewUUID() 174 workflowID := shuffle.String(testHistoryExecutionWorkflowID) 175 runID := primitives.NewUUID() 176 nextEventID := rand.Int63() 177 lastWriteVersion := rand.Int63() 178 179 execution := s.newRandomExecutionRow(shardID, namespaceID, workflowID, runID, nextEventID, lastWriteVersion) 180 result, err := s.store.UpdateExecutions(newExecutionContext(), &execution) 181 s.NoError(err) 182 rowsAffected, err := result.RowsAffected() 183 s.NoError(err) 184 s.Equal(0, int(rowsAffected)) 185 } 186 187 func (s *historyExecutionSuite) TestInsertUpdateSelect() { 188 shardID := rand.Int31() 189 namespaceID := primitives.NewUUID() 190 workflowID := shuffle.String(testHistoryExecutionWorkflowID) 191 runID := primitives.NewUUID() 192 nextEventID := rand.Int63() 193 lastWriteVersion := rand.Int63() 194 195 execution := s.newRandomExecutionRow(shardID, namespaceID, workflowID, runID, nextEventID, lastWriteVersion) 196 result, err := s.store.InsertIntoExecutions(newExecutionContext(), &execution) 197 s.NoError(err) 198 rowsAffected, err := result.RowsAffected() 199 s.NoError(err) 200 s.Equal(1, int(rowsAffected)) 201 202 execution = s.newRandomExecutionRow(shardID, namespaceID, workflowID, runID, rand.Int63(), rand.Int63()) 203 result, err = s.store.UpdateExecutions(newExecutionContext(), &execution) 204 s.NoError(err) 205 rowsAffected, err = result.RowsAffected() 206 s.NoError(err) 207 s.Equal(1, int(rowsAffected)) 208 209 filter := sqlplugin.ExecutionsFilter{ 210 ShardID: shardID, 211 NamespaceID: namespaceID, 212 WorkflowID: workflowID, 213 RunID: runID, 214 } 215 row, err := s.store.SelectFromExecutions(newExecutionContext(), filter) 216 s.NoError(err) 217 s.Equal(&execution, row) 218 } 219 220 func (s *historyExecutionSuite) TestDeleteSelect() { 221 shardID := rand.Int31() 222 namespaceID := primitives.NewUUID() 223 workflowID := shuffle.String(testHistoryExecutionWorkflowID) 224 runID := primitives.NewUUID() 225 226 filter := sqlplugin.ExecutionsFilter{ 227 ShardID: shardID, 228 NamespaceID: namespaceID, 229 WorkflowID: workflowID, 230 RunID: runID, 231 } 232 result, err := s.store.DeleteFromExecutions(newExecutionContext(), filter) 233 s.NoError(err) 234 rowsAffected, err := result.RowsAffected() 235 s.NoError(err) 236 s.Equal(0, int(rowsAffected)) 237 238 _, err = s.store.SelectFromExecutions(newExecutionContext(), filter) 239 s.Error(err) // TODO persistence layer should do proper error translation 240 } 241 242 func (s *historyExecutionSuite) TestInsertDeleteSelect() { 243 shardID := rand.Int31() 244 namespaceID := primitives.NewUUID() 245 workflowID := shuffle.String(testHistoryExecutionWorkflowID) 246 runID := primitives.NewUUID() 247 nextEventID := rand.Int63() 248 lastWriteVersion := rand.Int63() 249 250 execution := s.newRandomExecutionRow(shardID, namespaceID, workflowID, runID, nextEventID, lastWriteVersion) 251 result, err := s.store.InsertIntoExecutions(newExecutionContext(), &execution) 252 s.NoError(err) 253 rowsAffected, err := result.RowsAffected() 254 s.NoError(err) 255 s.Equal(1, int(rowsAffected)) 256 257 filter := sqlplugin.ExecutionsFilter{ 258 ShardID: shardID, 259 NamespaceID: namespaceID, 260 WorkflowID: workflowID, 261 RunID: runID, 262 } 263 result, err = s.store.DeleteFromExecutions(newExecutionContext(), filter) 264 s.NoError(err) 265 rowsAffected, err = result.RowsAffected() 266 s.NoError(err) 267 s.Equal(1, int(rowsAffected)) 268 269 _, err = s.store.SelectFromExecutions(newExecutionContext(), filter) 270 s.Error(err) // TODO persistence layer should do proper error translation 271 } 272 273 func (s *historyExecutionSuite) TestReadLock() { 274 shardID := rand.Int31() 275 namespaceID := primitives.NewUUID() 276 workflowID := shuffle.String(testHistoryExecutionWorkflowID) 277 runID := primitives.NewUUID() 278 nextEventID := rand.Int63() 279 lastWriteVersion := rand.Int63() 280 281 execution := s.newRandomExecutionRow(shardID, namespaceID, workflowID, runID, nextEventID, lastWriteVersion) 282 result, err := s.store.InsertIntoExecutions(newExecutionContext(), &execution) 283 s.NoError(err) 284 rowsAffected, err := result.RowsAffected() 285 s.NoError(err) 286 s.Equal(1, int(rowsAffected)) 287 288 filter := sqlplugin.ExecutionsFilter{ 289 ShardID: shardID, 290 NamespaceID: namespaceID, 291 WorkflowID: workflowID, 292 RunID: runID, 293 } 294 rowDBVersion, rowNextEventID, err := s.store.ReadLockExecutions(newExecutionContext(), filter) 295 s.NoError(err) 296 s.Equal(execution.DBRecordVersion, rowDBVersion) 297 s.Equal(execution.NextEventID, rowNextEventID) 298 } 299 300 func (s *historyExecutionSuite) TestWriteLock() { 301 shardID := rand.Int31() 302 namespaceID := primitives.NewUUID() 303 workflowID := shuffle.String(testHistoryExecutionWorkflowID) 304 runID := primitives.NewUUID() 305 nextEventID := rand.Int63() 306 lastWriteVersion := rand.Int63() 307 308 execution := s.newRandomExecutionRow(shardID, namespaceID, workflowID, runID, nextEventID, lastWriteVersion) 309 result, err := s.store.InsertIntoExecutions(newExecutionContext(), &execution) 310 s.NoError(err) 311 rowsAffected, err := result.RowsAffected() 312 s.NoError(err) 313 s.Equal(1, int(rowsAffected)) 314 315 filter := sqlplugin.ExecutionsFilter{ 316 ShardID: shardID, 317 NamespaceID: namespaceID, 318 WorkflowID: workflowID, 319 RunID: runID, 320 } 321 rowDBVersion, rowNextEventID, err := s.store.WriteLockExecutions(newExecutionContext(), filter) 322 s.NoError(err) 323 s.Equal(execution.DBRecordVersion, rowDBVersion) 324 s.Equal(execution.NextEventID, rowNextEventID) 325 } 326 327 func (s *historyExecutionSuite) newRandomExecutionRow( 328 shardID int32, 329 namespaceID primitives.UUID, 330 workflowID string, 331 runID primitives.UUID, 332 nextEventID int64, 333 lastWriteVersion int64, 334 ) sqlplugin.ExecutionsRow { 335 return sqlplugin.ExecutionsRow{ 336 ShardID: shardID, 337 NamespaceID: namespaceID, 338 WorkflowID: workflowID, 339 RunID: runID, 340 NextEventID: nextEventID, 341 LastWriteVersion: lastWriteVersion, 342 Data: shuffle.Bytes(testHistoryExecutionData), 343 DataEncoding: testHistoryExecutionEncoding, 344 State: shuffle.Bytes(testHistoryExecutionStateData), 345 StateEncoding: testHistoryExecutionStateEncoding, 346 } 347 }