go.temporal.io/server@v1.23.0/common/persistence/sql/sqlplugin/tests/visibility.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 "sort" 30 "testing" 31 "time" 32 33 "github.com/stretchr/testify/require" 34 "github.com/stretchr/testify/suite" 35 enumspb "go.temporal.io/api/enums/v1" 36 37 "go.temporal.io/server/common/convert" 38 "go.temporal.io/server/common/persistence/sql/sqlplugin" 39 "go.temporal.io/server/common/primitives" 40 "go.temporal.io/server/common/shuffle" 41 ) 42 43 type ( 44 visibilitySuite struct { 45 suite.Suite 46 *require.Assertions 47 48 store sqlplugin.Visibility 49 } 50 ) 51 52 const ( 53 testVisibilityEncoding = "random encoding" 54 testVisibilityWorkflowTypeName = "random workflow type name" 55 testVisibilityWorkflowID = "random workflow ID" 56 ) 57 58 var ( 59 testVisibilityData = []byte("random history execution activity data") 60 ) 61 62 var testVisibilityCloseStatus = []enumspb.WorkflowExecutionStatus{ 63 enumspb.WORKFLOW_EXECUTION_STATUS_COMPLETED, 64 enumspb.WORKFLOW_EXECUTION_STATUS_FAILED, 65 enumspb.WORKFLOW_EXECUTION_STATUS_CANCELED, 66 enumspb.WORKFLOW_EXECUTION_STATUS_TERMINATED, 67 enumspb.WORKFLOW_EXECUTION_STATUS_CONTINUED_AS_NEW, 68 enumspb.WORKFLOW_EXECUTION_STATUS_TIMED_OUT, 69 } 70 71 func NewVisibilitySuite( 72 t *testing.T, 73 store sqlplugin.Visibility, 74 ) *visibilitySuite { 75 return &visibilitySuite{ 76 Assertions: require.New(t), 77 store: store, 78 } 79 } 80 81 func (s *visibilitySuite) SetupSuite() { 82 83 } 84 85 func (s *visibilitySuite) TearDownSuite() { 86 87 } 88 89 func (s *visibilitySuite) SetupTest() { 90 s.Assertions = require.New(s.T()) 91 } 92 93 func (s *visibilitySuite) TearDownTest() { 94 95 } 96 97 func (s *visibilitySuite) TestInsertSelect_NonExists() { 98 namespaceID := primitives.NewUUID() 99 runID := primitives.NewUUID() 100 workflowTypeName := shuffle.String(testVisibilityWorkflowTypeName) 101 workflowID := shuffle.String(testVisibilityWorkflowID) 102 startTime := s.now() 103 executionTime := startTime.Add(time.Second) 104 status := int32(0) 105 closeTime := (*time.Time)(nil) 106 historyLength := (*int64)(nil) 107 108 visibility := s.newRandomVisibilityRow( 109 namespaceID, 110 runID, 111 workflowTypeName, 112 workflowID, 113 startTime, 114 executionTime, 115 status, 116 closeTime, 117 historyLength, 118 ) 119 result, err := s.store.InsertIntoVisibility(newVisibilityContext(), &visibility) 120 s.NoError(err) 121 rowsAffected, err := result.RowsAffected() 122 s.NoError(err) 123 s.Equal(1, int(rowsAffected)) 124 125 selectFilter := sqlplugin.VisibilitySelectFilter{ 126 NamespaceID: namespaceID.String(), 127 RunID: convert.StringPtr(runID.String()), 128 } 129 rows, err := s.store.SelectFromVisibility(newVisibilityContext(), selectFilter) 130 s.NoError(err) 131 for index := range rows { 132 rows[index].NamespaceID = namespaceID.String() 133 } 134 s.Equal([]sqlplugin.VisibilityRow{visibility}, rows) 135 } 136 137 func (s *visibilitySuite) TestInsertSelect_Exists() { 138 namespaceID := primitives.NewUUID() 139 runID := primitives.NewUUID() 140 workflowTypeName := shuffle.String(testVisibilityWorkflowTypeName) 141 workflowID := shuffle.String(testVisibilityWorkflowID) 142 startTime := s.now() 143 executionTime := startTime.Add(time.Second) 144 status := int32(0) 145 closeTime := (*time.Time)(nil) 146 historyLength := (*int64)(nil) 147 148 visibility1 := s.newRandomVisibilityRow( 149 namespaceID, 150 runID, 151 workflowTypeName, 152 workflowID, 153 startTime, 154 executionTime, 155 status, 156 closeTime, 157 historyLength, 158 ) 159 result, err := s.store.InsertIntoVisibility(newVisibilityContext(), &visibility1) 160 s.NoError(err) 161 rowsAffected, err := result.RowsAffected() 162 s.NoError(err) 163 s.Equal(1, int(rowsAffected)) 164 165 visibility2 := s.newRandomVisibilityRow( 166 namespaceID, 167 runID, 168 workflowTypeName, 169 workflowID, 170 startTime, 171 executionTime, 172 status, 173 closeTime, 174 historyLength, 175 ) 176 _, err = s.store.InsertIntoVisibility(newVisibilityContext(), &visibility2) 177 s.NoError(err) 178 // NOTE: cannot do assertion on affected rows 179 // PostgreSQL will return 0 180 // MySQL will return 1: ref https://dev.mysql.com/doc/c-api/5.7/en/mysql-affected-rows.html 181 182 selectFilter := sqlplugin.VisibilitySelectFilter{ 183 NamespaceID: namespaceID.String(), 184 RunID: convert.StringPtr(runID.String()), 185 } 186 rows, err := s.store.SelectFromVisibility(newVisibilityContext(), selectFilter) 187 s.NoError(err) 188 for index := range rows { 189 rows[index].NamespaceID = namespaceID.String() 190 } 191 s.Equal([]sqlplugin.VisibilityRow{visibility1}, rows) 192 } 193 194 func (s *visibilitySuite) TestReplaceSelect_NonExists() { 195 namespaceID := primitives.NewUUID() 196 runID := primitives.NewUUID() 197 workflowTypeName := shuffle.String(testVisibilityWorkflowTypeName) 198 workflowID := shuffle.String(testVisibilityWorkflowID) 199 startTime := s.now() 200 executionTime := startTime.Add(time.Second) 201 status := int32(0) 202 closeTime := executionTime.Add(time.Second) 203 historyLength := rand.Int63() 204 205 visibility := s.newRandomVisibilityRow( 206 namespaceID, 207 runID, 208 workflowTypeName, 209 workflowID, 210 startTime, 211 executionTime, 212 status, 213 timePtr(closeTime), 214 convert.Int64Ptr(historyLength), 215 ) 216 result, err := s.store.ReplaceIntoVisibility(newVisibilityContext(), &visibility) 217 s.NoError(err) 218 rowsAffected, err := result.RowsAffected() 219 s.NoError(err) 220 s.Equal(1, int(rowsAffected)) 221 222 selectFilter := sqlplugin.VisibilitySelectFilter{ 223 NamespaceID: namespaceID.String(), 224 RunID: convert.StringPtr(runID.String()), 225 } 226 rows, err := s.store.SelectFromVisibility(newVisibilityContext(), selectFilter) 227 s.NoError(err) 228 for index := range rows { 229 rows[index].NamespaceID = namespaceID.String() 230 } 231 s.Equal([]sqlplugin.VisibilityRow{visibility}, rows) 232 } 233 234 func (s *visibilitySuite) TestReplaceSelect_Exists() { 235 namespaceID := primitives.NewUUID() 236 runID := primitives.NewUUID() 237 workflowTypeName := shuffle.String(testVisibilityWorkflowTypeName) 238 workflowID := shuffle.String(testVisibilityWorkflowID) 239 startTime := s.now() 240 executionTime := startTime.Add(time.Second) 241 status := int32(0) 242 closeTime := executionTime.Add(time.Second) 243 historyLength := rand.Int63() 244 245 visibility := s.newRandomVisibilityRow( 246 namespaceID, 247 runID, 248 workflowTypeName, 249 workflowID, 250 startTime, 251 executionTime, 252 status, 253 timePtr(closeTime), 254 convert.Int64Ptr(historyLength), 255 ) 256 result, err := s.store.ReplaceIntoVisibility(newVisibilityContext(), &visibility) 257 s.NoError(err) 258 rowsAffected, err := result.RowsAffected() 259 s.NoError(err) 260 s.Equal(1, int(rowsAffected)) 261 262 visibility = s.newRandomVisibilityRow( 263 namespaceID, 264 runID, 265 workflowTypeName, 266 workflowID, 267 startTime, 268 executionTime, 269 status, 270 timePtr(closeTime), 271 convert.Int64Ptr(historyLength), 272 ) 273 _, err = s.store.ReplaceIntoVisibility(newVisibilityContext(), &visibility) 274 s.NoError(err) 275 // NOTE: cannot do assertion on affected rows 276 // PostgreSQL will return 1 277 // MySQL will return 2: ref https://dev.mysql.com/doc/c-api/5.7/en/mysql-affected-rows.html 278 279 selectFilter := sqlplugin.VisibilitySelectFilter{ 280 NamespaceID: namespaceID.String(), 281 RunID: convert.StringPtr(runID.String()), 282 } 283 rows, err := s.store.SelectFromVisibility(newVisibilityContext(), selectFilter) 284 s.NoError(err) 285 for index := range rows { 286 rows[index].NamespaceID = namespaceID.String() 287 } 288 s.Equal([]sqlplugin.VisibilityRow{visibility}, rows) 289 } 290 291 func (s *visibilitySuite) TestDeleteGet() { 292 namespaceID := primitives.NewUUID() 293 runID := primitives.NewUUID() 294 295 deleteFilter := sqlplugin.VisibilityDeleteFilter{ 296 NamespaceID: namespaceID.String(), 297 RunID: runID.String(), 298 } 299 result, err := s.store.DeleteFromVisibility(newVisibilityContext(), deleteFilter) 300 s.NoError(err) 301 rowsAffected, err := result.RowsAffected() 302 s.NoError(err) 303 s.Equal(0, int(rowsAffected)) 304 305 getFilter := sqlplugin.VisibilityGetFilter{ 306 NamespaceID: namespaceID.String(), 307 RunID: runID.String(), 308 } 309 _, err = s.store.GetFromVisibility(newVisibilityContext(), getFilter) 310 s.Error(err) // TODO persistence layer should do proper error translation 311 } 312 313 func (s *visibilitySuite) TestInsertDeleteGet() { 314 namespaceID := primitives.NewUUID() 315 runID := primitives.NewUUID() 316 workflowTypeName := shuffle.String(testVisibilityWorkflowTypeName) 317 workflowID := shuffle.String(testVisibilityWorkflowID) 318 startTime := s.now() 319 executionTime := startTime.Add(time.Second) 320 status := int32(0) 321 closeTime := (*time.Time)(nil) 322 historyLength := (*int64)(nil) 323 324 visibility := s.newRandomVisibilityRow( 325 namespaceID, 326 runID, 327 workflowTypeName, 328 workflowID, 329 startTime, 330 executionTime, 331 status, 332 closeTime, 333 historyLength, 334 ) 335 result, err := s.store.InsertIntoVisibility(newVisibilityContext(), &visibility) 336 s.NoError(err) 337 rowsAffected, err := result.RowsAffected() 338 s.NoError(err) 339 s.Equal(1, int(rowsAffected)) 340 341 deleteFilter := sqlplugin.VisibilityDeleteFilter{ 342 NamespaceID: namespaceID.String(), 343 RunID: runID.String(), 344 } 345 result, err = s.store.DeleteFromVisibility(newVisibilityContext(), deleteFilter) 346 s.NoError(err) 347 rowsAffected, err = result.RowsAffected() 348 s.NoError(err) 349 s.Equal(1, int(rowsAffected)) 350 351 getFilter := sqlplugin.VisibilityGetFilter{ 352 NamespaceID: namespaceID.String(), 353 RunID: runID.String(), 354 } 355 _, err = s.store.GetFromVisibility(newVisibilityContext(), getFilter) 356 s.Error(err) // TODO persistence layer should do proper error translation 357 } 358 359 func (s *visibilitySuite) TestReplaceDeleteGet() { 360 namespaceID := primitives.NewUUID() 361 runID := primitives.NewUUID() 362 workflowTypeName := shuffle.String(testVisibilityWorkflowTypeName) 363 workflowID := shuffle.String(testVisibilityWorkflowID) 364 startTime := s.now() 365 executionTime := startTime.Add(time.Second) 366 status := int32(0) 367 closeTime := executionTime.Add(time.Second) 368 historyLength := rand.Int63() 369 370 visibility := s.newRandomVisibilityRow( 371 namespaceID, 372 runID, 373 workflowTypeName, 374 workflowID, 375 startTime, 376 executionTime, 377 status, 378 timePtr(closeTime), 379 convert.Int64Ptr(historyLength), 380 ) 381 result, err := s.store.ReplaceIntoVisibility(newVisibilityContext(), &visibility) 382 s.NoError(err) 383 rowsAffected, err := result.RowsAffected() 384 s.NoError(err) 385 s.Equal(1, int(rowsAffected)) 386 387 deleteFilter := sqlplugin.VisibilityDeleteFilter{ 388 NamespaceID: namespaceID.String(), 389 RunID: runID.String(), 390 } 391 result, err = s.store.DeleteFromVisibility(newVisibilityContext(), deleteFilter) 392 s.NoError(err) 393 rowsAffected, err = result.RowsAffected() 394 s.NoError(err) 395 s.Equal(1, int(rowsAffected)) 396 397 getFilter := sqlplugin.VisibilityGetFilter{ 398 NamespaceID: namespaceID.String(), 399 RunID: runID.String(), 400 } 401 _, err = s.store.GetFromVisibility(newVisibilityContext(), getFilter) 402 s.Error(err) // TODO persistence layer should do proper error translation 403 } 404 405 func (s *visibilitySuite) TestSelect_MinStartTime_MaxStartTime_WorkflowID_StatusOpen_Single() { 406 pageSize := 1 407 408 namespaceID := primitives.NewUUID() 409 runID := primitives.NewUUID() 410 workflowTypeName := shuffle.String(testVisibilityWorkflowTypeName) 411 workflowID := shuffle.String(testVisibilityWorkflowID) 412 startTime := s.now() 413 executionTime := startTime.Add(time.Second) 414 status := int32(enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING) 415 closeTime := (*time.Time)(nil) 416 historyLength := (*int64)(nil) 417 418 visibility := s.newRandomVisibilityRow( 419 namespaceID, 420 runID, 421 workflowTypeName, 422 workflowID, 423 startTime, 424 executionTime, 425 status, 426 closeTime, 427 historyLength, 428 ) 429 result, err := s.store.InsertIntoVisibility(newVisibilityContext(), &visibility) 430 s.NoError(err) 431 rowsAffected, err := result.RowsAffected() 432 s.NoError(err) 433 s.Equal(1, int(rowsAffected)) 434 435 minStartTime := startTime 436 maxStartTime := startTime 437 selectFilter := sqlplugin.VisibilitySelectFilter{ 438 NamespaceID: namespaceID.String(), 439 WorkflowID: convert.StringPtr(workflowID), 440 RunID: convert.StringPtr(""), 441 WorkflowTypeName: nil, 442 MinTime: timePtr(minStartTime), 443 MaxTime: timePtr(maxStartTime), 444 Status: int32(enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING), 445 PageSize: convert.IntPtr(pageSize), 446 } 447 rows, err := s.store.SelectFromVisibility(newVisibilityContext(), selectFilter) 448 s.NoError(err) 449 for index := range rows { 450 rows[index].NamespaceID = namespaceID.String() 451 } 452 s.Equal([]sqlplugin.VisibilityRow{visibility}, rows) 453 } 454 455 func (s *visibilitySuite) TestSelect_MinStartTime_MaxStartTime_WorkflowID_StatusOpen_Multiple() { 456 numStartTime := 20 457 visibilityPerStartTime := 4 458 pageSize := 5 459 460 var visibilities []sqlplugin.VisibilityRow 461 462 namespaceID := primitives.NewUUID() 463 workflowID := shuffle.String(testVisibilityWorkflowID) 464 startTime := s.now() 465 minStartTime := startTime 466 maxStartTime := startTime.Add(time.Duration(numStartTime) * time.Second) 467 executionTime := startTime.Add(time.Second) 468 status := int32(enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING) 469 closeTime := (*time.Time)(nil) 470 historyLength := (*int64)(nil) 471 for i := 0; i < numStartTime; i++ { 472 for j := 0; j < visibilityPerStartTime; j++ { 473 runID := primitives.NewUUID() 474 workflowTypeName := shuffle.String(testVisibilityWorkflowTypeName) 475 visibility := s.newRandomVisibilityRow( 476 namespaceID, 477 runID, 478 workflowTypeName, 479 workflowID, 480 startTime, 481 executionTime, 482 status, 483 closeTime, 484 historyLength, 485 ) 486 result, err := s.store.InsertIntoVisibility(newVisibilityContext(), &visibility) 487 s.NoError(err) 488 rowsAffected, err := result.RowsAffected() 489 s.NoError(err) 490 s.Equal(1, int(rowsAffected)) 491 492 visibilities = append(visibilities, visibility) 493 } 494 495 startTime = startTime.Add(time.Second) 496 } 497 498 selectFilter := sqlplugin.VisibilitySelectFilter{ 499 NamespaceID: namespaceID.String(), 500 WorkflowID: convert.StringPtr(workflowID), 501 RunID: convert.StringPtr(""), 502 WorkflowTypeName: nil, 503 MinTime: timePtr(minStartTime), 504 MaxTime: timePtr(maxStartTime), 505 Status: int32(enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING), 506 PageSize: convert.IntPtr(pageSize), 507 } 508 var rows []sqlplugin.VisibilityRow 509 for { 510 rowsPerPage, err := s.store.SelectFromVisibility(newVisibilityContext(), selectFilter) 511 s.NoError(err) 512 rows = append(rows, rowsPerPage...) 513 514 if len(rowsPerPage) > 0 { 515 lastVisibility := rowsPerPage[len(rowsPerPage)-1] 516 selectFilter.MaxTime = timePtr(lastVisibility.StartTime) 517 selectFilter.RunID = convert.StringPtr(lastVisibility.RunID) 518 } else { 519 break 520 } 521 } 522 s.Len(rows, len(visibilities)) 523 s.sortByStartTimeDescRunIDAsc(visibilities) 524 for index := range rows { 525 rows[index].NamespaceID = namespaceID.String() 526 } 527 s.Equal(visibilities, rows) 528 } 529 530 func (s *visibilitySuite) TestSelect_MinStartTime_MaxStartTime_WorkflowID_StatusClose_Single() { 531 pageSize := 1 532 533 namespaceID := primitives.NewUUID() 534 runID := primitives.NewUUID() 535 workflowTypeName := shuffle.String(testVisibilityWorkflowTypeName) 536 workflowID := shuffle.String(testVisibilityWorkflowID) 537 startTime := s.now() 538 executionTime := startTime.Add(time.Second) 539 status := int32(enumspb.WORKFLOW_EXECUTION_STATUS_COMPLETED) 540 closeTime := executionTime.Add(time.Second) 541 historyLength := rand.Int63() 542 543 visibility := s.newRandomVisibilityRow( 544 namespaceID, 545 runID, 546 workflowTypeName, 547 workflowID, 548 startTime, 549 executionTime, 550 status, 551 timePtr(closeTime), 552 convert.Int64Ptr(historyLength), 553 ) 554 result, err := s.store.ReplaceIntoVisibility(newVisibilityContext(), &visibility) 555 s.NoError(err) 556 rowsAffected, err := result.RowsAffected() 557 s.NoError(err) 558 s.Equal(1, int(rowsAffected)) 559 560 minStartTime := closeTime 561 maxStartTime := closeTime 562 selectFilter := sqlplugin.VisibilitySelectFilter{ 563 NamespaceID: namespaceID.String(), 564 WorkflowID: convert.StringPtr(workflowID), 565 RunID: convert.StringPtr(""), 566 WorkflowTypeName: nil, 567 MinTime: timePtr(minStartTime), 568 MaxTime: timePtr(maxStartTime), 569 Status: int32(enumspb.WORKFLOW_EXECUTION_STATUS_UNSPECIFIED), 570 PageSize: convert.IntPtr(pageSize), 571 } 572 rows, err := s.store.SelectFromVisibility(newVisibilityContext(), selectFilter) 573 s.NoError(err) 574 for index := range rows { 575 rows[index].NamespaceID = namespaceID.String() 576 } 577 s.Equal([]sqlplugin.VisibilityRow{visibility}, rows) 578 } 579 580 func (s *visibilitySuite) TestSelect_MinStartTime_MaxStartTime_WorkflowID_StatusClose_Multiple() { 581 numStartTime := 20 582 visibilityPerStartTime := 4 583 pageSize := 5 584 585 var visibilities []sqlplugin.VisibilityRow 586 587 namespaceID := primitives.NewUUID() 588 workflowID := shuffle.String(testVisibilityWorkflowID) 589 startTime := s.now() 590 executionTime := startTime.Add(time.Second) 591 status := int32(enumspb.WORKFLOW_EXECUTION_STATUS_COMPLETED) 592 closeTime := executionTime.Add(time.Second) 593 historyLength := rand.Int63() 594 minStartTime := closeTime 595 maxStartTime := closeTime.Add(time.Duration(numStartTime) * time.Second) 596 for i := 0; i < numStartTime; i++ { 597 for j := 0; j < visibilityPerStartTime; j++ { 598 runID := primitives.NewUUID() 599 workflowTypeName := shuffle.String(testVisibilityWorkflowTypeName) 600 visibility := s.newRandomVisibilityRow( 601 namespaceID, 602 runID, 603 workflowTypeName, 604 workflowID, 605 startTime, 606 executionTime, 607 status, 608 timePtr(closeTime), 609 convert.Int64Ptr(historyLength), 610 ) 611 result, err := s.store.ReplaceIntoVisibility(newVisibilityContext(), &visibility) 612 s.NoError(err) 613 rowsAffected, err := result.RowsAffected() 614 s.NoError(err) 615 s.Equal(1, int(rowsAffected)) 616 617 visibilities = append(visibilities, visibility) 618 } 619 closeTime = closeTime.Add(time.Second) 620 } 621 622 selectFilter := sqlplugin.VisibilitySelectFilter{ 623 NamespaceID: namespaceID.String(), 624 WorkflowID: convert.StringPtr(workflowID), 625 RunID: convert.StringPtr(""), 626 WorkflowTypeName: nil, 627 MinTime: timePtr(minStartTime), 628 MaxTime: timePtr(maxStartTime), 629 Status: int32(enumspb.WORKFLOW_EXECUTION_STATUS_UNSPECIFIED), 630 PageSize: convert.IntPtr(pageSize), 631 } 632 var rows []sqlplugin.VisibilityRow 633 for { 634 rowsPerPage, err := s.store.SelectFromVisibility(newVisibilityContext(), selectFilter) 635 s.NoError(err) 636 rows = append(rows, rowsPerPage...) 637 638 if len(rowsPerPage) > 0 { 639 lastVisibility := rowsPerPage[len(rowsPerPage)-1] 640 selectFilter.MaxTime = lastVisibility.CloseTime 641 selectFilter.RunID = convert.StringPtr(lastVisibility.RunID) 642 } else { 643 break 644 } 645 } 646 s.Len(rows, len(visibilities)) 647 s.sortByCloseTimeDescRunIDAsc(visibilities) 648 for index := range rows { 649 rows[index].NamespaceID = namespaceID.String() 650 } 651 s.Equal(visibilities, rows) 652 } 653 654 func (s *visibilitySuite) TestSelect_MinStartTime_MaxStartTime_WorkflowTypeName_StatusOpen_Single() { 655 pageSize := 1 656 657 namespaceID := primitives.NewUUID() 658 runID := primitives.NewUUID() 659 workflowTypeName := shuffle.String(testVisibilityWorkflowTypeName) 660 workflowID := shuffle.String(testVisibilityWorkflowID) 661 startTime := s.now() 662 executionTime := startTime.Add(time.Second) 663 status := int32(enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING) 664 closeTime := (*time.Time)(nil) 665 historyLength := (*int64)(nil) 666 667 visibility := s.newRandomVisibilityRow( 668 namespaceID, 669 runID, 670 workflowTypeName, 671 workflowID, 672 startTime, 673 executionTime, 674 status, 675 closeTime, 676 historyLength, 677 ) 678 result, err := s.store.InsertIntoVisibility(newVisibilityContext(), &visibility) 679 s.NoError(err) 680 rowsAffected, err := result.RowsAffected() 681 s.NoError(err) 682 s.Equal(1, int(rowsAffected)) 683 684 minStartTime := startTime 685 maxStartTime := startTime 686 selectFilter := sqlplugin.VisibilitySelectFilter{ 687 NamespaceID: namespaceID.String(), 688 WorkflowID: nil, 689 RunID: convert.StringPtr(""), 690 WorkflowTypeName: convert.StringPtr(workflowTypeName), 691 MinTime: timePtr(minStartTime), 692 MaxTime: timePtr(maxStartTime), 693 Status: int32(enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING), 694 PageSize: convert.IntPtr(pageSize), 695 } 696 rows, err := s.store.SelectFromVisibility(newVisibilityContext(), selectFilter) 697 s.NoError(err) 698 for index := range rows { 699 rows[index].NamespaceID = namespaceID.String() 700 } 701 s.Equal([]sqlplugin.VisibilityRow{visibility}, rows) 702 } 703 704 func (s *visibilitySuite) TestSelect_MinStartTime_MaxStartTime_WorkflowTypeName_StatusOpen_Multiple() { 705 numStartTime := 20 706 visibilityPerStartTime := 4 707 pageSize := 5 708 709 var visibilities []sqlplugin.VisibilityRow 710 711 namespaceID := primitives.NewUUID() 712 workflowTypeName := shuffle.String(testVisibilityWorkflowTypeName) 713 startTime := s.now() 714 minStartTime := startTime 715 maxStartTime := startTime.Add(time.Duration(numStartTime) * time.Second) 716 executionTime := startTime.Add(time.Second) 717 status := int32(enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING) 718 closeTime := (*time.Time)(nil) 719 historyLength := (*int64)(nil) 720 for i := 0; i < numStartTime; i++ { 721 for j := 0; j < visibilityPerStartTime; j++ { 722 workflowID := shuffle.String(testVisibilityWorkflowID) 723 runID := primitives.NewUUID() 724 visibility := s.newRandomVisibilityRow( 725 namespaceID, 726 runID, 727 workflowTypeName, 728 workflowID, 729 startTime, 730 executionTime, 731 status, 732 closeTime, 733 historyLength, 734 ) 735 result, err := s.store.InsertIntoVisibility(newVisibilityContext(), &visibility) 736 s.NoError(err) 737 rowsAffected, err := result.RowsAffected() 738 s.NoError(err) 739 s.Equal(1, int(rowsAffected)) 740 741 visibilities = append(visibilities, visibility) 742 } 743 744 startTime = startTime.Add(time.Second) 745 } 746 747 selectFilter := sqlplugin.VisibilitySelectFilter{ 748 NamespaceID: namespaceID.String(), 749 WorkflowID: nil, 750 RunID: convert.StringPtr(""), 751 WorkflowTypeName: convert.StringPtr(workflowTypeName), 752 MinTime: timePtr(minStartTime), 753 MaxTime: timePtr(maxStartTime), 754 Status: int32(enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING), 755 PageSize: convert.IntPtr(pageSize), 756 } 757 var rows []sqlplugin.VisibilityRow 758 for { 759 rowsPerPage, err := s.store.SelectFromVisibility(newVisibilityContext(), selectFilter) 760 s.NoError(err) 761 rows = append(rows, rowsPerPage...) 762 763 if len(rowsPerPage) > 0 { 764 lastVisibility := rowsPerPage[len(rowsPerPage)-1] 765 selectFilter.MaxTime = timePtr(lastVisibility.StartTime) 766 selectFilter.RunID = convert.StringPtr(lastVisibility.RunID) 767 } else { 768 break 769 } 770 } 771 s.Len(rows, len(visibilities)) 772 s.sortByStartTimeDescRunIDAsc(visibilities) 773 for index := range rows { 774 rows[index].NamespaceID = namespaceID.String() 775 } 776 s.Equal(visibilities, rows) 777 } 778 779 func (s *visibilitySuite) TestSelect_MinStartTime_MaxStartTime_WorkflowTypeName_StatusClose_Single() { 780 pageSize := 1 781 782 namespaceID := primitives.NewUUID() 783 runID := primitives.NewUUID() 784 workflowTypeName := shuffle.String(testVisibilityWorkflowTypeName) 785 workflowID := shuffle.String(testVisibilityWorkflowID) 786 startTime := s.now() 787 executionTime := startTime.Add(time.Second) 788 status := int32(enumspb.WORKFLOW_EXECUTION_STATUS_COMPLETED) 789 closeTime := executionTime.Add(time.Second) 790 historyLength := rand.Int63() 791 792 visibility := s.newRandomVisibilityRow( 793 namespaceID, 794 runID, 795 workflowTypeName, 796 workflowID, 797 startTime, 798 executionTime, 799 status, 800 timePtr(closeTime), 801 convert.Int64Ptr(historyLength), 802 ) 803 result, err := s.store.ReplaceIntoVisibility(newVisibilityContext(), &visibility) 804 s.NoError(err) 805 rowsAffected, err := result.RowsAffected() 806 s.NoError(err) 807 s.Equal(1, int(rowsAffected)) 808 809 minStartTime := closeTime 810 maxStartTime := closeTime 811 selectFilter := sqlplugin.VisibilitySelectFilter{ 812 NamespaceID: namespaceID.String(), 813 WorkflowID: nil, 814 RunID: convert.StringPtr(""), 815 WorkflowTypeName: convert.StringPtr(workflowTypeName), 816 MinTime: timePtr(minStartTime), 817 MaxTime: timePtr(maxStartTime), 818 Status: int32(enumspb.WORKFLOW_EXECUTION_STATUS_UNSPECIFIED), 819 PageSize: convert.IntPtr(pageSize), 820 } 821 rows, err := s.store.SelectFromVisibility(newVisibilityContext(), selectFilter) 822 s.NoError(err) 823 for index := range rows { 824 rows[index].NamespaceID = namespaceID.String() 825 } 826 s.Equal([]sqlplugin.VisibilityRow{visibility}, rows) 827 } 828 829 func (s *visibilitySuite) TestSelect_MinStartTime_MaxStartTime_WorkflowTypeName_StatusClose_Multiple() { 830 numStartTime := 20 831 visibilityPerStartTime := 4 832 pageSize := 5 833 834 var visibilities []sqlplugin.VisibilityRow 835 836 namespaceID := primitives.NewUUID() 837 workflowTypeName := shuffle.String(testVisibilityWorkflowTypeName) 838 startTime := s.now() 839 executionTime := startTime.Add(time.Second) 840 status := int32(enumspb.WORKFLOW_EXECUTION_STATUS_COMPLETED) 841 closeTime := executionTime.Add(time.Second) 842 historyLength := rand.Int63() 843 minStartTime := closeTime 844 maxStartTime := closeTime.Add(time.Duration(numStartTime) * time.Second) 845 for i := 0; i < numStartTime; i++ { 846 for j := 0; j < visibilityPerStartTime; j++ { 847 workflowID := shuffle.String(testVisibilityWorkflowID) 848 runID := primitives.NewUUID() 849 visibility := s.newRandomVisibilityRow( 850 namespaceID, 851 runID, 852 workflowTypeName, 853 workflowID, 854 startTime, 855 executionTime, 856 status, 857 timePtr(closeTime), 858 convert.Int64Ptr(historyLength), 859 ) 860 result, err := s.store.ReplaceIntoVisibility(newVisibilityContext(), &visibility) 861 s.NoError(err) 862 rowsAffected, err := result.RowsAffected() 863 s.NoError(err) 864 s.Equal(1, int(rowsAffected)) 865 866 visibilities = append(visibilities, visibility) 867 } 868 closeTime = closeTime.Add(time.Second) 869 } 870 871 selectFilter := sqlplugin.VisibilitySelectFilter{ 872 NamespaceID: namespaceID.String(), 873 WorkflowID: nil, 874 RunID: convert.StringPtr(""), 875 WorkflowTypeName: convert.StringPtr(workflowTypeName), 876 MinTime: timePtr(minStartTime), 877 MaxTime: timePtr(maxStartTime), 878 Status: int32(enumspb.WORKFLOW_EXECUTION_STATUS_UNSPECIFIED), 879 PageSize: convert.IntPtr(pageSize), 880 } 881 var rows []sqlplugin.VisibilityRow 882 for { 883 rowsPerPage, err := s.store.SelectFromVisibility(newVisibilityContext(), selectFilter) 884 s.NoError(err) 885 rows = append(rows, rowsPerPage...) 886 887 if len(rowsPerPage) > 0 { 888 lastVisibility := rowsPerPage[len(rowsPerPage)-1] 889 selectFilter.MaxTime = lastVisibility.CloseTime 890 selectFilter.RunID = convert.StringPtr(lastVisibility.RunID) 891 } else { 892 break 893 } 894 } 895 s.Len(rows, len(visibilities)) 896 s.sortByCloseTimeDescRunIDAsc(visibilities) 897 for index := range rows { 898 rows[index].NamespaceID = namespaceID.String() 899 } 900 s.Equal(visibilities, rows) 901 } 902 903 func (s *visibilitySuite) TestSelect_MinStartTime_MaxStartTime_StatusOpen_Single() { 904 pageSize := 1 905 906 namespaceID := primitives.NewUUID() 907 runID := primitives.NewUUID() 908 workflowTypeName := shuffle.String(testVisibilityWorkflowTypeName) 909 workflowID := shuffle.String(testVisibilityWorkflowID) 910 startTime := s.now() 911 executionTime := startTime.Add(time.Second) 912 status := int32(enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING) 913 closeTime := (*time.Time)(nil) 914 historyLength := (*int64)(nil) 915 916 visibility := s.newRandomVisibilityRow( 917 namespaceID, 918 runID, 919 workflowTypeName, 920 workflowID, 921 startTime, 922 executionTime, 923 status, 924 closeTime, 925 historyLength, 926 ) 927 result, err := s.store.InsertIntoVisibility(newVisibilityContext(), &visibility) 928 s.NoError(err) 929 rowsAffected, err := result.RowsAffected() 930 s.NoError(err) 931 s.Equal(1, int(rowsAffected)) 932 933 minStartTime := startTime 934 maxStartTime := startTime 935 selectFilter := sqlplugin.VisibilitySelectFilter{ 936 NamespaceID: namespaceID.String(), 937 WorkflowID: nil, 938 RunID: convert.StringPtr(""), 939 WorkflowTypeName: nil, 940 MinTime: timePtr(minStartTime), 941 MaxTime: timePtr(maxStartTime), 942 Status: int32(enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING), 943 PageSize: convert.IntPtr(pageSize), 944 } 945 rows, err := s.store.SelectFromVisibility(newVisibilityContext(), selectFilter) 946 s.NoError(err) 947 for index := range rows { 948 rows[index].NamespaceID = namespaceID.String() 949 } 950 s.Equal([]sqlplugin.VisibilityRow{visibility}, rows) 951 } 952 953 func (s *visibilitySuite) TestSelect_MinStartTime_MaxStartTime_StatusOpen_Multiple() { 954 numStartTime := 20 955 visibilityPerStartTime := 4 956 pageSize := 5 957 958 var visibilities []sqlplugin.VisibilityRow 959 960 namespaceID := primitives.NewUUID() 961 startTime := s.now() 962 minStartTime := startTime 963 maxStartTime := startTime.Add(time.Duration(numStartTime) * time.Second) 964 executionTime := startTime.Add(time.Second) 965 status := int32(enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING) 966 closeTime := (*time.Time)(nil) 967 historyLength := (*int64)(nil) 968 for i := 0; i < numStartTime; i++ { 969 for j := 0; j < visibilityPerStartTime; j++ { 970 workflowID := shuffle.String(testVisibilityWorkflowID) 971 runID := primitives.NewUUID() 972 workflowTypeName := shuffle.String(testVisibilityWorkflowTypeName) 973 visibility := s.newRandomVisibilityRow( 974 namespaceID, 975 runID, 976 workflowTypeName, 977 workflowID, 978 startTime, 979 executionTime, 980 status, 981 closeTime, 982 historyLength, 983 ) 984 result, err := s.store.InsertIntoVisibility(newVisibilityContext(), &visibility) 985 s.NoError(err) 986 rowsAffected, err := result.RowsAffected() 987 s.NoError(err) 988 s.Equal(1, int(rowsAffected)) 989 990 visibilities = append(visibilities, visibility) 991 } 992 993 startTime = startTime.Add(time.Second) 994 } 995 996 selectFilter := sqlplugin.VisibilitySelectFilter{ 997 NamespaceID: namespaceID.String(), 998 WorkflowID: nil, 999 RunID: convert.StringPtr(""), 1000 WorkflowTypeName: nil, 1001 MinTime: timePtr(minStartTime), 1002 MaxTime: timePtr(maxStartTime), 1003 Status: int32(enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING), 1004 PageSize: convert.IntPtr(pageSize), 1005 } 1006 var rows []sqlplugin.VisibilityRow 1007 for { 1008 rowsPerPage, err := s.store.SelectFromVisibility(newVisibilityContext(), selectFilter) 1009 s.NoError(err) 1010 rows = append(rows, rowsPerPage...) 1011 1012 if len(rowsPerPage) > 0 { 1013 lastVisibility := rowsPerPage[len(rowsPerPage)-1] 1014 selectFilter.MaxTime = timePtr(lastVisibility.StartTime) 1015 selectFilter.RunID = convert.StringPtr(lastVisibility.RunID) 1016 } else { 1017 break 1018 } 1019 } 1020 s.Len(rows, len(visibilities)) 1021 s.sortByStartTimeDescRunIDAsc(visibilities) 1022 for index := range rows { 1023 rows[index].NamespaceID = namespaceID.String() 1024 } 1025 s.Equal(visibilities, rows) 1026 } 1027 1028 func (s *visibilitySuite) TestSelect_MinStartTime_MaxStartTime_StatusClose_Single() { 1029 for _, status := range testVisibilityCloseStatus { 1030 s.testSelectMinStartTimeMaxStartTimeStatusCloseSingle(status) 1031 } 1032 } 1033 1034 func (s *visibilitySuite) testSelectMinStartTimeMaxStartTimeStatusCloseSingle( 1035 status enumspb.WorkflowExecutionStatus, 1036 ) { 1037 pageSize := 1 1038 1039 namespaceID := primitives.NewUUID() 1040 runID := primitives.NewUUID() 1041 workflowTypeName := shuffle.String(testVisibilityWorkflowTypeName) 1042 workflowID := shuffle.String(testVisibilityWorkflowID) 1043 startTime := s.now() 1044 executionTime := startTime.Add(time.Second) 1045 closeTime := executionTime.Add(time.Second) 1046 historyLength := rand.Int63() 1047 1048 visibility := s.newRandomVisibilityRow( 1049 namespaceID, 1050 runID, 1051 workflowTypeName, 1052 workflowID, 1053 startTime, 1054 executionTime, 1055 int32(status), 1056 timePtr(closeTime), 1057 convert.Int64Ptr(historyLength), 1058 ) 1059 result, err := s.store.ReplaceIntoVisibility(newVisibilityContext(), &visibility) 1060 s.NoError(err) 1061 rowsAffected, err := result.RowsAffected() 1062 s.NoError(err) 1063 s.Equal(1, int(rowsAffected)) 1064 1065 minStartTime := closeTime 1066 maxStartTime := closeTime 1067 selectFilter := sqlplugin.VisibilitySelectFilter{ 1068 NamespaceID: namespaceID.String(), 1069 WorkflowID: nil, 1070 RunID: convert.StringPtr(""), 1071 WorkflowTypeName: nil, 1072 MinTime: timePtr(minStartTime), 1073 MaxTime: timePtr(maxStartTime), 1074 Status: int32(enumspb.WORKFLOW_EXECUTION_STATUS_UNSPECIFIED), 1075 PageSize: convert.IntPtr(pageSize), 1076 } 1077 rows, err := s.store.SelectFromVisibility(newVisibilityContext(), selectFilter) 1078 s.NoError(err) 1079 for index := range rows { 1080 rows[index].NamespaceID = namespaceID.String() 1081 } 1082 s.Equal([]sqlplugin.VisibilityRow{visibility}, rows) 1083 } 1084 1085 func (s *visibilitySuite) TestSelect_MinStartTime_MaxStartTime_StatusClose_Multiple() { 1086 numStartTime := 20 1087 visibilityPerStartTime := 4 1088 pageSize := 5 1089 1090 var visibilities []sqlplugin.VisibilityRow 1091 1092 namespaceID := primitives.NewUUID() 1093 startTime := s.now() 1094 executionTime := startTime.Add(time.Second) 1095 1096 closeTime := executionTime.Add(time.Second) 1097 historyLength := rand.Int63() 1098 minStartTime := closeTime 1099 maxStartTime := closeTime.Add(time.Duration(numStartTime) * time.Second) 1100 for i := 0; i < numStartTime; i++ { 1101 for j := 0; j < visibilityPerStartTime; j++ { 1102 workflowID := shuffle.String(testVisibilityWorkflowID) 1103 runID := primitives.NewUUID() 1104 workflowTypeName := shuffle.String(testVisibilityWorkflowTypeName) 1105 status := int32(testVisibilityCloseStatus[rand.Intn(len(testVisibilityCloseStatus))]) 1106 visibility := s.newRandomVisibilityRow( 1107 namespaceID, 1108 runID, 1109 workflowTypeName, 1110 workflowID, 1111 startTime, 1112 executionTime, 1113 status, 1114 timePtr(closeTime), 1115 convert.Int64Ptr(historyLength), 1116 ) 1117 result, err := s.store.ReplaceIntoVisibility(newVisibilityContext(), &visibility) 1118 s.NoError(err) 1119 rowsAffected, err := result.RowsAffected() 1120 s.NoError(err) 1121 s.Equal(1, int(rowsAffected)) 1122 1123 visibilities = append(visibilities, visibility) 1124 } 1125 closeTime = closeTime.Add(time.Second) 1126 } 1127 1128 selectFilter := sqlplugin.VisibilitySelectFilter{ 1129 NamespaceID: namespaceID.String(), 1130 WorkflowID: nil, 1131 RunID: convert.StringPtr(""), 1132 WorkflowTypeName: nil, 1133 MinTime: timePtr(minStartTime), 1134 MaxTime: timePtr(maxStartTime), 1135 Status: int32(enumspb.WORKFLOW_EXECUTION_STATUS_UNSPECIFIED), 1136 PageSize: convert.IntPtr(pageSize), 1137 } 1138 var rows []sqlplugin.VisibilityRow 1139 for { 1140 rowsPerPage, err := s.store.SelectFromVisibility(newVisibilityContext(), selectFilter) 1141 s.NoError(err) 1142 rows = append(rows, rowsPerPage...) 1143 1144 if len(rowsPerPage) > 0 { 1145 lastVisibility := rowsPerPage[len(rowsPerPage)-1] 1146 selectFilter.MaxTime = lastVisibility.CloseTime 1147 selectFilter.RunID = convert.StringPtr(lastVisibility.RunID) 1148 } else { 1149 break 1150 } 1151 } 1152 s.Len(rows, len(visibilities)) 1153 s.sortByCloseTimeDescRunIDAsc(visibilities) 1154 for index := range rows { 1155 rows[index].NamespaceID = namespaceID.String() 1156 } 1157 s.Equal(visibilities, rows) 1158 } 1159 1160 func (s *visibilitySuite) TestSelect_MinStartTime_MaxStartTime_StatusCloseByType_Single() { 1161 for _, status := range testVisibilityCloseStatus { 1162 s.testSelectMinStartTimeMaxStartTimeStatusCloseByTypeSingle(status) 1163 } 1164 } 1165 1166 func (s *visibilitySuite) testSelectMinStartTimeMaxStartTimeStatusCloseByTypeSingle( 1167 status enumspb.WorkflowExecutionStatus, 1168 ) { 1169 pageSize := 1 1170 1171 namespaceID := primitives.NewUUID() 1172 runID := primitives.NewUUID() 1173 workflowTypeName := shuffle.String(testVisibilityWorkflowTypeName) 1174 workflowID := shuffle.String(testVisibilityWorkflowID) 1175 startTime := s.now() 1176 executionTime := startTime.Add(time.Second) 1177 closeTime := executionTime.Add(time.Second) 1178 historyLength := rand.Int63() 1179 1180 visibility := s.newRandomVisibilityRow( 1181 namespaceID, 1182 runID, 1183 workflowTypeName, 1184 workflowID, 1185 startTime, 1186 executionTime, 1187 int32(status), 1188 timePtr(closeTime), 1189 convert.Int64Ptr(historyLength), 1190 ) 1191 result, err := s.store.ReplaceIntoVisibility(newVisibilityContext(), &visibility) 1192 s.NoError(err) 1193 rowsAffected, err := result.RowsAffected() 1194 s.NoError(err) 1195 s.Equal(1, int(rowsAffected)) 1196 1197 minStartTime := closeTime 1198 maxStartTime := closeTime 1199 selectFilter := sqlplugin.VisibilitySelectFilter{ 1200 NamespaceID: namespaceID.String(), 1201 WorkflowID: nil, 1202 RunID: convert.StringPtr(""), 1203 WorkflowTypeName: convert.StringPtr(workflowTypeName), 1204 MinTime: timePtr(minStartTime), 1205 MaxTime: timePtr(maxStartTime), 1206 Status: int32(status), 1207 PageSize: convert.IntPtr(pageSize), 1208 } 1209 rows, err := s.store.SelectFromVisibility(newVisibilityContext(), selectFilter) 1210 s.NoError(err) 1211 for index := range rows { 1212 rows[index].NamespaceID = namespaceID.String() 1213 } 1214 s.Equal([]sqlplugin.VisibilityRow{visibility}, rows) 1215 } 1216 1217 func (s *visibilitySuite) TestSelect_MinStartTime_MaxStartTime_StatusCloseByType_Multiple() { 1218 for _, status := range testVisibilityCloseStatus { 1219 s.testSelectMinStartTimeMaxStartTimeStatusCloseByTypeMultiple(status) 1220 } 1221 } 1222 1223 func (s *visibilitySuite) testSelectMinStartTimeMaxStartTimeStatusCloseByTypeMultiple( 1224 status enumspb.WorkflowExecutionStatus, 1225 ) { 1226 numStartTime := 20 1227 visibilityPerStartTime := 4 1228 pageSize := 5 1229 1230 var visibilities []sqlplugin.VisibilityRow 1231 1232 namespaceID := primitives.NewUUID() 1233 startTime := s.now() 1234 executionTime := startTime.Add(time.Second) 1235 closeTime := executionTime.Add(time.Second) 1236 historyLength := rand.Int63() 1237 minStartTime := closeTime 1238 maxStartTime := closeTime.Add(time.Duration(numStartTime) * time.Second) 1239 for i := 0; i < numStartTime; i++ { 1240 for j := 0; j < visibilityPerStartTime; j++ { 1241 workflowID := shuffle.String(testVisibilityWorkflowID) 1242 runID := primitives.NewUUID() 1243 workflowTypeName := shuffle.String(testVisibilityWorkflowTypeName) 1244 visibility := s.newRandomVisibilityRow( 1245 namespaceID, 1246 runID, 1247 workflowTypeName, 1248 workflowID, 1249 startTime, 1250 executionTime, 1251 int32(status), 1252 timePtr(closeTime), 1253 convert.Int64Ptr(historyLength), 1254 ) 1255 result, err := s.store.ReplaceIntoVisibility(newVisibilityContext(), &visibility) 1256 s.NoError(err) 1257 rowsAffected, err := result.RowsAffected() 1258 s.NoError(err) 1259 s.Equal(1, int(rowsAffected)) 1260 1261 visibilities = append(visibilities, visibility) 1262 } 1263 closeTime = closeTime.Add(time.Second) 1264 } 1265 1266 selectFilter := sqlplugin.VisibilitySelectFilter{ 1267 NamespaceID: namespaceID.String(), 1268 WorkflowID: nil, 1269 RunID: convert.StringPtr(""), 1270 WorkflowTypeName: nil, 1271 MinTime: timePtr(minStartTime), 1272 MaxTime: timePtr(maxStartTime), 1273 Status: int32(status), 1274 PageSize: convert.IntPtr(pageSize), 1275 } 1276 var rows []sqlplugin.VisibilityRow 1277 for { 1278 rowsPerPage, err := s.store.SelectFromVisibility(newVisibilityContext(), selectFilter) 1279 s.NoError(err) 1280 rows = append(rows, rowsPerPage...) 1281 1282 if len(rowsPerPage) > 0 { 1283 lastVisibility := rowsPerPage[len(rowsPerPage)-1] 1284 selectFilter.MaxTime = lastVisibility.CloseTime 1285 selectFilter.RunID = convert.StringPtr(lastVisibility.RunID) 1286 } else { 1287 break 1288 } 1289 } 1290 1291 s.Len(rows, len(visibilities)) 1292 s.sortByCloseTimeDescRunIDAsc(visibilities) 1293 for index := range rows { 1294 rows[index].NamespaceID = namespaceID.String() 1295 } 1296 s.Equal(visibilities, rows) 1297 } 1298 1299 func (s *visibilitySuite) sortByStartTimeDescRunIDAsc( 1300 visibilities []sqlplugin.VisibilityRow, 1301 ) { 1302 sort.Slice(visibilities, func(i, j int) bool { 1303 this := visibilities[i] 1304 that := visibilities[j] 1305 1306 // start time desc, run ID asc 1307 1308 if this.StartTime.Before(that.StartTime) { 1309 return false 1310 } else if that.StartTime.Before(this.StartTime) { 1311 return true 1312 } 1313 1314 if this.RunID < that.RunID { 1315 return true 1316 } else if this.RunID > that.RunID { 1317 return false 1318 } 1319 1320 // same 1321 return true 1322 }) 1323 } 1324 1325 func (s *visibilitySuite) sortByCloseTimeDescRunIDAsc( 1326 visibilities []sqlplugin.VisibilityRow, 1327 ) { 1328 sort.Slice(visibilities, func(i, j int) bool { 1329 this := visibilities[i] 1330 that := visibilities[j] 1331 1332 // close time desc, run ID asc 1333 1334 if this.CloseTime.Before(*that.CloseTime) { 1335 return false 1336 } else if that.CloseTime.Before(*this.CloseTime) { 1337 return true 1338 } 1339 1340 if this.RunID < that.RunID { 1341 return true 1342 } else if this.RunID > that.RunID { 1343 return false 1344 } 1345 1346 // same 1347 return true 1348 }) 1349 } 1350 1351 func (s *visibilitySuite) now() time.Time { 1352 return time.Now().UTC().Truncate(time.Millisecond) 1353 } 1354 1355 func (s *visibilitySuite) newRandomVisibilityRow( 1356 namespaceID primitives.UUID, 1357 runID primitives.UUID, 1358 workflowTypeName string, 1359 workflowID string, 1360 startTime time.Time, 1361 executionTime time.Time, 1362 status int32, 1363 closeTime *time.Time, 1364 historyLength *int64, 1365 ) sqlplugin.VisibilityRow { 1366 return sqlplugin.VisibilityRow{ 1367 NamespaceID: namespaceID.String(), 1368 RunID: runID.String(), 1369 WorkflowTypeName: workflowTypeName, 1370 WorkflowID: workflowID, 1371 StartTime: startTime, 1372 ExecutionTime: executionTime, 1373 Status: status, 1374 CloseTime: closeTime, 1375 HistoryLength: historyLength, 1376 Memo: shuffle.Bytes(testVisibilityData), 1377 Encoding: testVisibilityEncoding, 1378 } 1379 } 1380 1381 func timePtr(t time.Time) *time.Time { 1382 return &t 1383 }