go.temporal.io/server@v1.23.0/common/persistence/execution_manager.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 persistence
    26  
    27  import (
    28  	"context"
    29  	"fmt"
    30  
    31  	commonpb "go.temporal.io/api/common/v1"
    32  	enumspb "go.temporal.io/api/enums/v1"
    33  	historypb "go.temporal.io/api/history/v1"
    34  	"go.temporal.io/api/serviceerror"
    35  	workflowpb "go.temporal.io/api/workflow/v1"
    36  
    37  	historyspb "go.temporal.io/server/api/history/v1"
    38  	persistencespb "go.temporal.io/server/api/persistence/v1"
    39  	"go.temporal.io/server/common"
    40  	"go.temporal.io/server/common/definition"
    41  	"go.temporal.io/server/common/dynamicconfig"
    42  	"go.temporal.io/server/common/log"
    43  	"go.temporal.io/server/common/log/tag"
    44  	"go.temporal.io/server/common/persistence/serialization"
    45  	"go.temporal.io/server/common/persistence/versionhistory"
    46  	"go.temporal.io/server/service/history/tasks"
    47  )
    48  
    49  type (
    50  	// executionManagerImpl implements ExecutionManager based on ExecutionStore, statsComputer and Serializer
    51  	executionManagerImpl struct {
    52  		serializer            serialization.Serializer
    53  		eventBlobCache        XDCCache
    54  		persistence           ExecutionStore
    55  		logger                log.Logger
    56  		pagingTokenSerializer *jsonHistoryTokenSerializer
    57  		transactionSizeLimit  dynamicconfig.IntPropertyFn
    58  	}
    59  )
    60  
    61  var _ ExecutionManager = (*executionManagerImpl)(nil)
    62  
    63  // NewExecutionManager returns new ExecutionManager
    64  func NewExecutionManager(
    65  	persistence ExecutionStore,
    66  	serializer serialization.Serializer,
    67  	eventBlobCache XDCCache,
    68  	logger log.Logger,
    69  	transactionSizeLimit dynamicconfig.IntPropertyFn,
    70  ) ExecutionManager {
    71  	return &executionManagerImpl{
    72  		serializer:            serializer,
    73  		eventBlobCache:        eventBlobCache,
    74  		persistence:           persistence,
    75  		logger:                logger,
    76  		pagingTokenSerializer: newJSONHistoryTokenSerializer(),
    77  		transactionSizeLimit:  transactionSizeLimit,
    78  	}
    79  }
    80  
    81  func (m *executionManagerImpl) GetName() string {
    82  	return m.persistence.GetName()
    83  }
    84  
    85  func (m *executionManagerImpl) GetHistoryBranchUtil() HistoryBranchUtil {
    86  	return m.persistence.GetHistoryBranchUtil()
    87  }
    88  
    89  // The below three APIs are related to serialization/deserialization
    90  
    91  func (m *executionManagerImpl) CreateWorkflowExecution(
    92  	ctx context.Context,
    93  	request *CreateWorkflowExecutionRequest,
    94  ) (*CreateWorkflowExecutionResponse, error) {
    95  
    96  	newSnapshot := request.NewWorkflowSnapshot
    97  	newWorkflowXDCKVs, newWorkflowNewEvents, newHistoryDiff, err := m.serializeWorkflowEventBatches(
    98  		ctx,
    99  		request.ShardID,
   100  		request.NewWorkflowSnapshot.ExecutionInfo,
   101  		request.NewWorkflowEvents,
   102  	)
   103  	if err != nil {
   104  		return nil, err
   105  	}
   106  
   107  	newSnapshot.ExecutionInfo.ExecutionStats.HistorySize += int64(newHistoryDiff.SizeDiff)
   108  
   109  	if err := ValidateCreateWorkflowModeState(
   110  		request.Mode,
   111  		newSnapshot,
   112  	); err != nil {
   113  		return nil, err
   114  	}
   115  	if err := ValidateCreateWorkflowStateStatus(
   116  		newSnapshot.ExecutionState.State,
   117  		newSnapshot.ExecutionState.Status,
   118  	); err != nil {
   119  		return nil, err
   120  	}
   121  
   122  	serializedNewWorkflowSnapshot, err := m.SerializeWorkflowSnapshot(&newSnapshot)
   123  	if err != nil {
   124  		return nil, err
   125  	}
   126  
   127  	newRequest := &InternalCreateWorkflowExecutionRequest{
   128  		ShardID:                  request.ShardID,
   129  		RangeID:                  request.RangeID,
   130  		Mode:                     request.Mode,
   131  		PreviousRunID:            request.PreviousRunID,
   132  		PreviousLastWriteVersion: request.PreviousLastWriteVersion,
   133  		NewWorkflowSnapshot:      *serializedNewWorkflowSnapshot,
   134  		NewWorkflowNewEvents:     newWorkflowNewEvents,
   135  	}
   136  
   137  	if _, err := m.persistence.CreateWorkflowExecution(ctx, newRequest); err != nil {
   138  		return nil, err
   139  	}
   140  	m.addXDCCacheKV(newWorkflowXDCKVs)
   141  	return &CreateWorkflowExecutionResponse{
   142  		NewMutableStateStats: *statusOfInternalWorkflowSnapshot(
   143  			serializedNewWorkflowSnapshot,
   144  			newHistoryDiff,
   145  		),
   146  	}, nil
   147  }
   148  
   149  func (m *executionManagerImpl) UpdateWorkflowExecution(
   150  	ctx context.Context,
   151  	request *UpdateWorkflowExecutionRequest,
   152  ) (*UpdateWorkflowExecutionResponse, error) {
   153  
   154  	updateMutation := request.UpdateWorkflowMutation
   155  	newSnapshot := request.NewWorkflowSnapshot
   156  
   157  	updateWorkflowXDCKVs, updateWorkflowNewEvents, updateWorkflowHistoryDiff, err := m.serializeWorkflowEventBatches(
   158  		ctx,
   159  		request.ShardID,
   160  		request.UpdateWorkflowMutation.ExecutionInfo,
   161  		request.UpdateWorkflowEvents,
   162  	)
   163  	if err != nil {
   164  		return nil, err
   165  	}
   166  	updateMutation.ExecutionInfo.ExecutionStats.HistorySize += int64(updateWorkflowHistoryDiff.SizeDiff)
   167  
   168  	var newWorkflowXDCKVs map[XDCCacheKey]XDCCacheValue
   169  	var newWorkflowNewEvents []*InternalAppendHistoryNodesRequest
   170  	var newWorkflowHistoryDiff *HistoryStatistics
   171  	if newSnapshot != nil {
   172  		newWorkflowXDCKVs, newWorkflowNewEvents, newWorkflowHistoryDiff, err = m.serializeWorkflowEventBatches(
   173  			ctx,
   174  			request.ShardID,
   175  			request.NewWorkflowSnapshot.ExecutionInfo,
   176  			request.NewWorkflowEvents,
   177  		)
   178  		if err != nil {
   179  			return nil, err
   180  		}
   181  		newSnapshot.ExecutionInfo.ExecutionStats.HistorySize += int64(newWorkflowHistoryDiff.SizeDiff)
   182  	}
   183  
   184  	if err := ValidateUpdateWorkflowModeState(
   185  		request.Mode,
   186  		updateMutation,
   187  		newSnapshot,
   188  	); err != nil {
   189  		return nil, err
   190  	}
   191  	if err := ValidateUpdateWorkflowStateStatus(
   192  		updateMutation.ExecutionState.State,
   193  		updateMutation.ExecutionState.Status,
   194  	); err != nil {
   195  		return nil, err
   196  	}
   197  
   198  	serializedWorkflowMutation, err := m.SerializeWorkflowMutation(&updateMutation)
   199  	if err != nil {
   200  		return nil, err
   201  	}
   202  	var serializedNewWorkflowSnapshot *InternalWorkflowSnapshot
   203  	if newSnapshot != nil {
   204  		serializedNewWorkflowSnapshot, err = m.SerializeWorkflowSnapshot(newSnapshot)
   205  		if err != nil {
   206  			return nil, err
   207  		}
   208  	}
   209  
   210  	newRequest := &InternalUpdateWorkflowExecutionRequest{
   211  		ShardID: request.ShardID,
   212  		RangeID: request.RangeID,
   213  
   214  		Mode: request.Mode,
   215  
   216  		UpdateWorkflowMutation:  *serializedWorkflowMutation,
   217  		UpdateWorkflowNewEvents: updateWorkflowNewEvents,
   218  		NewWorkflowSnapshot:     serializedNewWorkflowSnapshot,
   219  		NewWorkflowNewEvents:    newWorkflowNewEvents,
   220  	}
   221  
   222  	err = m.persistence.UpdateWorkflowExecution(ctx, newRequest)
   223  	switch err.(type) {
   224  	case nil:
   225  		m.addXDCCacheKV(updateWorkflowXDCKVs)
   226  		m.addXDCCacheKV(newWorkflowXDCKVs)
   227  		return &UpdateWorkflowExecutionResponse{
   228  			UpdateMutableStateStats: *statusOfInternalWorkflowMutation(
   229  				&newRequest.UpdateWorkflowMutation,
   230  				updateWorkflowHistoryDiff,
   231  			),
   232  			NewMutableStateStats: statusOfInternalWorkflowSnapshot(
   233  				newRequest.NewWorkflowSnapshot,
   234  				newWorkflowHistoryDiff,
   235  			),
   236  		}, nil
   237  	case *CurrentWorkflowConditionFailedError,
   238  		*WorkflowConditionFailedError,
   239  		*ConditionFailedError:
   240  		m.trimHistoryNode(
   241  			ctx,
   242  			request.ShardID,
   243  			updateMutation.ExecutionInfo.NamespaceId,
   244  			updateMutation.ExecutionInfo.WorkflowId,
   245  			updateMutation.ExecutionState.RunId,
   246  		)
   247  		return nil, err
   248  	default:
   249  		return nil, err
   250  	}
   251  }
   252  
   253  func (m *executionManagerImpl) ConflictResolveWorkflowExecution(
   254  	ctx context.Context,
   255  	request *ConflictResolveWorkflowExecutionRequest,
   256  ) (*ConflictResolveWorkflowExecutionResponse, error) {
   257  
   258  	resetSnapshot := request.ResetWorkflowSnapshot
   259  	newSnapshot := request.NewWorkflowSnapshot
   260  	currentMutation := request.CurrentWorkflowMutation
   261  
   262  	resetWorkflowXDCKVs, resetWorkflowEvents, resetWorkflowHistoryDiff, err := m.serializeWorkflowEventBatches(
   263  		ctx,
   264  		request.ShardID,
   265  		request.ResetWorkflowSnapshot.ExecutionInfo,
   266  		request.ResetWorkflowEvents,
   267  	)
   268  	if err != nil {
   269  		return nil, err
   270  	}
   271  	resetSnapshot.ExecutionInfo.ExecutionStats.HistorySize += int64(resetWorkflowHistoryDiff.SizeDiff)
   272  
   273  	var newWorkflowXDCKVs map[XDCCacheKey]XDCCacheValue
   274  	var newWorkflowEvents []*InternalAppendHistoryNodesRequest
   275  	var newWorkflowHistoryDiff *HistoryStatistics
   276  	if newSnapshot != nil {
   277  		newWorkflowXDCKVs, newWorkflowEvents, newWorkflowHistoryDiff, err = m.serializeWorkflowEventBatches(
   278  			ctx,
   279  			request.ShardID,
   280  			request.NewWorkflowSnapshot.ExecutionInfo,
   281  			request.NewWorkflowEvents,
   282  		)
   283  		if err != nil {
   284  			return nil, err
   285  		}
   286  		newSnapshot.ExecutionInfo.ExecutionStats.HistorySize += int64(newWorkflowHistoryDiff.SizeDiff)
   287  	}
   288  
   289  	var currentWorkflowXDCKVs map[XDCCacheKey]XDCCacheValue
   290  	var currentWorkflowEvents []*InternalAppendHistoryNodesRequest
   291  	var currentWorkflowHistoryDiff *HistoryStatistics
   292  	if currentMutation != nil {
   293  		currentWorkflowXDCKVs, currentWorkflowEvents, currentWorkflowHistoryDiff, err = m.serializeWorkflowEventBatches(
   294  			ctx,
   295  			request.ShardID,
   296  			request.CurrentWorkflowMutation.ExecutionInfo,
   297  			request.CurrentWorkflowEvents,
   298  		)
   299  		if err != nil {
   300  			return nil, err
   301  		}
   302  		currentMutation.ExecutionInfo.ExecutionStats.HistorySize += int64(currentWorkflowHistoryDiff.SizeDiff)
   303  	}
   304  
   305  	if err := ValidateConflictResolveWorkflowModeState(
   306  		request.Mode,
   307  		resetSnapshot,
   308  		newSnapshot,
   309  		currentMutation,
   310  	); err != nil {
   311  		return nil, err
   312  	}
   313  
   314  	serializedResetWorkflowSnapshot, err := m.SerializeWorkflowSnapshot(&resetSnapshot)
   315  	if err != nil {
   316  		return nil, err
   317  	}
   318  	var serializedCurrentWorkflowMutation *InternalWorkflowMutation
   319  	if currentMutation != nil {
   320  		serializedCurrentWorkflowMutation, err = m.SerializeWorkflowMutation(currentMutation)
   321  		if err != nil {
   322  			return nil, err
   323  		}
   324  	}
   325  	var serializedNewWorkflowMutation *InternalWorkflowSnapshot
   326  	if newSnapshot != nil {
   327  		serializedNewWorkflowMutation, err = m.SerializeWorkflowSnapshot(newSnapshot)
   328  		if err != nil {
   329  			return nil, err
   330  		}
   331  	}
   332  
   333  	newRequest := &InternalConflictResolveWorkflowExecutionRequest{
   334  		ShardID: request.ShardID,
   335  		RangeID: request.RangeID,
   336  
   337  		Mode: request.Mode,
   338  
   339  		ResetWorkflowSnapshot:        *serializedResetWorkflowSnapshot,
   340  		ResetWorkflowEventsNewEvents: resetWorkflowEvents,
   341  
   342  		NewWorkflowSnapshot:        serializedNewWorkflowMutation,
   343  		NewWorkflowEventsNewEvents: newWorkflowEvents,
   344  
   345  		CurrentWorkflowMutation:        serializedCurrentWorkflowMutation,
   346  		CurrentWorkflowEventsNewEvents: currentWorkflowEvents,
   347  	}
   348  
   349  	err = m.persistence.ConflictResolveWorkflowExecution(ctx, newRequest)
   350  	switch err.(type) {
   351  	case nil:
   352  		m.addXDCCacheKV(resetWorkflowXDCKVs)
   353  		m.addXDCCacheKV(newWorkflowXDCKVs)
   354  		m.addXDCCacheKV(currentWorkflowXDCKVs)
   355  		return &ConflictResolveWorkflowExecutionResponse{
   356  			ResetMutableStateStats: *statusOfInternalWorkflowSnapshot(
   357  				&newRequest.ResetWorkflowSnapshot,
   358  				resetWorkflowHistoryDiff,
   359  			),
   360  			NewMutableStateStats: statusOfInternalWorkflowSnapshot(
   361  				newRequest.NewWorkflowSnapshot,
   362  				newWorkflowHistoryDiff,
   363  			),
   364  			CurrentMutableStateStats: statusOfInternalWorkflowMutation(
   365  				newRequest.CurrentWorkflowMutation,
   366  				currentWorkflowHistoryDiff,
   367  			),
   368  		}, nil
   369  	case *CurrentWorkflowConditionFailedError,
   370  		*WorkflowConditionFailedError,
   371  		*ConditionFailedError:
   372  		m.trimHistoryNode(
   373  			ctx,
   374  			request.ShardID,
   375  			resetSnapshot.ExecutionInfo.NamespaceId,
   376  			resetSnapshot.ExecutionInfo.WorkflowId,
   377  			resetSnapshot.ExecutionState.RunId,
   378  		)
   379  		if currentMutation != nil {
   380  			m.trimHistoryNode(
   381  				ctx,
   382  				request.ShardID,
   383  				currentMutation.ExecutionInfo.NamespaceId,
   384  				currentMutation.ExecutionInfo.WorkflowId,
   385  				currentMutation.ExecutionState.RunId,
   386  			)
   387  		}
   388  		return nil, err
   389  	default:
   390  		return nil, err
   391  	}
   392  }
   393  
   394  func (m *executionManagerImpl) GetWorkflowExecution(
   395  	ctx context.Context,
   396  	request *GetWorkflowExecutionRequest,
   397  ) (*GetWorkflowExecutionResponse, error) {
   398  	response, respErr := m.persistence.GetWorkflowExecution(ctx, request)
   399  	if respErr != nil && response == nil {
   400  		// try to utilize resp as much as possible, for RebuildMutableState API
   401  		return nil, respErr
   402  	}
   403  	state, err := m.toWorkflowMutableState(response.State)
   404  	if err != nil {
   405  		return nil, err
   406  	}
   407  	if state.ExecutionInfo.ExecutionStats == nil {
   408  		state.ExecutionInfo.ExecutionStats = &persistencespb.ExecutionStats{
   409  			HistorySize: 0,
   410  		}
   411  	}
   412  
   413  	newResponse := &GetWorkflowExecutionResponse{
   414  		State:             state,
   415  		DBRecordVersion:   response.DBRecordVersion,
   416  		MutableStateStats: *statusOfInternalWorkflow(response.State, state, nil),
   417  	}
   418  	return newResponse, respErr
   419  }
   420  
   421  func (m *executionManagerImpl) SetWorkflowExecution(
   422  	ctx context.Context,
   423  	request *SetWorkflowExecutionRequest,
   424  ) (*SetWorkflowExecutionResponse, error) {
   425  	serializedWorkflowSnapshot, err := m.SerializeWorkflowSnapshot(&request.SetWorkflowSnapshot)
   426  	if err != nil {
   427  		return nil, err
   428  	}
   429  
   430  	newRequest := &InternalSetWorkflowExecutionRequest{
   431  		ShardID: request.ShardID,
   432  		RangeID: request.RangeID,
   433  
   434  		SetWorkflowSnapshot: *serializedWorkflowSnapshot,
   435  	}
   436  
   437  	err = m.persistence.SetWorkflowExecution(ctx, newRequest)
   438  	if err != nil {
   439  		return nil, err
   440  	}
   441  	return &SetWorkflowExecutionResponse{}, nil
   442  }
   443  
   444  func (m *executionManagerImpl) serializeWorkflowEventBatches(
   445  	ctx context.Context,
   446  	shardID int32,
   447  	executionInfo *persistencespb.WorkflowExecutionInfo,
   448  	eventBatches []*WorkflowEvents,
   449  ) (map[XDCCacheKey]XDCCacheValue, []*InternalAppendHistoryNodesRequest, *HistoryStatistics, error) {
   450  	var historyStatistics HistoryStatistics
   451  	if len(eventBatches) == 0 {
   452  		return nil, nil, &historyStatistics, nil
   453  	}
   454  
   455  	xdcKVs := make(map[XDCCacheKey]XDCCacheValue, len(eventBatches))
   456  	workflowNewEvents := make([]*InternalAppendHistoryNodesRequest, 0, len(eventBatches))
   457  	for _, workflowEvents := range eventBatches {
   458  		newEvents, err := m.serializeWorkflowEvents(ctx, shardID, workflowEvents)
   459  		if err != nil {
   460  			return nil, nil, nil, err
   461  		}
   462  		versionHistoryItems, _, baseWorkflowInfo, err := GetXDCCacheValue(
   463  			executionInfo,
   464  			workflowEvents.Events[0].EventId,
   465  			workflowEvents.Events[0].Version,
   466  		)
   467  		if err != nil {
   468  			return nil, nil, nil, err
   469  		}
   470  		xdcKVs[NewXDCCacheKey(
   471  			definition.NewWorkflowKey(workflowEvents.NamespaceID, workflowEvents.WorkflowID, workflowEvents.RunID),
   472  			workflowEvents.Events[0].EventId,
   473  			workflowEvents.Events[len(workflowEvents.Events)-1].EventId+1,
   474  			workflowEvents.Events[0].Version,
   475  		)] = NewXDCCacheValue(
   476  			baseWorkflowInfo,
   477  			versionHistoryItems,
   478  			newEvents.Node.Events,
   479  		)
   480  		newEvents.ShardID = shardID
   481  		workflowNewEvents = append(workflowNewEvents, newEvents)
   482  		historyStatistics.SizeDiff += len(newEvents.Node.Events.Data)
   483  		historyStatistics.CountDiff += len(workflowEvents.Events)
   484  	}
   485  	return xdcKVs, workflowNewEvents, &historyStatistics, nil
   486  }
   487  
   488  func (m *executionManagerImpl) addXDCCacheKV(
   489  	xdcKVs map[XDCCacheKey]XDCCacheValue,
   490  ) {
   491  	if m.eventBlobCache == nil {
   492  		return
   493  	}
   494  	for k, v := range xdcKVs {
   495  		m.eventBlobCache.Put(k, v)
   496  	}
   497  }
   498  
   499  func (m *executionManagerImpl) DeserializeBufferedEvents( // unexport
   500  	blobs []*commonpb.DataBlob,
   501  ) ([]*historypb.HistoryEvent, error) {
   502  
   503  	events := make([]*historypb.HistoryEvent, 0)
   504  	for _, b := range blobs {
   505  		if b == nil {
   506  			// Should not happen, log and discard to prevent callers from consuming
   507  			m.logger.Warn("discarding nil buffered event")
   508  			continue
   509  		}
   510  
   511  		history, err := m.serializer.DeserializeEvents(b)
   512  		if err != nil {
   513  			return nil, err
   514  		}
   515  		events = append(events, history...)
   516  	}
   517  	return events, nil
   518  }
   519  
   520  func (m *executionManagerImpl) serializeWorkflowEvents(
   521  	ctx context.Context,
   522  	shardID int32,
   523  	workflowEvents *WorkflowEvents,
   524  ) (*InternalAppendHistoryNodesRequest, error) {
   525  	if len(workflowEvents.Events) == 0 {
   526  		return nil, nil // allow update workflow without events
   527  	}
   528  
   529  	request := &AppendHistoryNodesRequest{
   530  		ShardID:           shardID,
   531  		BranchToken:       workflowEvents.BranchToken,
   532  		Events:            workflowEvents.Events,
   533  		PrevTransactionID: workflowEvents.PrevTxnID,
   534  		TransactionID:     workflowEvents.TxnID,
   535  	}
   536  
   537  	if workflowEvents.Events[0].EventId == common.FirstEventID {
   538  		request.IsNewBranch = true
   539  		request.Info = BuildHistoryGarbageCleanupInfo(workflowEvents.NamespaceID, workflowEvents.WorkflowID, workflowEvents.RunID)
   540  	}
   541  
   542  	return m.serializeAppendHistoryNodesRequest(ctx, request)
   543  }
   544  
   545  func (m *executionManagerImpl) SerializeWorkflowMutation( // unexport
   546  	input *WorkflowMutation,
   547  ) (*InternalWorkflowMutation, error) {
   548  
   549  	tasks, err := serializeTasks(m.serializer, input.Tasks)
   550  	if err != nil {
   551  		return nil, err
   552  	}
   553  
   554  	result := &InternalWorkflowMutation{
   555  		NamespaceID: input.ExecutionInfo.GetNamespaceId(),
   556  		WorkflowID:  input.ExecutionInfo.GetWorkflowId(),
   557  		RunID:       input.ExecutionState.GetRunId(),
   558  
   559  		UpsertActivityInfos: make(map[int64]*commonpb.DataBlob, len(input.UpsertActivityInfos)),
   560  		DeleteActivityInfos: input.DeleteActivityInfos,
   561  
   562  		UpsertTimerInfos: make(map[string]*commonpb.DataBlob, len(input.UpsertTimerInfos)),
   563  		DeleteTimerInfos: input.DeleteTimerInfos,
   564  
   565  		UpsertChildExecutionInfos: make(map[int64]*commonpb.DataBlob, len(input.UpsertChildExecutionInfos)),
   566  		DeleteChildExecutionInfos: input.DeleteChildExecutionInfos,
   567  
   568  		UpsertRequestCancelInfos: make(map[int64]*commonpb.DataBlob, len(input.UpsertRequestCancelInfos)),
   569  		DeleteRequestCancelInfos: input.DeleteRequestCancelInfos,
   570  
   571  		UpsertSignalInfos: make(map[int64]*commonpb.DataBlob, len(input.UpsertSignalInfos)),
   572  		DeleteSignalInfos: input.DeleteSignalInfos,
   573  
   574  		UpsertSignalRequestedIDs: input.UpsertSignalRequestedIDs,
   575  		DeleteSignalRequestedIDs: input.DeleteSignalRequestedIDs,
   576  
   577  		NewBufferedEvents:   nil,
   578  		ClearBufferedEvents: input.ClearBufferedEvents,
   579  
   580  		ExecutionInfo:  input.ExecutionInfo,
   581  		ExecutionState: input.ExecutionState,
   582  
   583  		Tasks: tasks,
   584  
   585  		Condition:       input.Condition,
   586  		DBRecordVersion: input.DBRecordVersion,
   587  		NextEventID:     input.NextEventID,
   588  	}
   589  
   590  	result.ExecutionInfoBlob, err = m.serializer.WorkflowExecutionInfoToBlob(input.ExecutionInfo, enumspb.ENCODING_TYPE_PROTO3)
   591  	if err != nil {
   592  		return nil, err
   593  	}
   594  	result.ExecutionStateBlob, err = m.serializer.WorkflowExecutionStateToBlob(input.ExecutionState, enumspb.ENCODING_TYPE_PROTO3)
   595  	if err != nil {
   596  		return nil, err
   597  	}
   598  
   599  	for key, info := range input.UpsertActivityInfos {
   600  		blob, err := m.serializer.ActivityInfoToBlob(info, enumspb.ENCODING_TYPE_PROTO3)
   601  		if err != nil {
   602  			return nil, err
   603  		}
   604  		result.UpsertActivityInfos[key] = blob
   605  	}
   606  
   607  	for key, info := range input.UpsertTimerInfos {
   608  		blob, err := m.serializer.TimerInfoToBlob(info, enumspb.ENCODING_TYPE_PROTO3)
   609  		if err != nil {
   610  			return nil, err
   611  		}
   612  		result.UpsertTimerInfos[key] = blob
   613  	}
   614  
   615  	for key, info := range input.UpsertChildExecutionInfos {
   616  		blob, err := m.serializer.ChildExecutionInfoToBlob(info, enumspb.ENCODING_TYPE_PROTO3)
   617  		if err != nil {
   618  			return nil, err
   619  		}
   620  		result.UpsertChildExecutionInfos[key] = blob
   621  	}
   622  
   623  	for key, info := range input.UpsertRequestCancelInfos {
   624  		blob, err := m.serializer.RequestCancelInfoToBlob(info, enumspb.ENCODING_TYPE_PROTO3)
   625  		if err != nil {
   626  			return nil, err
   627  		}
   628  		result.UpsertRequestCancelInfos[key] = blob
   629  	}
   630  
   631  	for key, info := range input.UpsertSignalInfos {
   632  		blob, err := m.serializer.SignalInfoToBlob(info, enumspb.ENCODING_TYPE_PROTO3)
   633  		if err != nil {
   634  			return nil, err
   635  		}
   636  		result.UpsertSignalInfos[key] = blob
   637  	}
   638  
   639  	if len(input.NewBufferedEvents) > 0 {
   640  		result.NewBufferedEvents, err = m.serializer.SerializeEvents(input.NewBufferedEvents, enumspb.ENCODING_TYPE_PROTO3)
   641  		if err != nil {
   642  			return nil, err
   643  		}
   644  	}
   645  
   646  	result.LastWriteVersion, err = getCurrentBranchLastWriteVersion(input.ExecutionInfo.VersionHistories)
   647  	if err != nil {
   648  		return nil, err
   649  	}
   650  	result.Checksum, err = m.serializer.ChecksumToBlob(input.Checksum, enumspb.ENCODING_TYPE_PROTO3)
   651  	if err != nil {
   652  		return nil, err
   653  	}
   654  
   655  	return result, nil
   656  }
   657  
   658  func (m *executionManagerImpl) SerializeWorkflowSnapshot( // unexport
   659  	input *WorkflowSnapshot,
   660  ) (*InternalWorkflowSnapshot, error) {
   661  
   662  	tasks, err := serializeTasks(m.serializer, input.Tasks)
   663  	if err != nil {
   664  		return nil, err
   665  	}
   666  
   667  	result := &InternalWorkflowSnapshot{
   668  		NamespaceID: input.ExecutionInfo.GetNamespaceId(),
   669  		WorkflowID:  input.ExecutionInfo.GetWorkflowId(),
   670  		RunID:       input.ExecutionState.GetRunId(),
   671  
   672  		ActivityInfos:       make(map[int64]*commonpb.DataBlob, len(input.ActivityInfos)),
   673  		TimerInfos:          make(map[string]*commonpb.DataBlob, len(input.TimerInfos)),
   674  		ChildExecutionInfos: make(map[int64]*commonpb.DataBlob, len(input.ChildExecutionInfos)),
   675  		RequestCancelInfos:  make(map[int64]*commonpb.DataBlob, len(input.RequestCancelInfos)),
   676  		SignalInfos:         make(map[int64]*commonpb.DataBlob, len(input.SignalInfos)),
   677  
   678  		ExecutionInfo:      input.ExecutionInfo,
   679  		ExecutionState:     input.ExecutionState,
   680  		SignalRequestedIDs: make(map[string]struct{}),
   681  
   682  		Tasks: tasks,
   683  
   684  		Condition:       input.Condition,
   685  		DBRecordVersion: input.DBRecordVersion,
   686  		NextEventID:     input.NextEventID,
   687  	}
   688  
   689  	result.ExecutionInfoBlob, err = m.serializer.WorkflowExecutionInfoToBlob(input.ExecutionInfo, enumspb.ENCODING_TYPE_PROTO3)
   690  	if err != nil {
   691  		return nil, err
   692  	}
   693  	result.ExecutionStateBlob, err = m.serializer.WorkflowExecutionStateToBlob(input.ExecutionState, enumspb.ENCODING_TYPE_PROTO3)
   694  	if err != nil {
   695  		return nil, err
   696  	}
   697  	result.LastWriteVersion, err = getCurrentBranchLastWriteVersion(input.ExecutionInfo.VersionHistories)
   698  	if err != nil {
   699  		return nil, err
   700  	}
   701  
   702  	for key, info := range input.ActivityInfos {
   703  		blob, err := m.serializer.ActivityInfoToBlob(info, enumspb.ENCODING_TYPE_PROTO3)
   704  		if err != nil {
   705  			return nil, err
   706  		}
   707  		result.ActivityInfos[key] = blob
   708  	}
   709  	for key, info := range input.TimerInfos {
   710  		blob, err := m.serializer.TimerInfoToBlob(info, enumspb.ENCODING_TYPE_PROTO3)
   711  		if err != nil {
   712  			return nil, err
   713  		}
   714  		result.TimerInfos[key] = blob
   715  	}
   716  	for key, info := range input.ChildExecutionInfos {
   717  		blob, err := m.serializer.ChildExecutionInfoToBlob(info, enumspb.ENCODING_TYPE_PROTO3)
   718  		if err != nil {
   719  			return nil, err
   720  		}
   721  		result.ChildExecutionInfos[key] = blob
   722  	}
   723  	for key, info := range input.RequestCancelInfos {
   724  		blob, err := m.serializer.RequestCancelInfoToBlob(info, enumspb.ENCODING_TYPE_PROTO3)
   725  		if err != nil {
   726  			return nil, err
   727  		}
   728  		result.RequestCancelInfos[key] = blob
   729  	}
   730  	for key, info := range input.SignalInfos {
   731  		blob, err := m.serializer.SignalInfoToBlob(info, enumspb.ENCODING_TYPE_PROTO3)
   732  		if err != nil {
   733  			return nil, err
   734  		}
   735  		result.SignalInfos[key] = blob
   736  	}
   737  	for key := range input.SignalRequestedIDs {
   738  		result.SignalRequestedIDs[key] = struct{}{}
   739  	}
   740  
   741  	result.Checksum, err = m.serializer.ChecksumToBlob(input.Checksum, enumspb.ENCODING_TYPE_PROTO3)
   742  	if err != nil {
   743  		return nil, err
   744  	}
   745  
   746  	return result, nil
   747  }
   748  
   749  func (m *executionManagerImpl) DeleteWorkflowExecution(
   750  	ctx context.Context,
   751  	request *DeleteWorkflowExecutionRequest,
   752  ) error {
   753  	return m.persistence.DeleteWorkflowExecution(ctx, request)
   754  }
   755  
   756  func (m *executionManagerImpl) DeleteCurrentWorkflowExecution(
   757  	ctx context.Context,
   758  	request *DeleteCurrentWorkflowExecutionRequest,
   759  ) error {
   760  	return m.persistence.DeleteCurrentWorkflowExecution(ctx, request)
   761  }
   762  
   763  func (m *executionManagerImpl) GetCurrentExecution(
   764  	ctx context.Context,
   765  	request *GetCurrentExecutionRequest,
   766  ) (*GetCurrentExecutionResponse, error) {
   767  	response, respErr := m.persistence.GetCurrentExecution(ctx, request)
   768  	if respErr != nil && response == nil {
   769  		// try to utilize resp as much as possible, for RebuildMutableState API
   770  		return nil, respErr
   771  	}
   772  
   773  	return &GetCurrentExecutionResponse{
   774  		RunID:          response.RunID,
   775  		StartRequestID: response.ExecutionState.CreateRequestId,
   776  		State:          response.ExecutionState.State,
   777  		Status:         response.ExecutionState.Status,
   778  	}, respErr
   779  }
   780  
   781  func (m *executionManagerImpl) ListConcreteExecutions(
   782  	ctx context.Context,
   783  	request *ListConcreteExecutionsRequest,
   784  ) (*ListConcreteExecutionsResponse, error) {
   785  	response, err := m.persistence.ListConcreteExecutions(ctx, request)
   786  	if err != nil {
   787  		return nil, err
   788  	}
   789  	newResponse := &ListConcreteExecutionsResponse{
   790  		States:    make([]*persistencespb.WorkflowMutableState, len(response.States)),
   791  		PageToken: response.NextPageToken,
   792  	}
   793  	for i, s := range response.States {
   794  		state, err := m.toWorkflowMutableState(s)
   795  		if err != nil {
   796  			return nil, err
   797  		}
   798  		newResponse.States[i] = state
   799  	}
   800  	return newResponse, nil
   801  }
   802  
   803  func (m *executionManagerImpl) RegisterHistoryTaskReader(
   804  	ctx context.Context,
   805  	request *RegisterHistoryTaskReaderRequest,
   806  ) error {
   807  	return m.persistence.RegisterHistoryTaskReader(ctx, request)
   808  }
   809  
   810  func (m *executionManagerImpl) UnregisterHistoryTaskReader(
   811  	ctx context.Context,
   812  	request *UnregisterHistoryTaskReaderRequest,
   813  ) {
   814  	m.persistence.UnregisterHistoryTaskReader(ctx, request)
   815  }
   816  
   817  func (m *executionManagerImpl) UpdateHistoryTaskReaderProgress(
   818  	ctx context.Context,
   819  	request *UpdateHistoryTaskReaderProgressRequest,
   820  ) {
   821  	m.persistence.UpdateHistoryTaskReaderProgress(ctx, request)
   822  }
   823  
   824  func (m *executionManagerImpl) AddHistoryTasks(
   825  	ctx context.Context,
   826  	input *AddHistoryTasksRequest,
   827  ) error {
   828  	tasks, err := serializeTasks(m.serializer, input.Tasks)
   829  	if err != nil {
   830  		return err
   831  	}
   832  
   833  	return m.persistence.AddHistoryTasks(ctx, &InternalAddHistoryTasksRequest{
   834  		ShardID: input.ShardID,
   835  		RangeID: input.RangeID,
   836  
   837  		NamespaceID: input.NamespaceID,
   838  		WorkflowID:  input.WorkflowID,
   839  		RunID:       input.RunID,
   840  
   841  		Tasks: tasks,
   842  	})
   843  }
   844  
   845  func (m *executionManagerImpl) GetHistoryTasks(
   846  	ctx context.Context,
   847  	request *GetHistoryTasksRequest,
   848  ) (*GetHistoryTasksResponse, error) {
   849  	if err := validateTaskRange(
   850  		request.TaskCategory.Type(),
   851  		request.InclusiveMinTaskKey,
   852  		request.ExclusiveMaxTaskKey,
   853  	); err != nil {
   854  		return nil, err
   855  	}
   856  
   857  	resp, err := m.persistence.GetHistoryTasks(ctx, request)
   858  	if err != nil {
   859  		return nil, err
   860  	}
   861  
   862  	historyTasks := make([]tasks.Task, 0, len(resp.Tasks))
   863  	for _, internalTask := range resp.Tasks {
   864  		task, err := m.serializer.DeserializeTask(request.TaskCategory, internalTask.Blob)
   865  		if err != nil {
   866  			return nil, err
   867  		}
   868  
   869  		if !internalTask.Key.FireTime.Equal(tasks.DefaultFireTime) {
   870  			task.SetVisibilityTime(internalTask.Key.FireTime)
   871  		}
   872  		task.SetTaskID(internalTask.Key.TaskID)
   873  
   874  		historyTasks = append(historyTasks, task)
   875  	}
   876  
   877  	return &GetHistoryTasksResponse{
   878  		Tasks:         historyTasks,
   879  		NextPageToken: resp.NextPageToken,
   880  	}, nil
   881  }
   882  
   883  func (m *executionManagerImpl) CompleteHistoryTask(
   884  	ctx context.Context,
   885  	request *CompleteHistoryTaskRequest,
   886  ) error {
   887  	return m.persistence.CompleteHistoryTask(ctx, request)
   888  }
   889  
   890  func (m *executionManagerImpl) RangeCompleteHistoryTasks(
   891  	ctx context.Context,
   892  	request *RangeCompleteHistoryTasksRequest,
   893  ) error {
   894  	if err := validateTaskRange(
   895  		request.TaskCategory.Type(),
   896  		request.InclusiveMinTaskKey,
   897  		request.ExclusiveMaxTaskKey,
   898  	); err != nil {
   899  		return err
   900  	}
   901  
   902  	return m.persistence.RangeCompleteHistoryTasks(ctx, request)
   903  }
   904  
   905  func (m *executionManagerImpl) PutReplicationTaskToDLQ(
   906  	ctx context.Context,
   907  	request *PutReplicationTaskToDLQRequest,
   908  ) error {
   909  	return m.persistence.PutReplicationTaskToDLQ(ctx, request)
   910  }
   911  
   912  func (m *executionManagerImpl) GetReplicationTasksFromDLQ(
   913  	ctx context.Context,
   914  	request *GetReplicationTasksFromDLQRequest,
   915  ) (*GetHistoryTasksResponse, error) {
   916  	resp, err := m.persistence.GetReplicationTasksFromDLQ(ctx, request)
   917  	if err != nil {
   918  		return nil, err
   919  	}
   920  
   921  	category := tasks.CategoryReplication
   922  	dlqTasks := make([]tasks.Task, 0, len(resp.Tasks))
   923  	for i := range resp.Tasks {
   924  		internalTask := resp.Tasks[i]
   925  		task, err := m.serializer.DeserializeTask(category, internalTask.Blob)
   926  		if err != nil {
   927  			return nil, err
   928  		}
   929  
   930  		if !internalTask.Key.FireTime.Equal(tasks.DefaultFireTime) {
   931  			task.SetVisibilityTime(internalTask.Key.FireTime)
   932  		}
   933  		task.SetTaskID(internalTask.Key.TaskID)
   934  
   935  		dlqTasks = append(dlqTasks, task)
   936  	}
   937  
   938  	return &GetHistoryTasksResponse{
   939  		Tasks:         dlqTasks,
   940  		NextPageToken: resp.NextPageToken,
   941  	}, nil
   942  }
   943  
   944  func (m *executionManagerImpl) DeleteReplicationTaskFromDLQ(
   945  	ctx context.Context,
   946  	request *DeleteReplicationTaskFromDLQRequest,
   947  ) error {
   948  	return m.persistence.DeleteReplicationTaskFromDLQ(ctx, request)
   949  }
   950  
   951  func (m *executionManagerImpl) RangeDeleteReplicationTaskFromDLQ(
   952  	ctx context.Context,
   953  	request *RangeDeleteReplicationTaskFromDLQRequest,
   954  ) error {
   955  	return m.persistence.RangeDeleteReplicationTaskFromDLQ(ctx, request)
   956  }
   957  
   958  func (m *executionManagerImpl) IsReplicationDLQEmpty(
   959  	ctx context.Context,
   960  	request *GetReplicationTasksFromDLQRequest,
   961  ) (bool, error) {
   962  	return m.persistence.IsReplicationDLQEmpty(ctx, request)
   963  }
   964  
   965  func (m *executionManagerImpl) Close() {
   966  	m.persistence.Close()
   967  }
   968  
   969  func (m *executionManagerImpl) trimHistoryNode(
   970  	ctx context.Context,
   971  	shardID int32,
   972  	namespaceID string,
   973  	workflowID string,
   974  	runID string,
   975  ) {
   976  	response, err := m.GetWorkflowExecution(ctx, &GetWorkflowExecutionRequest{
   977  		ShardID:     shardID,
   978  		NamespaceID: namespaceID,
   979  		WorkflowID:  workflowID,
   980  		RunID:       runID,
   981  	})
   982  	if err != nil {
   983  		m.logger.Error("ExecutionManager unable to get mutable state for trimming history branch",
   984  			tag.WorkflowNamespaceID(namespaceID),
   985  			tag.WorkflowID(workflowID),
   986  			tag.WorkflowRunID(runID),
   987  			tag.Error(err),
   988  		)
   989  		return // best effort trim
   990  	}
   991  
   992  	executionInfo := response.State.ExecutionInfo
   993  	branchToken, err := getCurrentBranchToken(executionInfo.VersionHistories)
   994  	if err != nil {
   995  		return
   996  	}
   997  	mutableStateLastNodeID := executionInfo.LastFirstEventId
   998  	mutableStateLastNodeTransactionID := executionInfo.LastFirstEventTxnId
   999  	if _, err := m.TrimHistoryBranch(ctx, &TrimHistoryBranchRequest{
  1000  		ShardID:       shardID,
  1001  		BranchToken:   branchToken,
  1002  		NodeID:        mutableStateLastNodeID,
  1003  		TransactionID: mutableStateLastNodeTransactionID,
  1004  	}); err != nil {
  1005  		// best effort trim
  1006  		m.logger.Error("ExecutionManager unable to trim history branch",
  1007  			tag.WorkflowNamespaceID(namespaceID),
  1008  			tag.WorkflowID(workflowID),
  1009  			tag.WorkflowRunID(runID),
  1010  			tag.Error(err),
  1011  		)
  1012  		return
  1013  	}
  1014  }
  1015  
  1016  func (m *executionManagerImpl) toWorkflowMutableState(internState *InternalWorkflowMutableState) (*persistencespb.WorkflowMutableState, error) {
  1017  	state := &persistencespb.WorkflowMutableState{
  1018  		ActivityInfos:       make(map[int64]*persistencespb.ActivityInfo),
  1019  		TimerInfos:          make(map[string]*persistencespb.TimerInfo),
  1020  		ChildExecutionInfos: make(map[int64]*persistencespb.ChildExecutionInfo),
  1021  		RequestCancelInfos:  make(map[int64]*persistencespb.RequestCancelInfo),
  1022  		SignalInfos:         make(map[int64]*persistencespb.SignalInfo),
  1023  		SignalRequestedIds:  internState.SignalRequestedIDs,
  1024  		NextEventId:         internState.NextEventID,
  1025  		BufferedEvents:      make([]*historypb.HistoryEvent, len(internState.BufferedEvents)),
  1026  	}
  1027  	for key, blob := range internState.ActivityInfos {
  1028  		info, err := m.serializer.ActivityInfoFromBlob(blob)
  1029  		if err != nil {
  1030  			return nil, err
  1031  		}
  1032  		state.ActivityInfos[key] = info
  1033  	}
  1034  	for key, blob := range internState.TimerInfos {
  1035  		info, err := m.serializer.TimerInfoFromBlob(blob)
  1036  		if err != nil {
  1037  			return nil, err
  1038  		}
  1039  		state.TimerInfos[key] = info
  1040  	}
  1041  	for key, blob := range internState.ChildExecutionInfos {
  1042  		info, err := m.serializer.ChildExecutionInfoFromBlob(blob)
  1043  		if err != nil {
  1044  			return nil, err
  1045  		}
  1046  		state.ChildExecutionInfos[key] = info
  1047  	}
  1048  	for key, blob := range internState.RequestCancelInfos {
  1049  		info, err := m.serializer.RequestCancelInfoFromBlob(blob)
  1050  		if err != nil {
  1051  			return nil, err
  1052  		}
  1053  		state.RequestCancelInfos[key] = info
  1054  	}
  1055  	for key, blob := range internState.SignalInfos {
  1056  		info, err := m.serializer.SignalInfoFromBlob(blob)
  1057  		if err != nil {
  1058  			return nil, err
  1059  		}
  1060  		state.SignalInfos[key] = info
  1061  	}
  1062  	var err error
  1063  	state.ExecutionInfo, err = m.serializer.WorkflowExecutionInfoFromBlob(internState.ExecutionInfo)
  1064  	if err != nil {
  1065  		return nil, err
  1066  	}
  1067  	if state.ExecutionInfo.AutoResetPoints == nil {
  1068  		// TODO: check if we need this?
  1069  		state.ExecutionInfo.AutoResetPoints = &workflowpb.ResetPoints{}
  1070  	}
  1071  	state.ExecutionState, err = m.serializer.WorkflowExecutionStateFromBlob(internState.ExecutionState)
  1072  	if err != nil {
  1073  		return nil, err
  1074  	}
  1075  	state.BufferedEvents, err = m.DeserializeBufferedEvents(internState.BufferedEvents)
  1076  	if err != nil {
  1077  		return nil, err
  1078  	}
  1079  	if internState.Checksum != nil {
  1080  		state.Checksum, err = m.serializer.ChecksumFromBlob(internState.Checksum)
  1081  	}
  1082  	if err != nil {
  1083  		return nil, err
  1084  	}
  1085  
  1086  	return state, nil
  1087  }
  1088  
  1089  func getCurrentBranchToken(
  1090  	versionHistories *historyspb.VersionHistories,
  1091  ) ([]byte, error) {
  1092  	// TODO remove this if check once legacy execution tests are removed
  1093  	if versionHistories == nil {
  1094  		return nil, serviceerror.NewInternal("version history is empty")
  1095  	}
  1096  	versionHistory, err := versionhistory.GetCurrentVersionHistory(versionHistories)
  1097  	if err != nil {
  1098  		return nil, err
  1099  	}
  1100  	return versionHistory.BranchToken, nil
  1101  }
  1102  
  1103  func getCurrentBranchLastWriteVersion(
  1104  	versionHistories *historyspb.VersionHistories,
  1105  ) (int64, error) {
  1106  	// TODO remove this if check once legacy execution tests are removed
  1107  	if versionHistories == nil {
  1108  		return common.EmptyVersion, nil
  1109  	}
  1110  	versionHistory, err := versionhistory.GetCurrentVersionHistory(versionHistories)
  1111  	if err != nil {
  1112  		return 0, err
  1113  	}
  1114  	versionHistoryItem, err := versionhistory.GetLastVersionHistoryItem(versionHistory)
  1115  	if err != nil {
  1116  		return 0, err
  1117  	}
  1118  	return versionHistoryItem.GetVersion(), nil
  1119  }
  1120  
  1121  func serializeTasks(
  1122  	serializer serialization.Serializer,
  1123  	inputTasks map[tasks.Category][]tasks.Task,
  1124  ) (map[tasks.Category][]InternalHistoryTask, error) {
  1125  	outputTasks := make(map[tasks.Category][]InternalHistoryTask)
  1126  	for category, tasks := range inputTasks {
  1127  		serializedTasks := make([]InternalHistoryTask, 0, len(tasks))
  1128  		for _, task := range tasks {
  1129  			blob, err := serializer.SerializeTask(task)
  1130  			if err != nil {
  1131  				return nil, err
  1132  			}
  1133  			serializedTasks = append(serializedTasks, InternalHistoryTask{
  1134  				Key:  task.GetKey(),
  1135  				Blob: blob,
  1136  			})
  1137  		}
  1138  		outputTasks[category] = serializedTasks
  1139  	}
  1140  	return outputTasks, nil
  1141  }
  1142  
  1143  func validateTaskRange(
  1144  	taskCategoryType tasks.CategoryType,
  1145  	minTaskKey tasks.Key,
  1146  	maxTaskKey tasks.Key,
  1147  ) error {
  1148  	minTaskIDSpecified := minTaskKey.TaskID != 0
  1149  	minFireTimeSpecified := !minTaskKey.FireTime.IsZero() && !minTaskKey.FireTime.Equal(tasks.DefaultFireTime)
  1150  	maxTaskIDSpecified := maxTaskKey.TaskID != 0
  1151  	maxFireTimeSpecified := !maxTaskKey.FireTime.IsZero() && !maxTaskKey.FireTime.Equal(tasks.DefaultFireTime)
  1152  
  1153  	switch taskCategoryType {
  1154  	case tasks.CategoryTypeImmediate:
  1155  		if !maxTaskIDSpecified {
  1156  			return serviceerror.NewInvalidArgument("invalid task range, max taskID must be specified for immediate task category")
  1157  		}
  1158  		if minFireTimeSpecified || maxFireTimeSpecified {
  1159  			return serviceerror.NewInvalidArgument("invalid task range, fireTime must be empty for immediate task category")
  1160  		}
  1161  	case tasks.CategoryTypeScheduled:
  1162  		if !maxFireTimeSpecified {
  1163  			return serviceerror.NewInvalidArgument("invalid task range, max fire time must be specified for scheduled task category")
  1164  		}
  1165  		if minTaskIDSpecified || maxTaskIDSpecified {
  1166  			return serviceerror.NewInvalidArgument("invalid task range, taskID must be empty for scheduled task category")
  1167  		}
  1168  	default:
  1169  		return serviceerror.NewInvalidArgument(fmt.Sprintf("invalid task category type: %v", taskCategoryType))
  1170  	}
  1171  
  1172  	return nil
  1173  }