Files
tasks/common/persistence/sql/sqlplugin/mysql/execution.go
T
Alex Shtin b8169a84bf Merge remote-tracking branch 'cadence/master' into merge/cadence-12-19-19
Conflicts:
	.gen/go/history/history.go
	.gen/go/temporal/temporal.go
	cmd/server/cadence/cadence.go
	cmd/server/cadence/server.go
	cmd/tools/sql/main.go
	common/service/service.go
	docs/persistence.md
	go.mod
	go.sum
	service/frontend/dcRedirectionHandler.go
	service/frontend/service.go
	service/history/conflictResolver_test.go
	service/history/historyBuilder_test.go
	service/history/historyCache_test.go
	service/history/historyEngine.go
	service/history/historyEngine2_test.go
	service/history/historyEngine3_eventsv2_test.go
	service/history/historyEngine_test.go
	service/history/historyReplicator_test.go
	service/history/mutableStateBuilder_test.go
	service/history/nDCActivityReplicator_test.go
	service/history/nDCBranchMgr_test.go
	service/history/nDCConflictResolver_test.go
	service/history/nDCStateRebuilder_test.go
	service/history/nDCTransactionMgr_test.go
	service/history/nDCWorkflowResetter_test.go
	service/history/queueAckMgr_test.go
	service/history/replicatorQueueProcessor_test.go
	service/history/shardController_test.go
	service/history/stateBuilder_test.go
	service/history/taskProcessor_test.go
	service/history/timerQueueAckMgr_test.go
	service/history/timerQueueActiveProcessor_test.go
	service/history/timerQueueProcessorBase_test.go
	service/history/timerQueueStandbyProcessor_test.go
	service/history/transferQueueActiveProcessor_test.go
	service/history/transferQueueStandbyProcessor_test.go
	service/history/workflowResetor_test.go
	service/history/workflowResetter_test.go
	service/matching/handler.go
2019-12-19 16:07:20 -08:00

341 lines
16 KiB
Go

