go.temporal.io/server@v1.23.0/common/archiver/history_iterator_test.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 archiver 26 27 import ( 28 "context" 29 "errors" 30 "testing" 31 "time" 32 33 "github.com/golang/mock/gomock" 34 "github.com/stretchr/testify/require" 35 "github.com/stretchr/testify/suite" 36 enumspb "go.temporal.io/api/enums/v1" 37 historypb "go.temporal.io/api/history/v1" 38 "go.temporal.io/api/serviceerror" 39 taskqueuepb "go.temporal.io/api/taskqueue/v1" 40 "google.golang.org/protobuf/types/known/durationpb" 41 "google.golang.org/protobuf/types/known/timestamppb" 42 43 archiverspb "go.temporal.io/server/api/archiver/v1" 44 "go.temporal.io/server/common" 45 "go.temporal.io/server/common/persistence" 46 ) 47 48 const ( 49 testNamespaceID = "test-namespace-id" 50 testNamespace = "test-namespace" 51 testWorkflowID = "test-workflow-id" 52 testRunID = "test-run-id" 53 testShardID = int32(1) 54 testNextEventID = 1800 55 testCloseFailoverVersion = 100 56 testDefaultPersistencePageSize = 250 57 testDefaultTargetHistoryBlobSize = 2 * 1024 * 124 58 testDefaultHistoryEventSize = 50 59 ) 60 61 var ( 62 testBranchToken = []byte{1, 2, 3} 63 ) 64 65 type ( 66 HistoryIteratorSuite struct { 67 *require.Assertions 68 suite.Suite 69 70 controller *gomock.Controller 71 mockExecutionMgr *persistence.MockExecutionManager 72 } 73 74 page struct { 75 firstbatchIdx int 76 numBatches int 77 firstEventFailoverVersion int64 78 lastEventFailoverVersion int64 79 } 80 81 testSizeEstimator struct{} 82 ) 83 84 func (e *testSizeEstimator) EstimateSize(v interface{}) (int, error) { 85 historyBatch, ok := v.(*historypb.History) 86 if !ok { 87 return -1, errors.New("test size estimator only estimate the size of history batches") 88 } 89 return testDefaultHistoryEventSize * len(historyBatch.Events), nil 90 } 91 92 func newTestSizeEstimator() SizeEstimator { 93 return &testSizeEstimator{} 94 } 95 96 func TestHistoryIteratorSuite(t *testing.T) { 97 suite.Run(t, new(HistoryIteratorSuite)) 98 } 99 100 func (s *HistoryIteratorSuite) SetupTest() { 101 s.Assertions = require.New(s.T()) 102 s.controller = gomock.NewController(s.T()) 103 s.mockExecutionMgr = persistence.NewMockExecutionManager(s.controller) 104 } 105 106 func (s *HistoryIteratorSuite) TearDownTest() { 107 s.controller.Finish() 108 } 109 110 func (s *HistoryIteratorSuite) TestReadHistory_Failed_EventsV2() { 111 s.mockExecutionMgr.EXPECT().ReadHistoryBranchByBatch(gomock.Any(), gomock.Any()).Return(nil, errors.New("got error reading history branch")) 112 itr := s.constructTestHistoryIterator(s.mockExecutionMgr, testDefaultTargetHistoryBlobSize, nil) 113 history, err := itr.readHistory(context.Background(), common.FirstEventID) 114 s.Error(err) 115 s.Nil(history) 116 } 117 118 func (s *HistoryIteratorSuite) TestReadHistory_Success_EventsV2() { 119 resp := persistence.ReadHistoryBranchByBatchResponse{ 120 History: []*historypb.History{}, 121 NextPageToken: []byte{}, 122 } 123 s.mockExecutionMgr.EXPECT().ReadHistoryBranchByBatch(gomock.Any(), gomock.Any()).Return(&resp, nil) 124 itr := s.constructTestHistoryIterator(s.mockExecutionMgr, testDefaultTargetHistoryBlobSize, nil) 125 history, err := itr.readHistory(context.Background(), common.FirstEventID) 126 s.NoError(err) 127 s.Len(history, 0) 128 } 129 130 // In the following test: 131 // batchInfo represents # of events for each history batch. 132 // page represents the metadata of the set of history batches that should be requested by the iterator 133 // and returned by the history manager. Each page specifies the index of the first history batch it should 134 // return, # of batches to return and first/last event failover version for the set of batches returned. 135 // Note that is possible that a history batch is contained in multiple pages. 136 137 func (s *HistoryIteratorSuite) TestReadHistoryBatches_Fail_FirstCallToReadHistoryGivesError() { 138 batchInfo := []int{1} 139 pages := []page{ 140 { 141 firstbatchIdx: 0, 142 numBatches: 1, 143 firstEventFailoverVersion: 1, 144 lastEventFailoverVersion: 1, 145 }, 146 } 147 s.initMockExecutionManager(batchInfo, 0, false, pages...) 148 itr := s.constructTestHistoryIterator(s.mockExecutionMgr, testDefaultTargetHistoryBlobSize, nil) 149 startingIteratorState := s.copyIteratorState(itr) 150 events, nextIterState, err := itr.readHistoryBatches(context.Background(), common.FirstEventID) 151 s.Error(err) 152 s.Nil(events) 153 s.False(nextIterState.FinishedIteration) 154 s.Zero(nextIterState.NextEventID) 155 s.assertStateMatches(startingIteratorState, itr) 156 } 157 158 func (s *HistoryIteratorSuite) TestReadHistoryBatches_Fail_NonFirstCallToReadHistoryGivesError() { 159 batchInfo := []int{1, 1} 160 pages := []page{ 161 { 162 firstbatchIdx: 0, 163 numBatches: 1, 164 firstEventFailoverVersion: 1, 165 lastEventFailoverVersion: 1, 166 }, 167 { 168 firstbatchIdx: 1, 169 numBatches: 1, 170 firstEventFailoverVersion: 1, 171 lastEventFailoverVersion: 1, 172 }, 173 } 174 s.initMockExecutionManager(batchInfo, 1, false, pages...) 175 itr := s.constructTestHistoryIterator(s.mockExecutionMgr, testDefaultTargetHistoryBlobSize, nil) 176 startingIteratorState := s.copyIteratorState(itr) 177 events, nextIterState, err := itr.readHistoryBatches(context.Background(), common.FirstEventID) 178 s.Error(err) 179 s.Nil(events) 180 s.False(nextIterState.FinishedIteration) 181 s.Zero(nextIterState.NextEventID) 182 s.assertStateMatches(startingIteratorState, itr) 183 } 184 185 func (s *HistoryIteratorSuite) TestReadHistoryBatches_Success_ReadToHistoryEnd() { 186 batchInfo := []int{1, 2, 1, 1, 1, 3, 3, 1, 3} 187 pages := []page{ 188 { 189 firstbatchIdx: 0, 190 numBatches: 3, 191 firstEventFailoverVersion: 1, 192 lastEventFailoverVersion: 1, 193 }, 194 { 195 firstbatchIdx: 3, 196 numBatches: 2, 197 firstEventFailoverVersion: 1, 198 lastEventFailoverVersion: 1, 199 }, 200 { 201 firstbatchIdx: 5, 202 numBatches: 4, 203 firstEventFailoverVersion: 1, 204 lastEventFailoverVersion: 1, 205 }, 206 } 207 s.initMockExecutionManager(batchInfo, -1, true, pages...) 208 // ensure target history batches size is greater than total history length to ensure all of history is read 209 itr := s.constructTestHistoryIterator(s.mockExecutionMgr, 20*testDefaultHistoryEventSize, nil) 210 startingIteratorState := s.copyIteratorState(itr) 211 history, nextIterState, err := itr.readHistoryBatches(context.Background(), common.FirstEventID) 212 s.NoError(err) 213 s.NotNil(history) 214 s.Len(history, 9) 215 s.True(nextIterState.FinishedIteration) 216 s.Zero(nextIterState.NextEventID) 217 s.assertStateMatches(startingIteratorState, itr) 218 } 219 220 func (s *HistoryIteratorSuite) TestReadHistoryBatches_Success_TargetSizeSatisfiedWithoutReadingToEnd() { 221 batchInfo := []int{1, 2, 1, 1, 1, 3, 3, 1, 3} 222 pages := []page{ 223 { 224 firstbatchIdx: 0, 225 numBatches: 3, 226 firstEventFailoverVersion: 1, 227 lastEventFailoverVersion: 1, 228 }, 229 { 230 firstbatchIdx: 3, 231 numBatches: 2, 232 firstEventFailoverVersion: 1, 233 lastEventFailoverVersion: 1, 234 }, 235 { 236 firstbatchIdx: 5, 237 numBatches: 4, 238 firstEventFailoverVersion: 1, 239 lastEventFailoverVersion: 1, 240 }, 241 } 242 s.initMockExecutionManager(batchInfo, -1, false, pages...) 243 // ensure target history batches is smaller than full length of history so that not all of history is read 244 itr := s.constructTestHistoryIterator(s.mockExecutionMgr, 11*testDefaultHistoryEventSize, nil) 245 startingIteratorState := s.copyIteratorState(itr) 246 history, nextIterState, err := itr.readHistoryBatches(context.Background(), common.FirstEventID) 247 s.NoError(err) 248 s.NotNil(history) 249 s.Len(history, 7) 250 s.False(nextIterState.FinishedIteration) 251 s.Equal(int64(13), nextIterState.NextEventID) 252 s.assertStateMatches(startingIteratorState, itr) 253 } 254 255 func (s *HistoryIteratorSuite) TestReadHistoryBatches_Success_ReadExactlyToHistoryEnd() { 256 batchInfo := []int{1, 2, 1, 1, 1, 3, 3, 1, 3} 257 pages := []page{ 258 { 259 firstbatchIdx: 0, 260 numBatches: 3, 261 firstEventFailoverVersion: 1, 262 lastEventFailoverVersion: 1, 263 }, 264 { 265 firstbatchIdx: 3, 266 numBatches: 2, 267 firstEventFailoverVersion: 1, 268 lastEventFailoverVersion: 1, 269 }, 270 { 271 firstbatchIdx: 5, 272 numBatches: 4, 273 firstEventFailoverVersion: 1, 274 lastEventFailoverVersion: 1, 275 }, 276 } 277 s.initMockExecutionManager(batchInfo, -1, true, pages...) 278 // ensure target history batches size is equal to the full length of history so that all of history is read 279 itr := s.constructTestHistoryIterator(s.mockExecutionMgr, 16*testDefaultHistoryEventSize, nil) 280 startingIteratorState := s.copyIteratorState(itr) 281 history, nextIterState, err := itr.readHistoryBatches(context.Background(), common.FirstEventID) 282 s.NoError(err) 283 s.NotNil(history) 284 s.Len(history, 9) 285 s.True(nextIterState.FinishedIteration) 286 s.Zero(nextIterState.NextEventID) 287 s.assertStateMatches(startingIteratorState, itr) 288 } 289 290 func (s *HistoryIteratorSuite) TestReadHistoryBatches_Success_ReadPageMultipleTimes() { 291 batchInfo := []int{1, 3, 2} 292 pages := []page{ 293 { 294 firstbatchIdx: 0, 295 numBatches: 3, 296 firstEventFailoverVersion: 1, 297 lastEventFailoverVersion: 1, 298 }, 299 { 300 firstbatchIdx: 2, 301 numBatches: 1, 302 firstEventFailoverVersion: 1, 303 lastEventFailoverVersion: 1, 304 }, 305 } 306 s.initMockExecutionManager(batchInfo, -1, true, pages...) 307 // ensure target history batches is very small so that one page needs multiple read 308 itr := s.constructTestHistoryIterator(s.mockExecutionMgr, 2*testDefaultHistoryEventSize, nil) 309 startingIteratorState := s.copyIteratorState(itr) 310 history, nextIterState, err := itr.readHistoryBatches(context.Background(), common.FirstEventID) 311 s.NoError(err) 312 s.NotNil(history) 313 s.Len(history, 2) 314 s.False(nextIterState.FinishedIteration) 315 s.Equal(int64(5), nextIterState.NextEventID) 316 s.assertStateMatches(startingIteratorState, itr) 317 318 history, nextIterState, err = itr.readHistoryBatches(context.Background(), nextIterState.NextEventID) 319 s.NoError(err) 320 s.NotNil(history) 321 s.Len(history, 1) 322 s.True(nextIterState.FinishedIteration) 323 s.Zero(nextIterState.NextEventID) 324 s.assertStateMatches(startingIteratorState, itr) 325 } 326 327 func (s *HistoryIteratorSuite) TestNext_Fail_IteratorDepleted() { 328 batchInfo := []int{1, 3, 2, 1, 2, 3, 4} 329 pages := []page{ 330 { 331 firstbatchIdx: 0, 332 numBatches: 2, 333 firstEventFailoverVersion: 1, 334 lastEventFailoverVersion: 1, 335 }, 336 { 337 firstbatchIdx: 2, 338 numBatches: 1, 339 firstEventFailoverVersion: 1, 340 lastEventFailoverVersion: 2, 341 }, 342 { 343 firstbatchIdx: 3, 344 numBatches: 4, 345 firstEventFailoverVersion: 2, 346 lastEventFailoverVersion: 5, 347 }, 348 } 349 s.initMockExecutionManager(batchInfo, -1, true, pages...) 350 // set target history batches such that a single call to next will read all of history 351 itr := s.constructTestHistoryIterator(s.mockExecutionMgr, 16*testDefaultHistoryEventSize, nil) 352 blob, err := itr.Next(context.Background()) 353 s.Nil(err) 354 355 expectedIteratorState := historyIteratorState{ 356 // when iteration is finished page token is not advanced 357 FinishedIteration: true, 358 NextEventID: 0, 359 } 360 s.assertStateMatches(expectedIteratorState, itr) 361 s.NotNil(blob) 362 expectedHeader := &archiverspb.HistoryBlobHeader{ 363 Namespace: testNamespace, 364 NamespaceId: testNamespaceID, 365 WorkflowId: testWorkflowID, 366 RunId: testRunID, 367 IsLast: true, 368 FirstFailoverVersion: 1, 369 LastFailoverVersion: 5, 370 FirstEventId: common.FirstEventID, 371 LastEventId: 16, 372 EventCount: 16, 373 } 374 s.Equal(expectedHeader, blob.Header) 375 s.Len(blob.Body, 7) 376 s.NoError(err) 377 s.False(itr.HasNext()) 378 379 blob, err = itr.Next(context.Background()) 380 s.Equal(err, errIteratorDepleted) 381 s.Nil(blob) 382 s.assertStateMatches(expectedIteratorState, itr) 383 } 384 385 func (s *HistoryIteratorSuite) TestNext_Fail_ReturnErrOnSecondCallToNext() { 386 batchInfo := []int{1, 3, 2, 1, 3, 2} 387 pages := []page{ 388 { 389 firstbatchIdx: 0, 390 numBatches: 2, 391 firstEventFailoverVersion: 1, 392 lastEventFailoverVersion: 1, 393 }, 394 { 395 firstbatchIdx: 2, 396 numBatches: 1, 397 firstEventFailoverVersion: 1, 398 lastEventFailoverVersion: 1, 399 }, 400 { 401 firstbatchIdx: 3, 402 numBatches: 2, 403 firstEventFailoverVersion: 1, 404 lastEventFailoverVersion: 1, 405 }, 406 { 407 firstbatchIdx: 5, 408 numBatches: 1, 409 firstEventFailoverVersion: 1, 410 lastEventFailoverVersion: 1, 411 }, 412 } 413 s.initMockExecutionManager(batchInfo, 3, false, pages...) 414 // set target blob size such that the first two pages are read for blob one without error, third page will return error 415 itr := s.constructTestHistoryIterator(s.mockExecutionMgr, 6*testDefaultHistoryEventSize, nil) 416 blob, err := itr.Next(context.Background()) 417 s.NoError(err) 418 expectedIteratorState := historyIteratorState{ 419 FinishedIteration: false, 420 NextEventID: 7, 421 } 422 s.assertStateMatches(expectedIteratorState, itr) 423 s.NotNil(blob) 424 expectedHeader := &archiverspb.HistoryBlobHeader{ 425 Namespace: testNamespace, 426 NamespaceId: testNamespaceID, 427 WorkflowId: testWorkflowID, 428 RunId: testRunID, 429 IsLast: false, 430 FirstFailoverVersion: 1, 431 LastFailoverVersion: 1, 432 FirstEventId: common.FirstEventID, 433 LastEventId: 6, 434 EventCount: 6, 435 } 436 s.Equal(expectedHeader, blob.Header) 437 s.NoError(err) 438 s.True(itr.HasNext()) 439 440 blob, err = itr.Next(context.Background()) 441 s.Error(err) 442 s.Nil(blob) 443 s.assertStateMatches(expectedIteratorState, itr) 444 } 445 446 func (s *HistoryIteratorSuite) TestNext_Success_TenCallsToNext() { 447 var batchInfo []int 448 for i := 0; i < 100; i++ { 449 batchInfo = append(batchInfo, []int{1, 2, 3, 4, 4, 3, 2, 1}...) 450 } 451 var pages []page 452 for i := 0; i < 100; i++ { 453 p := page{ 454 firstbatchIdx: i * 8, 455 numBatches: 8, 456 firstEventFailoverVersion: 1, 457 lastEventFailoverVersion: 1, 458 } 459 pages = append(pages, p) 460 } 461 s.initMockExecutionManager(batchInfo, -1, true, pages...) 462 // set target blob size size such that every 10 persistence pages is one group of history batches 463 itr := s.constructTestHistoryIterator(s.mockExecutionMgr, 20*10*testDefaultHistoryEventSize, nil) 464 expectedIteratorState := historyIteratorState{ 465 FinishedIteration: false, 466 NextEventID: common.FirstEventID, 467 } 468 for i := 0; i < 10; i++ { 469 s.assertStateMatches(expectedIteratorState, itr) 470 s.True(itr.HasNext()) 471 blob, err := itr.Next(context.Background()) 472 s.NoError(err) 473 s.NotNil(blob) 474 expectedHeader := &archiverspb.HistoryBlobHeader{ 475 Namespace: testNamespace, 476 NamespaceId: testNamespaceID, 477 WorkflowId: testWorkflowID, 478 RunId: testRunID, 479 IsLast: false, 480 FirstFailoverVersion: 1, 481 LastFailoverVersion: 1, 482 FirstEventId: common.FirstEventID + int64(i*200), 483 LastEventId: int64(200 + (i * 200)), 484 EventCount: 200, 485 } 486 if i == 9 { 487 expectedHeader.IsLast = true 488 } 489 s.Equal(expectedHeader, blob.Header) 490 491 if i < 9 { 492 expectedIteratorState.FinishedIteration = false 493 expectedIteratorState.NextEventID = int64(200*(i+1) + 1) 494 } else { 495 expectedIteratorState.NextEventID = 0 496 expectedIteratorState.FinishedIteration = true 497 } 498 } 499 s.assertStateMatches(expectedIteratorState, itr) 500 s.False(itr.HasNext()) 501 } 502 503 func (s *HistoryIteratorSuite) TestNext_Success_SameHistoryDifferentPage() { 504 batchInfo := []int{2, 4, 4, 3, 2, 1, 1, 2} 505 pages := []page{ 506 { 507 firstbatchIdx: 0, 508 numBatches: 3, 509 firstEventFailoverVersion: 1, 510 lastEventFailoverVersion: 1, 511 }, 512 { 513 firstbatchIdx: 2, 514 numBatches: 1, 515 firstEventFailoverVersion: 1, 516 lastEventFailoverVersion: 1, 517 }, 518 { 519 firstbatchIdx: 3, 520 numBatches: 2, 521 firstEventFailoverVersion: 1, 522 lastEventFailoverVersion: 1, 523 }, 524 { 525 firstbatchIdx: 4, 526 numBatches: 1, 527 firstEventFailoverVersion: 1, 528 lastEventFailoverVersion: 1, 529 }, 530 { 531 firstbatchIdx: 5, 532 numBatches: 3, 533 firstEventFailoverVersion: 1, 534 lastEventFailoverVersion: 1, 535 }, 536 } 537 eventsPerRead := 6 538 targetBlobSize := eventsPerRead * testDefaultHistoryEventSize 539 s.initMockExecutionManager(batchInfo, -1, true, pages...) 540 itr1 := s.constructTestHistoryIterator(s.mockExecutionMgr, targetBlobSize, nil) 541 542 pages = []page{ 543 { 544 firstbatchIdx: 0, 545 numBatches: 1, 546 firstEventFailoverVersion: 1, 547 lastEventFailoverVersion: 1, 548 }, 549 { 550 firstbatchIdx: 1, 551 numBatches: 3, 552 firstEventFailoverVersion: 1, 553 lastEventFailoverVersion: 1, 554 }, 555 { 556 firstbatchIdx: 2, 557 numBatches: 1, 558 firstEventFailoverVersion: 1, 559 lastEventFailoverVersion: 1, 560 }, 561 { 562 firstbatchIdx: 3, 563 numBatches: 5, 564 firstEventFailoverVersion: 1, 565 lastEventFailoverVersion: 1, 566 }, 567 { 568 firstbatchIdx: 4, 569 numBatches: 4, 570 firstEventFailoverVersion: 1, 571 lastEventFailoverVersion: 1, 572 }, 573 } 574 s.initMockExecutionManager(batchInfo, -1, true, pages...) 575 itr2 := s.constructTestHistoryIterator(s.mockExecutionMgr, targetBlobSize, nil) 576 577 totalPages := 3 578 expectedFirstEventID := []int64{1, 7, 14} 579 for i := 0; i != totalPages; i++ { 580 s.True(itr1.HasNext()) 581 history1, err := itr1.Next(context.Background()) 582 s.NoError(err) 583 584 s.True(itr2.HasNext()) 585 history2, err := itr2.Next(context.Background()) 586 s.NoError(err) 587 588 s.Equal(history1.Header, history2.Header) 589 s.Equal(len(history1.Body), len(history2.Body)) 590 s.Equal(expectedFirstEventID[i], history1.Body[0].Events[0].GetEventId()) 591 s.Equal(expectedFirstEventID[i], history2.Body[0].Events[0].GetEventId()) 592 } 593 expectedIteratorState := historyIteratorState{ 594 NextEventID: 0, 595 FinishedIteration: true, 596 } 597 s.assertStateMatches(expectedIteratorState, itr1) 598 s.assertStateMatches(expectedIteratorState, itr2) 599 s.False(itr1.HasNext()) 600 s.False(itr2.HasNext()) 601 } 602 603 func (s *HistoryIteratorSuite) TestNewIteratorWithState() { 604 itr := s.constructTestHistoryIterator(nil, testDefaultTargetHistoryBlobSize, nil) 605 testIteratorState := historyIteratorState{ 606 FinishedIteration: true, 607 NextEventID: 4, 608 } 609 itr.historyIteratorState = testIteratorState 610 stateToken, err := itr.GetState() 611 s.NoError(err) 612 613 newItr := s.constructTestHistoryIterator(nil, testDefaultTargetHistoryBlobSize, stateToken) 614 s.assertStateMatches(testIteratorState, newItr) 615 } 616 617 func (s *HistoryIteratorSuite) initMockExecutionManager(batchInfo []int, returnErrorOnPage int, addNotExistCall bool, pages ...page) { 618 firstEventIDs := []int64{common.FirstEventID} 619 for i, batchSize := range batchInfo { 620 firstEventIDs = append(firstEventIDs, firstEventIDs[i]+int64(batchSize)) 621 } 622 623 testShardId := testShardID 624 for i, p := range pages { 625 req := &persistence.ReadHistoryBranchRequest{ 626 BranchToken: testBranchToken, 627 MinEventID: firstEventIDs[p.firstbatchIdx], 628 MaxEventID: common.EndEventID, 629 PageSize: testDefaultPersistencePageSize, 630 ShardID: testShardId, 631 } 632 if returnErrorOnPage == i { 633 s.mockExecutionMgr.EXPECT().ReadHistoryBranchByBatch(gomock.Any(), req).Return(nil, errors.New("got error getting workflow execution history")) 634 return 635 } 636 637 resp := &persistence.ReadHistoryBranchByBatchResponse{ 638 History: s.constructHistoryBatches(batchInfo, p, firstEventIDs[p.firstbatchIdx]), 639 } 640 s.mockExecutionMgr.EXPECT().ReadHistoryBranchByBatch(gomock.Any(), req).Return(resp, nil).MaxTimes(2) 641 } 642 643 if addNotExistCall { 644 req := &persistence.ReadHistoryBranchRequest{ 645 BranchToken: testBranchToken, 646 MinEventID: firstEventIDs[len(firstEventIDs)-1], 647 MaxEventID: common.EndEventID, 648 PageSize: testDefaultPersistencePageSize, 649 ShardID: testShardId, 650 } 651 s.mockExecutionMgr.EXPECT().ReadHistoryBranchByBatch(gomock.Any(), req).Return(nil, serviceerror.NewNotFound("Reach the end")) 652 } 653 } 654 655 func (s *HistoryIteratorSuite) copyIteratorState(itr *historyIterator) historyIteratorState { 656 return itr.historyIteratorState 657 } 658 659 func (s *HistoryIteratorSuite) assertStateMatches(expected historyIteratorState, itr *historyIterator) { 660 s.Equal(expected.NextEventID, itr.NextEventID) 661 s.Equal(expected.FinishedIteration, itr.FinishedIteration) 662 } 663 664 func (s *HistoryIteratorSuite) constructHistoryBatches(batchInfo []int, page page, firstEventID int64) []*historypb.History { 665 var batches []*historypb.History 666 eventsID := firstEventID 667 for batchIdx, numEvents := range batchInfo[page.firstbatchIdx : page.firstbatchIdx+page.numBatches] { 668 var events []*historypb.HistoryEvent 669 for i := 0; i < numEvents; i++ { 670 event := &historypb.HistoryEvent{ 671 EventId: eventsID, 672 Version: page.firstEventFailoverVersion, 673 } 674 eventsID++ 675 if batchIdx == page.numBatches-1 { 676 event.Version = page.lastEventFailoverVersion 677 } 678 events = append(events, event) 679 } 680 batches = append(batches, &historypb.History{ 681 Events: events, 682 }) 683 } 684 return batches 685 } 686 687 func (s *HistoryIteratorSuite) constructTestHistoryIterator( 688 mockExecutionMgr *persistence.MockExecutionManager, 689 targetHistoryBlobSize int, 690 initialState []byte, 691 ) *historyIterator { 692 request := &ArchiveHistoryRequest{ 693 ShardID: testShardID, 694 NamespaceID: testNamespaceID, 695 Namespace: testNamespace, 696 WorkflowID: testWorkflowID, 697 RunID: testRunID, 698 BranchToken: testBranchToken, 699 NextEventID: testNextEventID, 700 CloseFailoverVersion: testCloseFailoverVersion, 701 } 702 itr := newHistoryIterator(request, mockExecutionMgr, targetHistoryBlobSize) 703 if initialState != nil { 704 err := itr.reset(initialState) 705 s.NoError(err) 706 } 707 itr.sizeEstimator = newTestSizeEstimator() 708 return itr 709 } 710 func (s *HistoryIteratorSuite) TestJSONSizeEstimator() { 711 e := NewJSONSizeEstimator() 712 713 historyEvent := &historypb.HistoryEvent{ 714 EventId: 1, 715 EventTime: timestamppb.New(time.Date(1978, 8, 22, 12, 59, 59, 999999, time.UTC)), 716 TaskId: 1, 717 Version: 1, 718 } 719 historyEvent.EventType = enumspb.EVENT_TYPE_WORKFLOW_TASK_SCHEDULED 720 historyEvent.Attributes = &historypb.HistoryEvent_WorkflowTaskScheduledEventAttributes{WorkflowTaskScheduledEventAttributes: &historypb.WorkflowTaskScheduledEventAttributes{ 721 TaskQueue: &taskqueuepb.TaskQueue{ 722 Name: "taskQueue", 723 Kind: enumspb.TASK_QUEUE_KIND_NORMAL, 724 }, 725 StartToCloseTimeout: durationpb.New(10 * time.Second), 726 Attempt: 1, 727 }} 728 729 h := &historypb.History{ 730 Events: []*historypb.HistoryEvent{ 731 historyEvent, 732 }, 733 } 734 735 size, err := e.EstimateSize(h) 736 s.NoError(err) 737 738 // The size seems to fluctuate between compiles using google's protoc toolchain. I'd like to delete this altogether 739 s.Contains([]int{295, 303}, size) 740 }