go.temporal.io/server@v1.23.0/common/archiver/gcloud/history_archiver_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 gcloud 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 "google.golang.org/protobuf/types/known/timestamppb" 40 41 archiverspb "go.temporal.io/server/api/archiver/v1" 42 "go.temporal.io/server/common" 43 "go.temporal.io/server/common/archiver" 44 "go.temporal.io/server/common/archiver/gcloud/connector" 45 "go.temporal.io/server/common/convert" 46 "go.temporal.io/server/common/log" 47 "go.temporal.io/server/common/metrics" 48 ) 49 50 const ( 51 testNamespaceID = "test-namespace-id" 52 testNamespace = "test-namespace" 53 testWorkflowID = "test-workflow-id" 54 testRunID = "test-run-id" 55 testNextEventID = 1800 56 testCloseFailoverVersion = 100 57 testPageSize = 100 58 exampleOldHistoryRecord = `[{"events":[{"eventId":1,"eventTime": "2020-07-30T00:30:03.082421843Z","eventType":"WorkflowExecutionStarted","version":-24,"taskId":5242897,"workflowExecutionStartedEventAttributes":{"workflowType":{"name":"MobileOnlyWorkflow::processMobileOnly"},"taskQueue":{"name":"MobileOnly"},"input":null,"workflowExecutionTimeout":"300s","workflowTaskTimeout":"60s","originalExecutionRunId":"1fd5d4c8-1590-4a0a-8027-535e8729de8e","identity":"","firstExecutionRunId":"1fd5d4c8-1590-4a0a-8027-535e8729de8e","attempt":1,"firstWorkflowTaskBackoff":"0s"}}]}]` 59 exampleNewHistoryRecord = `[{"events":[{"eventId":1,"eventTime": "2020-07-30T00:30:03.082421843Z","eventType":"EVENT_TYPE_WORKFLOW_EXECUTION_STARTED","version":-24,"taskId":5242897,"workflowExecutionStartedEventAttributes":{"workflowType":{"name":"MobileOnlyWorkflow::processMobileOnly"},"taskQueue":{"name":"MobileOnly"},"input":null,"workflowExecutionTimeout":"300s","workflowTaskTimeout":"60s","originalExecutionRunId":"1fd5d4c8-1590-4a0a-8027-535e8729de8e","identity":"","firstExecutionRunId":"1fd5d4c8-1590-4a0a-8027-535e8729de8e","attempt":1,"firstWorkflowTaskBackoff":"0s"}}]}]` 60 twoEventsExampleHistoryRecord = `[{"events":[{"eventId":1,"eventTime": "2020-07-30T00:30:03.082421843Z","eventType":"WorkflowExecutionStarted","version":-24,"taskId":5242897,"workflowExecutionStartedEventAttributes":{"workflowType":{"name":"MobileOnlyWorkflow::processMobileOnly"},"taskQueue":{"name":"MobileOnly"},"input":null,"workflowExecutionTimeout":"300s","workflowTaskTimeout":"60s","originalExecutionRunId":"1fd5d4c8-1590-4a0a-8027-535e8729de8e","identity":"","firstExecutionRunId":"1fd5d4c8-1590-4a0a-8027-535e8729de8e","attempt":1,"firstWorkflowTaskBackoff":"0s"}},{"eventId":2,"eventTime": "2020-07-30T00:30:03.082421843Z","eventType":"WorkflowExecutionStarted","version":-24,"taskId":5242897,"workflowExecutionStartedEventAttributes":{"workflowType":{"name":"MobileOnlyWorkflow::processMobileOnly"},"taskQueue":{"name":"MobileOnly"},"input":null,"workflowExecutionTimeout":"300s","workflowTaskTimeout":"60s","originalExecutionRunId":"1fd5d4c8-1590-4a0a-8027-535e8729de8e","identity":"","firstExecutionRunId":"1fd5d4c8-1590-4a0a-8027-535e8729de8e","attempt":1,"firstWorkflowTaskBackoff":"0s"}}]}]` 61 ) 62 63 var ( 64 testBranchToken = []byte{1, 2, 3} 65 ) 66 67 func (h *historyArchiverSuite) SetupTest() { 68 h.Assertions = require.New(h.T()) 69 h.controller = gomock.NewController(h.T()) 70 h.container = &archiver.HistoryBootstrapContainer{ 71 Logger: log.NewNoopLogger(), 72 MetricsHandler: metrics.NoopMetricsHandler, 73 } 74 h.testArchivalURI, _ = archiver.NewURI("gs://my-bucket-cad/temporal_archival/development") 75 } 76 77 func (h *historyArchiverSuite) TearDownTest() { 78 h.controller.Finish() 79 } 80 81 func TestHistoryArchiverSuite(t *testing.T) { 82 suite.Run(t, new(historyArchiverSuite)) 83 } 84 85 type historyArchiverSuite struct { 86 *require.Assertions 87 suite.Suite 88 89 controller *gomock.Controller 90 91 container *archiver.HistoryBootstrapContainer 92 testArchivalURI archiver.URI 93 } 94 95 func getCanceledContext() context.Context { 96 ctx, cancel := context.WithCancel(context.Background()) 97 cancel() 98 return ctx 99 } 100 101 func (h *historyArchiverSuite) TestValidateURI() { 102 ctx := context.Background() 103 testCases := []struct { 104 URI string 105 expectedErr error 106 }{ 107 { 108 URI: "wrongscheme:///a/b/c", 109 expectedErr: archiver.ErrURISchemeMismatch, 110 }, 111 { 112 URI: "gs:my-bucket-cad/temporal_archival/development", 113 expectedErr: archiver.ErrInvalidURI, 114 }, 115 { 116 URI: "gs://", 117 expectedErr: archiver.ErrInvalidURI, 118 }, 119 { 120 URI: "gs://my-bucket-cad", 121 expectedErr: archiver.ErrInvalidURI, 122 }, 123 { 124 URI: "gs:/my-bucket-cad/temporal_archival/development", 125 expectedErr: archiver.ErrInvalidURI, 126 }, 127 { 128 URI: "gs://my-bucket-cad/temporal_archival/development", 129 expectedErr: nil, 130 }, 131 } 132 133 storageWrapper := connector.NewMockClient(h.controller) 134 storageWrapper.EXPECT().Exist(ctx, gomock.Any(), "").Return(false, nil) 135 historyArchiver := new(historyArchiver) 136 historyArchiver.gcloudStorage = storageWrapper 137 for _, tc := range testCases { 138 URI, err := archiver.NewURI(tc.URI) 139 h.NoError(err) 140 h.Equal(tc.expectedErr, historyArchiver.ValidateURI(URI)) 141 } 142 } 143 144 func (h *historyArchiverSuite) TestArchive_Fail_InvalidURI() { 145 mockStorageClient := connector.NewMockGcloudStorageClient(h.controller) 146 storageWrapper, _ := connector.NewClientWithParams(mockStorageClient) 147 148 historyIterator := archiver.NewMockHistoryIterator(h.controller) 149 150 historyArchiver := newHistoryArchiver(h.container, historyIterator, storageWrapper) 151 request := &archiver.ArchiveHistoryRequest{ 152 NamespaceID: testNamespaceID, 153 Namespace: testNamespace, 154 WorkflowID: testWorkflowID, 155 RunID: testRunID, 156 BranchToken: testBranchToken, 157 NextEventID: testNextEventID, 158 CloseFailoverVersion: testCloseFailoverVersion, 159 } 160 URI, err := archiver.NewURI("wrongscheme://") 161 h.NoError(err) 162 err = historyArchiver.Archive(context.Background(), URI, request) 163 h.Error(err) 164 } 165 166 func (h *historyArchiverSuite) TestArchive_Fail_InvalidRequest() { 167 ctx := context.Background() 168 storageWrapper := connector.NewMockClient(h.controller) 169 storageWrapper.EXPECT().Exist(ctx, h.testArchivalURI, "").Return(true, nil) 170 171 historyIterator := archiver.NewMockHistoryIterator(h.controller) 172 173 historyArchiver := newHistoryArchiver(h.container, historyIterator, storageWrapper) 174 request := &archiver.ArchiveHistoryRequest{ 175 NamespaceID: testNamespaceID, 176 Namespace: testNamespace, 177 WorkflowID: "", 178 RunID: testRunID, 179 BranchToken: testBranchToken, 180 NextEventID: testNextEventID, 181 CloseFailoverVersion: testCloseFailoverVersion, 182 } 183 184 err := historyArchiver.Archive(ctx, h.testArchivalURI, request) 185 h.Error(err) 186 } 187 188 func (h *historyArchiverSuite) TestArchive_Fail_ErrorOnReadHistory() { 189 ctx := context.Background() 190 storageWrapper := connector.NewMockClient(h.controller) 191 storageWrapper.EXPECT().Exist(ctx, h.testArchivalURI, "").Return(true, nil) 192 193 historyIterator := archiver.NewMockHistoryIterator(h.controller) 194 gomock.InOrder( 195 historyIterator.EXPECT().HasNext().Return(true), 196 historyIterator.EXPECT().Next(gomock.Any()).Return(nil, errors.New("some random error")), 197 ) 198 199 historyArchiver := newHistoryArchiver(h.container, historyIterator, storageWrapper) 200 request := &archiver.ArchiveHistoryRequest{ 201 NamespaceID: testNamespaceID, 202 Namespace: testNamespace, 203 WorkflowID: testWorkflowID, 204 RunID: testRunID, 205 BranchToken: testBranchToken, 206 NextEventID: testNextEventID, 207 CloseFailoverVersion: testCloseFailoverVersion, 208 } 209 err := historyArchiver.Archive(ctx, h.testArchivalURI, request) 210 h.Error(err) 211 } 212 213 func (h *historyArchiverSuite) TestArchive_Fail_TimeoutWhenReadingHistory() { 214 215 ctx := getCanceledContext() 216 storageWrapper := connector.NewMockClient(h.controller) 217 storageWrapper.EXPECT().Exist(gomock.Any(), gomock.Any(), "").Return(true, nil) 218 219 historyIterator := archiver.NewMockHistoryIterator(h.controller) 220 gomock.InOrder( 221 historyIterator.EXPECT().HasNext().Return(true), 222 historyIterator.EXPECT().Next(gomock.Any()).Return(nil, serviceerror.NewResourceExhausted(enumspb.RESOURCE_EXHAUSTED_CAUSE_RPS_LIMIT, "")), 223 ) 224 225 historyArchiver := newHistoryArchiver(h.container, historyIterator, storageWrapper) 226 request := &archiver.ArchiveHistoryRequest{ 227 NamespaceID: testNamespaceID, 228 Namespace: testNamespace, 229 WorkflowID: testWorkflowID, 230 RunID: testRunID, 231 BranchToken: testBranchToken, 232 NextEventID: testNextEventID, 233 CloseFailoverVersion: testCloseFailoverVersion, 234 } 235 err := historyArchiver.Archive(ctx, h.testArchivalURI, request) 236 h.Error(err) 237 } 238 239 func (h *historyArchiverSuite) TestArchive_Fail_HistoryMutated() { 240 ctx := context.Background() 241 storageWrapper := connector.NewMockClient(h.controller) 242 storageWrapper.EXPECT().Exist(ctx, h.testArchivalURI, "").Return(true, nil) 243 244 historyIterator := archiver.NewMockHistoryIterator(h.controller) 245 historyBatches := []*historypb.History{ 246 { 247 Events: []*historypb.HistoryEvent{ 248 { 249 EventId: common.FirstEventID + 1, 250 EventTime: timestamppb.New(time.Now().UTC()), 251 Version: testCloseFailoverVersion + 1, 252 }, 253 }, 254 }, 255 } 256 historyBlob := &archiverspb.HistoryBlob{ 257 Header: &archiverspb.HistoryBlobHeader{ 258 IsLast: true, 259 }, 260 Body: historyBatches, 261 } 262 gomock.InOrder( 263 historyIterator.EXPECT().HasNext().Return(true), 264 historyIterator.EXPECT().Next(gomock.Any()).Return(historyBlob, nil), 265 ) 266 267 historyArchiver := newHistoryArchiver(h.container, historyIterator, storageWrapper) 268 request := &archiver.ArchiveHistoryRequest{ 269 NamespaceID: testNamespaceID, 270 Namespace: testNamespace, 271 WorkflowID: testWorkflowID, 272 RunID: testRunID, 273 BranchToken: testBranchToken, 274 NextEventID: testNextEventID, 275 CloseFailoverVersion: testCloseFailoverVersion, 276 } 277 err := historyArchiver.Archive(ctx, h.testArchivalURI, request) 278 h.Error(err) 279 } 280 281 func (h *historyArchiverSuite) TestArchive_Fail_NonRetryableErrorOption() { 282 283 ctx := context.Background() 284 storageWrapper := connector.NewMockClient(h.controller) 285 storageWrapper.EXPECT().Exist(ctx, h.testArchivalURI, "").Return(true, nil) 286 287 historyIterator := archiver.NewMockHistoryIterator(h.controller) 288 gomock.InOrder( 289 historyIterator.EXPECT().HasNext().Return(true), 290 historyIterator.EXPECT().Next(gomock.Any()).Return(nil, errors.New("upload non-retryable error")), 291 ) 292 293 historyArchiver := newHistoryArchiver(h.container, historyIterator, storageWrapper) 294 request := &archiver.ArchiveHistoryRequest{ 295 NamespaceID: testNamespaceID, 296 Namespace: testNamespace, 297 WorkflowID: testWorkflowID, 298 RunID: testRunID, 299 BranchToken: testBranchToken, 300 NextEventID: testNextEventID, 301 CloseFailoverVersion: testCloseFailoverVersion, 302 } 303 err := historyArchiver.Archive(ctx, h.testArchivalURI, request, archiver.GetNonRetryableErrorOption(errUploadNonRetryable)) 304 h.Equal(errUploadNonRetryable, err) 305 } 306 307 func (h *historyArchiverSuite) TestArchive_Skip() { 308 ctx := context.Background() 309 310 storageWrapper := connector.NewMockClient(h.controller) 311 storageWrapper.EXPECT().Exist(ctx, h.testArchivalURI, "").Return(true, nil) 312 storageWrapper.EXPECT().Exist(ctx, h.testArchivalURI, gomock.Any()).Return(false, nil) 313 storageWrapper.EXPECT().Upload(ctx, h.testArchivalURI, gomock.Any(), gomock.Any()).Return(nil) 314 315 historyIterator := archiver.NewMockHistoryIterator(h.controller) 316 historyBlob := &archiverspb.HistoryBlob{ 317 Header: &archiverspb.HistoryBlobHeader{ 318 IsLast: false, 319 }, 320 Body: []*historypb.History{ 321 { 322 Events: []*historypb.HistoryEvent{ 323 { 324 EventId: common.FirstEventID, 325 EventTime: timestamppb.New(time.Now().UTC()), 326 Version: testCloseFailoverVersion, 327 }, 328 }, 329 }, 330 }, 331 } 332 gomock.InOrder( 333 historyIterator.EXPECT().HasNext().Return(true), 334 historyIterator.EXPECT().Next(gomock.Any()).Return(historyBlob, nil), 335 historyIterator.EXPECT().HasNext().Return(true), 336 historyIterator.EXPECT().Next(gomock.Any()).Return(nil, serviceerror.NewNotFound("workflow not found")), 337 ) 338 339 historyArchiver := newHistoryArchiver(h.container, historyIterator, storageWrapper) 340 request := &archiver.ArchiveHistoryRequest{ 341 NamespaceID: testNamespaceID, 342 Namespace: testNamespace, 343 WorkflowID: testWorkflowID, 344 RunID: testRunID, 345 BranchToken: testBranchToken, 346 NextEventID: testNextEventID, 347 CloseFailoverVersion: testCloseFailoverVersion, 348 } 349 err := historyArchiver.Archive(ctx, h.testArchivalURI, request) 350 h.NoError(err) 351 } 352 353 func (h *historyArchiverSuite) TestArchive_Success() { 354 355 ctx := context.Background() 356 357 storageWrapper := connector.NewMockClient(h.controller) 358 storageWrapper.EXPECT().Exist(ctx, h.testArchivalURI, gomock.Any()).Return(false, nil).Times(2) 359 storageWrapper.EXPECT().Upload(ctx, h.testArchivalURI, gomock.Any(), gomock.Any()).Return(nil) 360 361 historyIterator := archiver.NewMockHistoryIterator(h.controller) 362 historyBatches := []*historypb.History{ 363 { 364 Events: []*historypb.HistoryEvent{ 365 { 366 EventId: common.FirstEventID + 1, 367 EventTime: timestamppb.New(time.Now().UTC()), 368 Version: testCloseFailoverVersion, 369 }, 370 { 371 EventId: common.FirstEventID + 2, 372 EventTime: timestamppb.New(time.Now().UTC()), 373 Version: testCloseFailoverVersion, 374 }, 375 }, 376 }, 377 { 378 Events: []*historypb.HistoryEvent{ 379 { 380 EventId: testNextEventID - 1, 381 EventTime: timestamppb.New(time.Now().UTC()), 382 Version: testCloseFailoverVersion, 383 }, 384 }, 385 }, 386 } 387 historyBlob := &archiverspb.HistoryBlob{ 388 Header: &archiverspb.HistoryBlobHeader{ 389 IsLast: true, 390 }, 391 Body: historyBatches, 392 } 393 gomock.InOrder( 394 historyIterator.EXPECT().HasNext().Return(true), 395 historyIterator.EXPECT().Next(gomock.Any()).Return(historyBlob, nil), 396 historyIterator.EXPECT().HasNext().Return(false), 397 ) 398 399 historyArchiver := newHistoryArchiver(h.container, historyIterator, storageWrapper) 400 401 request := &archiver.ArchiveHistoryRequest{ 402 NamespaceID: testNamespaceID, 403 Namespace: testNamespace, 404 WorkflowID: testWorkflowID, 405 RunID: testRunID, 406 BranchToken: testBranchToken, 407 NextEventID: testNextEventID, 408 CloseFailoverVersion: testCloseFailoverVersion, 409 } 410 411 err := historyArchiver.Archive(ctx, h.testArchivalURI, request) 412 h.NoError(err) 413 } 414 415 func (h *historyArchiverSuite) TestGet_Fail_InvalidURI() { 416 ctx := context.Background() 417 mockStorageClient := connector.NewMockGcloudStorageClient(h.controller) 418 storageWrapper, _ := connector.NewClientWithParams(mockStorageClient) 419 historyIterator := archiver.NewMockHistoryIterator(h.controller) 420 historyArchiver := newHistoryArchiver(h.container, historyIterator, storageWrapper) 421 422 request := &archiver.GetHistoryRequest{ 423 NamespaceID: testNamespaceID, 424 WorkflowID: testWorkflowID, 425 RunID: testRunID, 426 PageSize: 100, 427 } 428 URI, err := archiver.NewURI("wrongscheme://") 429 h.NoError(err) 430 response, err := historyArchiver.Get(ctx, URI, request) 431 h.Nil(response) 432 h.Error(err) 433 } 434 435 func (h *historyArchiverSuite) TestGet_Fail_InvalidToken() { 436 ctx := context.Background() 437 mockStorageClient := connector.NewMockGcloudStorageClient(h.controller) 438 storageWrapper, _ := connector.NewClientWithParams(mockStorageClient) 439 historyIterator := archiver.NewMockHistoryIterator(h.controller) 440 historyArchiver := newHistoryArchiver(h.container, historyIterator, storageWrapper) 441 request := &archiver.GetHistoryRequest{ 442 NamespaceID: testNamespaceID, 443 WorkflowID: testWorkflowID, 444 RunID: testRunID, 445 PageSize: testPageSize, 446 NextPageToken: []byte{'r', 'a', 'n', 'd', 'o', 'm'}, 447 } 448 URI, err := archiver.NewURI("gs:///") 449 h.NoError(err) 450 response, err := historyArchiver.Get(ctx, URI, request) 451 h.Nil(response) 452 h.Error(err) 453 h.IsType(&serviceerror.InvalidArgument{}, err) 454 } 455 456 func (h *historyArchiverSuite) TestGet_Success_PickHighestVersion() { 457 ctx := context.Background() 458 storageWrapper := connector.NewMockClient(h.controller) 459 storageWrapper.EXPECT().Exist(ctx, h.testArchivalURI, "").Return(true, nil) 460 storageWrapper.EXPECT().Query(ctx, h.testArchivalURI, gomock.Any()).Return([]string{"905702227796330300141628222723188294514017512010591354159_-24_0.history", "905702227796330300141628222723188294514017512010591354159_-25_0.history"}, nil) 461 storageWrapper.EXPECT().Get(ctx, h.testArchivalURI, "141323698701063509081739672280485489488911532452831150339470_-24_0.history").Return([]byte(exampleNewHistoryRecord), nil) 462 historyIterator := archiver.NewMockHistoryIterator(h.controller) 463 historyArchiver := newHistoryArchiver(h.container, historyIterator, storageWrapper) 464 request := &archiver.GetHistoryRequest{ 465 NamespaceID: testNamespaceID, 466 WorkflowID: testWorkflowID, 467 RunID: testRunID, 468 PageSize: testPageSize, 469 } 470 471 response, err := historyArchiver.Get(ctx, h.testArchivalURI, request) 472 h.NoError(err) 473 h.Nil(response.NextPageToken) 474 } 475 476 func (h *historyArchiverSuite) TestGet_Success_PickHighestVersion_OldJSON() { 477 ctx := context.Background() 478 storageWrapper := connector.NewMockClient(h.controller) 479 storageWrapper.EXPECT().Exist(ctx, h.testArchivalURI, "").Return(true, nil) 480 storageWrapper.EXPECT().Query(ctx, h.testArchivalURI, gomock.Any()).Return([]string{"905702227796330300141628222723188294514017512010591354159_-24_0.history", "905702227796330300141628222723188294514017512010591354159_-25_0.history"}, nil) 481 storageWrapper.EXPECT().Get(ctx, h.testArchivalURI, "141323698701063509081739672280485489488911532452831150339470_-24_0.history").Return([]byte(exampleOldHistoryRecord), nil) 482 historyIterator := archiver.NewMockHistoryIterator(h.controller) 483 historyArchiver := newHistoryArchiver(h.container, historyIterator, storageWrapper) 484 request := &archiver.GetHistoryRequest{ 485 NamespaceID: testNamespaceID, 486 WorkflowID: testWorkflowID, 487 RunID: testRunID, 488 PageSize: testPageSize, 489 } 490 491 response, err := historyArchiver.Get(ctx, h.testArchivalURI, request) 492 h.NoError(err) 493 h.Nil(response.NextPageToken) 494 } 495 496 func (h *historyArchiverSuite) TestGet_Success_UseProvidedVersion() { 497 ctx := context.Background() 498 storageWrapper := connector.NewMockClient(h.controller) 499 storageWrapper.EXPECT().Exist(ctx, h.testArchivalURI, "").Return(true, nil) 500 storageWrapper.EXPECT().Query(ctx, h.testArchivalURI, "141323698701063509081739672280485489488911532452831150339470").Return([]string{"905702227796330300141628222723188294514017512010591354159_-24_0.history", "905702227796330300141628222723188294514017512010591354159_-25_0.history"}, nil) 501 storageWrapper.EXPECT().Get(ctx, h.testArchivalURI, "141323698701063509081739672280485489488911532452831150339470_-25_0.history").Return([]byte(exampleNewHistoryRecord), nil) 502 historyIterator := archiver.NewMockHistoryIterator(h.controller) 503 historyArchiver := newHistoryArchiver(h.container, historyIterator, storageWrapper) 504 request := &archiver.GetHistoryRequest{ 505 NamespaceID: testNamespaceID, 506 WorkflowID: testWorkflowID, 507 RunID: testRunID, 508 PageSize: testPageSize, 509 CloseFailoverVersion: convert.Int64Ptr(-25), 510 } 511 512 response, err := historyArchiver.Get(ctx, h.testArchivalURI, request) 513 h.NoError(err) 514 h.Nil(response.NextPageToken) 515 } 516 517 func (h *historyArchiverSuite) TestGet_Success_PageSize() { 518 ctx := context.Background() 519 storageWrapper := connector.NewMockClient(h.controller) 520 storageWrapper.EXPECT().Exist(ctx, h.testArchivalURI, "").Return(true, nil) 521 storageWrapper.EXPECT().Query(ctx, h.testArchivalURI, "141323698701063509081739672280485489488911532452831150339470").Return([]string{"905702227796330300141628222723188294514017512010591354159_-24_0.history", "905702227796330300141628222723188294514017512010591354159_-24_1.history", "905702227796330300141628222723188294514017512010591354159_-24_2.history", "905702227796330300141628222723188294514017512010591354159_-24_3.history", "905702227796330300141628222723188294514017512010591354159_-25_0.history"}, nil) 522 storageWrapper.EXPECT().Get(ctx, h.testArchivalURI, "141323698701063509081739672280485489488911532452831150339470_-24_0.history").Return([]byte(exampleNewHistoryRecord), nil) 523 storageWrapper.EXPECT().Get(ctx, h.testArchivalURI, "141323698701063509081739672280485489488911532452831150339470_-24_1.history").Return([]byte(exampleNewHistoryRecord), nil) 524 525 historyIterator := archiver.NewMockHistoryIterator(h.controller) 526 historyArchiver := newHistoryArchiver(h.container, historyIterator, storageWrapper) 527 request := &archiver.GetHistoryRequest{ 528 NamespaceID: testNamespaceID, 529 WorkflowID: testWorkflowID, 530 RunID: testRunID, 531 PageSize: 2, 532 } 533 534 response, err := historyArchiver.Get(ctx, h.testArchivalURI, request) 535 h.NoError(err) 536 h.NotNil(response.NextPageToken) 537 h.EqualValues(len(response.HistoryBatches), 2) 538 } 539 540 func (h *historyArchiverSuite) TestGet_Success_FromToken() { 541 ctx := context.Background() 542 storageWrapper := connector.NewMockClient(h.controller) 543 storageWrapper.EXPECT().Exist(ctx, h.testArchivalURI, "").Return(true, nil) 544 storageWrapper.EXPECT().Get(ctx, h.testArchivalURI, "141323698701063509081739672280485489488911532452831150339470_-24_2.history").Return([]byte(exampleNewHistoryRecord), nil) 545 storageWrapper.EXPECT().Get(ctx, h.testArchivalURI, "141323698701063509081739672280485489488911532452831150339470_-24_3.history").Return([]byte(twoEventsExampleHistoryRecord), nil) 546 storageWrapper.EXPECT().Get(ctx, h.testArchivalURI, "141323698701063509081739672280485489488911532452831150339470_-24_4.history").Return([]byte(exampleNewHistoryRecord), nil) 547 548 historyIterator := archiver.NewMockHistoryIterator(h.controller) 549 historyArchiver := newHistoryArchiver(h.container, historyIterator, storageWrapper) 550 551 token := &getHistoryToken{ 552 CloseFailoverVersion: -24, 553 HighestPart: 5, 554 CurrentPart: 2, 555 BatchIdxOffset: 0, 556 } 557 558 nextPageToken, err := serializeToken(token) 559 h.NoError(err) 560 561 request := &archiver.GetHistoryRequest{ 562 NamespaceID: testNamespaceID, 563 WorkflowID: testWorkflowID, 564 RunID: testRunID, 565 PageSize: 4, 566 NextPageToken: nextPageToken, 567 } 568 569 h.NoError(err) 570 response, err := historyArchiver.Get(ctx, h.testArchivalURI, request) 571 h.NoError(err) 572 h.NotNil(response.NextPageToken) 573 574 token, err = deserializeGetHistoryToken(response.NextPageToken) 575 h.NoError(err) 576 577 h.EqualValues(5, token.HighestPart) 578 h.EqualValues(5, token.CurrentPart) 579 h.EqualValues(3, len(response.HistoryBatches)) 580 numOfEvents := 0 581 for _, batch := range response.HistoryBatches { 582 numOfEvents += len(batch.Events) 583 } 584 585 h.EqualValues(4, numOfEvents) 586 } 587 588 func (h *historyArchiverSuite) TestGet_NoHistory() { 589 590 ctx := context.Background() 591 storageWrapper := connector.NewMockClient(h.controller) 592 storageWrapper.EXPECT().Exist(ctx, h.testArchivalURI, "").Return(true, nil) 593 storageWrapper.EXPECT().Query(ctx, h.testArchivalURI, "141323698701063509081739672280485489488911532452831150339470").Return([]string{}, nil) 594 595 historyIterator := archiver.NewMockHistoryIterator(h.controller) 596 historyArchiver := newHistoryArchiver(h.container, historyIterator, storageWrapper) 597 request := &archiver.GetHistoryRequest{ 598 NamespaceID: testNamespaceID, 599 WorkflowID: testWorkflowID, 600 RunID: testRunID, 601 PageSize: 2, 602 } 603 604 _, err := historyArchiver.Get(ctx, h.testArchivalURI, request) 605 h.Assert().IsType(&serviceerror.NotFound{}, err) 606 }