// Copyright (c) 2017 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package mysql
import (
"database/sql"
"github.com/temporalio/temporal/common/persistence/sql/sqlplugin"
)
const (
executionsColumns = `shard_id, domain_id, workflow_id, run_id, next_event_id, last_write_version, data, data_encoding`
createExecutionQuery = `INSERT INTO executions(` + executionsColumns + `)
VALUES(:shard_id, :domain_id, :workflow_id, :run_id, :next_event_id, :last_write_version, :data, :data_encoding)`
updateExecutionQuery = `UPDATE executions SET
next_event_id = :next_event_id, last_write_version = :last_write_version, data = :data, data_encoding = :data_encoding
WHERE shard_id = :shard_id AND domain_id = :domain_id AND workflow_id = :workflow_id AND run_id = :run_id`
getExecutionQuery = `SELECT ` + executionsColumns + ` FROM executions
WHERE shard_id = ? AND domain_id = ? AND workflow_id = ? AND run_id = ?`
deleteExecutionQuery = `DELETE FROM executions
WHERE shard_id = ? AND domain_id = ? AND workflow_id = ? AND run_id = ?`
lockExecutionQueryBase = `SELECT next_event_id FROM executions
WHERE shard_id = ? AND domain_id = ? AND workflow_id = ? AND run_id = ?`
writeLockExecutionQuery = lockExecutionQueryBase + ` FOR UPDATE`
readLockExecutionQuery = lockExecutionQueryBase + ` LOCK IN SHARE MODE`
createCurrentExecutionQuery = `INSERT INTO current_executions
(shard_id, domain_id, workflow_id, run_id, create_request_id, state, close_status, start_version, last_write_version) VALUES
(:shard_id, :domain_id, :workflow_id, :run_id, :create_request_id, :state, :close_status, :start_version, :last_write_version)`
deleteCurrentExecutionQuery = "DELETE FROM current_executions WHERE shard_id=? AND domain_id=? AND workflow_id=? AND run_id=?"
getCurrentExecutionQuery = `SELECT
shard_id, domain_id, workflow_id, run_id, create_request_id, state, close_status, start_version, last_write_version
FROM current_executions WHERE shard_id = ? AND domain_id = ? AND workflow_id = ?`
lockCurrentExecutionJoinExecutionsQuery = `SELECT
ce.shard_id, ce.domain_id, ce.workflow_id, ce.run_id, ce.create_request_id, ce.state, ce.close_status, ce.start_version, e.last_write_version
FROM current_executions ce
INNER JOIN executions e ON e.shard_id = ce.shard_id AND e.domain_id = ce.domain_id AND e.workflow_id = ce.workflow_id AND e.run_id = ce.run_id
WHERE ce.shard_id = ? AND ce.domain_id = ? AND ce.workflow_id = ? FOR UPDATE`
lockCurrentExecutionQuery = getCurrentExecutionQuery + ` FOR UPDATE`
updateCurrentExecutionsQuery = `UPDATE current_executions SET
run_id = :run_id,
create_request_id = :create_request_id,
state = :state,
close_status = :close_status,
start_version = :start_version,
last_write_version = :last_write_version
WHERE
shard_id = :shard_id AND
domain_id = :domain_id AND
workflow_id = :workflow_id
`
getTransferTasksQuery = `SELECT task_id, data, data_encoding
FROM transfer_tasks WHERE shard_id = ? AND task_id > ? AND task_id <= ? ORDER BY shard_id, task_id`
createTransferTasksQuery = `INSERT INTO transfer_tasks(shard_id, task_id, data, data_encoding)
VALUES(:shard_id, :task_id, :data, :data_encoding)`
deleteTransferTaskQuery = `DELETE FROM transfer_tasks WHERE shard_id = ? AND task_id = ?`
rangeDeleteTransferTaskQuery = `DELETE FROM transfer_tasks WHERE shard_id = ? AND task_id > ? AND task_id <= ?`
createTimerTasksQuery = `INSERT INTO timer_tasks (shard_id, visibility_timestamp, task_id, data, data_encoding)
VALUES (:shard_id, :visibility_timestamp, :task_id, :data, :data_encoding)`
getTimerTasksQuery = `SELECT visibility_timestamp, task_id, data, data_encoding FROM timer_tasks
WHERE shard_id = ?
AND ((visibility_timestamp >= ? AND task_id >= ?) OR visibility_timestamp > ?)
AND visibility_timestamp < ?
ORDER BY visibility_timestamp,task_id LIMIT ?`
deleteTimerTaskQuery = `DELETE FROM timer_tasks WHERE shard_id = ? AND visibility_timestamp = ? AND task_id = ?`
rangeDeleteTimerTaskQuery = `DELETE FROM timer_tasks WHERE shard_id = ? AND visibility_timestamp >= ? AND visibility_timestamp < ?`
createReplicationTasksQuery = `INSERT INTO replication_tasks (shard_id, task_id, data, data_encoding)
VALUES(:shard_id, :task_id, :data, :data_encoding)`
getReplicationTasksQuery = `SELECT task_id, data, data_encoding FROM replication_tasks WHERE
shard_id = ? AND
task_id > ? AND
task_id <= ?
ORDER BY task_id LIMIT ?`
deleteReplicationTaskQuery = `DELETE FROM replication_tasks WHERE shard_id = ? AND task_id = ?`
rangeDeleteReplicationTaskQuery = `DELETE FROM replication_tasks WHERE shard_id = ? AND task_id <= ?`
getReplicationTasksDLQQuery = `SELECT task_id, data, data_encoding FROM replication_tasks_dlq WHERE
source_cluster_name = ? AND
shard_id = ? AND
task_id > ? AND
task_id <= ?
ORDER BY task_id LIMIT ?`
bufferedEventsColumns = `shard_id, domain_id, workflow_id, run_id, data, data_encoding`
createBufferedEventsQuery = `INSERT INTO buffered_events(` + bufferedEventsColumns + `)
VALUES (:shard_id, :domain_id, :workflow_id, :run_id, :data, :data_encoding)`
deleteBufferedEventsQuery = `DELETE FROM buffered_events WHERE shard_id=? AND domain_id=? AND workflow_id=? AND run_id=?`
getBufferedEventsQuery = `SELECT data, data_encoding FROM buffered_events WHERE
shard_id=? AND domain_id=? AND workflow_id=? AND run_id=?`
insertReplicationTaskDLQQuery = `
INSERT INTO replication_tasks_dlq
(source_cluster_name,
shard_id,
task_id,
data,
data_encoding)
VALUES (:source_cluster_name,
:shard_id,
:task_id,
:data,
:data_encoding)
`
)
// InsertIntoExecutions inserts a row into executions table
func (mdb *db) InsertIntoExecutions(row *sqlplugin.ExecutionsRow) (sql.Result, error) {
return mdb.conn.NamedExec(createExecutionQuery, row)
}
// UpdateExecutions updates a single row in executions table
func (mdb *db) UpdateExecutions(row *sqlplugin.ExecutionsRow) (sql.Result, error) {
return mdb.conn.NamedExec(updateExecutionQuery, row)
}
// SelectFromExecutions reads a single row from executions table
func (mdb *db) SelectFromExecutions(filter *sqlplugin.ExecutionsFilter) (*sqlplugin.ExecutionsRow, error) {
var row sqlplugin.ExecutionsRow
err := mdb.conn.Get(&row, getExecutionQuery, filter.ShardID, filter.DomainID, filter.WorkflowID, filter.RunID)
if err != nil {
return nil, err
}
return &row, err
}
// DeleteFromExecutions deletes a single row from executions table
func (mdb *db) DeleteFromExecutions(filter *sqlplugin.ExecutionsFilter) (sql.Result, error) {
return mdb.conn.Exec(deleteExecutionQuery, filter.ShardID, filter.DomainID, filter.WorkflowID, filter.RunID)
}
// ReadLockExecutions acquires a write lock on a single row in executions table
func (mdb *db) ReadLockExecutions(filter *sqlplugin.ExecutionsFilter) (int, error) {
var nextEventID int
err := mdb.conn.Get(&nextEventID, readLockExecutionQuery, filter.ShardID, filter.DomainID, filter.WorkflowID, filter.RunID)
return nextEventID, err
}
// WriteLockExecutions acquires a write lock on a single row in executions table
func (mdb *db) WriteLockExecutions(filter *sqlplugin.ExecutionsFilter) (int, error) {
var nextEventID int
err := mdb.conn.Get(&nextEventID, writeLockExecutionQuery, filter.ShardID, filter.DomainID, filter.WorkflowID, filter.RunID)
return nextEventID, err
}
// InsertIntoCurrentExecutions inserts a single row into current_executions table
func (mdb *db) InsertIntoCurrentExecutions(row *sqlplugin.CurrentExecutionsRow) (sql.Result, error) {
return mdb.conn.NamedExec(createCurrentExecutionQuery, row)
}
// UpdateCurrentExecutions updates a single row in current_executions table
func (mdb *db) UpdateCurrentExecutions(row *sqlplugin.CurrentExecutionsRow) (sql.Result, error) {
return mdb.conn.NamedExec(updateCurrentExecutionsQuery, row)
}
// SelectFromCurrentExecutions reads one or more rows from current_executions table
func (mdb *db) SelectFromCurrentExecutions(filter *sqlplugin.CurrentExecutionsFilter) (*sqlplugin.CurrentExecutionsRow, error) {
var row sqlplugin.CurrentExecutionsRow
err := mdb.conn.Get(&row, getCurrentExecutionQuery, filter.ShardID, filter.DomainID, filter.WorkflowID)
return &row, err
}
// DeleteFromCurrentExecutions deletes a single row in current_executions table
func (mdb *db) DeleteFromCurrentExecutions(filter *sqlplugin.CurrentExecutionsFilter) (sql.Result, error) {
return mdb.conn.Exec(deleteCurrentExecutionQuery, filter.ShardID, filter.DomainID, filter.WorkflowID, filter.RunID)
}
// LockCurrentExecutions acquires a write lock on a single row in current_executions table
func (mdb *db) LockCurrentExecutions(filter *sqlplugin.CurrentExecutionsFilter) (*sqlplugin.CurrentExecutionsRow, error) {
var row sqlplugin.CurrentExecutionsRow
err := mdb.conn.Get(&row, lockCurrentExecutionQuery, filter.ShardID, filter.DomainID, filter.WorkflowID)
return &row, err
}
// LockCurrentExecutionsJoinExecutions joins a row in current_executions with executions table and acquires a
// write lock on the result
func (mdb *db) LockCurrentExecutionsJoinExecutions(filter *sqlplugin.CurrentExecutionsFilter) ([]sqlplugin.CurrentExecutionsRow, error) {
var rows []sqlplugin.CurrentExecutionsRow
err := mdb.conn.Select(&rows, lockCurrentExecutionJoinExecutionsQuery, filter.ShardID, filter.DomainID, filter.WorkflowID)
return rows, err
}
// InsertIntoTransferTasks inserts one or more rows into transfer_tasks table
func (mdb *db) InsertIntoTransferTasks(rows []sqlplugin.TransferTasksRow) (sql.Result, error) {
return mdb.conn.NamedExec(createTransferTasksQuery, rows)
}
// SelectFromTransferTasks reads one or more rows from transfer_tasks table
func (mdb *db) SelectFromTransferTasks(filter *sqlplugin.TransferTasksFilter) ([]sqlplugin.TransferTasksRow, error) {
var rows []sqlplugin.TransferTasksRow
err := mdb.conn.Select(&rows, getTransferTasksQuery, filter.ShardID, *filter.MinTaskID, *filter.MaxTaskID)
if err != nil {
return nil, err
}
return rows, err
}
// DeleteFromTransferTasks deletes one or more rows from transfer_tasks table
func (mdb *db) DeleteFromTransferTasks(filter *sqlplugin.TransferTasksFilter) (sql.Result, error) {
if filter.MinTaskID != nil {
return mdb.conn.Exec(rangeDeleteTransferTaskQuery, filter.ShardID, *filter.MinTaskID, *filter.MaxTaskID)
}
return mdb.conn.Exec(deleteTransferTaskQuery, filter.ShardID, *filter.TaskID)
}
// InsertIntoTimerTasks inserts one or more rows into timer_tasks table
func (mdb *db) InsertIntoTimerTasks(rows []sqlplugin.TimerTasksRow) (sql.Result, error) {
for i := range rows {
rows[i].VisibilityTimestamp = mdb.converter.ToMySQLDateTime(rows[i].VisibilityTimestamp)
}
return mdb.conn.NamedExec(createTimerTasksQuery, rows)
}
// SelectFromTimerTasks reads one or more rows from timer_tasks table
func (mdb *db) SelectFromTimerTasks(filter *sqlplugin.TimerTasksFilter) ([]sqlplugin.TimerTasksRow, error) {
var rows []sqlplugin.TimerTasksRow
*filter.MinVisibilityTimestamp = mdb.converter.ToMySQLDateTime(*filter.MinVisibilityTimestamp)
*filter.MaxVisibilityTimestamp = mdb.converter.ToMySQLDateTime(*filter.MaxVisibilityTimestamp)
err := mdb.conn.Select(&rows, getTimerTasksQuery, filter.ShardID, *filter.MinVisibilityTimestamp,
filter.TaskID, *filter.MinVisibilityTimestamp, *filter.MaxVisibilityTimestamp, *filter.PageSize)
if err != nil {
return nil, err
}
for i := range rows {
rows[i].VisibilityTimestamp = mdb.converter.FromMySQLDateTime(rows[i].VisibilityTimestamp)
}
return rows, err
}
// DeleteFromTimerTasks deletes one or more rows from timer_tasks table
func (mdb *db) DeleteFromTimerTasks(filter *sqlplugin.TimerTasksFilter) (sql.Result, error) {
if filter.MinVisibilityTimestamp != nil {
*filter.MinVisibilityTimestamp = mdb.converter.ToMySQLDateTime(*filter.MinVisibilityTimestamp)
*filter.MaxVisibilityTimestamp = mdb.converter.ToMySQLDateTime(*filter.MaxVisibilityTimestamp)
return mdb.conn.Exec(rangeDeleteTimerTaskQuery, filter.ShardID, *filter.MinVisibilityTimestamp, *filter.MaxVisibilityTimestamp)
}
*filter.VisibilityTimestamp = mdb.converter.ToMySQLDateTime(*filter.VisibilityTimestamp)
return mdb.conn.Exec(deleteTimerTaskQuery, filter.ShardID, *filter.VisibilityTimestamp, filter.TaskID)
}
// InsertIntoBufferedEvents inserts one or more rows into buffered_events table
func (mdb *db) InsertIntoBufferedEvents(rows []sqlplugin.BufferedEventsRow) (sql.Result, error) {
return mdb.conn.NamedExec(createBufferedEventsQuery, rows)
}
// SelectFromBufferedEvents reads one or more rows from buffered_events table
func (mdb *db) SelectFromBufferedEvents(filter *sqlplugin.BufferedEventsFilter) ([]sqlplugin.BufferedEventsRow, error) {
var rows []sqlplugin.BufferedEventsRow
err := mdb.conn.Select(&rows, getBufferedEventsQuery, filter.ShardID, filter.DomainID, filter.WorkflowID, filter.RunID)
for i := 0; i < len(rows); i++ {
rows[i].DomainID = filter.DomainID
rows[i].WorkflowID = filter.WorkflowID
rows[i].RunID = filter.RunID
rows[i].ShardID = filter.ShardID
}
return rows, err
}
// DeleteFromBufferedEvents deletes one or more rows from buffered_events table
func (mdb *db) DeleteFromBufferedEvents(filter *sqlplugin.BufferedEventsFilter) (sql.Result, error) {
return mdb.conn.Exec(deleteBufferedEventsQuery, filter.ShardID, filter.DomainID, filter.WorkflowID, filter.RunID)
}
// InsertIntoReplicationTasks inserts one or more rows into replication_tasks table
func (mdb *db) InsertIntoReplicationTasks(rows []sqlplugin.ReplicationTasksRow) (sql.Result, error) {
return mdb.conn.NamedExec(createReplicationTasksQuery, rows)
}
// SelectFromReplicationTasks reads one or more rows from replication_tasks table
func (mdb *db) SelectFromReplicationTasks(filter *sqlplugin.ReplicationTasksFilter) ([]sqlplugin.ReplicationTasksRow, error) {
var rows []sqlplugin.ReplicationTasksRow
err := mdb.conn.Select(&rows, getReplicationTasksQuery, filter.ShardID, filter.MinTaskID, filter.MaxTaskID, filter.PageSize)
return rows, err
}
// DeleteFromReplicationTasks deletes one row from replication_tasks table
func (mdb *db) DeleteFromReplicationTasks(filter *sqlplugin.ReplicationTasksFilter) (sql.Result, error) {
return mdb.conn.Exec(deleteReplicationTaskQuery, filter.ShardID, filter.TaskID)
}
// RangeDeleteFromReplicationTasks deletes multi rows from replication_tasks table
func (mdb *db) RangeDeleteFromReplicationTasks(filter *sqlplugin.ReplicationTasksFilter) (sql.Result, error) {
return mdb.conn.Exec(rangeDeleteReplicationTaskQuery, filter.ShardID, filter.InclusiveEndTaskID)
}
// InsertIntoReplicationTasksDLQ inserts one or more rows into replication_tasks_dlq table
func (mdb *db) InsertIntoReplicationTasksDLQ(row *sqlplugin.ReplicationTaskDLQRow) (sql.Result, error) {
return mdb.conn.NamedExec(insertReplicationTaskDLQQuery, row)
}
// SelectFromReplicationTasksDLQ reads one or more rows from replication_tasks_dlq table
func (mdb *db) SelectFromReplicationTasksDLQ(filter *sqlplugin.ReplicationTasksDLQFilter) ([]sqlplugin.ReplicationTasksRow, error) {
var rows []sqlplugin.ReplicationTasksRow
err := mdb.conn.Select(
&rows, getReplicationTasksDLQQuery,
filter.SourceClusterName,
filter.ShardID,
filter.MinTaskID,
filter.MaxTaskID,
filter.PageSize)
return rows, err
}