go.temporal.io/server@v1.23.0/common/persistence/tests/execution_mutable_state_task.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  	"context"
    29  	"math"
    30  	"math/rand"
    31  	"testing"
    32  	"time"
    33  
    34  	"github.com/google/uuid"
    35  	"github.com/stretchr/testify/require"
    36  	"github.com/stretchr/testify/suite"
    37  	commonpb "go.temporal.io/api/common/v1"
    38  	enumspb "go.temporal.io/api/enums/v1"
    39  	"google.golang.org/protobuf/proto"
    40  	"google.golang.org/protobuf/types/known/timestamppb"
    41  
    42  	persistencespb "go.temporal.io/server/api/persistence/v1"
    43  	"go.temporal.io/server/common"
    44  	"go.temporal.io/server/common/debug"
    45  	"go.temporal.io/server/common/definition"
    46  	"go.temporal.io/server/common/dynamicconfig"
    47  	"go.temporal.io/server/common/log"
    48  	"go.temporal.io/server/common/persistence"
    49  	p "go.temporal.io/server/common/persistence"
    50  	"go.temporal.io/server/common/persistence/serialization"
    51  	"go.temporal.io/server/service/history/tasks"
    52  )
    53  
    54  type (
    55  	ExecutionMutableStateTaskSuite struct {
    56  		suite.Suite
    57  		*require.Assertions
    58  
    59  		ShardID     int32
    60  		RangeID     int64
    61  		Owner       string
    62  		WorkflowKey definition.WorkflowKey
    63  
    64  		ShardManager     p.ShardManager
    65  		ExecutionManager p.ExecutionManager
    66  		Logger           log.Logger
    67  
    68  		Ctx    context.Context
    69  		Cancel context.CancelFunc
    70  	}
    71  
    72  	testSerializer struct {
    73  		serialization.Serializer
    74  	}
    75  )
    76  
    77  var (
    78  	fakeImmediateTaskCategory = tasks.NewCategory(1234, tasks.CategoryTypeImmediate, "fake-immediate")
    79  	fakeScheduledTaskCategory = tasks.NewCategory(2345, tasks.CategoryTypeScheduled, "fake-scheduled")
    80  
    81  	taskCategories = []tasks.Category{
    82  		tasks.CategoryTransfer,
    83  		tasks.CategoryTimer,
    84  		tasks.CategoryReplication,
    85  		tasks.CategoryVisibility,
    86  		fakeImmediateTaskCategory,
    87  		fakeScheduledTaskCategory,
    88  	}
    89  )
    90  
    91  func NewExecutionMutableStateTaskSuite(
    92  	t *testing.T,
    93  	shardStore p.ShardStore,
    94  	executionStore p.ExecutionStore,
    95  	serializer serialization.Serializer,
    96  	logger log.Logger,
    97  ) *ExecutionMutableStateTaskSuite {
    98  	serializer = newTestSerializer(serializer)
    99  	return &ExecutionMutableStateTaskSuite{
   100  		Assertions: require.New(t),
   101  		ShardManager: p.NewShardManager(
   102  			shardStore,
   103  			serializer,
   104  		),
   105  		ExecutionManager: p.NewExecutionManager(
   106  			executionStore,
   107  			serializer,
   108  			nil,
   109  			logger,
   110  			dynamicconfig.GetIntPropertyFn(4*1024*1024),
   111  		),
   112  		Logger: logger,
   113  	}
   114  }
   115  
   116  func (s *ExecutionMutableStateTaskSuite) SetupTest() {
   117  	s.Assertions = require.New(s.T())
   118  	s.Ctx, s.Cancel = context.WithTimeout(context.Background(), 30*time.Second*debug.TimeoutMultiplier)
   119  
   120  	s.ShardID++
   121  	resp, err := s.ShardManager.GetOrCreateShard(s.Ctx, &p.GetOrCreateShardRequest{
   122  		ShardID: s.ShardID,
   123  		InitialShardInfo: &persistencespb.ShardInfo{
   124  			ShardId: s.ShardID,
   125  			RangeId: 1,
   126  			Owner:   "test-shard-owner",
   127  		},
   128  	})
   129  	s.NoError(err)
   130  	previousRangeID := resp.ShardInfo.RangeId
   131  	resp.ShardInfo.RangeId++
   132  	err = s.ShardManager.UpdateShard(s.Ctx, &p.UpdateShardRequest{
   133  		ShardInfo:       resp.ShardInfo,
   134  		PreviousRangeID: previousRangeID,
   135  	})
   136  	s.NoError(err)
   137  	s.RangeID = resp.ShardInfo.RangeId
   138  	s.Owner = resp.ShardInfo.Owner
   139  
   140  	s.WorkflowKey = definition.NewWorkflowKey(
   141  		uuid.New().String(),
   142  		uuid.New().String(),
   143  		uuid.New().String(),
   144  	)
   145  
   146  	for _, category := range taskCategories {
   147  		err := s.ExecutionManager.RegisterHistoryTaskReader(s.Ctx, &p.RegisterHistoryTaskReaderRequest{
   148  			ShardID:      s.ShardID,
   149  			ShardOwner:   s.Owner,
   150  			TaskCategory: category,
   151  			ReaderID:     common.DefaultQueueReaderID,
   152  		})
   153  		s.NoError(err)
   154  	}
   155  }
   156  
   157  func (s *ExecutionMutableStateTaskSuite) TearDownTest() {
   158  	for _, category := range []tasks.Category{tasks.CategoryTransfer, tasks.CategoryReplication, tasks.CategoryVisibility} {
   159  		err := s.ExecutionManager.RangeCompleteHistoryTasks(s.Ctx, &p.RangeCompleteHistoryTasksRequest{
   160  			ShardID:             s.ShardID,
   161  			TaskCategory:        category,
   162  			InclusiveMinTaskKey: tasks.NewImmediateKey(0),
   163  			ExclusiveMaxTaskKey: tasks.NewImmediateKey(math.MaxInt64),
   164  		})
   165  		s.NoError(err)
   166  	}
   167  	err := s.ExecutionManager.RangeCompleteHistoryTasks(s.Ctx, &p.RangeCompleteHistoryTasksRequest{
   168  		ShardID:             s.ShardID,
   169  		TaskCategory:        tasks.CategoryTimer,
   170  		InclusiveMinTaskKey: tasks.NewKey(time.Unix(0, 0), 0),
   171  		ExclusiveMaxTaskKey: tasks.NewKey(time.Unix(0, math.MaxInt64), 0),
   172  	})
   173  	s.NoError(err)
   174  
   175  	for _, category := range taskCategories {
   176  		s.ExecutionManager.UnregisterHistoryTaskReader(s.Ctx, &p.UnregisterHistoryTaskReaderRequest{
   177  			ShardID:      s.ShardID,
   178  			ShardOwner:   s.Owner,
   179  			TaskCategory: category,
   180  			ReaderID:     common.DefaultQueueReaderID,
   181  		})
   182  	}
   183  
   184  	s.Cancel()
   185  }
   186  
   187  func (s *ExecutionMutableStateTaskSuite) TestAddGetCompleteImmediateTask_Single() {
   188  	immediateTasks := s.AddRandomTasks(
   189  		fakeImmediateTaskCategory,
   190  		1,
   191  		func(workflowKey definition.WorkflowKey, taskID int64, visibilityTimestamp time.Time) tasks.Task {
   192  			fakeTask := tasks.NewFakeTask(
   193  				workflowKey,
   194  				fakeImmediateTaskCategory,
   195  				visibilityTimestamp,
   196  			)
   197  			fakeTask.SetTaskID(taskID)
   198  			return fakeTask
   199  		},
   200  	)
   201  	s.GetAndCompleteHistoryTask(fakeImmediateTaskCategory, immediateTasks[0])
   202  }
   203  
   204  func (s *ExecutionMutableStateTaskSuite) TestAddGetRangeCompleteImmediateTasks_Multiple() {
   205  	numTasks := 20
   206  	immediateTasks := s.AddRandomTasks(
   207  		fakeImmediateTaskCategory,
   208  		numTasks,
   209  		func(workflowKey definition.WorkflowKey, taskID int64, visibilityTimestamp time.Time) tasks.Task {
   210  			fakeTask := tasks.NewFakeTask(
   211  				workflowKey,
   212  				fakeImmediateTaskCategory,
   213  				visibilityTimestamp,
   214  			)
   215  			fakeTask.SetTaskID(taskID)
   216  			return fakeTask
   217  		},
   218  	)
   219  
   220  	immediateTasks, inclusiveMinTaskKey, exclusiveMaxTaskKey := s.RandomPaginateRange(immediateTasks)
   221  	loadedTasks := s.PaginateTasks(
   222  		fakeImmediateTaskCategory,
   223  		inclusiveMinTaskKey,
   224  		exclusiveMaxTaskKey,
   225  		rand.Intn(len(immediateTasks)*2)+1,
   226  	)
   227  	s.Equal(immediateTasks, loadedTasks)
   228  
   229  	err := s.ExecutionManager.RangeCompleteHistoryTasks(s.Ctx, &p.RangeCompleteHistoryTasksRequest{
   230  		ShardID:             s.ShardID,
   231  		TaskCategory:        fakeImmediateTaskCategory,
   232  		InclusiveMinTaskKey: tasks.NewImmediateKey(0),
   233  		ExclusiveMaxTaskKey: tasks.NewImmediateKey(math.MaxInt64),
   234  	})
   235  	s.NoError(err)
   236  
   237  	loadedTasks = s.PaginateTasks(
   238  		fakeImmediateTaskCategory,
   239  		inclusiveMinTaskKey,
   240  		exclusiveMaxTaskKey,
   241  		1,
   242  	)
   243  	s.Empty(loadedTasks)
   244  }
   245  
   246  func (s *ExecutionMutableStateTaskSuite) TestAddGetCompleteScheduledTask_Single() {
   247  	scheduledTasks := s.AddRandomTasks(
   248  		fakeScheduledTaskCategory,
   249  		1,
   250  		func(workflowKey definition.WorkflowKey, taskID int64, visibilityTimestamp time.Time) tasks.Task {
   251  			fakeTask := tasks.NewFakeTask(
   252  				workflowKey,
   253  				fakeScheduledTaskCategory,
   254  				visibilityTimestamp,
   255  			)
   256  			fakeTask.SetTaskID(taskID)
   257  			return fakeTask
   258  		},
   259  	)
   260  	s.GetAndCompleteHistoryTask(fakeScheduledTaskCategory, scheduledTasks[0])
   261  }
   262  
   263  func (s *ExecutionMutableStateTaskSuite) TestAddGetRangeCompleteScheduledTasks_Multiple() {
   264  	numTasks := 20
   265  	scheduledTasks := s.AddRandomTasks(
   266  		fakeScheduledTaskCategory,
   267  		numTasks,
   268  		func(workflowKey definition.WorkflowKey, taskID int64, visibilityTimestamp time.Time) tasks.Task {
   269  			fakeTask := tasks.NewFakeTask(
   270  				workflowKey,
   271  				fakeScheduledTaskCategory,
   272  				visibilityTimestamp,
   273  			)
   274  			fakeTask.SetTaskID(taskID)
   275  			return fakeTask
   276  		},
   277  	)
   278  
   279  	scheduledTasks, inclusiveMinTaskKey, exclusiveMaxTaskKey := s.RandomPaginateRange(scheduledTasks)
   280  	loadedTasks := s.PaginateTasks(
   281  		fakeScheduledTaskCategory,
   282  		inclusiveMinTaskKey,
   283  		exclusiveMaxTaskKey,
   284  		rand.Intn(len(scheduledTasks)*2)+1,
   285  	)
   286  	s.Equal(scheduledTasks, loadedTasks)
   287  
   288  	err := s.ExecutionManager.RangeCompleteHistoryTasks(s.Ctx, &p.RangeCompleteHistoryTasksRequest{
   289  		ShardID:             s.ShardID,
   290  		TaskCategory:        fakeScheduledTaskCategory,
   291  		InclusiveMinTaskKey: tasks.NewKey(time.Unix(0, 0), 0),
   292  		ExclusiveMaxTaskKey: tasks.NewKey(time.Unix(0, math.MaxInt64), 0),
   293  	})
   294  	s.NoError(err)
   295  
   296  	loadedTasks = s.PaginateTasks(
   297  		fakeScheduledTaskCategory,
   298  		inclusiveMinTaskKey,
   299  		exclusiveMaxTaskKey,
   300  		1,
   301  	)
   302  	s.Empty(loadedTasks)
   303  }
   304  
   305  func (s *ExecutionMutableStateTaskSuite) TestAddGetCompleteTransferTask_Single() {
   306  	transferTasks := s.AddRandomTasks(
   307  		tasks.CategoryTransfer,
   308  		1,
   309  		func(workflowKey definition.WorkflowKey, taskID int64, visibilityTimestamp time.Time) tasks.Task {
   310  			return &tasks.ActivityTask{
   311  				WorkflowKey:         workflowKey,
   312  				TaskID:              taskID,
   313  				VisibilityTimestamp: visibilityTimestamp,
   314  			}
   315  		},
   316  	)
   317  	s.GetAndCompleteHistoryTask(tasks.CategoryTransfer, transferTasks[0])
   318  }
   319  
   320  func (s *ExecutionMutableStateTaskSuite) TestAddGetTransferTasks_Multiple() {
   321  	numTasks := 20
   322  	transferTasks := s.AddRandomTasks(
   323  		tasks.CategoryTransfer,
   324  		numTasks,
   325  		func(workflowKey definition.WorkflowKey, taskID int64, visibilityTimestamp time.Time) tasks.Task {
   326  			return &tasks.ActivityTask{
   327  				WorkflowKey:         workflowKey,
   328  				TaskID:              taskID,
   329  				VisibilityTimestamp: visibilityTimestamp,
   330  			}
   331  		},
   332  	)
   333  
   334  	transferTasks, inclusiveMinTaskKey, exclusiveMaxTaskKey := s.RandomPaginateRange(transferTasks)
   335  	loadedTasks := s.PaginateTasks(
   336  		tasks.CategoryTransfer,
   337  		inclusiveMinTaskKey,
   338  		exclusiveMaxTaskKey,
   339  		rand.Intn(len(transferTasks)*2)+1,
   340  	)
   341  	s.Equal(transferTasks, loadedTasks)
   342  }
   343  
   344  func (s *ExecutionMutableStateTaskSuite) TestAddGetCompleteTimerTask_Single() {
   345  	timerTasks := s.AddRandomTasks(
   346  		tasks.CategoryTimer,
   347  		1,
   348  		func(workflowKey definition.WorkflowKey, taskID int64, visibilityTimestamp time.Time) tasks.Task {
   349  			return &tasks.UserTimerTask{
   350  				WorkflowKey:         workflowKey,
   351  				TaskID:              taskID,
   352  				VisibilityTimestamp: visibilityTimestamp,
   353  			}
   354  		},
   355  	)
   356  	s.GetAndCompleteHistoryTask(tasks.CategoryTimer, timerTasks[0])
   357  }
   358  
   359  func (s *ExecutionMutableStateTaskSuite) TestAddGetTimerTasks_Multiple() {
   360  	numTasks := 20
   361  	timerTasks := s.AddRandomTasks(
   362  		tasks.CategoryTimer,
   363  		numTasks,
   364  		func(workflowKey definition.WorkflowKey, taskID int64, visibilityTimestamp time.Time) tasks.Task {
   365  			return &tasks.UserTimerTask{
   366  				WorkflowKey:         workflowKey,
   367  				TaskID:              taskID,
   368  				VisibilityTimestamp: visibilityTimestamp,
   369  			}
   370  		},
   371  	)
   372  
   373  	timerTasks, inclusiveMinTaskKey, exclusiveMaxTaskKey := s.RandomPaginateRange(timerTasks)
   374  	loadedTasks := s.PaginateTasks(
   375  		tasks.CategoryTimer,
   376  		inclusiveMinTaskKey,
   377  		exclusiveMaxTaskKey,
   378  		rand.Intn(len(timerTasks)*2)+1,
   379  	)
   380  	s.Equal(timerTasks, loadedTasks)
   381  }
   382  
   383  func (s *ExecutionMutableStateTaskSuite) TestAddGetCompleteReplicationTask_Single() {
   384  	replicationTasks := s.AddRandomTasks(
   385  		tasks.CategoryReplication,
   386  		1,
   387  		func(workflowKey definition.WorkflowKey, taskID int64, visibilityTimestamp time.Time) tasks.Task {
   388  			return &tasks.HistoryReplicationTask{
   389  				WorkflowKey:         workflowKey,
   390  				TaskID:              taskID,
   391  				VisibilityTimestamp: visibilityTimestamp,
   392  			}
   393  		},
   394  	)
   395  	s.GetAndCompleteHistoryTask(tasks.CategoryReplication, replicationTasks[0])
   396  }
   397  
   398  func (s *ExecutionMutableStateTaskSuite) TestAddGetReplicationTasks_Multiple() {
   399  	numTasks := 20
   400  	replicationTasks := s.AddRandomTasks(
   401  		tasks.CategoryReplication,
   402  		numTasks,
   403  		func(workflowKey definition.WorkflowKey, taskID int64, visibilityTimestamp time.Time) tasks.Task {
   404  			return &tasks.HistoryReplicationTask{
   405  				WorkflowKey:         workflowKey,
   406  				TaskID:              taskID,
   407  				VisibilityTimestamp: visibilityTimestamp,
   408  			}
   409  		},
   410  	)
   411  
   412  	replicationTasks, inclusiveMinTaskKey, exclusiveMaxTaskKey := s.RandomPaginateRange(replicationTasks)
   413  	loadedTasks := s.PaginateTasks(
   414  		tasks.CategoryReplication,
   415  		inclusiveMinTaskKey,
   416  		exclusiveMaxTaskKey,
   417  		rand.Intn(len(replicationTasks)*2)+1,
   418  	)
   419  	s.Equal(replicationTasks, loadedTasks)
   420  }
   421  
   422  func (s *ExecutionMutableStateTaskSuite) TestAddGetCompleteVisibilityTask_Single() {
   423  	visibilityTasks := s.AddRandomTasks(
   424  		tasks.CategoryVisibility,
   425  		1,
   426  		func(workflowKey definition.WorkflowKey, taskID int64, visibilityTimestamp time.Time) tasks.Task {
   427  			return &tasks.StartExecutionVisibilityTask{
   428  				WorkflowKey:         workflowKey,
   429  				TaskID:              taskID,
   430  				VisibilityTimestamp: visibilityTimestamp,
   431  			}
   432  		},
   433  	)
   434  	s.GetAndCompleteHistoryTask(tasks.CategoryVisibility, visibilityTasks[0])
   435  }
   436  
   437  func (s *ExecutionMutableStateTaskSuite) TestAddGetVisibilityTasks_Multiple() {
   438  	numTasks := 20
   439  	visibilityTasks := s.AddRandomTasks(
   440  		tasks.CategoryVisibility,
   441  		numTasks,
   442  		func(workflowKey definition.WorkflowKey, taskID int64, visibilityTimestamp time.Time) tasks.Task {
   443  			return &tasks.StartExecutionVisibilityTask{
   444  				WorkflowKey:         workflowKey,
   445  				TaskID:              taskID,
   446  				VisibilityTimestamp: visibilityTimestamp,
   447  			}
   448  		},
   449  	)
   450  
   451  	visibilityTasks, inclusiveMinTaskKey, exclusiveMaxTaskKey := s.RandomPaginateRange(visibilityTasks)
   452  	loadedTasks := s.PaginateTasks(
   453  		tasks.CategoryVisibility,
   454  		inclusiveMinTaskKey,
   455  		exclusiveMaxTaskKey,
   456  		rand.Intn(len(visibilityTasks)*2)+1,
   457  	)
   458  	s.Equal(visibilityTasks, loadedTasks)
   459  }
   460  
   461  func (s *ExecutionMutableStateTaskSuite) TestIsReplicationDLQEmpty() {
   462  	testShardID := int32(1)
   463  	isEmpty, err := s.ExecutionManager.IsReplicationDLQEmpty(context.Background(), &p.GetReplicationTasksFromDLQRequest{
   464  		GetHistoryTasksRequest: p.GetHistoryTasksRequest{
   465  			ShardID:             testShardID,
   466  			TaskCategory:        tasks.CategoryReplication,
   467  			InclusiveMinTaskKey: tasks.NewImmediateKey(0),
   468  		},
   469  		SourceClusterName: "test",
   470  	})
   471  	s.NoError(err)
   472  	s.True(isEmpty)
   473  	err = s.ExecutionManager.PutReplicationTaskToDLQ(context.Background(), &p.PutReplicationTaskToDLQRequest{
   474  		ShardID:           testShardID,
   475  		SourceClusterName: "test",
   476  		TaskInfo:          &persistencespb.ReplicationTaskInfo{},
   477  	})
   478  	s.NoError(err)
   479  	isEmpty, err = s.ExecutionManager.IsReplicationDLQEmpty(context.Background(), &p.GetReplicationTasksFromDLQRequest{
   480  		GetHistoryTasksRequest: p.GetHistoryTasksRequest{
   481  			ShardID:             testShardID,
   482  			TaskCategory:        tasks.CategoryReplication,
   483  			InclusiveMinTaskKey: tasks.NewImmediateKey(0),
   484  		},
   485  		SourceClusterName: "test",
   486  	})
   487  	s.NoError(err)
   488  	s.False(isEmpty)
   489  }
   490  
   491  func (s *ExecutionMutableStateTaskSuite) TestGetTimerTasksOrdered() {
   492  	now := time.Now().Truncate(p.ScheduledTaskMinPrecision)
   493  	timerTasks := []tasks.Task{
   494  		&tasks.UserTimerTask{
   495  			WorkflowKey:         s.WorkflowKey,
   496  			TaskID:              100,
   497  			VisibilityTimestamp: now.Add(time.Nanosecond * 10),
   498  		},
   499  		&tasks.UserTimerTask{
   500  			WorkflowKey:         s.WorkflowKey,
   501  			TaskID:              50,
   502  			VisibilityTimestamp: now.Add(time.Nanosecond * 20),
   503  		},
   504  	}
   505  
   506  	err := s.ExecutionManager.AddHistoryTasks(s.Ctx, &p.AddHistoryTasksRequest{
   507  		ShardID:     s.ShardID,
   508  		RangeID:     s.RangeID,
   509  		NamespaceID: s.WorkflowKey.NamespaceID,
   510  		WorkflowID:  s.WorkflowKey.WorkflowID,
   511  		RunID:       s.WorkflowKey.RunID,
   512  		Tasks: map[tasks.Category][]tasks.Task{
   513  			tasks.CategoryTimer: timerTasks,
   514  		},
   515  	})
   516  	s.NoError(err)
   517  
   518  	// due to persistence layer precision loss,
   519  	// two tasks can be returned in either order,
   520  	// but must be ordered in terms of tasks.Key
   521  	loadedTasks := s.PaginateTasks(
   522  		tasks.CategoryTimer,
   523  		tasks.NewKey(now, 0),
   524  		tasks.NewKey(now.Add(time.Second), 0),
   525  		10,
   526  	)
   527  	s.Len(loadedTasks, 2)
   528  	s.True(loadedTasks[0].GetKey().CompareTo(loadedTasks[1].GetKey()) < 0)
   529  }
   530  
   531  func (s *ExecutionMutableStateTaskSuite) TestGetScheduledTasksOrdered() {
   532  	now := time.Now().Truncate(p.ScheduledTaskMinPrecision)
   533  	scheduledTasks := []tasks.Task{
   534  		tasks.NewFakeTask(
   535  			s.WorkflowKey,
   536  			fakeScheduledTaskCategory,
   537  			now.Add(time.Nanosecond*10),
   538  		),
   539  		tasks.NewFakeTask(
   540  			s.WorkflowKey,
   541  			fakeScheduledTaskCategory,
   542  			now.Add(time.Nanosecond*20),
   543  		),
   544  	}
   545  	scheduledTasks[0].SetTaskID(100)
   546  	scheduledTasks[1].SetTaskID(50)
   547  
   548  	err := s.ExecutionManager.AddHistoryTasks(s.Ctx, &p.AddHistoryTasksRequest{
   549  		ShardID:     s.ShardID,
   550  		RangeID:     s.RangeID,
   551  		NamespaceID: s.WorkflowKey.NamespaceID,
   552  		WorkflowID:  s.WorkflowKey.WorkflowID,
   553  		RunID:       s.WorkflowKey.RunID,
   554  		Tasks: map[tasks.Category][]tasks.Task{
   555  			fakeScheduledTaskCategory: scheduledTasks,
   556  		},
   557  	})
   558  	s.NoError(err)
   559  
   560  	// due to persistence layer precision loss,
   561  	// two tasks can be returned in either order,
   562  	// but must be ordered in terms of tasks.Key
   563  	loadedTasks := s.PaginateTasks(
   564  		fakeScheduledTaskCategory,
   565  		tasks.NewKey(now, 0),
   566  		tasks.NewKey(now.Add(time.Second), 0),
   567  		10,
   568  	)
   569  	s.Len(loadedTasks, 2)
   570  	s.True(loadedTasks[0].GetKey().CompareTo(loadedTasks[1].GetKey()) < 0)
   571  
   572  	err = s.ExecutionManager.RangeCompleteHistoryTasks(s.Ctx, &p.RangeCompleteHistoryTasksRequest{
   573  		ShardID:             s.ShardID,
   574  		TaskCategory:        fakeScheduledTaskCategory,
   575  		InclusiveMinTaskKey: tasks.NewKey(now, 0),
   576  		ExclusiveMaxTaskKey: tasks.NewKey(now.Add(time.Second), 0),
   577  	})
   578  	s.NoError(err)
   579  
   580  	response, err := s.ExecutionManager.GetHistoryTasks(s.Ctx, &p.GetHistoryTasksRequest{
   581  		ShardID:             s.ShardID,
   582  		TaskCategory:        fakeScheduledTaskCategory,
   583  		ReaderID:            common.DefaultQueueReaderID,
   584  		InclusiveMinTaskKey: tasks.NewKey(now, 0),
   585  		ExclusiveMaxTaskKey: tasks.NewKey(now.Add(time.Second), 0),
   586  		BatchSize:           10,
   587  	})
   588  	s.NoError(err)
   589  	s.Empty(response.Tasks)
   590  }
   591  
   592  func (s *ExecutionMutableStateTaskSuite) AddRandomTasks(
   593  	category tasks.Category,
   594  	numTasks int,
   595  	newTaskFn func(definition.WorkflowKey, int64, time.Time) tasks.Task,
   596  ) []tasks.Task {
   597  	currentTaskID := int64(1)
   598  	now := time.Now().UTC()
   599  	randomTasks := make([]tasks.Task, 0, numTasks)
   600  	for i := 0; i != numTasks; i++ {
   601  		now = now.Truncate(p.ScheduledTaskMinPrecision)
   602  		randomTasks = append(randomTasks, newTaskFn(s.WorkflowKey, currentTaskID, now))
   603  		currentTaskID += rand.Int63n(100) + 1
   604  		now = now.Add(time.Duration(rand.Int63n(1000_000_000)) + time.Millisecond)
   605  	}
   606  
   607  	err := s.ExecutionManager.AddHistoryTasks(s.Ctx, &p.AddHistoryTasksRequest{
   608  		ShardID:     s.ShardID,
   609  		RangeID:     s.RangeID,
   610  		NamespaceID: s.WorkflowKey.NamespaceID,
   611  		WorkflowID:  s.WorkflowKey.WorkflowID,
   612  		RunID:       s.WorkflowKey.RunID,
   613  		Tasks: map[tasks.Category][]tasks.Task{
   614  			category: randomTasks,
   615  		},
   616  	})
   617  	s.NoError(err)
   618  
   619  	return randomTasks
   620  }
   621  
   622  func (s *ExecutionMutableStateTaskSuite) PaginateTasks(
   623  	category tasks.Category,
   624  	inclusiveMinTaskKey tasks.Key,
   625  	exclusiveMaxTaskKey tasks.Key,
   626  	batchSize int,
   627  ) []tasks.Task {
   628  	request := &p.GetHistoryTasksRequest{
   629  		ShardID:             s.ShardID,
   630  		TaskCategory:        category,
   631  		ReaderID:            common.DefaultQueueReaderID,
   632  		InclusiveMinTaskKey: inclusiveMinTaskKey,
   633  		ExclusiveMaxTaskKey: exclusiveMaxTaskKey,
   634  		BatchSize:           batchSize,
   635  	}
   636  	var loadedTasks []tasks.Task
   637  	for {
   638  		response, err := s.ExecutionManager.GetHistoryTasks(s.Ctx, request)
   639  		s.NoError(err)
   640  		s.True(len(response.Tasks) <= batchSize)
   641  		loadedTasks = append(loadedTasks, response.Tasks...)
   642  		if len(response.NextPageToken) == 0 {
   643  			break
   644  		}
   645  		request.NextPageToken = response.NextPageToken
   646  	}
   647  	return loadedTasks
   648  }
   649  
   650  func (s *ExecutionMutableStateTaskSuite) RandomPaginateRange(
   651  	createdTasks []tasks.Task,
   652  ) ([]tasks.Task, tasks.Key, tasks.Key) {
   653  	numTasks := len(createdTasks)
   654  	firstTaskIdx := rand.Intn(numTasks/2 - 1)
   655  	nextTaskIdx := firstTaskIdx + rand.Intn(numTasks/2-1) + 1
   656  
   657  	inclusiveMinTaskKey := createdTasks[firstTaskIdx].GetKey()
   658  	var exclusiveMaxTaskKey tasks.Key
   659  	if nextTaskIdx == numTasks {
   660  		exclusiveMaxTaskKey = tasks.NewKey(
   661  			createdTasks[numTasks-1].GetVisibilityTime().Add(time.Second),
   662  			createdTasks[numTasks-1].GetTaskID()+10,
   663  		)
   664  	} else {
   665  		exclusiveMaxTaskKey = createdTasks[nextTaskIdx].GetKey()
   666  	}
   667  
   668  	taskCategory := createdTasks[0].GetCategory()
   669  	switch taskCategory.Type() {
   670  	case tasks.CategoryTypeImmediate:
   671  		inclusiveMinTaskKey.FireTime = tasks.DefaultFireTime
   672  		exclusiveMaxTaskKey.FireTime = tasks.DefaultFireTime
   673  	case tasks.CategoryTypeScheduled:
   674  		inclusiveMinTaskKey.TaskID = 0
   675  		exclusiveMaxTaskKey.TaskID = 0
   676  	}
   677  
   678  	return createdTasks[firstTaskIdx:nextTaskIdx], inclusiveMinTaskKey, exclusiveMaxTaskKey
   679  }
   680  
   681  func (s *ExecutionMutableStateTaskSuite) GetAndCompleteHistoryTask(
   682  	category tasks.Category,
   683  	task tasks.Task,
   684  ) {
   685  	key := task.GetKey()
   686  	var minKey, maxKey tasks.Key
   687  	if category.Type() == tasks.CategoryTypeImmediate {
   688  		minKey = key
   689  		maxKey = minKey.Next()
   690  	} else {
   691  		minKey = tasks.NewKey(key.FireTime, 0)
   692  		maxKey = tasks.NewKey(key.FireTime.Add(persistence.ScheduledTaskMinPrecision), 0)
   693  	}
   694  
   695  	historyTasks := s.PaginateTasks(category, minKey, maxKey, 1)
   696  	s.Len(historyTasks, 1)
   697  	s.Equal(task, historyTasks[0])
   698  
   699  	err := s.ExecutionManager.CompleteHistoryTask(s.Ctx, &p.CompleteHistoryTaskRequest{
   700  		ShardID:      s.ShardID,
   701  		TaskCategory: category,
   702  		TaskKey:      key,
   703  	})
   704  	s.NoError(err)
   705  
   706  	historyTasks = s.PaginateTasks(category, minKey, maxKey, 1)
   707  	s.Empty(historyTasks)
   708  }
   709  
   710  func newTestSerializer(
   711  	serializer serialization.Serializer,
   712  ) serialization.Serializer {
   713  	return &testSerializer{
   714  		Serializer: serializer,
   715  	}
   716  }
   717  
   718  func (s *testSerializer) SerializeTask(
   719  	task tasks.Task,
   720  ) (*commonpb.DataBlob, error) {
   721  	if fakeTask, ok := task.(*tasks.FakeTask); ok {
   722  		data, err := proto.Marshal(&persistencespb.TransferTaskInfo{
   723  			NamespaceId:    fakeTask.WorkflowKey.NamespaceID,
   724  			WorkflowId:     fakeTask.WorkflowKey.WorkflowID,
   725  			RunId:          fakeTask.WorkflowKey.RunID,
   726  			TaskType:       fakeTask.GetType(),
   727  			Version:        fakeTask.Version,
   728  			TaskId:         fakeTask.TaskID,
   729  			VisibilityTime: timestamppb.New(fakeTask.VisibilityTimestamp),
   730  		})
   731  		if err != nil {
   732  			return nil, err
   733  		}
   734  		return &commonpb.DataBlob{
   735  			Data:         data,
   736  			EncodingType: enumspb.ENCODING_TYPE_PROTO3,
   737  		}, nil
   738  	}
   739  
   740  	return s.Serializer.SerializeTask(task)
   741  }
   742  
   743  func (s *testSerializer) DeserializeTask(
   744  	category tasks.Category,
   745  	blob *commonpb.DataBlob,
   746  ) (tasks.Task, error) {
   747  	categoryID := category.ID()
   748  	if categoryID != fakeImmediateTaskCategory.ID() &&
   749  		categoryID != fakeScheduledTaskCategory.ID() {
   750  		return s.Serializer.DeserializeTask(category, blob)
   751  	}
   752  
   753  	taskInfo := &persistencespb.TransferTaskInfo{}
   754  	if err := proto.Unmarshal(blob.Data, taskInfo); err != nil {
   755  		return nil, err
   756  	}
   757  
   758  	fakeTask := tasks.NewFakeTask(
   759  		definition.NewWorkflowKey(
   760  			taskInfo.NamespaceId,
   761  			taskInfo.WorkflowId,
   762  			taskInfo.RunId,
   763  		),
   764  		category,
   765  		taskInfo.VisibilityTime.AsTime(),
   766  	)
   767  	fakeTask.SetTaskID(taskInfo.TaskId)
   768  
   769  	return fakeTask, nil
   770  }