go.temporal.io/server@v1.23.0/common/persistence/cassandra/mutable_state_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  
    31  	commonpb "go.temporal.io/api/common/v1"
    32  	enumspb "go.temporal.io/api/enums/v1"
    33  	"go.temporal.io/api/serviceerror"
    34  
    35  	enumsspb "go.temporal.io/server/api/enums/v1"
    36  	persistencespb "go.temporal.io/server/api/persistence/v1"
    37  	"go.temporal.io/server/common/log"
    38  	p "go.temporal.io/server/common/persistence"
    39  	"go.temporal.io/server/common/persistence/nosql/nosqlplugin/cassandra/gocql"
    40  	"go.temporal.io/server/common/persistence/serialization"
    41  )
    42  
    43  const (
    44  	templateUpdateLeaseQuery = `UPDATE executions ` +
    45  		`SET range_id = ? ` +
    46  		`WHERE shard_id = ? ` +
    47  		`and type = ? ` +
    48  		`and namespace_id = ? ` +
    49  		`and workflow_id = ? ` +
    50  		`and run_id = ? ` +
    51  		`and visibility_ts = ? ` +
    52  		`and task_id = ? ` +
    53  		`IF range_id = ?`
    54  
    55  	templateUpdateCurrentWorkflowExecutionQuery = `UPDATE executions USING TTL 0 ` +
    56  		`SET current_run_id = ?, execution_state = ?, execution_state_encoding = ?, workflow_last_write_version = ?, workflow_state = ? ` +
    57  		`WHERE shard_id = ? ` +
    58  		`and type = ? ` +
    59  		`and namespace_id = ? ` +
    60  		`and workflow_id = ? ` +
    61  		`and run_id = ? ` +
    62  		`and visibility_ts = ? ` +
    63  		`and task_id = ? ` +
    64  		`IF current_run_id = ? `
    65  
    66  	templateUpdateCurrentWorkflowExecutionForNewQuery = templateUpdateCurrentWorkflowExecutionQuery +
    67  		`and workflow_last_write_version = ? ` +
    68  		`and workflow_state = ? `
    69  
    70  	templateCreateCurrentWorkflowExecutionQuery = `INSERT INTO executions (` +
    71  		`shard_id, type, namespace_id, workflow_id, run_id, ` +
    72  		`visibility_ts, task_id, current_run_id, execution_state, execution_state_encoding, ` +
    73  		`workflow_last_write_version, workflow_state) ` +
    74  		`VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) IF NOT EXISTS USING TTL 0 `
    75  
    76  	templateCreateWorkflowExecutionQuery = `INSERT INTO executions (` +
    77  		`shard_id, namespace_id, workflow_id, run_id, type, ` +
    78  		`execution, execution_encoding, execution_state, execution_state_encoding, next_event_id, db_record_version, ` +
    79  		`visibility_ts, task_id, checksum, checksum_encoding) ` +
    80  		`VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) IF NOT EXISTS `
    81  
    82  	templateGetWorkflowExecutionQuery = `SELECT execution, execution_encoding, execution_state, execution_state_encoding, next_event_id, activity_map, activity_map_encoding, timer_map, timer_map_encoding, ` +
    83  		`child_executions_map, child_executions_map_encoding, request_cancel_map, request_cancel_map_encoding, signal_map, signal_map_encoding, signal_requested, buffered_events_list, ` +
    84  		`checksum, checksum_encoding, db_record_version ` +
    85  		`FROM executions ` +
    86  		`WHERE shard_id = ? ` +
    87  		`and type = ? ` +
    88  		`and namespace_id = ? ` +
    89  		`and workflow_id = ? ` +
    90  		`and run_id = ? ` +
    91  		`and visibility_ts = ? ` +
    92  		`and task_id = ?`
    93  
    94  	templateGetCurrentExecutionQuery = `SELECT current_run_id, execution, execution_encoding, execution_state, execution_state_encoding, workflow_last_write_version ` +
    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  
   104  	templateListWorkflowExecutionQuery = `SELECT run_id, execution, execution_encoding, execution_state, execution_state_encoding, next_event_id ` +
   105  		`FROM executions ` +
   106  		`WHERE shard_id = ? ` +
   107  		`and type = ?`
   108  
   109  	// TODO deprecate templateUpdateWorkflowExecutionQueryDeprecated in favor of templateUpdateWorkflowExecutionQuery
   110  	// Deprecated.
   111  	templateUpdateWorkflowExecutionQueryDeprecated = `UPDATE executions ` +
   112  		`SET execution = ? ` +
   113  		`, execution_encoding = ? ` +
   114  		`, execution_state = ? ` +
   115  		`, execution_state_encoding = ? ` +
   116  		`, next_event_id = ? ` +
   117  		`, db_record_version = ? ` +
   118  		`, checksum = ? ` +
   119  		`, checksum_encoding = ? ` +
   120  		`WHERE shard_id = ? ` +
   121  		`and type = ? ` +
   122  		`and namespace_id = ? ` +
   123  		`and workflow_id = ? ` +
   124  		`and run_id = ? ` +
   125  		`and visibility_ts = ? ` +
   126  		`and task_id = ? ` +
   127  		`IF next_event_id = ? `
   128  	templateUpdateWorkflowExecutionQuery = `UPDATE executions ` +
   129  		`SET execution = ? ` +
   130  		`, execution_encoding = ? ` +
   131  		`, execution_state = ? ` +
   132  		`, execution_state_encoding = ? ` +
   133  		`, next_event_id = ? ` +
   134  		`, db_record_version = ? ` +
   135  		`, checksum = ? ` +
   136  		`, checksum_encoding = ? ` +
   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  		`IF db_record_version = ? `
   145  
   146  	templateUpdateActivityInfoQuery = `UPDATE executions ` +
   147  		`SET activity_map[ ? ] = ?, activity_map_encoding = ? ` +
   148  		`WHERE shard_id = ? ` +
   149  		`and type = ? ` +
   150  		`and namespace_id = ? ` +
   151  		`and workflow_id = ? ` +
   152  		`and run_id = ? ` +
   153  		`and visibility_ts = ? ` +
   154  		`and task_id = ? `
   155  
   156  	templateResetActivityInfoQuery = `UPDATE executions ` +
   157  		`SET activity_map = ?, activity_map_encoding = ? ` +
   158  		`WHERE shard_id = ? ` +
   159  		`and type = ? ` +
   160  		`and namespace_id = ? ` +
   161  		`and workflow_id = ? ` +
   162  		`and run_id = ? ` +
   163  		`and visibility_ts = ? ` +
   164  		`and task_id = ? `
   165  
   166  	templateUpdateTimerInfoQuery = `UPDATE executions ` +
   167  		`SET timer_map[ ? ] = ?, timer_map_encoding = ? ` +
   168  		`WHERE shard_id = ? ` +
   169  		`and type = ? ` +
   170  		`and namespace_id = ? ` +
   171  		`and workflow_id = ? ` +
   172  		`and run_id = ? ` +
   173  		`and visibility_ts = ? ` +
   174  		`and task_id = ? `
   175  
   176  	templateResetTimerInfoQuery = `UPDATE executions ` +
   177  		`SET timer_map = ?, timer_map_encoding = ? ` +
   178  		`WHERE shard_id = ? ` +
   179  		`and type = ? ` +
   180  		`and namespace_id = ? ` +
   181  		`and workflow_id = ? ` +
   182  		`and run_id = ? ` +
   183  		`and visibility_ts = ? ` +
   184  		`and task_id = ? `
   185  
   186  	templateUpdateChildExecutionInfoQuery = `UPDATE executions ` +
   187  		`SET child_executions_map[ ? ] = ?, child_executions_map_encoding = ? ` +
   188  		`WHERE shard_id = ? ` +
   189  		`and type = ? ` +
   190  		`and namespace_id = ? ` +
   191  		`and workflow_id = ? ` +
   192  		`and run_id = ? ` +
   193  		`and visibility_ts = ? ` +
   194  		`and task_id = ? `
   195  
   196  	templateResetChildExecutionInfoQuery = `UPDATE executions ` +
   197  		`SET child_executions_map = ?, child_executions_map_encoding = ? ` +
   198  		`WHERE shard_id = ? ` +
   199  		`and type = ? ` +
   200  		`and namespace_id = ? ` +
   201  		`and workflow_id = ? ` +
   202  		`and run_id = ? ` +
   203  		`and visibility_ts = ? ` +
   204  		`and task_id = ? `
   205  
   206  	templateUpdateRequestCancelInfoQuery = `UPDATE executions ` +
   207  		`SET request_cancel_map[ ? ] = ?, request_cancel_map_encoding = ? ` +
   208  		`WHERE shard_id = ? ` +
   209  		`and type = ? ` +
   210  		`and namespace_id = ? ` +
   211  		`and workflow_id = ? ` +
   212  		`and run_id = ? ` +
   213  		`and visibility_ts = ? ` +
   214  		`and task_id = ? `
   215  
   216  	templateResetRequestCancelInfoQuery = `UPDATE executions ` +
   217  		`SET request_cancel_map = ?, request_cancel_map_encoding = ? ` +
   218  		`WHERE shard_id = ? ` +
   219  		`and type = ? ` +
   220  		`and namespace_id = ? ` +
   221  		`and workflow_id = ? ` +
   222  		`and run_id = ? ` +
   223  		`and visibility_ts = ? ` +
   224  		`and task_id = ? `
   225  
   226  	templateUpdateSignalInfoQuery = `UPDATE executions ` +
   227  		`SET signal_map[ ? ] = ?, signal_map_encoding = ? ` +
   228  		`WHERE shard_id = ? ` +
   229  		`and type = ? ` +
   230  		`and namespace_id = ? ` +
   231  		`and workflow_id = ? ` +
   232  		`and run_id = ? ` +
   233  		`and visibility_ts = ? ` +
   234  		`and task_id = ? `
   235  
   236  	templateResetSignalInfoQuery = `UPDATE executions ` +
   237  		`SET signal_map = ?, signal_map_encoding = ? ` +
   238  		`WHERE shard_id = ? ` +
   239  		`and type = ? ` +
   240  		`and namespace_id = ? ` +
   241  		`and workflow_id = ? ` +
   242  		`and run_id = ? ` +
   243  		`and visibility_ts = ? ` +
   244  		`and task_id = ? `
   245  
   246  	templateUpdateSignalRequestedQuery = `UPDATE executions ` +
   247  		`SET signal_requested = signal_requested + ? ` +
   248  		`WHERE shard_id = ? ` +
   249  		`and type = ? ` +
   250  		`and namespace_id = ? ` +
   251  		`and workflow_id = ? ` +
   252  		`and run_id = ? ` +
   253  		`and visibility_ts = ? ` +
   254  		`and task_id = ? `
   255  
   256  	templateResetSignalRequestedQuery = `UPDATE executions ` +
   257  		`SET signal_requested = ?` +
   258  		`WHERE shard_id = ? ` +
   259  		`and type = ? ` +
   260  		`and namespace_id = ? ` +
   261  		`and workflow_id = ? ` +
   262  		`and run_id = ? ` +
   263  		`and visibility_ts = ? ` +
   264  		`and task_id = ? `
   265  
   266  	templateAppendBufferedEventsQuery = `UPDATE executions ` +
   267  		`SET buffered_events_list = buffered_events_list + ? ` +
   268  		`WHERE shard_id = ? ` +
   269  		`and type = ? ` +
   270  		`and namespace_id = ? ` +
   271  		`and workflow_id = ? ` +
   272  		`and run_id = ? ` +
   273  		`and visibility_ts = ? ` +
   274  		`and task_id = ? `
   275  
   276  	templateDeleteBufferedEventsQuery = `UPDATE executions ` +
   277  		`SET buffered_events_list = [] ` +
   278  		`WHERE shard_id = ? ` +
   279  		`and type = ? ` +
   280  		`and namespace_id = ? ` +
   281  		`and workflow_id = ? ` +
   282  		`and run_id = ? ` +
   283  		`and visibility_ts = ? ` +
   284  		`and task_id = ? `
   285  
   286  	templateDeleteActivityInfoQuery = `DELETE activity_map[ ? ] ` +
   287  		`FROM executions ` +
   288  		`WHERE shard_id = ? ` +
   289  		`and type = ? ` +
   290  		`and namespace_id = ? ` +
   291  		`and workflow_id = ? ` +
   292  		`and run_id = ? ` +
   293  		`and visibility_ts = ? ` +
   294  		`and task_id = ? `
   295  
   296  	templateDeleteTimerInfoQuery = `DELETE timer_map[ ? ] ` +
   297  		`FROM executions ` +
   298  		`WHERE shard_id = ? ` +
   299  		`and type = ? ` +
   300  		`and namespace_id = ? ` +
   301  		`and workflow_id = ? ` +
   302  		`and run_id = ? ` +
   303  		`and visibility_ts = ? ` +
   304  		`and task_id = ? `
   305  
   306  	templateDeleteChildExecutionInfoQuery = `DELETE child_executions_map[ ? ] ` +
   307  		`FROM executions ` +
   308  		`WHERE shard_id = ? ` +
   309  		`and type = ? ` +
   310  		`and namespace_id = ? ` +
   311  		`and workflow_id = ? ` +
   312  		`and run_id = ? ` +
   313  		`and visibility_ts = ? ` +
   314  		`and task_id = ? `
   315  
   316  	templateDeleteRequestCancelInfoQuery = `DELETE request_cancel_map[ ? ] ` +
   317  		`FROM executions ` +
   318  		`WHERE shard_id = ? ` +
   319  		`and type = ? ` +
   320  		`and namespace_id = ? ` +
   321  		`and workflow_id = ? ` +
   322  		`and run_id = ? ` +
   323  		`and visibility_ts = ? ` +
   324  		`and task_id = ? `
   325  
   326  	templateDeleteSignalInfoQuery = `DELETE signal_map[ ? ] ` +
   327  		`FROM executions ` +
   328  		`WHERE shard_id = ? ` +
   329  		`and type = ? ` +
   330  		`and namespace_id = ? ` +
   331  		`and workflow_id = ? ` +
   332  		`and run_id = ? ` +
   333  		`and visibility_ts = ? ` +
   334  		`and task_id = ? `
   335  
   336  	templateDeleteWorkflowExecutionMutableStateQuery = `DELETE FROM executions ` +
   337  		`WHERE shard_id = ? ` +
   338  		`and type = ? ` +
   339  		`and namespace_id = ? ` +
   340  		`and workflow_id = ? ` +
   341  		`and run_id = ? ` +
   342  		`and visibility_ts = ? ` +
   343  		`and task_id = ? `
   344  
   345  	templateDeleteWorkflowExecutionCurrentRowQuery = templateDeleteWorkflowExecutionMutableStateQuery + " if current_run_id = ? "
   346  
   347  	templateDeleteWorkflowExecutionSignalRequestedQuery = `UPDATE executions ` +
   348  		`SET signal_requested = signal_requested - ? ` +
   349  		`WHERE shard_id = ? ` +
   350  		`and type = ? ` +
   351  		`and namespace_id = ? ` +
   352  		`and workflow_id = ? ` +
   353  		`and run_id = ? ` +
   354  		`and visibility_ts = ? ` +
   355  		`and task_id = ? `
   356  )
   357  
   358  type (
   359  	MutableStateStore struct {
   360  		Session gocql.Session
   361  		Logger  log.Logger
   362  	}
   363  )
   364  
   365  func NewMutableStateStore(
   366  	session gocql.Session,
   367  	logger log.Logger,
   368  ) *MutableStateStore {
   369  	return &MutableStateStore{
   370  		Session: session,
   371  		Logger:  logger,
   372  	}
   373  }
   374  
   375  func (d *MutableStateStore) CreateWorkflowExecution(
   376  	ctx context.Context,
   377  	request *p.InternalCreateWorkflowExecutionRequest,
   378  ) (*p.InternalCreateWorkflowExecutionResponse, error) {
   379  	batch := d.Session.NewBatch(gocql.LoggedBatch).WithContext(ctx)
   380  
   381  	shardID := request.ShardID
   382  	newWorkflow := request.NewWorkflowSnapshot
   383  	lastWriteVersion := newWorkflow.LastWriteVersion
   384  	namespaceID := newWorkflow.NamespaceID
   385  	workflowID := newWorkflow.WorkflowID
   386  	runID := newWorkflow.RunID
   387  
   388  	var requestCurrentRunID string
   389  
   390  	switch request.Mode {
   391  	case p.CreateWorkflowModeBypassCurrent:
   392  		// noop
   393  
   394  	case p.CreateWorkflowModeUpdateCurrent:
   395  		batch.Query(templateUpdateCurrentWorkflowExecutionForNewQuery,
   396  			runID,
   397  			newWorkflow.ExecutionStateBlob.Data,
   398  			newWorkflow.ExecutionStateBlob.EncodingType.String(),
   399  			lastWriteVersion,
   400  			newWorkflow.ExecutionState.State,
   401  			shardID,
   402  			rowTypeExecution,
   403  			namespaceID,
   404  			workflowID,
   405  			permanentRunID,
   406  			defaultVisibilityTimestamp,
   407  			rowTypeExecutionTaskID,
   408  			request.PreviousRunID,
   409  			request.PreviousLastWriteVersion,
   410  			enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED,
   411  		)
   412  
   413  		requestCurrentRunID = request.PreviousRunID
   414  
   415  	case p.CreateWorkflowModeBrandNew:
   416  		batch.Query(templateCreateCurrentWorkflowExecutionQuery,
   417  			shardID,
   418  			rowTypeExecution,
   419  			namespaceID,
   420  			workflowID,
   421  			permanentRunID,
   422  			defaultVisibilityTimestamp,
   423  			rowTypeExecutionTaskID,
   424  			runID,
   425  			newWorkflow.ExecutionStateBlob.Data,
   426  			newWorkflow.ExecutionStateBlob.EncodingType.String(),
   427  			lastWriteVersion,
   428  			newWorkflow.ExecutionState.State,
   429  		)
   430  
   431  		requestCurrentRunID = ""
   432  
   433  	default:
   434  		return nil, serviceerror.NewInternal(fmt.Sprintf("CreateWorkflowExecution: unknown mode: %v", request.Mode))
   435  	}
   436  
   437  	if err := applyWorkflowSnapshotBatchAsNew(batch,
   438  		request.ShardID,
   439  		&newWorkflow,
   440  	); err != nil {
   441  		return nil, err
   442  	}
   443  
   444  	batch.Query(templateUpdateLeaseQuery,
   445  		request.RangeID,
   446  		request.ShardID,
   447  		rowTypeShard,
   448  		rowTypeShardNamespaceID,
   449  		rowTypeShardWorkflowID,
   450  		rowTypeShardRunID,
   451  		defaultVisibilityTimestamp,
   452  		rowTypeShardTaskID,
   453  		request.RangeID,
   454  	)
   455  
   456  	conflictRecord := newConflictRecord()
   457  	applied, conflictIter, err := d.Session.MapExecuteBatchCAS(batch, conflictRecord)
   458  	if err != nil {
   459  		return nil, gocql.ConvertError("CreateWorkflowExecution", err)
   460  	}
   461  	defer func() {
   462  		_ = conflictIter.Close()
   463  	}()
   464  
   465  	if !applied {
   466  		return nil, convertErrors(
   467  			conflictRecord,
   468  			conflictIter,
   469  			shardID,
   470  			request.RangeID,
   471  			requestCurrentRunID,
   472  			[]executionCASCondition{{
   473  				runID: newWorkflow.ExecutionState.RunId,
   474  				// dbVersion is for CAS, so the db record version will be set to `updateWorkflow.DBRecordVersion`
   475  				// while CAS on `updateWorkflow.DBRecordVersion - 1`
   476  				dbVersion:   newWorkflow.DBRecordVersion - 1,
   477  				nextEventID: newWorkflow.Condition,
   478  			}},
   479  		)
   480  	}
   481  
   482  	return &p.InternalCreateWorkflowExecutionResponse{}, nil
   483  }
   484  
   485  func (d *MutableStateStore) GetWorkflowExecution(
   486  	ctx context.Context,
   487  	request *p.GetWorkflowExecutionRequest,
   488  ) (*p.InternalGetWorkflowExecutionResponse, error) {
   489  	query := d.Session.Query(templateGetWorkflowExecutionQuery,
   490  		request.ShardID,
   491  		rowTypeExecution,
   492  		request.NamespaceID,
   493  		request.WorkflowID,
   494  		request.RunID,
   495  		defaultVisibilityTimestamp,
   496  		rowTypeExecutionTaskID,
   497  	).WithContext(ctx)
   498  
   499  	result := make(map[string]interface{})
   500  	if err := query.MapScan(result); err != nil {
   501  		return nil, gocql.ConvertError("GetWorkflowExecution", err)
   502  	}
   503  
   504  	state, err := mutableStateFromRow(result)
   505  	if err != nil {
   506  		return nil, serviceerror.NewUnavailable(fmt.Sprintf("GetWorkflowExecution operation failed. Error: %v", err))
   507  	}
   508  
   509  	activityInfos := make(map[int64]*commonpb.DataBlob)
   510  	aMap := result["activity_map"].(map[int64][]byte)
   511  	aMapEncoding := result["activity_map_encoding"].(string)
   512  	for key, value := range aMap {
   513  		activityInfos[key] = p.NewDataBlob(value, aMapEncoding)
   514  	}
   515  	state.ActivityInfos = activityInfos
   516  
   517  	timerInfos := make(map[string]*commonpb.DataBlob)
   518  	tMapEncoding := result["timer_map_encoding"].(string)
   519  	tMap := result["timer_map"].(map[string][]byte)
   520  	for key, value := range tMap {
   521  		timerInfos[key] = p.NewDataBlob(value, tMapEncoding)
   522  	}
   523  	state.TimerInfos = timerInfos
   524  
   525  	childExecutionInfos := make(map[int64]*commonpb.DataBlob)
   526  	cMap := result["child_executions_map"].(map[int64][]byte)
   527  	cMapEncoding := result["child_executions_map_encoding"].(string)
   528  	for key, value := range cMap {
   529  		childExecutionInfos[key] = p.NewDataBlob(value, cMapEncoding)
   530  	}
   531  	state.ChildExecutionInfos = childExecutionInfos
   532  
   533  	requestCancelInfos := make(map[int64]*commonpb.DataBlob)
   534  	rMapEncoding := result["request_cancel_map_encoding"].(string)
   535  	rMap := result["request_cancel_map"].(map[int64][]byte)
   536  	for key, value := range rMap {
   537  		requestCancelInfos[key] = p.NewDataBlob(value, rMapEncoding)
   538  	}
   539  	state.RequestCancelInfos = requestCancelInfos
   540  
   541  	signalInfos := make(map[int64]*commonpb.DataBlob)
   542  	sMapEncoding := result["signal_map_encoding"].(string)
   543  	sMap := result["signal_map"].(map[int64][]byte)
   544  	for key, value := range sMap {
   545  		signalInfos[key] = p.NewDataBlob(value, sMapEncoding)
   546  	}
   547  	state.SignalInfos = signalInfos
   548  	state.SignalRequestedIDs = gocql.UUIDsToStringSlice(result["signal_requested"])
   549  
   550  	eList := result["buffered_events_list"].([]map[string]interface{})
   551  	bufferedEventsBlobs := make([]*commonpb.DataBlob, 0, len(eList))
   552  	for _, v := range eList {
   553  		blob := createHistoryEventBatchBlob(v)
   554  		bufferedEventsBlobs = append(bufferedEventsBlobs, blob)
   555  	}
   556  	state.BufferedEvents = bufferedEventsBlobs
   557  
   558  	state.Checksum = p.NewDataBlob(result["checksum"].([]byte), result["checksum_encoding"].(string))
   559  
   560  	dbVersion := int64(0)
   561  	if dbRecordVersion, ok := result["db_record_version"]; ok {
   562  		dbVersion = dbRecordVersion.(int64)
   563  	} else {
   564  		dbVersion = 0
   565  	}
   566  
   567  	return &p.InternalGetWorkflowExecutionResponse{
   568  		State:           state,
   569  		DBRecordVersion: dbVersion,
   570  	}, nil
   571  }
   572  
   573  func (d *MutableStateStore) UpdateWorkflowExecution(
   574  	ctx context.Context,
   575  	request *p.InternalUpdateWorkflowExecutionRequest,
   576  ) error {
   577  	batch := d.Session.NewBatch(gocql.LoggedBatch).WithContext(ctx)
   578  
   579  	updateWorkflow := request.UpdateWorkflowMutation
   580  	newWorkflow := request.NewWorkflowSnapshot
   581  
   582  	namespaceID := updateWorkflow.NamespaceID
   583  	workflowID := updateWorkflow.WorkflowID
   584  	runID := updateWorkflow.RunID
   585  	shardID := request.ShardID
   586  
   587  	switch request.Mode {
   588  	case p.UpdateWorkflowModeBypassCurrent:
   589  		if err := d.assertNotCurrentExecution(
   590  			ctx,
   591  			request.ShardID,
   592  			namespaceID,
   593  			workflowID,
   594  			runID,
   595  		); err != nil {
   596  			return err
   597  		}
   598  
   599  	case p.UpdateWorkflowModeUpdateCurrent:
   600  		if newWorkflow != nil {
   601  			newLastWriteVersion := newWorkflow.LastWriteVersion
   602  			newNamespaceID := newWorkflow.NamespaceID
   603  			newWorkflowID := newWorkflow.WorkflowID
   604  			newRunID := newWorkflow.RunID
   605  
   606  			if namespaceID != newNamespaceID {
   607  				return serviceerror.NewInternal("UpdateWorkflowExecution: cannot continue as new to another namespace")
   608  			}
   609  
   610  			batch.Query(templateUpdateCurrentWorkflowExecutionQuery,
   611  				newRunID,
   612  				newWorkflow.ExecutionStateBlob.Data,
   613  				newWorkflow.ExecutionStateBlob.EncodingType.String(),
   614  				newLastWriteVersion,
   615  				newWorkflow.ExecutionState.State,
   616  				shardID,
   617  				rowTypeExecution,
   618  				newNamespaceID,
   619  				newWorkflowID,
   620  				permanentRunID,
   621  				defaultVisibilityTimestamp,
   622  				rowTypeExecutionTaskID,
   623  				runID,
   624  			)
   625  
   626  		} else {
   627  			lastWriteVersion := updateWorkflow.LastWriteVersion
   628  
   629  			executionStateDatablob, err := serialization.WorkflowExecutionStateToBlob(updateWorkflow.ExecutionState)
   630  			if err != nil {
   631  				return err
   632  			}
   633  
   634  			batch.Query(templateUpdateCurrentWorkflowExecutionQuery,
   635  				runID,
   636  				executionStateDatablob.Data,
   637  				executionStateDatablob.EncodingType.String(),
   638  				lastWriteVersion,
   639  				updateWorkflow.ExecutionState.State,
   640  				request.ShardID,
   641  				rowTypeExecution,
   642  				namespaceID,
   643  				workflowID,
   644  				permanentRunID,
   645  				defaultVisibilityTimestamp,
   646  				rowTypeExecutionTaskID,
   647  				runID,
   648  			)
   649  		}
   650  
   651  	default:
   652  		return serviceerror.NewInternal(fmt.Sprintf("UpdateWorkflowExecution: unknown mode: %v", request.Mode))
   653  	}
   654  
   655  	if err := applyWorkflowMutationBatch(batch, shardID, &updateWorkflow); err != nil {
   656  		return err
   657  	}
   658  	if newWorkflow != nil {
   659  		if err := applyWorkflowSnapshotBatchAsNew(batch,
   660  			request.ShardID,
   661  			newWorkflow,
   662  		); err != nil {
   663  			return err
   664  		}
   665  	}
   666  
   667  	// Verifies that the RangeID has not changed
   668  	batch.Query(templateUpdateLeaseQuery,
   669  		request.RangeID,
   670  		request.ShardID,
   671  		rowTypeShard,
   672  		rowTypeShardNamespaceID,
   673  		rowTypeShardWorkflowID,
   674  		rowTypeShardRunID,
   675  		defaultVisibilityTimestamp,
   676  		rowTypeShardTaskID,
   677  		request.RangeID,
   678  	)
   679  
   680  	conflictRecord := newConflictRecord()
   681  	applied, conflictIter, err := d.Session.MapExecuteBatchCAS(batch, conflictRecord)
   682  	if err != nil {
   683  		return gocql.ConvertError("UpdateWorkflowExecution", err)
   684  	}
   685  	defer func() {
   686  		_ = conflictIter.Close()
   687  	}()
   688  
   689  	if !applied {
   690  		return convertErrors(
   691  			conflictRecord,
   692  			conflictIter,
   693  			request.ShardID,
   694  			request.RangeID,
   695  			updateWorkflow.ExecutionState.RunId,
   696  			[]executionCASCondition{{
   697  				runID: updateWorkflow.ExecutionState.RunId,
   698  				// dbVersion is for CAS, so the db record version will be set to `updateWorkflow.DBRecordVersion`
   699  				// while CAS on `updateWorkflow.DBRecordVersion - 1`
   700  				dbVersion:   updateWorkflow.DBRecordVersion - 1,
   701  				nextEventID: updateWorkflow.Condition,
   702  			}},
   703  		)
   704  	}
   705  	return nil
   706  }
   707  
   708  func (d *MutableStateStore) ConflictResolveWorkflowExecution(
   709  	ctx context.Context,
   710  	request *p.InternalConflictResolveWorkflowExecutionRequest,
   711  ) error {
   712  	batch := d.Session.NewBatch(gocql.LoggedBatch).WithContext(ctx)
   713  
   714  	currentWorkflow := request.CurrentWorkflowMutation
   715  	resetWorkflow := request.ResetWorkflowSnapshot
   716  	newWorkflow := request.NewWorkflowSnapshot
   717  
   718  	shardID := request.ShardID
   719  
   720  	namespaceID := resetWorkflow.NamespaceID
   721  	workflowID := resetWorkflow.WorkflowID
   722  
   723  	var currentRunID string
   724  
   725  	switch request.Mode {
   726  	case p.ConflictResolveWorkflowModeBypassCurrent:
   727  		if err := d.assertNotCurrentExecution(
   728  			ctx,
   729  			shardID,
   730  			namespaceID,
   731  			workflowID,
   732  			resetWorkflow.ExecutionState.RunId,
   733  		); err != nil {
   734  			return err
   735  		}
   736  
   737  	case p.ConflictResolveWorkflowModeUpdateCurrent:
   738  		executionState := resetWorkflow.ExecutionState
   739  		lastWriteVersion := resetWorkflow.LastWriteVersion
   740  		if newWorkflow != nil {
   741  			lastWriteVersion = newWorkflow.LastWriteVersion
   742  			executionState = newWorkflow.ExecutionState
   743  		}
   744  		runID := executionState.RunId
   745  		createRequestID := executionState.CreateRequestId
   746  		state := executionState.State
   747  		status := executionState.Status
   748  
   749  		executionStateDatablob, err := serialization.WorkflowExecutionStateToBlob(&persistencespb.WorkflowExecutionState{
   750  			RunId:           runID,
   751  			CreateRequestId: createRequestID,
   752  			State:           state,
   753  			Status:          status,
   754  		})
   755  		if err != nil {
   756  			return serviceerror.NewUnavailable(fmt.Sprintf("ConflictResolveWorkflowExecution operation failed. Error: %v", err))
   757  		}
   758  
   759  		if currentWorkflow != nil {
   760  			currentRunID = currentWorkflow.ExecutionState.RunId
   761  
   762  			batch.Query(templateUpdateCurrentWorkflowExecutionQuery,
   763  				runID,
   764  				executionStateDatablob.Data,
   765  				executionStateDatablob.EncodingType.String(),
   766  				lastWriteVersion,
   767  				state,
   768  				shardID,
   769  				rowTypeExecution,
   770  				namespaceID,
   771  				workflowID,
   772  				permanentRunID,
   773  				defaultVisibilityTimestamp,
   774  				rowTypeExecutionTaskID,
   775  				currentRunID,
   776  			)
   777  
   778  		} else {
   779  			// reset workflow is current
   780  			currentRunID = resetWorkflow.ExecutionState.RunId
   781  
   782  			batch.Query(templateUpdateCurrentWorkflowExecutionQuery,
   783  				runID,
   784  				executionStateDatablob.Data,
   785  				executionStateDatablob.EncodingType.String(),
   786  				lastWriteVersion,
   787  				state,
   788  				shardID,
   789  				rowTypeExecution,
   790  				namespaceID,
   791  				workflowID,
   792  				permanentRunID,
   793  				defaultVisibilityTimestamp,
   794  				rowTypeExecutionTaskID,
   795  				currentRunID,
   796  			)
   797  		}
   798  
   799  	default:
   800  		return serviceerror.NewInternal(fmt.Sprintf("ConflictResolveWorkflowExecution: unknown mode: %v", request.Mode))
   801  	}
   802  
   803  	if err := applyWorkflowSnapshotBatchAsReset(batch, shardID, &resetWorkflow); err != nil {
   804  		return err
   805  	}
   806  
   807  	if currentWorkflow != nil {
   808  		if err := applyWorkflowMutationBatch(batch, shardID, currentWorkflow); err != nil {
   809  			return err
   810  		}
   811  	}
   812  	if newWorkflow != nil {
   813  		if err := applyWorkflowSnapshotBatchAsNew(batch, shardID, newWorkflow); err != nil {
   814  			return err
   815  		}
   816  	}
   817  
   818  	// Verifies that the RangeID has not changed
   819  	batch.Query(templateUpdateLeaseQuery,
   820  		request.RangeID,
   821  		request.ShardID,
   822  		rowTypeShard,
   823  		rowTypeShardNamespaceID,
   824  		rowTypeShardWorkflowID,
   825  		rowTypeShardRunID,
   826  		defaultVisibilityTimestamp,
   827  		rowTypeShardTaskID,
   828  		request.RangeID,
   829  	)
   830  
   831  	conflictRecord := newConflictRecord()
   832  	applied, conflictIter, err := d.Session.MapExecuteBatchCAS(batch, conflictRecord)
   833  	if err != nil {
   834  		return gocql.ConvertError("ConflictResolveWorkflowExecution", err)
   835  	}
   836  	defer func() {
   837  		_ = conflictIter.Close()
   838  	}()
   839  
   840  	if !applied {
   841  		executionCASConditions := []executionCASCondition{{
   842  			runID: resetWorkflow.RunID,
   843  			// dbVersion is for CAS, so the db record version will be set to `resetWorkflow.DBRecordVersion`
   844  			// while CAS on `resetWorkflow.DBRecordVersion - 1`
   845  			dbVersion:   resetWorkflow.DBRecordVersion - 1,
   846  			nextEventID: resetWorkflow.Condition,
   847  		}}
   848  		if currentWorkflow != nil {
   849  			executionCASConditions = append(executionCASConditions, executionCASCondition{
   850  				runID: currentWorkflow.RunID,
   851  				// dbVersion is for CAS, so the db record version will be set to `currentWorkflow.DBRecordVersion`
   852  				// while CAS on `currentWorkflow.DBRecordVersion - 1`
   853  				dbVersion:   currentWorkflow.DBRecordVersion - 1,
   854  				nextEventID: currentWorkflow.Condition,
   855  			})
   856  		}
   857  		return convertErrors(
   858  			conflictRecord,
   859  			conflictIter,
   860  			request.ShardID,
   861  			request.RangeID,
   862  			currentRunID,
   863  			executionCASConditions,
   864  		)
   865  	}
   866  	return nil
   867  }
   868  
   869  func (d *MutableStateStore) assertNotCurrentExecution(
   870  	ctx context.Context,
   871  	shardID int32,
   872  	namespaceID string,
   873  	workflowID string,
   874  	runID string,
   875  ) error {
   876  
   877  	if resp, err := d.GetCurrentExecution(ctx, &p.GetCurrentExecutionRequest{
   878  		ShardID:     shardID,
   879  		NamespaceID: namespaceID,
   880  		WorkflowID:  workflowID,
   881  	}); err != nil {
   882  		if _, isNotFound := err.(*serviceerror.NotFound); isNotFound {
   883  			// allow bypassing no current record
   884  			return nil
   885  		}
   886  		return err
   887  	} else if resp.RunID == runID {
   888  		return &p.CurrentWorkflowConditionFailedError{
   889  			Msg:              fmt.Sprintf("Assertion on current record failed. Current run ID is not expected: %v", resp.RunID),
   890  			RequestID:        "",
   891  			RunID:            "",
   892  			State:            enumsspb.WORKFLOW_EXECUTION_STATE_UNSPECIFIED,
   893  			Status:           enumspb.WORKFLOW_EXECUTION_STATUS_UNSPECIFIED,
   894  			LastWriteVersion: 0,
   895  		}
   896  	}
   897  
   898  	return nil
   899  }
   900  
   901  func (d *MutableStateStore) DeleteWorkflowExecution(
   902  	ctx context.Context,
   903  	request *p.DeleteWorkflowExecutionRequest,
   904  ) error {
   905  	query := d.Session.Query(templateDeleteWorkflowExecutionMutableStateQuery,
   906  		request.ShardID,
   907  		rowTypeExecution,
   908  		request.NamespaceID,
   909  		request.WorkflowID,
   910  		request.RunID,
   911  		defaultVisibilityTimestamp,
   912  		rowTypeExecutionTaskID,
   913  	).WithContext(ctx)
   914  
   915  	err := query.Exec()
   916  	return gocql.ConvertError("DeleteWorkflowExecution", err)
   917  }
   918  
   919  func (d *MutableStateStore) DeleteCurrentWorkflowExecution(
   920  	ctx context.Context,
   921  	request *p.DeleteCurrentWorkflowExecutionRequest,
   922  ) error {
   923  	query := d.Session.Query(templateDeleteWorkflowExecutionCurrentRowQuery,
   924  		request.ShardID,
   925  		rowTypeExecution,
   926  		request.NamespaceID,
   927  		request.WorkflowID,
   928  		permanentRunID,
   929  		defaultVisibilityTimestamp,
   930  		rowTypeExecutionTaskID,
   931  		request.RunID,
   932  	).WithContext(ctx)
   933  
   934  	err := query.Exec()
   935  	return gocql.ConvertError("DeleteWorkflowCurrentRow", err)
   936  }
   937  
   938  func (d *MutableStateStore) GetCurrentExecution(
   939  	ctx context.Context,
   940  	request *p.GetCurrentExecutionRequest,
   941  ) (*p.InternalGetCurrentExecutionResponse, error) {
   942  	query := d.Session.Query(templateGetCurrentExecutionQuery,
   943  		request.ShardID,
   944  		rowTypeExecution,
   945  		request.NamespaceID,
   946  		request.WorkflowID,
   947  		permanentRunID,
   948  		defaultVisibilityTimestamp,
   949  		rowTypeExecutionTaskID,
   950  	).WithContext(ctx)
   951  
   952  	result := make(map[string]interface{})
   953  	if err := query.MapScan(result); err != nil {
   954  		return nil, gocql.ConvertError("GetCurrentExecution", err)
   955  	}
   956  
   957  	currentRunID := gocql.UUIDToString(result["current_run_id"])
   958  	executionStateBlob, err := executionStateBlobFromRow(result)
   959  	if err != nil {
   960  		return nil, serviceerror.NewUnavailable(fmt.Sprintf("GetCurrentExecution operation failed. Error: %v", err))
   961  	}
   962  
   963  	// TODO: fix blob ExecutionState in storage should not be a blob.
   964  	executionState, err := serialization.WorkflowExecutionStateFromBlob(executionStateBlob.Data, executionStateBlob.EncodingType.String())
   965  	if err != nil {
   966  		return nil, err
   967  	}
   968  
   969  	return &p.InternalGetCurrentExecutionResponse{
   970  		RunID:          currentRunID,
   971  		ExecutionState: executionState,
   972  	}, nil
   973  }
   974  
   975  func (d *MutableStateStore) SetWorkflowExecution(
   976  	ctx context.Context,
   977  	request *p.InternalSetWorkflowExecutionRequest,
   978  ) error {
   979  	batch := d.Session.NewBatch(gocql.LoggedBatch).WithContext(ctx)
   980  
   981  	shardID := request.ShardID
   982  	setSnapshot := request.SetWorkflowSnapshot
   983  
   984  	if err := applyWorkflowSnapshotBatchAsReset(batch, shardID, &setSnapshot); err != nil {
   985  		return err
   986  	}
   987  
   988  	// Verifies that the RangeID has not changed
   989  	batch.Query(templateUpdateLeaseQuery,
   990  		request.RangeID,
   991  		request.ShardID,
   992  		rowTypeShard,
   993  		rowTypeShardNamespaceID,
   994  		rowTypeShardWorkflowID,
   995  		rowTypeShardRunID,
   996  		defaultVisibilityTimestamp,
   997  		rowTypeShardTaskID,
   998  		request.RangeID,
   999  	)
  1000  
  1001  	conflictRecord := newConflictRecord()
  1002  	applied, conflictIter, err := d.Session.MapExecuteBatchCAS(batch, conflictRecord)
  1003  	if err != nil {
  1004  		return gocql.ConvertError("SetWorkflowExecution", err)
  1005  	}
  1006  	defer func() {
  1007  		_ = conflictIter.Close()
  1008  	}()
  1009  
  1010  	if !applied {
  1011  		executionCASConditions := []executionCASCondition{{
  1012  			runID: setSnapshot.RunID,
  1013  			// dbVersion is for CAS, so the db record version will be set to `setSnapshot.DBRecordVersion`
  1014  			// while CAS on `setSnapshot.DBRecordVersion - 1`
  1015  			dbVersion:   setSnapshot.DBRecordVersion - 1,
  1016  			nextEventID: setSnapshot.Condition,
  1017  		}}
  1018  		return convertErrors(
  1019  			conflictRecord,
  1020  			conflictIter,
  1021  			request.ShardID,
  1022  			request.RangeID,
  1023  			"",
  1024  			executionCASConditions,
  1025  		)
  1026  	}
  1027  	return nil
  1028  }
  1029  
  1030  func (d *MutableStateStore) ListConcreteExecutions(
  1031  	ctx context.Context,
  1032  	request *p.ListConcreteExecutionsRequest,
  1033  ) (*p.InternalListConcreteExecutionsResponse, error) {
  1034  	query := d.Session.Query(
  1035  		templateListWorkflowExecutionQuery,
  1036  		request.ShardID,
  1037  		rowTypeExecution,
  1038  	).WithContext(ctx)
  1039  	iter := query.PageSize(request.PageSize).PageState(request.PageToken).Iter()
  1040  
  1041  	response := &p.InternalListConcreteExecutionsResponse{}
  1042  	result := make(map[string]interface{})
  1043  	for iter.MapScan(result) {
  1044  		runID := gocql.UUIDToString(result["run_id"])
  1045  		if runID == permanentRunID {
  1046  			result = make(map[string]interface{})
  1047  			continue
  1048  		}
  1049  		if _, ok := result["execution"]; ok {
  1050  			state, err := mutableStateFromRow(result)
  1051  			if err != nil {
  1052  				return nil, err
  1053  			}
  1054  			response.States = append(response.States, state)
  1055  		}
  1056  		result = make(map[string]interface{})
  1057  	}
  1058  	if len(iter.PageState()) > 0 {
  1059  		response.NextPageToken = iter.PageState()
  1060  	}
  1061  	return response, nil
  1062  }
  1063  
  1064  func mutableStateFromRow(
  1065  	result map[string]interface{},
  1066  ) (*p.InternalWorkflowMutableState, error) {
  1067  	eiBytes, ok := result["execution"].([]byte)
  1068  	if !ok {
  1069  		return nil, newPersistedTypeMismatchError("execution", "", eiBytes, result)
  1070  	}
  1071  
  1072  	eiEncoding, ok := result["execution_encoding"].(string)
  1073  	if !ok {
  1074  		return nil, newPersistedTypeMismatchError("execution_encoding", "", eiEncoding, result)
  1075  	}
  1076  
  1077  	nextEventID, ok := result["next_event_id"].(int64)
  1078  	if !ok {
  1079  		return nil, newPersistedTypeMismatchError("next_event_id", "", nextEventID, result)
  1080  	}
  1081  
  1082  	protoState, err := executionStateBlobFromRow(result)
  1083  	if err != nil {
  1084  		return nil, err
  1085  	}
  1086  
  1087  	mutableState := &p.InternalWorkflowMutableState{
  1088  		ExecutionInfo:  p.NewDataBlob(eiBytes, eiEncoding),
  1089  		ExecutionState: protoState,
  1090  		NextEventID:    nextEventID,
  1091  	}
  1092  	return mutableState, nil
  1093  }
  1094  
  1095  func executionStateBlobFromRow(
  1096  	result map[string]interface{},
  1097  ) (*commonpb.DataBlob, error) {
  1098  	state, ok := result["execution_state"].([]byte)
  1099  	if !ok {
  1100  		return nil, newPersistedTypeMismatchError("execution_state", "", state, result)
  1101  	}
  1102  
  1103  	stateEncoding, ok := result["execution_state_encoding"].(string)
  1104  	if !ok {
  1105  		return nil, newPersistedTypeMismatchError("execution_state_encoding", "", stateEncoding, result)
  1106  	}
  1107  
  1108  	return p.NewDataBlob(state, stateEncoding), nil
  1109  }