go.temporal.io/server@v1.23.0/common/persistence/cassandra/mutable_state_task_store.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 cassandra
    26  
    27  import (
    28  	"context"
    29  	"fmt"
    30  	"time"
    31  
    32  	"go.temporal.io/api/serviceerror"
    33  
    34  	"go.temporal.io/server/common/log"
    35  	p "go.temporal.io/server/common/persistence"
    36  	"go.temporal.io/server/common/persistence/nosql/nosqlplugin/cassandra/gocql"
    37  	"go.temporal.io/server/common/persistence/serialization"
    38  	"go.temporal.io/server/service/history/tasks"
    39  )
    40  
    41  const (
    42  	templateCreateTransferTaskQuery = `INSERT INTO executions (` +
    43  		`shard_id, type, namespace_id, workflow_id, run_id, transfer, transfer_encoding, visibility_ts, task_id) ` +
    44  		`VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)`
    45  
    46  	templateCreateReplicationTaskQuery = `INSERT INTO executions (` +
    47  		`shard_id, type, namespace_id, workflow_id, run_id, replication, replication_encoding, visibility_ts, task_id) ` +
    48  		`VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)`
    49  
    50  	templateCreateVisibilityTaskQuery = `INSERT INTO executions (` +
    51  		`shard_id, type, namespace_id, workflow_id, run_id, visibility_task_data, visibility_task_encoding, visibility_ts, task_id) ` +
    52  		`VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)`
    53  
    54  	templateCreateTimerTaskQuery = `INSERT INTO executions (` +
    55  		`shard_id, type, namespace_id, workflow_id, run_id, timer, timer_encoding, visibility_ts, task_id) ` +
    56  		`VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)`
    57  
    58  	templateCreateHistoryTaskQuery = `INSERT INTO executions (` +
    59  		`shard_id, type, namespace_id, workflow_id, run_id, task_data, task_encoding, visibility_ts, task_id) ` +
    60  		`VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)`
    61  
    62  	templateGetHistoryImmediateTasksQuery = `SELECT task_id, task_data, task_encoding ` +
    63  		`FROM executions ` +
    64  		`WHERE shard_id = ? ` +
    65  		`and type = ? ` +
    66  		`and namespace_id = ? ` +
    67  		`and workflow_id = ? ` +
    68  		`and run_id = ? ` +
    69  		`and visibility_ts = ? ` +
    70  		`and task_id >= ? ` +
    71  		`and task_id < ?`
    72  
    73  	templateGetHistoryScheduledTasksQuery = `SELECT visibility_ts, task_id, task_data, task_encoding ` +
    74  		`FROM executions ` +
    75  		`WHERE shard_id = ? ` +
    76  		`and type = ?` +
    77  		`and namespace_id = ? ` +
    78  		`and workflow_id = ?` +
    79  		`and run_id = ?` +
    80  		`and visibility_ts >= ? ` +
    81  		`and visibility_ts < ?`
    82  
    83  	templateGetTransferTasksQuery = `SELECT task_id, transfer, transfer_encoding ` +
    84  		`FROM executions ` +
    85  		`WHERE shard_id = ? ` +
    86  		`and type = ? ` +
    87  		`and namespace_id = ? ` +
    88  		`and workflow_id = ? ` +
    89  		`and run_id = ? ` +
    90  		`and visibility_ts = ? ` +
    91  		`and task_id >= ? ` +
    92  		`and task_id < ?`
    93  
    94  	templateGetVisibilityTasksQuery = `SELECT task_id, visibility_task_data, visibility_task_encoding ` +
    95  		`FROM executions ` +
    96  		`WHERE shard_id = ? ` +
    97  		`and type = ? ` +
    98  		`and namespace_id = ? ` +
    99  		`and workflow_id = ? ` +
   100  		`and run_id = ? ` +
   101  		`and visibility_ts = ? ` +
   102  		`and task_id >= ? ` +
   103  		`and task_id < ?`
   104  
   105  	templateGetReplicationTasksQuery = `SELECT task_id, replication, replication_encoding ` +
   106  		`FROM executions ` +
   107  		`WHERE shard_id = ? ` +
   108  		`and type = ? ` +
   109  		`and namespace_id = ? ` +
   110  		`and workflow_id = ? ` +
   111  		`and run_id = ? ` +
   112  		`and visibility_ts = ? ` +
   113  		`and task_id >= ? ` +
   114  		`and task_id < ?`
   115  
   116  	templateIsQueueEmptyQuery = `SELECT task_id ` +
   117  		`FROM executions ` +
   118  		`WHERE shard_id = ? ` +
   119  		`and type = ? ` +
   120  		`and namespace_id = ? ` +
   121  		`and workflow_id = ? ` +
   122  		`and run_id = ? ` +
   123  		`and visibility_ts = ? ` +
   124  		`and task_id >= ? ` +
   125  		`limit 1`
   126  
   127  	templateCompleteTransferTaskQuery = `DELETE FROM executions ` +
   128  		`WHERE shard_id = ? ` +
   129  		`and type = ? ` +
   130  		`and namespace_id = ? ` +
   131  		`and workflow_id = ? ` +
   132  		`and run_id = ? ` +
   133  		`and visibility_ts = ? ` +
   134  		`and task_id = ?`
   135  
   136  	templateRangeCompleteTransferTaskQuery = `DELETE FROM executions ` +
   137  		`WHERE shard_id = ? ` +
   138  		`and type = ? ` +
   139  		`and namespace_id = ? ` +
   140  		`and workflow_id = ? ` +
   141  		`and run_id = ? ` +
   142  		`and visibility_ts = ? ` +
   143  		`and task_id >= ? ` +
   144  		`and task_id < ?`
   145  
   146  	templateCompleteVisibilityTaskQuery = templateCompleteTransferTaskQuery
   147  
   148  	templateRangeCompleteVisibilityTaskQuery = templateRangeCompleteTransferTaskQuery
   149  
   150  	templateCompleteReplicationTaskQuery = templateCompleteTransferTaskQuery
   151  
   152  	templateRangeCompleteReplicationTaskQuery = templateRangeCompleteTransferTaskQuery
   153  
   154  	templateCompleteHistoryTaskQuery = templateCompleteTransferTaskQuery
   155  
   156  	templateRangeCompleteHistoryImmediateTasksQuery = templateRangeCompleteTransferTaskQuery
   157  
   158  	templateRangeCompleteHistoryScheduledTasksQuery = templateRangeCompleteTimerTaskQuery
   159  
   160  	templateGetTimerTasksQuery = `SELECT visibility_ts, task_id, timer, timer_encoding ` +
   161  		`FROM executions ` +
   162  		`WHERE shard_id = ? ` +
   163  		`and type = ?` +
   164  		`and namespace_id = ? ` +
   165  		`and workflow_id = ?` +
   166  		`and run_id = ?` +
   167  		`and visibility_ts >= ? ` +
   168  		`and visibility_ts < ?`
   169  
   170  	templateCompleteTimerTaskQuery = `DELETE FROM executions ` +
   171  		`WHERE shard_id = ? ` +
   172  		`and type = ? ` +
   173  		`and namespace_id = ? ` +
   174  		`and workflow_id = ?` +
   175  		`and run_id = ?` +
   176  		`and visibility_ts = ? ` +
   177  		`and task_id = ?`
   178  
   179  	templateRangeCompleteTimerTaskQuery = `DELETE FROM executions ` +
   180  		`WHERE shard_id = ? ` +
   181  		`and type = ? ` +
   182  		`and namespace_id = ? ` +
   183  		`and workflow_id = ?` +
   184  		`and run_id = ?` +
   185  		`and visibility_ts >= ? ` +
   186  		`and visibility_ts < ?`
   187  )
   188  
   189  type (
   190  	MutableStateTaskStore struct {
   191  		Session gocql.Session
   192  		Logger  log.Logger
   193  	}
   194  )
   195  
   196  func NewMutableStateTaskStore(
   197  	session gocql.Session,
   198  	logger log.Logger,
   199  ) *MutableStateTaskStore {
   200  	return &MutableStateTaskStore{
   201  		Session: session,
   202  		Logger:  logger,
   203  	}
   204  }
   205  
   206  func (d *MutableStateTaskStore) RegisterHistoryTaskReader(
   207  	_ context.Context,
   208  	_ *p.RegisterHistoryTaskReaderRequest,
   209  ) error {
   210  	// no-op
   211  	return nil
   212  }
   213  
   214  func (d *MutableStateTaskStore) UnregisterHistoryTaskReader(
   215  	_ context.Context,
   216  	_ *p.UnregisterHistoryTaskReaderRequest,
   217  ) {
   218  	// no-op
   219  }
   220  
   221  func (d *MutableStateTaskStore) UpdateHistoryTaskReaderProgress(
   222  	_ context.Context,
   223  	_ *p.UpdateHistoryTaskReaderProgressRequest,
   224  ) {
   225  	// no-op
   226  }
   227  
   228  func (d *MutableStateTaskStore) AddHistoryTasks(
   229  	ctx context.Context,
   230  	request *p.InternalAddHistoryTasksRequest,
   231  ) error {
   232  	batch := d.Session.NewBatch(gocql.LoggedBatch).WithContext(ctx)
   233  
   234  	if err := applyTasks(
   235  		batch,
   236  		request.ShardID,
   237  		request.Tasks,
   238  	); err != nil {
   239  		return err
   240  	}
   241  
   242  	batch.Query(templateUpdateLeaseQuery,
   243  		request.RangeID,
   244  		request.ShardID,
   245  		rowTypeShard,
   246  		rowTypeShardNamespaceID,
   247  		rowTypeShardWorkflowID,
   248  		rowTypeShardRunID,
   249  		defaultVisibilityTimestamp,
   250  		rowTypeShardTaskID,
   251  		request.RangeID,
   252  	)
   253  
   254  	previous := make(map[string]interface{})
   255  	applied, iter, err := d.Session.MapExecuteBatchCAS(batch, previous)
   256  	if err != nil {
   257  		return gocql.ConvertError("AddTasks", err)
   258  	}
   259  	defer func() {
   260  		_ = iter.Close()
   261  	}()
   262  
   263  	if !applied {
   264  		if previousRangeID, ok := previous["range_id"].(int64); ok && previousRangeID != request.RangeID {
   265  			// CreateWorkflowExecution failed because rangeID was modified
   266  			return &p.ShardOwnershipLostError{
   267  				ShardID: request.ShardID,
   268  				Msg:     fmt.Sprintf("Failed to add tasks.  Request RangeID: %v, Actual RangeID: %v", request.RangeID, previousRangeID),
   269  			}
   270  		} else {
   271  			return serviceerror.NewUnavailable("AddTasks operation failed: %v")
   272  		}
   273  	}
   274  	return nil
   275  }
   276  
   277  func (d *MutableStateTaskStore) GetHistoryTasks(
   278  	ctx context.Context,
   279  	request *p.GetHistoryTasksRequest,
   280  ) (*p.InternalGetHistoryTasksResponse, error) {
   281  	switch request.TaskCategory.ID() {
   282  	case tasks.CategoryIDTransfer:
   283  		return d.getTransferTasks(ctx, request)
   284  	case tasks.CategoryIDTimer:
   285  		return d.getTimerTasks(ctx, request)
   286  	case tasks.CategoryIDVisibility:
   287  		return d.getVisibilityTasks(ctx, request)
   288  	case tasks.CategoryIDReplication:
   289  		return d.getReplicationTasks(ctx, request)
   290  	default:
   291  		return d.getHistoryTasks(ctx, request)
   292  	}
   293  }
   294  
   295  func (d *MutableStateTaskStore) CompleteHistoryTask(
   296  	ctx context.Context,
   297  	request *p.CompleteHistoryTaskRequest,
   298  ) error {
   299  	switch request.TaskCategory.ID() {
   300  	case tasks.CategoryIDTransfer:
   301  		return d.completeTransferTask(ctx, request)
   302  	case tasks.CategoryIDTimer:
   303  		return d.completeTimerTask(ctx, request)
   304  	case tasks.CategoryIDVisibility:
   305  		return d.completeVisibilityTask(ctx, request)
   306  	case tasks.CategoryIDReplication:
   307  		return d.completeReplicationTask(ctx, request)
   308  	default:
   309  		return d.completeHistoryTask(ctx, request)
   310  	}
   311  }
   312  
   313  func (d *MutableStateTaskStore) RangeCompleteHistoryTasks(
   314  	ctx context.Context,
   315  	request *p.RangeCompleteHistoryTasksRequest,
   316  ) error {
   317  	switch request.TaskCategory.ID() {
   318  	case tasks.CategoryIDTransfer:
   319  		return d.rangeCompleteTransferTasks(ctx, request)
   320  	case tasks.CategoryIDTimer:
   321  		return d.rangeCompleteTimerTasks(ctx, request)
   322  	case tasks.CategoryIDVisibility:
   323  		return d.rangeCompleteVisibilityTasks(ctx, request)
   324  	case tasks.CategoryIDReplication:
   325  		return d.rangeCompleteReplicationTasks(ctx, request)
   326  	default:
   327  		return d.rangeCompleteHistoryTasks(ctx, request)
   328  	}
   329  }
   330  
   331  func (d *MutableStateTaskStore) getTransferTasks(
   332  	ctx context.Context,
   333  	request *p.GetHistoryTasksRequest,
   334  ) (*p.InternalGetHistoryTasksResponse, error) {
   335  
   336  	// Reading transfer tasks need to be quorum level consistent, otherwise we could lose task
   337  	query := d.Session.Query(templateGetTransferTasksQuery,
   338  		request.ShardID,
   339  		rowTypeTransferTask,
   340  		rowTypeTransferNamespaceID,
   341  		rowTypeTransferWorkflowID,
   342  		rowTypeTransferRunID,
   343  		defaultVisibilityTimestamp,
   344  		request.InclusiveMinTaskKey.TaskID,
   345  		request.ExclusiveMaxTaskKey.TaskID,
   346  	).WithContext(ctx)
   347  	iter := query.PageSize(request.BatchSize).PageState(request.NextPageToken).Iter()
   348  
   349  	response := &p.InternalGetHistoryTasksResponse{}
   350  	var taskID int64
   351  	var data []byte
   352  	var encoding string
   353  
   354  	for iter.Scan(&taskID, &data, &encoding) {
   355  		response.Tasks = append(response.Tasks, p.InternalHistoryTask{
   356  			Key:  tasks.NewImmediateKey(taskID),
   357  			Blob: p.NewDataBlob(data, encoding),
   358  		})
   359  
   360  		taskID = 0
   361  		data = nil
   362  		encoding = ""
   363  	}
   364  	if len(iter.PageState()) > 0 {
   365  		response.NextPageToken = iter.PageState()
   366  	}
   367  
   368  	if err := iter.Close(); err != nil {
   369  		return nil, gocql.ConvertError("GetTransferTasks", err)
   370  	}
   371  
   372  	return response, nil
   373  }
   374  
   375  func (d *MutableStateTaskStore) completeTransferTask(
   376  	ctx context.Context,
   377  	request *p.CompleteHistoryTaskRequest,
   378  ) error {
   379  	query := d.Session.Query(templateCompleteTransferTaskQuery,
   380  		request.ShardID,
   381  		rowTypeTransferTask,
   382  		rowTypeTransferNamespaceID,
   383  		rowTypeTransferWorkflowID,
   384  		rowTypeTransferRunID,
   385  		defaultVisibilityTimestamp,
   386  		request.TaskKey.TaskID,
   387  	).WithContext(ctx)
   388  
   389  	err := query.Exec()
   390  	return gocql.ConvertError("CompleteTransferTask", err)
   391  }
   392  
   393  func (d *MutableStateTaskStore) rangeCompleteTransferTasks(
   394  	ctx context.Context,
   395  	request *p.RangeCompleteHistoryTasksRequest,
   396  ) error {
   397  	query := d.Session.Query(templateRangeCompleteTransferTaskQuery,
   398  		request.ShardID,
   399  		rowTypeTransferTask,
   400  		rowTypeTransferNamespaceID,
   401  		rowTypeTransferWorkflowID,
   402  		rowTypeTransferRunID,
   403  		defaultVisibilityTimestamp,
   404  		request.InclusiveMinTaskKey.TaskID,
   405  		request.ExclusiveMaxTaskKey.TaskID,
   406  	).WithContext(ctx)
   407  
   408  	err := query.Exec()
   409  	return gocql.ConvertError("RangeCompleteTransferTask", err)
   410  }
   411  
   412  func (d *MutableStateTaskStore) getTimerTasks(
   413  	ctx context.Context,
   414  	request *p.GetHistoryTasksRequest,
   415  ) (*p.InternalGetHistoryTasksResponse, error) {
   416  	// Reading timer tasks need to be quorum level consistent, otherwise we could lose tasks
   417  	minTimestamp := p.UnixMilliseconds(request.InclusiveMinTaskKey.FireTime)
   418  	maxTimestamp := p.UnixMilliseconds(request.ExclusiveMaxTaskKey.FireTime)
   419  	query := d.Session.Query(templateGetTimerTasksQuery,
   420  		request.ShardID,
   421  		rowTypeTimerTask,
   422  		rowTypeTimerNamespaceID,
   423  		rowTypeTimerWorkflowID,
   424  		rowTypeTimerRunID,
   425  		minTimestamp,
   426  		maxTimestamp,
   427  	).WithContext(ctx)
   428  	iter := query.PageSize(request.BatchSize).PageState(request.NextPageToken).Iter()
   429  
   430  	response := &p.InternalGetHistoryTasksResponse{}
   431  	var timestamp time.Time
   432  	var taskID int64
   433  	var data []byte
   434  	var encoding string
   435  
   436  	for iter.Scan(&timestamp, &taskID, &data, &encoding) {
   437  		response.Tasks = append(response.Tasks, p.InternalHistoryTask{
   438  			Key:  tasks.NewKey(timestamp, taskID),
   439  			Blob: p.NewDataBlob(data, encoding),
   440  		})
   441  
   442  		timestamp = time.Time{}
   443  		taskID = 0
   444  		data = nil
   445  		encoding = ""
   446  	}
   447  	if len(iter.PageState()) > 0 {
   448  		response.NextPageToken = iter.PageState()
   449  	}
   450  
   451  	if err := iter.Close(); err != nil {
   452  		return nil, gocql.ConvertError("GetTimerTasks", err)
   453  	}
   454  
   455  	return response, nil
   456  }
   457  
   458  func (d *MutableStateTaskStore) completeTimerTask(
   459  	ctx context.Context,
   460  	request *p.CompleteHistoryTaskRequest,
   461  ) error {
   462  	ts := p.UnixMilliseconds(request.TaskKey.FireTime)
   463  	query := d.Session.Query(templateCompleteTimerTaskQuery,
   464  		request.ShardID,
   465  		rowTypeTimerTask,
   466  		rowTypeTimerNamespaceID,
   467  		rowTypeTimerWorkflowID,
   468  		rowTypeTimerRunID,
   469  		ts,
   470  		request.TaskKey.TaskID,
   471  	).WithContext(ctx)
   472  
   473  	err := query.Exec()
   474  	return gocql.ConvertError("CompleteTimerTask", err)
   475  }
   476  
   477  func (d *MutableStateTaskStore) rangeCompleteTimerTasks(
   478  	ctx context.Context,
   479  	request *p.RangeCompleteHistoryTasksRequest,
   480  ) error {
   481  	start := p.UnixMilliseconds(request.InclusiveMinTaskKey.FireTime)
   482  	end := p.UnixMilliseconds(request.ExclusiveMaxTaskKey.FireTime)
   483  	query := d.Session.Query(templateRangeCompleteTimerTaskQuery,
   484  		request.ShardID,
   485  		rowTypeTimerTask,
   486  		rowTypeTimerNamespaceID,
   487  		rowTypeTimerWorkflowID,
   488  		rowTypeTimerRunID,
   489  		start,
   490  		end,
   491  	).WithContext(ctx)
   492  
   493  	err := query.Exec()
   494  	return gocql.ConvertError("RangeCompleteTimerTask", err)
   495  }
   496  
   497  func (d *MutableStateTaskStore) getReplicationTasks(
   498  	ctx context.Context,
   499  	request *p.GetHistoryTasksRequest,
   500  ) (*p.InternalGetHistoryTasksResponse, error) {
   501  
   502  	// Reading replication tasks need to be quorum level consistent, otherwise we could lose task
   503  	query := d.Session.Query(templateGetReplicationTasksQuery,
   504  		request.ShardID,
   505  		rowTypeReplicationTask,
   506  		rowTypeReplicationNamespaceID,
   507  		rowTypeReplicationWorkflowID,
   508  		rowTypeReplicationRunID,
   509  		defaultVisibilityTimestamp,
   510  		request.InclusiveMinTaskKey.TaskID,
   511  		request.ExclusiveMaxTaskKey.TaskID,
   512  	).WithContext(ctx).PageSize(request.BatchSize).PageState(request.NextPageToken)
   513  
   514  	return d.populateGetReplicationTasksResponse(query, "GetReplicationTasks")
   515  }
   516  
   517  func (d *MutableStateTaskStore) completeReplicationTask(
   518  	ctx context.Context,
   519  	request *p.CompleteHistoryTaskRequest,
   520  ) error {
   521  	query := d.Session.Query(templateCompleteReplicationTaskQuery,
   522  		request.ShardID,
   523  		rowTypeReplicationTask,
   524  		rowTypeReplicationNamespaceID,
   525  		rowTypeReplicationWorkflowID,
   526  		rowTypeReplicationRunID,
   527  		defaultVisibilityTimestamp,
   528  		request.TaskKey.TaskID,
   529  	).WithContext(ctx)
   530  
   531  	err := query.Exec()
   532  	return gocql.ConvertError("CompleteReplicationTask", err)
   533  }
   534  
   535  func (d *MutableStateTaskStore) rangeCompleteReplicationTasks(
   536  	ctx context.Context,
   537  	request *p.RangeCompleteHistoryTasksRequest,
   538  ) error {
   539  	query := d.Session.Query(templateRangeCompleteReplicationTaskQuery,
   540  		request.ShardID,
   541  		rowTypeReplicationTask,
   542  		rowTypeReplicationNamespaceID,
   543  		rowTypeReplicationWorkflowID,
   544  		rowTypeReplicationRunID,
   545  		defaultVisibilityTimestamp,
   546  		request.InclusiveMinTaskKey.TaskID,
   547  		request.ExclusiveMaxTaskKey.TaskID,
   548  	).WithContext(ctx)
   549  
   550  	err := query.Exec()
   551  	return gocql.ConvertError("RangeCompleteReplicationTask", err)
   552  }
   553  
   554  func (d *MutableStateTaskStore) PutReplicationTaskToDLQ(
   555  	ctx context.Context,
   556  	request *p.PutReplicationTaskToDLQRequest,
   557  ) error {
   558  	task := request.TaskInfo
   559  	datablob, err := serialization.ReplicationTaskInfoToBlob(task)
   560  	if err != nil {
   561  		return gocql.ConvertError("PutReplicationTaskToDLQ", err)
   562  	}
   563  
   564  	// Use source cluster name as the workflow id for replication dlq
   565  	query := d.Session.Query(templateCreateReplicationTaskQuery,
   566  		request.ShardID,
   567  		rowTypeDLQ,
   568  		rowTypeDLQNamespaceID,
   569  		request.SourceClusterName,
   570  		rowTypeDLQRunID,
   571  		datablob.Data,
   572  		datablob.EncodingType.String(),
   573  		defaultVisibilityTimestamp,
   574  		task.GetTaskId(),
   575  	).WithContext(ctx)
   576  
   577  	err = query.Exec()
   578  	if err != nil {
   579  		return gocql.ConvertError("PutReplicationTaskToDLQ", err)
   580  	}
   581  
   582  	return nil
   583  }
   584  
   585  func (d *MutableStateTaskStore) GetReplicationTasksFromDLQ(
   586  	ctx context.Context,
   587  	request *p.GetReplicationTasksFromDLQRequest,
   588  ) (*p.InternalGetHistoryTasksResponse, error) {
   589  	// Reading replication tasks need to be quorum level consistent, otherwise we could lose tasks
   590  	query := d.Session.Query(templateGetReplicationTasksQuery,
   591  		request.ShardID,
   592  		rowTypeDLQ,
   593  		rowTypeDLQNamespaceID,
   594  		request.SourceClusterName,
   595  		rowTypeDLQRunID,
   596  		defaultVisibilityTimestamp,
   597  		request.InclusiveMinTaskKey.TaskID,
   598  		request.ExclusiveMaxTaskKey.TaskID,
   599  	).WithContext(ctx).PageSize(request.BatchSize).PageState(request.NextPageToken)
   600  
   601  	return d.populateGetReplicationTasksResponse(query, "GetReplicationTasksFromDLQ")
   602  }
   603  
   604  func (d *MutableStateTaskStore) DeleteReplicationTaskFromDLQ(
   605  	ctx context.Context,
   606  	request *p.DeleteReplicationTaskFromDLQRequest,
   607  ) error {
   608  
   609  	query := d.Session.Query(templateCompleteReplicationTaskQuery,
   610  		request.ShardID,
   611  		rowTypeDLQ,
   612  		rowTypeDLQNamespaceID,
   613  		request.SourceClusterName,
   614  		rowTypeDLQRunID,
   615  		defaultVisibilityTimestamp,
   616  		request.TaskKey.TaskID,
   617  	).WithContext(ctx)
   618  
   619  	err := query.Exec()
   620  	return gocql.ConvertError("DeleteReplicationTaskFromDLQ", err)
   621  }
   622  
   623  func (d *MutableStateTaskStore) RangeDeleteReplicationTaskFromDLQ(
   624  	ctx context.Context,
   625  	request *p.RangeDeleteReplicationTaskFromDLQRequest,
   626  ) error {
   627  
   628  	query := d.Session.Query(templateRangeCompleteReplicationTaskQuery,
   629  		request.ShardID,
   630  		rowTypeDLQ,
   631  		rowTypeDLQNamespaceID,
   632  		request.SourceClusterName,
   633  		rowTypeDLQRunID,
   634  		defaultVisibilityTimestamp,
   635  		request.InclusiveMinTaskKey.TaskID,
   636  		request.ExclusiveMaxTaskKey.TaskID,
   637  	).WithContext(ctx)
   638  
   639  	err := query.Exec()
   640  	return gocql.ConvertError("RangeDeleteReplicationTaskFromDLQ", err)
   641  }
   642  
   643  func (d *MutableStateTaskStore) IsReplicationDLQEmpty(
   644  	ctx context.Context,
   645  	request *p.GetReplicationTasksFromDLQRequest,
   646  ) (bool, error) {
   647  
   648  	query := d.Session.Query(templateIsQueueEmptyQuery,
   649  		request.ShardID,
   650  		rowTypeDLQ,
   651  		rowTypeDLQNamespaceID,
   652  		request.SourceClusterName,
   653  		rowTypeDLQRunID,
   654  		defaultVisibilityTimestamp,
   655  		request.InclusiveMinTaskKey.TaskID,
   656  	).WithContext(ctx)
   657  
   658  	if err := query.Scan(nil); err != nil {
   659  		if gocql.IsNotFoundError(err) {
   660  			return true, nil
   661  		}
   662  		return true, gocql.ConvertError("IsReplicationDLQEmpty", err)
   663  	}
   664  	return false, nil
   665  }
   666  
   667  func (d *MutableStateTaskStore) getVisibilityTasks(
   668  	ctx context.Context,
   669  	request *p.GetHistoryTasksRequest,
   670  ) (*p.InternalGetHistoryTasksResponse, error) {
   671  
   672  	// Reading Visibility tasks need to be quorum level consistent, otherwise we could lose task
   673  	query := d.Session.Query(templateGetVisibilityTasksQuery,
   674  		request.ShardID,
   675  		rowTypeVisibilityTask,
   676  		rowTypeVisibilityTaskNamespaceID,
   677  		rowTypeVisibilityTaskWorkflowID,
   678  		rowTypeVisibilityTaskRunID,
   679  		defaultVisibilityTimestamp,
   680  		request.InclusiveMinTaskKey.TaskID,
   681  		request.ExclusiveMaxTaskKey.TaskID,
   682  	).WithContext(ctx)
   683  	iter := query.PageSize(request.BatchSize).PageState(request.NextPageToken).Iter()
   684  
   685  	response := &p.InternalGetHistoryTasksResponse{}
   686  	var taskID int64
   687  	var data []byte
   688  	var encoding string
   689  
   690  	for iter.Scan(&taskID, &data, &encoding) {
   691  		response.Tasks = append(response.Tasks, p.InternalHistoryTask{
   692  			Key:  tasks.NewImmediateKey(taskID),
   693  			Blob: p.NewDataBlob(data, encoding),
   694  		})
   695  
   696  		taskID = 0
   697  		data = nil
   698  		encoding = ""
   699  	}
   700  	if len(iter.PageState()) > 0 {
   701  		response.NextPageToken = iter.PageState()
   702  	}
   703  
   704  	if err := iter.Close(); err != nil {
   705  		return nil, gocql.ConvertError("GetVisibilityTasks", err)
   706  	}
   707  
   708  	return response, nil
   709  }
   710  
   711  func (d *MutableStateTaskStore) completeVisibilityTask(
   712  	ctx context.Context,
   713  	request *p.CompleteHistoryTaskRequest,
   714  ) error {
   715  	query := d.Session.Query(templateCompleteVisibilityTaskQuery,
   716  		request.ShardID,
   717  		rowTypeVisibilityTask,
   718  		rowTypeVisibilityTaskNamespaceID,
   719  		rowTypeVisibilityTaskWorkflowID,
   720  		rowTypeVisibilityTaskRunID,
   721  		defaultVisibilityTimestamp,
   722  		request.TaskKey.TaskID,
   723  	).WithContext(ctx)
   724  
   725  	err := query.Exec()
   726  	return gocql.ConvertError("CompleteVisibilityTask", err)
   727  }
   728  
   729  func (d *MutableStateTaskStore) rangeCompleteVisibilityTasks(
   730  	ctx context.Context,
   731  	request *p.RangeCompleteHistoryTasksRequest,
   732  ) error {
   733  	query := d.Session.Query(templateRangeCompleteVisibilityTaskQuery,
   734  		request.ShardID,
   735  		rowTypeVisibilityTask,
   736  		rowTypeVisibilityTaskNamespaceID,
   737  		rowTypeVisibilityTaskWorkflowID,
   738  		rowTypeVisibilityTaskRunID,
   739  		defaultVisibilityTimestamp,
   740  		request.InclusiveMinTaskKey.TaskID,
   741  		request.ExclusiveMaxTaskKey.TaskID,
   742  	).WithContext(ctx)
   743  
   744  	err := query.Exec()
   745  	return gocql.ConvertError("RangeCompleteVisibilityTask", err)
   746  }
   747  
   748  func (d *MutableStateTaskStore) populateGetReplicationTasksResponse(
   749  	query gocql.Query,
   750  	operation string,
   751  ) (*p.InternalGetHistoryTasksResponse, error) {
   752  	iter := query.Iter()
   753  
   754  	response := &p.InternalGetHistoryTasksResponse{}
   755  	var taskID int64
   756  	var data []byte
   757  	var encoding string
   758  
   759  	for iter.Scan(&taskID, &data, &encoding) {
   760  		response.Tasks = append(response.Tasks, p.InternalHistoryTask{
   761  			Key:  tasks.NewImmediateKey(taskID),
   762  			Blob: p.NewDataBlob(data, encoding),
   763  		})
   764  
   765  		taskID = 0
   766  		data = nil
   767  		encoding = ""
   768  	}
   769  	if len(iter.PageState()) > 0 {
   770  		response.NextPageToken = iter.PageState()
   771  	}
   772  
   773  	if err := iter.Close(); err != nil {
   774  		return nil, gocql.ConvertError(operation, err)
   775  	}
   776  
   777  	return response, nil
   778  }
   779  
   780  func (d *MutableStateTaskStore) getHistoryTasks(
   781  	ctx context.Context,
   782  	request *p.GetHistoryTasksRequest,
   783  ) (*p.InternalGetHistoryTasksResponse, error) {
   784  	switch request.TaskCategory.Type() {
   785  	case tasks.CategoryTypeImmediate:
   786  		return d.getHistoryImmedidateTasks(ctx, request)
   787  	case tasks.CategoryTypeScheduled:
   788  		return d.getHistoryScheduledTasks(ctx, request)
   789  	default:
   790  		panic(fmt.Sprintf("Unknown task category type: %v", request.TaskCategory.Type().String()))
   791  	}
   792  }
   793  
   794  func (d *MutableStateTaskStore) getHistoryImmedidateTasks(
   795  	ctx context.Context,
   796  	request *p.GetHistoryTasksRequest,
   797  ) (*p.InternalGetHistoryTasksResponse, error) {
   798  	// execution manager should already validated the request
   799  	// Reading history tasks need to be quorum level consistent, otherwise we could lose task
   800  
   801  	query := d.Session.Query(templateGetHistoryImmediateTasksQuery,
   802  		request.ShardID,
   803  		request.TaskCategory.ID(),
   804  		rowTypeHistoryTaskNamespaceID,
   805  		rowTypeHistoryTaskWorkflowID,
   806  		rowTypeHistoryTaskRunID,
   807  		defaultVisibilityTimestamp,
   808  		request.InclusiveMinTaskKey.TaskID,
   809  		request.ExclusiveMaxTaskKey.TaskID,
   810  	).WithContext(ctx)
   811  
   812  	iter := query.PageSize(request.BatchSize).PageState(request.NextPageToken).Iter()
   813  
   814  	response := &p.InternalGetHistoryTasksResponse{}
   815  	var taskID int64
   816  	var data []byte
   817  	var encoding string
   818  
   819  	for iter.Scan(&taskID, &data, &encoding) {
   820  		response.Tasks = append(response.Tasks, p.InternalHistoryTask{
   821  			Key:  tasks.NewImmediateKey(taskID),
   822  			Blob: p.NewDataBlob(data, encoding),
   823  		})
   824  
   825  		taskID = 0
   826  		data = nil
   827  		encoding = ""
   828  	}
   829  	if len(iter.PageState()) > 0 {
   830  		response.NextPageToken = iter.PageState()
   831  	}
   832  
   833  	if err := iter.Close(); err != nil {
   834  		return nil, gocql.ConvertError("GetHistoryImmediateTasks", err)
   835  	}
   836  
   837  	return response, nil
   838  }
   839  
   840  func (d *MutableStateTaskStore) getHistoryScheduledTasks(
   841  	ctx context.Context,
   842  	request *p.GetHistoryTasksRequest,
   843  ) (*p.InternalGetHistoryTasksResponse, error) {
   844  	// execution manager should already validated the request
   845  	// Reading history tasks need to be quorum level consistent, otherwise we could lose task
   846  
   847  	minTimestamp := p.UnixMilliseconds(request.InclusiveMinTaskKey.FireTime)
   848  	maxTimestamp := p.UnixMilliseconds(request.ExclusiveMaxTaskKey.FireTime)
   849  	query := d.Session.Query(templateGetHistoryScheduledTasksQuery,
   850  		request.ShardID,
   851  		request.TaskCategory.ID(),
   852  		rowTypeHistoryTaskNamespaceID,
   853  		rowTypeHistoryTaskWorkflowID,
   854  		rowTypeHistoryTaskRunID,
   855  		minTimestamp,
   856  		maxTimestamp,
   857  	).WithContext(ctx)
   858  
   859  	iter := query.PageSize(request.BatchSize).PageState(request.NextPageToken).Iter()
   860  
   861  	response := &p.InternalGetHistoryTasksResponse{}
   862  	var timestamp time.Time
   863  	var taskID int64
   864  	var data []byte
   865  	var encoding string
   866  
   867  	for iter.Scan(&timestamp, &taskID, &data, &encoding) {
   868  		response.Tasks = append(response.Tasks, p.InternalHistoryTask{
   869  			Key:  tasks.NewKey(timestamp, taskID),
   870  			Blob: p.NewDataBlob(data, encoding),
   871  		})
   872  
   873  		timestamp = time.Time{}
   874  		taskID = 0
   875  		data = nil
   876  		encoding = ""
   877  	}
   878  	if len(iter.PageState()) > 0 {
   879  		response.NextPageToken = iter.PageState()
   880  	}
   881  
   882  	if err := iter.Close(); err != nil {
   883  		return nil, gocql.ConvertError("GetHistoryScheduledTasks", err)
   884  	}
   885  
   886  	return response, nil
   887  }
   888  
   889  func (d *MutableStateTaskStore) completeHistoryTask(
   890  	ctx context.Context,
   891  	request *p.CompleteHistoryTaskRequest,
   892  ) error {
   893  	ts := defaultVisibilityTimestamp
   894  	if request.TaskCategory.Type() == tasks.CategoryTypeScheduled {
   895  		ts = p.UnixMilliseconds(request.TaskKey.FireTime)
   896  	}
   897  	query := d.Session.Query(templateCompleteHistoryTaskQuery,
   898  		request.ShardID,
   899  		request.TaskCategory.ID(),
   900  		rowTypeHistoryTaskNamespaceID,
   901  		rowTypeHistoryTaskWorkflowID,
   902  		rowTypeHistoryTaskRunID,
   903  		ts,
   904  		request.TaskKey.TaskID,
   905  	).WithContext(ctx)
   906  
   907  	err := query.Exec()
   908  	return gocql.ConvertError("CompleteHistoryTask", err)
   909  }
   910  
   911  func (d *MutableStateTaskStore) rangeCompleteHistoryTasks(
   912  	ctx context.Context,
   913  	request *p.RangeCompleteHistoryTasksRequest,
   914  ) error {
   915  	// execution manager should already validated the request
   916  	var query gocql.Query
   917  	if request.TaskCategory.Type() == tasks.CategoryTypeImmediate {
   918  		query = d.Session.Query(templateRangeCompleteHistoryImmediateTasksQuery,
   919  			request.ShardID,
   920  			request.TaskCategory.ID(),
   921  			rowTypeHistoryTaskNamespaceID,
   922  			rowTypeHistoryTaskWorkflowID,
   923  			rowTypeHistoryTaskRunID,
   924  			defaultVisibilityTimestamp,
   925  			request.InclusiveMinTaskKey.TaskID,
   926  			request.ExclusiveMaxTaskKey.TaskID,
   927  		).WithContext(ctx)
   928  	} else {
   929  		minTimestamp := p.UnixMilliseconds(request.InclusiveMinTaskKey.FireTime)
   930  		maxTimestamp := p.UnixMilliseconds(request.ExclusiveMaxTaskKey.FireTime)
   931  		query = d.Session.Query(templateRangeCompleteHistoryScheduledTasksQuery,
   932  			request.ShardID,
   933  			request.TaskCategory.ID(),
   934  			rowTypeHistoryTaskNamespaceID,
   935  			rowTypeHistoryTaskWorkflowID,
   936  			rowTypeHistoryTaskRunID,
   937  			minTimestamp,
   938  			maxTimestamp,
   939  		).WithContext(ctx)
   940  	}
   941  
   942  	err := query.Exec()
   943  	return gocql.ConvertError("RangeCompleteHistoryTasks", err)
   944  }