go.temporal.io/server@v1.23.0/common/persistence/sql/execution_util.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 sql
    26  
    27  import (
    28  	"bytes"
    29  	"context"
    30  	"database/sql"
    31  	"fmt"
    32  
    33  	commonpb "go.temporal.io/api/common/v1"
    34  	enumspb "go.temporal.io/api/enums/v1"
    35  	"go.temporal.io/api/serviceerror"
    36  
    37  	enumsspb "go.temporal.io/server/api/enums/v1"
    38  	persistencespb "go.temporal.io/server/api/persistence/v1"
    39  	p "go.temporal.io/server/common/persistence"
    40  	"go.temporal.io/server/common/persistence/serialization"
    41  	"go.temporal.io/server/common/persistence/sql/sqlplugin"
    42  	"go.temporal.io/server/common/primitives"
    43  	"go.temporal.io/server/service/history/tasks"
    44  )
    45  
    46  func applyWorkflowMutationTx(
    47  	ctx context.Context,
    48  	tx sqlplugin.Tx,
    49  	shardID int32,
    50  	workflowMutation *p.InternalWorkflowMutation,
    51  ) error {
    52  	lastWriteVersion := workflowMutation.LastWriteVersion
    53  	namespaceID := workflowMutation.NamespaceID
    54  	workflowID := workflowMutation.WorkflowID
    55  	runID := workflowMutation.ExecutionState.RunId
    56  
    57  	namespaceIDBytes, err := primitives.ParseUUID(namespaceID)
    58  	if err != nil {
    59  		return serviceerror.NewInternal(fmt.Sprintf("uuid parse failed. Error: %v", err))
    60  	}
    61  
    62  	runIDBytes, err := primitives.ParseUUID(runID)
    63  	if err != nil {
    64  		return serviceerror.NewInternal(fmt.Sprintf("uuid parse failed. Error: %v", err))
    65  	}
    66  
    67  	// TODO Remove me if UPDATE holds the lock to the end of a transaction
    68  	if err := lockAndCheckExecution(ctx,
    69  		tx,
    70  		shardID,
    71  		namespaceIDBytes,
    72  		workflowID,
    73  		runIDBytes,
    74  		workflowMutation.Condition,
    75  		workflowMutation.DBRecordVersion,
    76  	); err != nil {
    77  		switch err.(type) {
    78  		case *p.WorkflowConditionFailedError, *p.ConditionFailedError:
    79  			return err
    80  		default:
    81  			return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowMutationTx failed. Failed to lock executions row. Error: %v", err))
    82  		}
    83  	}
    84  
    85  	if err := updateExecution(ctx,
    86  		tx,
    87  		namespaceID,
    88  		workflowID,
    89  		workflowMutation.ExecutionInfoBlob,
    90  		workflowMutation.ExecutionState,
    91  		workflowMutation.NextEventID,
    92  		lastWriteVersion,
    93  		workflowMutation.DBRecordVersion,
    94  		shardID,
    95  	); err != nil {
    96  		return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowMutationTx failed. Failed to update executions row. Erorr: %v", err))
    97  	}
    98  
    99  	if err := applyTasks(ctx,
   100  		tx,
   101  		shardID,
   102  		workflowMutation.Tasks,
   103  	); err != nil {
   104  		return err
   105  	}
   106  
   107  	if err := updateActivityInfos(ctx,
   108  		tx,
   109  		workflowMutation.UpsertActivityInfos,
   110  		workflowMutation.DeleteActivityInfos,
   111  		shardID,
   112  		namespaceIDBytes,
   113  		workflowID,
   114  		runIDBytes,
   115  	); err != nil {
   116  		return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowMutationTx failed. Error: %v", err))
   117  	}
   118  
   119  	if err := updateTimerInfos(ctx,
   120  		tx,
   121  		workflowMutation.UpsertTimerInfos,
   122  		workflowMutation.DeleteTimerInfos,
   123  		shardID,
   124  		namespaceIDBytes,
   125  		workflowID,
   126  		runIDBytes,
   127  	); err != nil {
   128  		return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowMutationTx failed. Error: %v", err))
   129  	}
   130  
   131  	if err := updateChildExecutionInfos(ctx,
   132  		tx,
   133  		workflowMutation.UpsertChildExecutionInfos,
   134  		workflowMutation.DeleteChildExecutionInfos,
   135  		shardID,
   136  		namespaceIDBytes,
   137  		workflowID,
   138  		runIDBytes,
   139  	); err != nil {
   140  		return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowMutationTx failed. Error: %v", err))
   141  	}
   142  
   143  	if err := updateRequestCancelInfos(ctx,
   144  		tx,
   145  		workflowMutation.UpsertRequestCancelInfos,
   146  		workflowMutation.DeleteRequestCancelInfos,
   147  		shardID,
   148  		namespaceIDBytes,
   149  		workflowID,
   150  		runIDBytes,
   151  	); err != nil {
   152  		return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowMutationTx failed. Error: %v", err))
   153  	}
   154  
   155  	if err := updateSignalInfos(ctx,
   156  		tx,
   157  		workflowMutation.UpsertSignalInfos,
   158  		workflowMutation.DeleteSignalInfos,
   159  		shardID,
   160  		namespaceIDBytes,
   161  		workflowID,
   162  		runIDBytes,
   163  	); err != nil {
   164  		return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowMutationTx failed. Error: %v", err))
   165  	}
   166  
   167  	if err := updateSignalsRequested(ctx,
   168  		tx,
   169  		workflowMutation.UpsertSignalRequestedIDs,
   170  		workflowMutation.DeleteSignalRequestedIDs,
   171  		shardID,
   172  		namespaceIDBytes,
   173  		workflowID,
   174  		runIDBytes); err != nil {
   175  		return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowMutationTx failed. Error: %v", err))
   176  	}
   177  
   178  	if workflowMutation.ClearBufferedEvents {
   179  		if err := deleteBufferedEvents(ctx,
   180  			tx,
   181  			shardID,
   182  			namespaceIDBytes,
   183  			workflowID,
   184  			runIDBytes,
   185  		); err != nil {
   186  			return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowMutationTx failed. Error: %v", err))
   187  		}
   188  	}
   189  
   190  	if err := updateBufferedEvents(ctx,
   191  		tx,
   192  		workflowMutation.NewBufferedEvents,
   193  		shardID,
   194  		namespaceIDBytes,
   195  		workflowID,
   196  		runIDBytes,
   197  	); err != nil {
   198  		return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowMutationTx failed. Error: %v", err))
   199  	}
   200  	return nil
   201  }
   202  
   203  func applyWorkflowSnapshotTxAsReset(
   204  	ctx context.Context,
   205  	tx sqlplugin.Tx,
   206  	shardID int32,
   207  	workflowSnapshot *p.InternalWorkflowSnapshot,
   208  ) error {
   209  
   210  	lastWriteVersion := workflowSnapshot.LastWriteVersion
   211  	workflowID := workflowSnapshot.WorkflowID
   212  	namespaceID := workflowSnapshot.NamespaceID
   213  	runID := workflowSnapshot.ExecutionState.RunId
   214  	namespaceIDBytes, err := primitives.ParseUUID(namespaceID)
   215  	if err != nil {
   216  		return err
   217  	}
   218  	runIDBytes, err := primitives.ParseUUID(runID)
   219  	if err != nil {
   220  		return err
   221  	}
   222  
   223  	// TODO Is there a way to modify the various map tables without fear of other people adding rows after we delete, without locking the executions row?
   224  	if err := lockAndCheckExecution(ctx,
   225  		tx,
   226  		shardID,
   227  		namespaceIDBytes,
   228  		workflowID,
   229  		runIDBytes,
   230  		workflowSnapshot.Condition,
   231  		workflowSnapshot.DBRecordVersion,
   232  	); err != nil {
   233  		switch err.(type) {
   234  		case *p.WorkflowConditionFailedError, *p.ConditionFailedError:
   235  			return err
   236  		default:
   237  			return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowSnapshotTxAsReset failed. Failed to lock executions row. Error: %v", err))
   238  		}
   239  	}
   240  
   241  	if err := updateExecution(ctx,
   242  		tx,
   243  		namespaceID,
   244  		workflowID,
   245  		workflowSnapshot.ExecutionInfoBlob,
   246  		workflowSnapshot.ExecutionState,
   247  		workflowSnapshot.NextEventID,
   248  		lastWriteVersion,
   249  		workflowSnapshot.DBRecordVersion,
   250  		shardID,
   251  	); err != nil {
   252  		return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowSnapshotTxAsReset failed. Failed to update executions row. Erorr: %v", err))
   253  	}
   254  
   255  	if err := applyTasks(ctx,
   256  		tx,
   257  		shardID,
   258  		workflowSnapshot.Tasks,
   259  	); err != nil {
   260  		return err
   261  	}
   262  
   263  	if err := deleteActivityInfoMap(ctx,
   264  		tx,
   265  		shardID,
   266  		namespaceIDBytes,
   267  		workflowID,
   268  		runIDBytes,
   269  	); err != nil {
   270  		return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowSnapshotTxAsReset failed. Failed to clear activity info map. Error: %v", err))
   271  	}
   272  
   273  	if err := updateActivityInfos(ctx,
   274  		tx,
   275  		workflowSnapshot.ActivityInfos,
   276  		nil,
   277  		shardID,
   278  		namespaceIDBytes,
   279  		workflowID,
   280  		runIDBytes,
   281  	); err != nil {
   282  		return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowSnapshotTxAsReset failed. Failed to insert into activity info map after clearing. Error: %v", err))
   283  	}
   284  
   285  	if err := deleteTimerInfoMap(ctx,
   286  		tx,
   287  		shardID,
   288  		namespaceIDBytes,
   289  		workflowID,
   290  		runIDBytes,
   291  	); err != nil {
   292  		return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowSnapshotTxAsReset failed. Failed to clear timer info map. Error: %v", err))
   293  	}
   294  
   295  	if err := updateTimerInfos(ctx,
   296  		tx,
   297  		workflowSnapshot.TimerInfos,
   298  		nil,
   299  		shardID,
   300  		namespaceIDBytes,
   301  		workflowID,
   302  		runIDBytes,
   303  	); err != nil {
   304  		return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowSnapshotTxAsReset failed. Failed to insert into timer info map after clearing. Error: %v", err))
   305  	}
   306  
   307  	if err := deleteChildExecutionInfoMap(ctx,
   308  		tx,
   309  		shardID,
   310  		namespaceIDBytes,
   311  		workflowID,
   312  		runIDBytes,
   313  	); err != nil {
   314  		return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowSnapshotTxAsReset failed. Failed to clear child execution info map. Error: %v", err))
   315  	}
   316  
   317  	if err := updateChildExecutionInfos(ctx,
   318  		tx,
   319  		workflowSnapshot.ChildExecutionInfos,
   320  		nil,
   321  		shardID,
   322  		namespaceIDBytes,
   323  		workflowID,
   324  		runIDBytes,
   325  	); err != nil {
   326  		return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowSnapshotTxAsReset failed. Failed to insert into activity info map after clearing. Error: %v", err))
   327  	}
   328  
   329  	if err := deleteRequestCancelInfoMap(ctx,
   330  		tx,
   331  		shardID,
   332  		namespaceIDBytes,
   333  		workflowID,
   334  		runIDBytes,
   335  	); err != nil {
   336  		return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowSnapshotTxAsReset failed. Failed to clear request cancel info map. Error: %v", err))
   337  	}
   338  
   339  	if err := updateRequestCancelInfos(ctx,
   340  		tx,
   341  		workflowSnapshot.RequestCancelInfos,
   342  		nil,
   343  		shardID,
   344  		namespaceIDBytes,
   345  		workflowID,
   346  		runIDBytes,
   347  	); err != nil {
   348  		return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowSnapshotTxAsReset failed. Failed to insert into request cancel info map after clearing. Error: %v", err))
   349  	}
   350  
   351  	if err := deleteSignalInfoMap(ctx,
   352  		tx,
   353  		shardID,
   354  		namespaceIDBytes,
   355  		workflowID,
   356  		runIDBytes,
   357  	); err != nil {
   358  		return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowSnapshotTxAsReset failed. Failed to clear signal info map. Error: %v", err))
   359  	}
   360  
   361  	if err := updateSignalInfos(ctx,
   362  		tx,
   363  		workflowSnapshot.SignalInfos,
   364  		nil,
   365  		shardID,
   366  		namespaceIDBytes,
   367  		workflowID,
   368  		runIDBytes,
   369  	); err != nil {
   370  		return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowSnapshotTxAsReset failed. Failed to insert into signal info map after clearing. Error: %v", err))
   371  	}
   372  
   373  	if err := deleteSignalsRequestedSet(ctx,
   374  		tx,
   375  		shardID,
   376  		namespaceIDBytes,
   377  		workflowID,
   378  		runIDBytes); err != nil {
   379  		return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowSnapshotTxAsReset failed. Failed to clear signals requested set. Error: %v", err))
   380  	}
   381  
   382  	if err := updateSignalsRequested(ctx,
   383  		tx,
   384  		workflowSnapshot.SignalRequestedIDs,
   385  		nil,
   386  		shardID,
   387  		namespaceIDBytes,
   388  		workflowID,
   389  		runIDBytes,
   390  	); err != nil {
   391  		return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowSnapshotTxAsReset failed. Failed to insert into signals requested set after clearing. Error: %v", err))
   392  	}
   393  
   394  	if err := deleteBufferedEvents(ctx,
   395  		tx,
   396  		shardID,
   397  		namespaceIDBytes,
   398  		workflowID,
   399  		runIDBytes,
   400  	); err != nil {
   401  		return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowSnapshotTxAsReset failed. Failed to clear buffered events. Error: %v", err))
   402  	}
   403  	return nil
   404  }
   405  
   406  func (m *sqlExecutionStore) applyWorkflowSnapshotTxAsNew(
   407  	ctx context.Context,
   408  	tx sqlplugin.Tx,
   409  	shardID int32,
   410  	workflowSnapshot *p.InternalWorkflowSnapshot,
   411  ) error {
   412  
   413  	lastWriteVersion := workflowSnapshot.LastWriteVersion
   414  	workflowID := workflowSnapshot.WorkflowID
   415  	namespaceID := workflowSnapshot.NamespaceID
   416  	runID := workflowSnapshot.ExecutionState.RunId
   417  	namespaceIDBytes, err := primitives.ParseUUID(namespaceID)
   418  	if err != nil {
   419  		return err
   420  	}
   421  	runIDBytes, err := primitives.ParseUUID(runID)
   422  	if err != nil {
   423  		return err
   424  	}
   425  
   426  	if err := m.createExecution(ctx,
   427  		tx,
   428  		namespaceID,
   429  		workflowID,
   430  		workflowSnapshot.ExecutionInfoBlob,
   431  		workflowSnapshot.ExecutionState,
   432  		workflowSnapshot.NextEventID,
   433  		lastWriteVersion,
   434  		workflowSnapshot.DBRecordVersion,
   435  		shardID,
   436  	); err != nil {
   437  		return err
   438  	}
   439  
   440  	if err := applyTasks(ctx,
   441  		tx,
   442  		shardID,
   443  		workflowSnapshot.Tasks,
   444  	); err != nil {
   445  		return err
   446  	}
   447  
   448  	if err := updateActivityInfos(ctx,
   449  		tx,
   450  		workflowSnapshot.ActivityInfos,
   451  		nil,
   452  		shardID,
   453  		namespaceIDBytes,
   454  		workflowID,
   455  		runIDBytes,
   456  	); err != nil {
   457  		return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowSnapshotTxAsNew failed. Failed to insert into activity info map after clearing. Error: %v", err))
   458  	}
   459  
   460  	if err := updateTimerInfos(ctx,
   461  		tx,
   462  		workflowSnapshot.TimerInfos,
   463  		nil,
   464  		shardID,
   465  		namespaceIDBytes,
   466  		workflowID,
   467  		runIDBytes,
   468  	); err != nil {
   469  		return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowSnapshotTxAsNew failed. Failed to insert into timer info map after clearing. Error: %v", err))
   470  	}
   471  
   472  	if err := updateChildExecutionInfos(ctx,
   473  		tx,
   474  		workflowSnapshot.ChildExecutionInfos,
   475  		nil,
   476  		shardID,
   477  		namespaceIDBytes,
   478  		workflowID,
   479  		runIDBytes,
   480  	); err != nil {
   481  		return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowSnapshotTxAsNew failed. Failed to insert into activity info map after clearing. Error: %v", err))
   482  	}
   483  
   484  	if err := updateRequestCancelInfos(ctx,
   485  		tx,
   486  		workflowSnapshot.RequestCancelInfos,
   487  		nil,
   488  		shardID,
   489  		namespaceIDBytes,
   490  		workflowID,
   491  		runIDBytes,
   492  	); err != nil {
   493  		return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowSnapshotTxAsNew failed. Failed to insert into request cancel info map after clearing. Error: %v", err))
   494  	}
   495  
   496  	if err := updateSignalInfos(ctx,
   497  		tx,
   498  		workflowSnapshot.SignalInfos,
   499  		nil,
   500  		shardID,
   501  		namespaceIDBytes,
   502  		workflowID,
   503  		runIDBytes,
   504  	); err != nil {
   505  		return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowSnapshotTxAsNew failed. Failed to insert into signal info map after clearing. Error: %v", err))
   506  	}
   507  
   508  	if err := updateSignalsRequested(ctx,
   509  		tx,
   510  		workflowSnapshot.SignalRequestedIDs,
   511  		nil,
   512  		shardID,
   513  		namespaceIDBytes,
   514  		workflowID,
   515  		runIDBytes,
   516  	); err != nil {
   517  		return serviceerror.NewUnavailable(fmt.Sprintf("applyWorkflowSnapshotTxAsNew failed. Failed to insert into signals requested set after clearing. Error: %v", err))
   518  	}
   519  
   520  	return nil
   521  }
   522  
   523  func applyTasks(
   524  	ctx context.Context,
   525  	tx sqlplugin.Tx,
   526  	shardID int32,
   527  	insertTasks map[tasks.Category][]p.InternalHistoryTask,
   528  ) error {
   529  
   530  	var err error
   531  	for category, tasksByCategory := range insertTasks {
   532  		switch category.Type() {
   533  		case tasks.CategoryTypeImmediate:
   534  			err = createImmediateTasks(ctx, tx, shardID, category.ID(), tasksByCategory)
   535  		case tasks.CategoryTypeScheduled:
   536  			err = createScheduledTasks(ctx, tx, shardID, category.ID(), tasksByCategory)
   537  		default:
   538  			err = serviceerror.NewInternal(fmt.Sprintf("Unknown task category type: %v", category))
   539  		}
   540  
   541  		if err != nil {
   542  			return err
   543  		}
   544  	}
   545  
   546  	return nil
   547  }
   548  
   549  // lockCurrentExecutionIfExists returns current execution or nil if none is found for the workflowID
   550  // locking it in the DB
   551  func lockCurrentExecutionIfExists(
   552  	ctx context.Context,
   553  	tx sqlplugin.Tx,
   554  	shardID int32,
   555  	namespaceID primitives.UUID,
   556  	workflowID string,
   557  ) (*sqlplugin.CurrentExecutionsRow, error) {
   558  	rows, err := tx.LockCurrentExecutionsJoinExecutions(ctx, sqlplugin.CurrentExecutionsFilter{
   559  		ShardID: shardID, NamespaceID: namespaceID, WorkflowID: workflowID,
   560  	})
   561  	if err != nil {
   562  		if err != sql.ErrNoRows {
   563  			return nil, serviceerror.NewUnavailable(fmt.Sprintf("lockCurrentExecutionIfExists failed. Failed to get current_executions row for (shard,namespace,workflow) = (%v, %v, %v). Error: %v", shardID, namespaceID, workflowID, err))
   564  		}
   565  	}
   566  	size := len(rows)
   567  	if size > 1 {
   568  		return nil, serviceerror.NewUnavailable(fmt.Sprintf("lockCurrentExecutionIfExists failed. Multiple current_executions rows for (shard,namespace,workflow) = (%v, %v, %v).", shardID, namespaceID, workflowID))
   569  	}
   570  	if size == 0 {
   571  		return nil, nil
   572  	}
   573  	return &rows[0], nil
   574  }
   575  
   576  func createOrUpdateCurrentExecution(
   577  	ctx context.Context,
   578  	tx sqlplugin.Tx,
   579  	createMode p.CreateWorkflowMode,
   580  	shardID int32,
   581  	namespaceID primitives.UUID,
   582  	workflowID string,
   583  	runID primitives.UUID,
   584  	state enumsspb.WorkflowExecutionState,
   585  	status enumspb.WorkflowExecutionStatus,
   586  	createRequestID string,
   587  	lastWriteVersion int64,
   588  ) error {
   589  
   590  	row := sqlplugin.CurrentExecutionsRow{
   591  		ShardID:          shardID,
   592  		NamespaceID:      namespaceID,
   593  		WorkflowID:       workflowID,
   594  		RunID:            runID,
   595  		CreateRequestID:  createRequestID,
   596  		State:            state,
   597  		Status:           status,
   598  		LastWriteVersion: lastWriteVersion,
   599  	}
   600  
   601  	switch createMode {
   602  	case p.CreateWorkflowModeUpdateCurrent:
   603  		if err := updateCurrentExecution(ctx,
   604  			tx,
   605  			shardID,
   606  			namespaceID,
   607  			workflowID,
   608  			runID,
   609  			createRequestID,
   610  			state,
   611  			status,
   612  			row.LastWriteVersion,
   613  		); err != nil {
   614  			return serviceerror.NewUnavailable(fmt.Sprintf("createOrUpdateCurrentExecution failed. Failed to reuse workflow ID. Error: %v", err))
   615  		}
   616  	case p.CreateWorkflowModeBrandNew:
   617  		if _, err := tx.InsertIntoCurrentExecutions(ctx, &row); err != nil {
   618  			return serviceerror.NewUnavailable(fmt.Sprintf("createOrUpdateCurrentExecution failed. Failed to insert into current_executions table. Error: %v", err))
   619  		}
   620  	case p.CreateWorkflowModeBypassCurrent:
   621  		// noop
   622  	default:
   623  		return fmt.Errorf("createOrUpdateCurrentExecution failed. Unknown workflow creation mode: %v", createMode)
   624  	}
   625  
   626  	return nil
   627  }
   628  
   629  func lockAndCheckExecution(
   630  	ctx context.Context,
   631  	tx sqlplugin.Tx,
   632  	shardID int32,
   633  	namespaceID primitives.UUID,
   634  	workflowID string,
   635  	runID primitives.UUID,
   636  	condition int64,
   637  	dbRecordVersion int64,
   638  ) error {
   639  
   640  	version, nextEventID, err := lockExecution(ctx, tx, shardID, namespaceID, workflowID, runID)
   641  	if err != nil {
   642  		return err
   643  	}
   644  
   645  	if dbRecordVersion == 0 {
   646  		if nextEventID != condition {
   647  			return &p.WorkflowConditionFailedError{
   648  				Msg:             fmt.Sprintf("lockAndCheckExecution failed. Next_event_id was %v when it should have been %v.", nextEventID, condition),
   649  				NextEventID:     nextEventID,
   650  				DBRecordVersion: version,
   651  			}
   652  		}
   653  	} else {
   654  		dbRecordVersion -= 1
   655  		if version != dbRecordVersion {
   656  			return &p.WorkflowConditionFailedError{
   657  				Msg:             fmt.Sprintf("lockAndCheckExecution failed. DBRecordVersion expected: %v, actually %v.", dbRecordVersion, version),
   658  				NextEventID:     nextEventID,
   659  				DBRecordVersion: version,
   660  			}
   661  		}
   662  	}
   663  
   664  	return nil
   665  }
   666  
   667  func lockExecution(
   668  	ctx context.Context,
   669  	tx sqlplugin.Tx,
   670  	shardID int32,
   671  	namespaceID primitives.UUID,
   672  	workflowID string,
   673  	runID primitives.UUID,
   674  ) (int64, int64, error) {
   675  
   676  	dbRecordVersion, nextEventID, err := tx.WriteLockExecutions(ctx, sqlplugin.ExecutionsFilter{
   677  		ShardID:     shardID,
   678  		NamespaceID: namespaceID,
   679  		WorkflowID:  workflowID,
   680  		RunID:       runID,
   681  	})
   682  	if err != nil {
   683  		if err == sql.ErrNoRows {
   684  			return 0, 0, &p.ConditionFailedError{
   685  				Msg: fmt.Sprintf("WriteLockExecutions failed. Unable to lock (shard, namespace, workflow, run) = (%v,%v,%v,%v) which does not exist.",
   686  					shardID,
   687  					namespaceID,
   688  					workflowID,
   689  					runID),
   690  			}
   691  		}
   692  		return 0, 0, serviceerror.NewUnavailable(fmt.Sprintf("lockNextEventID failed. Error: %v", err))
   693  	}
   694  	return dbRecordVersion, nextEventID, nil
   695  }
   696  
   697  func createImmediateTasks(
   698  	ctx context.Context,
   699  	tx sqlplugin.Tx,
   700  	shardID int32,
   701  	categoryID int,
   702  	immedidateTasks []p.InternalHistoryTask,
   703  ) error {
   704  	// This is for backward compatiblity.
   705  	// These task categories exist before the general history_immediate_tasks table is created,
   706  	// so they have their own tables.
   707  	switch categoryID {
   708  	case tasks.CategoryIDTransfer:
   709  		return createTransferTasks(ctx, tx, shardID, immedidateTasks)
   710  	case tasks.CategoryIDVisibility:
   711  		return createVisibilityTasks(ctx, tx, shardID, immedidateTasks)
   712  	case tasks.CategoryIDReplication:
   713  		return createReplicationTasks(ctx, tx, shardID, immedidateTasks)
   714  	}
   715  
   716  	if len(immedidateTasks) == 0 {
   717  		return nil
   718  	}
   719  
   720  	immediateTasksRows := make([]sqlplugin.HistoryImmediateTasksRow, 0, len(immedidateTasks))
   721  	for _, task := range immedidateTasks {
   722  		immediateTasksRows = append(immediateTasksRows, sqlplugin.HistoryImmediateTasksRow{
   723  			ShardID:      shardID,
   724  			CategoryID:   int32(categoryID),
   725  			TaskID:       task.Key.TaskID,
   726  			Data:         task.Blob.Data,
   727  			DataEncoding: task.Blob.EncodingType.String(),
   728  		})
   729  	}
   730  
   731  	result, err := tx.InsertIntoHistoryImmediateTasks(ctx, immediateTasksRows)
   732  	if err != nil {
   733  		return serviceerror.NewUnavailable(fmt.Sprintf("createImmediateTasks failed. Error: %v", err))
   734  	}
   735  
   736  	rowsAffected, err := result.RowsAffected()
   737  	if err != nil {
   738  		return serviceerror.NewUnavailable(fmt.Sprintf("createImmediateTasks failed. Could not verify number of rows inserted. Error: %v", err))
   739  	}
   740  
   741  	if int(rowsAffected) != len(immediateTasksRows) {
   742  		return serviceerror.NewUnavailable(fmt.Sprintf("createImmediateTasks failed. Inserted %v instead of %v rows into history_immediate_tasks. Error: %v", rowsAffected, len(immediateTasksRows), err))
   743  	}
   744  	return nil
   745  }
   746  
   747  func createScheduledTasks(
   748  	ctx context.Context,
   749  	tx sqlplugin.Tx,
   750  	shardID int32,
   751  	categoryID int,
   752  	scheduledTasks []p.InternalHistoryTask,
   753  ) error {
   754  	// This is for backward compatiblity.
   755  	// These task categories exists before the general history_scheduled_tasks table is created,
   756  	// so they have their own tables.
   757  	if categoryID == tasks.CategoryIDTimer {
   758  		return createTimerTasks(ctx, tx, shardID, scheduledTasks)
   759  	}
   760  
   761  	if len(scheduledTasks) == 0 {
   762  		return nil
   763  	}
   764  
   765  	scheduledTasksRows := make([]sqlplugin.HistoryScheduledTasksRow, 0, len(scheduledTasks))
   766  	for _, task := range scheduledTasks {
   767  		scheduledTasksRows = append(scheduledTasksRows, sqlplugin.HistoryScheduledTasksRow{
   768  			ShardID:             shardID,
   769  			CategoryID:          int32(categoryID),
   770  			VisibilityTimestamp: task.Key.FireTime,
   771  			TaskID:              task.Key.TaskID,
   772  			Data:                task.Blob.Data,
   773  			DataEncoding:        task.Blob.EncodingType.String(),
   774  		})
   775  	}
   776  
   777  	result, err := tx.InsertIntoHistoryScheduledTasks(ctx, scheduledTasksRows)
   778  	if err != nil {
   779  		return serviceerror.NewUnavailable(fmt.Sprintf("createScheduledTasks failed. Error: %v", err))
   780  	}
   781  	rowsAffected, err := result.RowsAffected()
   782  	if err != nil {
   783  		return serviceerror.NewUnavailable(fmt.Sprintf("createScheduledTasks failed. Could not verify number of rows inserted. Error: %v", err))
   784  	}
   785  
   786  	if int(rowsAffected) != len(scheduledTasks) {
   787  		return serviceerror.NewUnavailable(fmt.Sprintf("createScheduledTasks failed. Inserted %v instead of %v rows into history_scheduled_tasks. Error: %v", rowsAffected, len(scheduledTasks), err))
   788  	}
   789  	return nil
   790  }
   791  
   792  func createTransferTasks(
   793  	ctx context.Context,
   794  	tx sqlplugin.Tx,
   795  	shardID int32,
   796  	transferTasks []p.InternalHistoryTask,
   797  ) error {
   798  
   799  	if len(transferTasks) == 0 {
   800  		return nil
   801  	}
   802  
   803  	transferTasksRows := make([]sqlplugin.TransferTasksRow, 0, len(transferTasks))
   804  	for _, task := range transferTasks {
   805  		transferTasksRows = append(transferTasksRows, sqlplugin.TransferTasksRow{
   806  			ShardID:      shardID,
   807  			TaskID:       task.Key.TaskID,
   808  			Data:         task.Blob.Data,
   809  			DataEncoding: task.Blob.EncodingType.String(),
   810  		})
   811  	}
   812  
   813  	result, err := tx.InsertIntoTransferTasks(ctx, transferTasksRows)
   814  	if err != nil {
   815  		return serviceerror.NewUnavailable(fmt.Sprintf("createTransferTasks failed. Error: %v", err))
   816  	}
   817  
   818  	rowsAffected, err := result.RowsAffected()
   819  	if err != nil {
   820  		return serviceerror.NewUnavailable(fmt.Sprintf("createTransferTasks failed. Could not verify number of rows inserted. Error: %v", err))
   821  	}
   822  
   823  	if int(rowsAffected) != len(transferTasks) {
   824  		return serviceerror.NewUnavailable(fmt.Sprintf("createTransferTasks failed. Inserted %v instead of %v rows into transfer_tasks. Error: %v", rowsAffected, len(transferTasks), err))
   825  	}
   826  	return nil
   827  }
   828  
   829  func createTimerTasks(
   830  	ctx context.Context,
   831  	tx sqlplugin.Tx,
   832  	shardID int32,
   833  	timerTasks []p.InternalHistoryTask,
   834  ) error {
   835  
   836  	if len(timerTasks) == 0 {
   837  		return nil
   838  	}
   839  
   840  	timerTasksRows := make([]sqlplugin.TimerTasksRow, 0, len(timerTasks))
   841  	for _, task := range timerTasks {
   842  		timerTasksRows = append(timerTasksRows, sqlplugin.TimerTasksRow{
   843  			ShardID:             shardID,
   844  			VisibilityTimestamp: task.Key.FireTime,
   845  			TaskID:              task.Key.TaskID,
   846  			Data:                task.Blob.Data,
   847  			DataEncoding:        task.Blob.EncodingType.String(),
   848  		})
   849  	}
   850  
   851  	result, err := tx.InsertIntoTimerTasks(ctx, timerTasksRows)
   852  	if err != nil {
   853  		return serviceerror.NewUnavailable(fmt.Sprintf("createTimerTasks failed. Error: %v", err))
   854  	}
   855  	rowsAffected, err := result.RowsAffected()
   856  	if err != nil {
   857  		return serviceerror.NewUnavailable(fmt.Sprintf("createTimerTasks failed. Could not verify number of rows inserted. Error: %v", err))
   858  	}
   859  
   860  	if int(rowsAffected) != len(timerTasks) {
   861  		return serviceerror.NewUnavailable(fmt.Sprintf("createTimerTasks failed. Inserted %v instead of %v rows into timer_tasks. Error: %v", rowsAffected, len(timerTasks), err))
   862  	}
   863  	return nil
   864  }
   865  
   866  func createReplicationTasks(
   867  	ctx context.Context,
   868  	tx sqlplugin.Tx,
   869  	shardID int32,
   870  	replicationTasks []p.InternalHistoryTask,
   871  ) error {
   872  
   873  	if len(replicationTasks) == 0 {
   874  		return nil
   875  	}
   876  
   877  	replicationTasksRows := make([]sqlplugin.ReplicationTasksRow, 0, len(replicationTasks))
   878  	for _, task := range replicationTasks {
   879  		replicationTasksRows = append(replicationTasksRows, sqlplugin.ReplicationTasksRow{
   880  			ShardID:      shardID,
   881  			TaskID:       task.Key.TaskID,
   882  			Data:         task.Blob.Data,
   883  			DataEncoding: task.Blob.EncodingType.String(),
   884  		})
   885  	}
   886  
   887  	result, err := tx.InsertIntoReplicationTasks(ctx, replicationTasksRows)
   888  	if err != nil {
   889  		return serviceerror.NewUnavailable(fmt.Sprintf("createReplicationTasks failed. Error: %v", err))
   890  	}
   891  
   892  	rowsAffected, err := result.RowsAffected()
   893  	if err != nil {
   894  		return serviceerror.NewUnavailable(fmt.Sprintf("createReplicationTasks failed. Could not verify number of rows inserted. Error: %v", err))
   895  	}
   896  
   897  	if int(rowsAffected) != len(replicationTasks) {
   898  		return serviceerror.NewUnavailable(fmt.Sprintf("createReplicationTasks failed. Inserted %v instead of %v rows into transfer_tasks. Error: %v", rowsAffected, len(replicationTasks), err))
   899  	}
   900  	return nil
   901  }
   902  
   903  func createVisibilityTasks(
   904  	ctx context.Context,
   905  	tx sqlplugin.Tx,
   906  	shardID int32,
   907  	visibilityTasks []p.InternalHistoryTask,
   908  ) error {
   909  
   910  	if len(visibilityTasks) == 0 {
   911  		return nil
   912  	}
   913  
   914  	visibilityTasksRows := make([]sqlplugin.VisibilityTasksRow, 0, len(visibilityTasks))
   915  	for _, task := range visibilityTasks {
   916  		visibilityTasksRows = append(visibilityTasksRows, sqlplugin.VisibilityTasksRow{
   917  			ShardID:      shardID,
   918  			TaskID:       task.Key.TaskID,
   919  			Data:         task.Blob.Data,
   920  			DataEncoding: task.Blob.EncodingType.String(),
   921  		})
   922  	}
   923  
   924  	result, err := tx.InsertIntoVisibilityTasks(ctx, visibilityTasksRows)
   925  	if err != nil {
   926  		return serviceerror.NewUnavailable(fmt.Sprintf("createTransferTasks failed. Error: %v", err))
   927  	}
   928  
   929  	rowsAffected, err := result.RowsAffected()
   930  	if err != nil {
   931  		return serviceerror.NewUnavailable(fmt.Sprintf("createTransferTasks failed. Could not verify number of rows inserted. Error: %v", err))
   932  	}
   933  
   934  	if int(rowsAffected) != len(visibilityTasksRows) {
   935  		return serviceerror.NewUnavailable(fmt.Sprintf("createTransferTasks failed. Inserted %v instead of %v rows into transfer_tasks. Error: %v", rowsAffected, len(visibilityTasksRows), err))
   936  	}
   937  	return nil
   938  }
   939  
   940  func assertNotCurrentExecution(
   941  	ctx context.Context,
   942  	tx sqlplugin.Tx,
   943  	shardID int32,
   944  	namespaceID primitives.UUID,
   945  	workflowID string,
   946  	runID primitives.UUID,
   947  ) error {
   948  	currentRow, err := tx.LockCurrentExecutions(ctx, sqlplugin.CurrentExecutionsFilter{
   949  		ShardID:     shardID,
   950  		NamespaceID: namespaceID,
   951  		WorkflowID:  workflowID,
   952  	})
   953  	if err != nil {
   954  		if err == sql.ErrNoRows {
   955  			// allow bypassing no current record
   956  			return nil
   957  		}
   958  		return serviceerror.NewUnavailable(fmt.Sprintf("assertCurrentExecution failed. Unable to load current record. Error: %v", err))
   959  	}
   960  	return assertRunIDMismatch(runID, currentRow)
   961  }
   962  
   963  func assertRunIDAndUpdateCurrentExecution(
   964  	ctx context.Context,
   965  	tx sqlplugin.Tx,
   966  	shardID int32,
   967  	namespaceID primitives.UUID,
   968  	workflowID string,
   969  	newRunID primitives.UUID,
   970  	previousRunID primitives.UUID,
   971  	createRequestID string,
   972  	state enumsspb.WorkflowExecutionState,
   973  	status enumspb.WorkflowExecutionStatus,
   974  	lastWriteVersion int64,
   975  ) error {
   976  
   977  	assertFn := func(currentRow *sqlplugin.CurrentExecutionsRow) error {
   978  		if !bytes.Equal(currentRow.RunID, previousRunID) {
   979  			return &p.CurrentWorkflowConditionFailedError{
   980  				Msg: fmt.Sprintf(
   981  					"assertRunIDAndUpdateCurrentExecution failed. current run ID: %v, request run ID: %v",
   982  					currentRow.RunID,
   983  					previousRunID,
   984  				),
   985  				RequestID:        currentRow.CreateRequestID,
   986  				RunID:            currentRow.RunID.String(),
   987  				State:            currentRow.State,
   988  				Status:           currentRow.Status,
   989  				LastWriteVersion: currentRow.LastWriteVersion,
   990  			}
   991  		}
   992  		return nil
   993  	}
   994  	if err := assertCurrentExecution(ctx,
   995  		tx,
   996  		shardID,
   997  		namespaceID,
   998  		workflowID,
   999  		assertFn,
  1000  	); err != nil {
  1001  		return err
  1002  	}
  1003  
  1004  	return updateCurrentExecution(ctx,
  1005  		tx,
  1006  		shardID,
  1007  		namespaceID,
  1008  		workflowID,
  1009  		newRunID,
  1010  		createRequestID,
  1011  		state,
  1012  		status,
  1013  		lastWriteVersion,
  1014  	)
  1015  }
  1016  
  1017  func assertCurrentExecution(
  1018  	ctx context.Context,
  1019  	tx sqlplugin.Tx,
  1020  	shardID int32,
  1021  	namespaceID primitives.UUID,
  1022  	workflowID string,
  1023  	assertFn func(currentRow *sqlplugin.CurrentExecutionsRow) error,
  1024  ) error {
  1025  
  1026  	currentRow, err := tx.LockCurrentExecutions(ctx, sqlplugin.CurrentExecutionsFilter{
  1027  		ShardID:     shardID,
  1028  		NamespaceID: namespaceID,
  1029  		WorkflowID:  workflowID,
  1030  	})
  1031  	if err != nil {
  1032  		return serviceerror.NewUnavailable(fmt.Sprintf("assertCurrentExecution failed. Unable to load current record. Error: %v", err))
  1033  	}
  1034  	return assertFn(currentRow)
  1035  }
  1036  
  1037  func assertRunIDMismatch(requestRunID primitives.UUID, currentRow *sqlplugin.CurrentExecutionsRow) error {
  1038  	// zombie workflow creation with existence of current record, this is a noop
  1039  	if currentRow == nil {
  1040  		return nil
  1041  	}
  1042  	if bytes.Equal(currentRow.RunID, requestRunID) {
  1043  		return extractCurrentWorkflowConflictError(
  1044  			currentRow,
  1045  			fmt.Sprintf(
  1046  				"assertRunIDMismatch failed. request run ID: %v, current run ID: %v",
  1047  				requestRunID,
  1048  				currentRow.RunID.String(),
  1049  			),
  1050  		)
  1051  	}
  1052  	return nil
  1053  }
  1054  
  1055  func updateCurrentExecution(
  1056  	ctx context.Context,
  1057  	tx sqlplugin.Tx,
  1058  	shardID int32,
  1059  	namespaceID primitives.UUID,
  1060  	workflowID string,
  1061  	runID primitives.UUID,
  1062  	createRequestID string,
  1063  	state enumsspb.WorkflowExecutionState,
  1064  	status enumspb.WorkflowExecutionStatus,
  1065  	lastWriteVersion int64,
  1066  ) error {
  1067  
  1068  	result, err := tx.UpdateCurrentExecutions(ctx, &sqlplugin.CurrentExecutionsRow{
  1069  		ShardID:          shardID,
  1070  		NamespaceID:      namespaceID,
  1071  		WorkflowID:       workflowID,
  1072  		RunID:            runID,
  1073  		CreateRequestID:  createRequestID,
  1074  		State:            state,
  1075  		Status:           status,
  1076  		LastWriteVersion: lastWriteVersion,
  1077  	})
  1078  	if err != nil {
  1079  		return serviceerror.NewUnavailable(fmt.Sprintf("updateCurrentExecution failed. Error: %v", err))
  1080  	}
  1081  	rowsAffected, err := result.RowsAffected()
  1082  	if err != nil {
  1083  		return serviceerror.NewUnavailable(fmt.Sprintf("updateCurrentExecution failed. Failed to check number of rows updated in current_executions table. Error: %v", err))
  1084  	}
  1085  	if rowsAffected != 1 {
  1086  		return serviceerror.NewUnavailable(fmt.Sprintf("updateCurrentExecution failed. %v rows of current_executions updated instead of 1.", rowsAffected))
  1087  	}
  1088  	return nil
  1089  }
  1090  
  1091  func buildExecutionRow(
  1092  	namespaceID string,
  1093  	workflowID string,
  1094  	executionInfo *commonpb.DataBlob,
  1095  	executionState *persistencespb.WorkflowExecutionState,
  1096  	nextEventID int64,
  1097  	lastWriteVersion int64,
  1098  	dbRecordVersion int64,
  1099  	shardID int32,
  1100  ) (row *sqlplugin.ExecutionsRow, err error) {
  1101  
  1102  	stateBlob, err := serialization.WorkflowExecutionStateToBlob(executionState)
  1103  	if err != nil {
  1104  		return nil, err
  1105  	}
  1106  
  1107  	nsBytes, err := primitives.ParseUUID(namespaceID)
  1108  	if err != nil {
  1109  		return nil, err
  1110  	}
  1111  
  1112  	ridBytes, err := primitives.ParseUUID(executionState.RunId)
  1113  	if err != nil {
  1114  		return nil, err
  1115  	}
  1116  
  1117  	return &sqlplugin.ExecutionsRow{
  1118  		ShardID:          shardID,
  1119  		NamespaceID:      nsBytes,
  1120  		WorkflowID:       workflowID,
  1121  		RunID:            ridBytes,
  1122  		NextEventID:      nextEventID,
  1123  		LastWriteVersion: lastWriteVersion,
  1124  		Data:             executionInfo.Data,
  1125  		DataEncoding:     executionInfo.EncodingType.String(),
  1126  		State:            stateBlob.Data,
  1127  		StateEncoding:    stateBlob.EncodingType.String(),
  1128  		DBRecordVersion:  dbRecordVersion,
  1129  	}, nil
  1130  }
  1131  
  1132  func (m *sqlExecutionStore) createExecution(
  1133  	ctx context.Context,
  1134  	tx sqlplugin.Tx,
  1135  	namespaceID string,
  1136  	workflowID string,
  1137  	executionInfo *commonpb.DataBlob,
  1138  	executionState *persistencespb.WorkflowExecutionState,
  1139  	nextEventID int64,
  1140  	lastWriteVersion int64,
  1141  	dbRecordVersion int64,
  1142  	shardID int32,
  1143  ) error {
  1144  
  1145  	row, err := buildExecutionRow(
  1146  		namespaceID,
  1147  		workflowID,
  1148  		executionInfo,
  1149  		executionState,
  1150  		nextEventID,
  1151  		lastWriteVersion,
  1152  		dbRecordVersion,
  1153  		shardID,
  1154  	)
  1155  	if err != nil {
  1156  		return err
  1157  	}
  1158  	result, err := tx.InsertIntoExecutions(ctx, row)
  1159  	if err != nil {
  1160  		if m.Db.IsDupEntryError(err) {
  1161  			return &p.WorkflowConditionFailedError{
  1162  				Msg:             fmt.Sprintf("Workflow execution already running. WorkflowId: %v", workflowID),
  1163  				NextEventID:     0,
  1164  				DBRecordVersion: 0,
  1165  			}
  1166  		}
  1167  		return serviceerror.NewUnavailable(fmt.Sprintf("createExecution failed. Erorr: %v", err))
  1168  	}
  1169  	rowsAffected, err := result.RowsAffected()
  1170  	if err != nil {
  1171  		return serviceerror.NewUnavailable(fmt.Sprintf("createExecution failed. Failed to verify number of rows affected. Erorr: %v", err))
  1172  	}
  1173  	if rowsAffected != 1 {
  1174  		return serviceerror.NewNotFound(fmt.Sprintf("createExecution failed. Affected %v rows updated instead of 1.", rowsAffected))
  1175  	}
  1176  
  1177  	return nil
  1178  }
  1179  
  1180  func updateExecution(
  1181  	ctx context.Context,
  1182  	tx sqlplugin.Tx,
  1183  	namespaceID string,
  1184  	workflowID string,
  1185  	executionInfo *commonpb.DataBlob,
  1186  	executionState *persistencespb.WorkflowExecutionState,
  1187  	nextEventID int64,
  1188  	lastWriteVersion int64,
  1189  	dbRecordVersion int64,
  1190  	shardID int32,
  1191  ) error {
  1192  	row, err := buildExecutionRow(
  1193  		namespaceID,
  1194  		workflowID,
  1195  		executionInfo,
  1196  		executionState,
  1197  		nextEventID,
  1198  		lastWriteVersion,
  1199  		dbRecordVersion,
  1200  		shardID,
  1201  	)
  1202  	if err != nil {
  1203  		return err
  1204  	}
  1205  	result, err := tx.UpdateExecutions(ctx, row)
  1206  	if err != nil {
  1207  		return serviceerror.NewUnavailable(fmt.Sprintf("updateExecution failed. Erorr: %v", err))
  1208  	}
  1209  	rowsAffected, err := result.RowsAffected()
  1210  	if err != nil {
  1211  		return serviceerror.NewUnavailable(fmt.Sprintf("updateExecution failed. Failed to verify number of rows affected. Erorr: %v", err))
  1212  	}
  1213  	if rowsAffected != 1 {
  1214  		return serviceerror.NewNotFound(fmt.Sprintf("updateExecution failed. Affected %v rows updated instead of 1.", rowsAffected))
  1215  	}
  1216  
  1217  	return nil
  1218  }