Remove support for standard visibility (#5387)

## What changed?
<!-- Describe what has changed in this PR -->
Remove support for standard visibility

## Why?
<!-- Tell your future self why have you made these changes -->
Standard visibility is deprecated.

## How did you test it?
<!-- How have you verified this change? Tested locally? Added a unit
test? Checked in staging env? -->

## Potential risks
<!-- Assuming the worst case, what can be broken when deploying this
change to production? -->

## Is hotfix candidate?
<!-- Is this PR a hotfix candidate or does it require a notification to
be sent to the broader community? (Yes/No) -->
This commit is contained in:
Rodrigo Zhou
2024-02-29 12:05:20 -06:00
committed by GitHub
parent 39ec799966
commit f6937601ef
126 changed files with 405 additions and 5437 deletions

View File

@@ -133,7 +133,7 @@ jobs:
fail-fast: false
matrix:
runs-on: [ubuntu-latest]
name: [cass_es, cass_es8, sqlite, mysql, mysql8, postgres, postgres_pgx, postgres12, postgres12_pgx]
name: [cass_es, cass_es8, sqlite, mysql8, postgres12, postgres12_pgx]
shard_index: [0, 1, 2]
include:
- name: cass_es
@@ -148,22 +148,10 @@ jobs:
persistence_type: sql
persistence_driver: sqlite
containers: []
- name: mysql
persistence_type: sql
persistence_driver: mysql
containers: [mysql, elasticsearch]
- name: mysql8
persistence_type: sql
persistence_driver: mysql8
containers: [mysql]
- name: postgres
persistence_type: sql
persistence_driver: postgres
containers: [postgresql, elasticsearch]
- name: postgres_pgx
persistence_type: sql
persistence_driver: postgres_pgx
containers: [postgresql, elasticsearch]
- name: postgres12
persistence_type: sql
persistence_driver: postgres12
@@ -214,7 +202,7 @@ jobs:
fail-fast: false
matrix:
runs-on: [ubuntu-latest]
name: [cass_es, cass_es8, mysql, mysql8, postgres, postgres_pgx, postgres12, postgres12_pgx]
name: [cass_es, cass_es8, mysql8, postgres12, postgres12_pgx]
include:
- name: cass_es
persistence_type: nosql
@@ -224,22 +212,10 @@ jobs:
persistence_type: nosql
persistence_driver: elasticsearch
containers: [cassandra, elasticsearch8]
- name: mysql
persistence_type: sql
persistence_driver: mysql
containers: [mysql, elasticsearch]
- name: mysql8
persistence_type: sql
persistence_driver: mysql8
containers: [mysql]
- name: postgres
persistence_type: sql
persistence_driver: postgres12
containers: [postgresql, elasticsearch]
- name: postgres_pgx
persistence_type: sql
persistence_driver: postgres12_pgx
containers: [postgresql, elasticsearch]
- name: postgres12
persistence_type: sql
persistence_driver: postgres12
@@ -288,7 +264,7 @@ jobs:
fail-fast: false
matrix:
runs-on: [ubuntu-latest]
name: [cass_es, cass_es8, mysql, mysql8, postgres, postgres_pgx, postgres12, postgres12_pgx]
name: [cass_es, cass_es8, mysql8, postgres12, postgres12_pgx]
include:
- name: cass_es
persistence_type: nosql
@@ -298,22 +274,10 @@ jobs:
persistence_type: nosql
persistence_driver: elasticsearch
containers: [cassandra, elasticsearch8]
- name: mysql
persistence_type: sql
persistence_driver: mysql
containers: [mysql, elasticsearch]
- name: mysql8
persistence_type: sql
persistence_driver: mysql8
containers: [mysql]
- name: postgres
persistence_type: sql
persistence_driver: postgres12
containers: [postgresql, elasticsearch]
- name: postgres_pgx
persistence_type: sql
persistence_driver: postgres12_pgx
containers: [postgresql, elasticsearch]
- name: postgres12
persistence_type: sql
persistence_driver: postgres12

View File

@@ -396,49 +396,31 @@ install-schema-cass-es: temporal-cassandra-tool install-schema-es
./temporal-cassandra-tool -k $(TEMPORAL_DB) setup-schema -v 0.0
./temporal-cassandra-tool -k $(TEMPORAL_DB) update-schema -d ./schema/cassandra/temporal/versioned
install-schema-mysql: temporal-sql-tool
@printf $(COLOR) "Install MySQL schema..."
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) --db $(TEMPORAL_DB) drop -f
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) --db $(TEMPORAL_DB) create
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) --db $(TEMPORAL_DB) setup-schema -v 0.0
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) --db $(TEMPORAL_DB) update-schema -d ./schema/mysql/v57/temporal/versioned
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) --db $(VISIBILITY_DB) drop -f
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) --db $(VISIBILITY_DB) create
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) --db $(VISIBILITY_DB) setup-schema -v 0.0
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) --db $(VISIBILITY_DB) update-schema -d ./schema/mysql/v57/visibility/versioned
install-schema-mysql: install-schema-mysql8
install-schema-mysql8: temporal-sql-tool
@printf $(COLOR) "Install MySQL schema..."
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) --db $(TEMPORAL_DB) drop -f
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) --db $(TEMPORAL_DB) create
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) --db $(TEMPORAL_DB) setup-schema -v 0.0
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) --db $(TEMPORAL_DB) update-schema -d ./schema/mysql/v8/temporal/versioned
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) --db $(VISIBILITY_DB) drop -f
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) --db $(VISIBILITY_DB) create
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) --db $(VISIBILITY_DB) setup-schema -v 0.0
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) --db $(VISIBILITY_DB) update-schema -d ./schema/mysql/v8/visibility/versioned
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) --pl mysql8 --db $(TEMPORAL_DB) drop -f
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) --pl mysql8 --db $(TEMPORAL_DB) create
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) --pl mysql8 --db $(TEMPORAL_DB) setup-schema -v 0.0
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) --pl mysql8 --db $(TEMPORAL_DB) update-schema -d ./schema/mysql/v8/temporal/versioned
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) --pl mysql8 --db $(VISIBILITY_DB) drop -f
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) --pl mysql8 --db $(VISIBILITY_DB) create
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) --pl mysql8 --db $(VISIBILITY_DB) setup-schema -v 0.0
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) --pl mysql8 --db $(VISIBILITY_DB) update-schema -d ./schema/mysql/v8/visibility/versioned
install-schema-postgresql: temporal-sql-tool
@printf $(COLOR) "Install Postgres schema..."
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) -p 5432 --pl postgres --db $(TEMPORAL_DB) drop -f
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) -p 5432 --pl postgres --db $(TEMPORAL_DB) create
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) -p 5432 --pl postgres --db $(TEMPORAL_DB) setup -v 0.0
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) -p 5432 --pl postgres --db $(TEMPORAL_DB) update-schema -d ./schema/postgresql/v96/temporal/versioned
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) -p 5432 --pl postgres --db $(VISIBILITY_DB) drop -f
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) -p 5432 --pl postgres --db $(VISIBILITY_DB) create
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) -p 5432 --pl postgres --db $(VISIBILITY_DB) setup-schema -v 0.0
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) -p 5432 --pl postgres --db $(VISIBILITY_DB) update-schema -d ./schema/postgresql/v96/visibility/versioned
install-schema-postgresql: install-schema-postgresql12
install-schema-postgresql12: temporal-sql-tool
@printf $(COLOR) "Install Postgres schema..."
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) -p 5432 --pl postgres --db $(TEMPORAL_DB) drop -f
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) -p 5432 --pl postgres --db $(TEMPORAL_DB) create
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) -p 5432 --pl postgres --db $(TEMPORAL_DB) setup -v 0.0
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) -p 5432 --pl postgres --db $(TEMPORAL_DB) update-schema -d ./schema/postgresql/v12/temporal/versioned
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) -p 5432 --pl postgres --db $(VISIBILITY_DB) drop -f
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) -p 5432 --pl postgres --db $(VISIBILITY_DB) create
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) -p 5432 --pl postgres --db $(VISIBILITY_DB) setup-schema -v 0.0
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) -p 5432 --pl postgres --db $(VISIBILITY_DB) update-schema -d ./schema/postgresql/v12/visibility/versioned
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) -p 5432 --pl postgres12 --db $(TEMPORAL_DB) drop -f
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) -p 5432 --pl postgres12 --db $(TEMPORAL_DB) create
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) -p 5432 --pl postgres12 --db $(TEMPORAL_DB) setup -v 0.0
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) -p 5432 --pl postgres12 --db $(TEMPORAL_DB) update-schema -d ./schema/postgresql/v12/temporal/versioned
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) -p 5432 --pl postgres12 --db $(VISIBILITY_DB) drop -f
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) -p 5432 --pl postgres12 --db $(VISIBILITY_DB) create
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) -p 5432 --pl postgres12 --db $(VISIBILITY_DB) setup-schema -v 0.0
./temporal-sql-tool -u $(SQL_USER) --pw $(SQL_PASSWORD) -p 5432 --pl postgres12 --db $(VISIBILITY_DB) update-schema -d ./schema/postgresql/v12/visibility/versioned
install-schema-es:
@printf $(COLOR) "Install Elasticsearch schema..."
@@ -500,8 +482,7 @@ start-cass-es: temporal-server
start-es-fi: temporal-server
./temporal-server --env development-cass-es-fi --allow-no-auth start
start-mysql: temporal-server
./temporal-server --env development-mysql --allow-no-auth start
start-mysql: start-mysql8
start-mysql8: temporal-server
./temporal-server --env development-mysql8 --allow-no-auth start
@@ -509,8 +490,7 @@ start-mysql8: temporal-server
start-mysql-es: temporal-server
./temporal-server --env development-mysql-es --allow-no-auth start
start-postgres: temporal-server
./temporal-server --env development-postgres --allow-no-auth start
start-postgres: start-postgres12
start-postgres12: temporal-server
./temporal-server --env development-postgres12 --allow-no-auth start

View File

@@ -149,9 +149,9 @@ func NewTestBaseWithSQL(options *TestBaseOptions) *TestBase {
if options.DBPort == 0 {
switch options.SQLDBPluginName {
case mysql.PluginName, mysql.PluginNameV8:
case mysql.PluginNameV8:
options.DBPort = environment.GetMySQLPort()
case postgresql.PluginName, postgresql.PluginNamePGX, postgresql.PluginNameV12, postgresql.PluginNameV12PGX:
case postgresql.PluginNameV12, postgresql.PluginNameV12PGX:
options.DBPort = environment.GetPostgreSQLPort()
case sqlite.PluginName:
options.DBPort = 0
@@ -161,9 +161,9 @@ func NewTestBaseWithSQL(options *TestBaseOptions) *TestBase {
}
if options.DBHost == "" {
switch options.SQLDBPluginName {
case mysql.PluginName, mysql.PluginNameV8:
case mysql.PluginNameV8:
options.DBHost = environment.GetMySQLAddress()
case postgresql.PluginName, postgresql.PluginNamePGX:
case postgresql.PluginNameV12, postgresql.PluginNameV12PGX:
options.DBHost = environment.GetPostgreSQLAddress()
case sqlite.PluginName:
options.DBHost = environment.GetLocalhostIP()

View File

@@ -35,12 +35,10 @@ import (
const (
testMySQLUser = "temporal"
testMySQLPassword = "temporal"
testMySQLSchemaDir = "schema/mysql/v57"
testMySQL8SchemaDir = "schema/mysql/v8"
testPostgreSQLUser = "temporal"
testPostgreSQLPassword = "temporal"
testPostgreSQLSchemaDir = "schema/postgresql/v96"
testPostgreSQL12SchemaDir = "schema/postgresql/v12"
testSQLiteUser = ""
@@ -50,19 +48,6 @@ const (
testSQLiteSchemaDir = "schema/sqlite/v3" // specify if mode is not "memory"
)
// GetMySQLTestClusterOption return test options
func GetMySQLTestClusterOption() *TestBaseOptions {
return &TestBaseOptions{
SQLDBPluginName: mysql.PluginName,
DBUsername: testMySQLUser,
DBPassword: testMySQLPassword,
DBHost: environment.GetMySQLAddress(),
DBPort: environment.GetMySQLPort(),
SchemaDir: testMySQLSchemaDir,
StoreType: config.StoreTypeSQL,
}
}
// GetMySQL8TestClusterOption return test options
func GetMySQL8TestClusterOption() *TestBaseOptions {
return &TestBaseOptions{
@@ -76,32 +61,6 @@ func GetMySQL8TestClusterOption() *TestBaseOptions {
}
}
// GetPostgreSQLTestClusterOption return test options
func GetPostgreSQLTestClusterOption() *TestBaseOptions {
return &TestBaseOptions{
SQLDBPluginName: postgresql.PluginName,
DBUsername: testPostgreSQLUser,
DBPassword: testPostgreSQLPassword,
DBHost: environment.GetPostgreSQLAddress(),
DBPort: environment.GetPostgreSQLPort(),
SchemaDir: testPostgreSQLSchemaDir,
StoreType: config.StoreTypeSQL,
}
}
// GetPostgreSQLPGXTestClusterOption return test options
func GetPostgreSQLPGXTestClusterOption() *TestBaseOptions {
return &TestBaseOptions{
SQLDBPluginName: postgresql.PluginNamePGX,
DBUsername: testPostgreSQLUser,
DBPassword: testPostgreSQLPassword,
DBHost: environment.GetPostgreSQLAddress(),
DBPort: environment.GetPostgreSQLPort(),
SchemaDir: testPostgreSQLSchemaDir,
StoreType: config.StoreTypeSQL,
}
}
// GetPostgreSQL12TestClusterOption return test options
func GetPostgreSQL12TestClusterOption() *TestBaseOptions {
return &TestBaseOptions{

View File

@@ -58,7 +58,7 @@ const (
`PRIMARY KEY (version_partition, year, month, update_time));`
// NOTE: we have to use %v because somehow mysql doesn't work with ? here
createDatabaseQuery = "CREATE DATABASE IF NOT EXISTS %v CHARACTER SET UTF8"
createDatabaseQuery = "CREATE DATABASE IF NOT EXISTS %v CHARACTER SET utf8mb4"
dropDatabaseQuery = "DROP DATABASE IF EXISTS %v"

View File

@@ -1,39 +0,0 @@
// The MIT License
//
// Copyright (c) 2020 Temporal Technologies Inc. All rights reserved.
//
// Copyright (c) 2020 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 (
"fmt"
)
const (
// NOTE: we have to use %v because somehow mysql doesn't work with ? here
createDatabaseQuery_v8 = "CREATE DATABASE IF NOT EXISTS %v CHARACTER SET utf8mb4"
)
// CreateDatabase creates a database if it doesn't exist
func (mdb *dbV8) CreateDatabase(name string) error {
return mdb.Exec(fmt.Sprintf(createDatabaseQuery_v8, name))
}

View File

@@ -33,7 +33,7 @@ import (
"go.temporal.io/server/common/persistence/schema"
"go.temporal.io/server/common/persistence/sql/sqlplugin"
mysqlschemaV57 "go.temporal.io/server/schema/mysql/v57"
mysqlschemaV8 "go.temporal.io/server/schema/mysql/v8"
)
// db represents a logical connection to mysql database
@@ -108,7 +108,7 @@ func (mdb *db) Close() error {
// PluginName returns the name of the mysql plugin
func (mdb *db) PluginName() string {
return PluginName
return PluginNameV8
}
// DbName returns the name of the database
@@ -120,9 +120,9 @@ func (mdb *db) DbName() string {
func (mdb *db) ExpectedVersion() string {
switch mdb.dbKind {
case sqlplugin.DbKindMain:
return mysqlschemaV57.Version
return mysqlschemaV8.Version
case sqlplugin.DbKindVisibility:
return mysqlschemaV57.VisibilityVersion
return mysqlschemaV8.VisibilityVersion
default:
panic(fmt.Sprintf("unknown db kind %v", mdb.dbKind))
}

View File

@@ -1,101 +0,0 @@
// The MIT License
//
// Copyright (c) 2020 Temporal Technologies Inc. All rights reserved.
//
// Copyright (c) 2020 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 (
"context"
"fmt"
"github.com/jmoiron/sqlx"
"go.temporal.io/server/common/persistence/schema"
"go.temporal.io/server/common/persistence/sql/sqlplugin"
mysqlschemaV8 "go.temporal.io/server/schema/mysql/v8"
)
// db represents a logical connection to mysql database
type dbV8 struct {
db
}
var _ sqlplugin.AdminDB = (*dbV8)(nil)
var _ sqlplugin.DB = (*dbV8)(nil)
var _ sqlplugin.Tx = (*dbV8)(nil)
// newDB returns an instance of DB, which is a logical
// connection to the underlying mysql database
func newDBV8(
dbKind sqlplugin.DbKind,
dbName string,
xdb *sqlx.DB,
tx *sqlx.Tx,
) *dbV8 {
mdb := &dbV8{
db: db{
dbKind: dbKind,
dbName: dbName,
db: xdb,
tx: tx,
},
}
mdb.conn = xdb
if tx != nil {
mdb.conn = tx
}
mdb.converter = &converter{}
return mdb
}
// BeginTx starts a new transaction and returns a reference to the Tx object
func (mdb *dbV8) BeginTx(ctx context.Context) (sqlplugin.Tx, error) {
xtx, err := mdb.db.db.BeginTxx(ctx, nil)
if err != nil {
return nil, err
}
return newDBV8(mdb.dbKind, mdb.dbName, mdb.db.db, xtx), nil
}
// PluginName returns the name of the mysql plugin
func (mdb *dbV8) PluginName() string {
return PluginNameV8
}
// ExpectedVersion returns expected version.
func (mdb *dbV8) ExpectedVersion() string {
switch mdb.dbKind {
case sqlplugin.DbKindMain:
return mysqlschemaV8.Version
case sqlplugin.DbKindVisibility:
return mysqlschemaV8.VisibilityVersion
default:
panic(fmt.Sprintf("unknown db kind %v", mdb.dbKind))
}
}
// VerifyVersion verify schema version is up to date
func (mdb *dbV8) VerifyVersion() error {
expectedVersion := mdb.ExpectedVersion()
return schema.VerifyCompatibleVersion(mdb, mdb.dbName, expectedVersion)
}

View File

@@ -36,7 +36,7 @@ import (
const (
// PluginName is the name of the plugin
PluginName = "mysql"
PluginNameV8 = "mysql8"
)
type plugin struct{}
@@ -44,7 +44,7 @@ type plugin struct{}
var _ sqlplugin.Plugin = (*plugin)(nil)
func init() {
sql.RegisterPlugin(PluginName, &plugin{})
sql.RegisterPlugin(PluginNameV8, &plugin{})
}
// CreateDB initialize the db object

View File

@@ -1,75 +0,0 @@
// The MIT License
//
// Copyright (c) 2020 Temporal Technologies Inc. All rights reserved.
//
// Copyright (c) 2020 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 (
"go.temporal.io/server/common/config"
"go.temporal.io/server/common/persistence/sql"
"go.temporal.io/server/common/persistence/sql/sqlplugin"
"go.temporal.io/server/common/resolver"
)
const (
// PluginName is the name of the plugin
PluginNameV8 = "mysql8"
)
type pluginV8 struct {
plugin
}
var _ sqlplugin.Plugin = (*pluginV8)(nil)
func init() {
sql.RegisterPlugin(PluginNameV8, &pluginV8{})
}
// CreateDB initialize the db object
func (p *pluginV8) CreateDB(
dbKind sqlplugin.DbKind,
cfg *config.SQL,
r resolver.ServiceResolver,
) (sqlplugin.DB, error) {
conn, err := p.createDBConnection(cfg, r)
if err != nil {
return nil, err
}
db := newDBV8(dbKind, cfg.DatabaseName, conn, nil)
return db, nil
}
// CreateAdminDB initialize the db object
func (p *pluginV8) CreateAdminDB(
dbKind sqlplugin.DbKind,
cfg *config.SQL,
r resolver.ServiceResolver,
) (sqlplugin.AdminDB, error) {
conn, err := p.createDBConnection(cfg, r)
if err != nil {
return nil, err
}
db := newDBV8(dbKind, cfg.DatabaseName, conn, nil)
return db, nil
}

View File

@@ -29,148 +29,161 @@ import (
"database/sql"
"errors"
"fmt"
"strings"
"go.temporal.io/server/common/persistence/sql/sqlplugin"
"go.temporal.io/server/common/persistence/visibility/store"
)
const (
templateCreateWorkflowExecutionStarted = `INSERT INTO executions_visibility (` +
`namespace_id, workflow_id, run_id, start_time, execution_time, workflow_type_name, status, memo, encoding, task_queue) ` +
`VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ` +
`ON DUPLICATE KEY UPDATE ` +
`run_id=VALUES(run_id)`
var (
templateInsertWorkflowExecution = fmt.Sprintf(
`INSERT INTO executions_visibility (%s)
VALUES (%s)
ON DUPLICATE KEY UPDATE run_id = VALUES(run_id)`,
strings.Join(sqlplugin.DbFields, ", "),
sqlplugin.BuildNamedPlaceholder(sqlplugin.DbFields...),
)
templateCreateWorkflowExecutionClosed = `INSERT INTO executions_visibility (` +
`namespace_id, workflow_id, run_id, start_time, execution_time, workflow_type_name, close_time, status, history_length, memo, encoding, task_queue) ` +
`VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ` +
`ON DUPLICATE KEY UPDATE workflow_id = VALUES(workflow_id), start_time = VALUES(start_time), execution_time = VALUES(execution_time), workflow_type_name = VALUES(workflow_type_name), ` +
`close_time = VALUES(close_time), status = VALUES(status), history_length = VALUES(history_length), memo = VALUES(memo), encoding = VALUES(encoding), task_queue = VALUES(task_queue)`
templateInsertCustomSearchAttributes = `
INSERT INTO custom_search_attributes (
namespace_id, run_id, search_attributes
) VALUES (:namespace_id, :run_id, :search_attributes)
ON DUPLICATE KEY UPDATE run_id = VALUES(run_id)`
// RunID condition is needed for correct pagination
templateConditions = ` AND namespace_id = ?
AND start_time >= ?
AND start_time <= ?
AND ((run_id > ? and start_time = ?) OR (start_time < ?))
ORDER BY start_time DESC, run_id
LIMIT ?`
templateUpsertWorkflowExecution = fmt.Sprintf(
`INSERT INTO executions_visibility (%s)
VALUES (%s)
%s`,
strings.Join(sqlplugin.DbFields, ", "),
sqlplugin.BuildNamedPlaceholder(sqlplugin.DbFields...),
buildOnDuplicateKeyUpdate(sqlplugin.DbFields...),
)
templateConditionsClosedWorkflows = ` AND namespace_id = ?
AND close_time >= ?
AND close_time <= ?
AND ((run_id > ? and close_time = ?) OR (close_time < ?))
ORDER BY close_time DESC, run_id
LIMIT ?`
templateUpsertCustomSearchAttributes = `
INSERT INTO custom_search_attributes (
namespace_id, run_id, search_attributes
) VALUES (:namespace_id, :run_id, :search_attributes)
ON DUPLICATE KEY UPDATE search_attributes = VALUES(search_attributes)`
templateOpenFieldNames = `workflow_id, run_id, start_time, execution_time, workflow_type_name, status, memo, encoding, task_queue`
templateOpenSelect = `SELECT ` + templateOpenFieldNames + ` FROM executions_visibility WHERE status = 1 `
templateDeleteWorkflowExecution_v8 = `
DELETE FROM executions_visibility
WHERE namespace_id = :namespace_id AND run_id = :run_id`
templateClosedSelect = `SELECT ` + templateOpenFieldNames + `, close_time, history_length
FROM executions_visibility WHERE status != 1 `
templateDeleteCustomSearchAttributes = `
DELETE FROM custom_search_attributes
WHERE namespace_id = :namespace_id AND run_id = :run_id`
templateGetOpenWorkflowExecutions = templateOpenSelect + templateConditions
templateGetClosedWorkflowExecutions = templateClosedSelect + templateConditionsClosedWorkflows
templateGetOpenWorkflowExecutionsByType = templateOpenSelect + `AND workflow_type_name = ?` + templateConditions
templateGetClosedWorkflowExecutionsByType = templateClosedSelect + `AND workflow_type_name = ?` + templateConditionsClosedWorkflows
templateGetOpenWorkflowExecutionsByID = templateOpenSelect + `AND workflow_id = ?` + templateConditions
templateGetClosedWorkflowExecutionsByID = templateClosedSelect + `AND workflow_id = ?` + templateConditionsClosedWorkflows
templateGetClosedWorkflowExecutionsByStatus = templateClosedSelect + `AND status = ?` + templateConditionsClosedWorkflows
templateGetClosedWorkflowExecution = `SELECT workflow_id, run_id, start_time, execution_time, memo, encoding, close_time, workflow_type_name, status, history_length, task_queue
FROM executions_visibility
WHERE namespace_id = ? AND status != 1
AND run_id = ?`
templateGetWorkflowExecution = `
SELECT
workflow_id,
run_id,
start_time,
execution_time,
memo,
encoding,
close_time,
workflow_type_name,
status,
history_length,
task_queue
FROM executions_visibility
WHERE namespace_id = ? AND run_id = ?`
templateDeleteWorkflowExecution = "DELETE FROM executions_visibility WHERE namespace_id = ? AND run_id = ?"
templateGetWorkflowExecution_v8 = fmt.Sprintf(
`SELECT %s FROM executions_visibility
WHERE namespace_id = :namespace_id AND run_id = :run_id`,
strings.Join(sqlplugin.DbFields, ", "),
)
)
var errCloseParams = errors.New("missing one of {CloseTime, HistoryLength} params")
func buildOnDuplicateKeyUpdate(fields ...string) string {
items := make([]string, len(fields))
for i, field := range fields {
items[i] = fmt.Sprintf("%s = VALUES(%s)", field, field)
}
return fmt.Sprintf("ON DUPLICATE KEY UPDATE %s", strings.Join(items, ", "))
}
// InsertIntoVisibility inserts a row into visibility table. If an row already exist,
// its left as such and no update will be made
func (mdb *db) InsertIntoVisibility(
ctx context.Context,
row *sqlplugin.VisibilityRow,
) (sql.Result, error) {
row.StartTime = mdb.converter.ToMySQLDateTime(row.StartTime)
row.ExecutionTime = mdb.converter.ToMySQLDateTime(row.ExecutionTime)
return mdb.conn.ExecContext(ctx,
templateCreateWorkflowExecutionStarted,
row.NamespaceID,
row.WorkflowID,
row.RunID,
row.StartTime,
row.ExecutionTime,
row.WorkflowTypeName,
row.Status,
row.Memo,
row.Encoding,
row.TaskQueue,
)
) (result sql.Result, retError error) {
finalRow := mdb.prepareRowForDB(row)
tx, err := mdb.db.BeginTxx(ctx, nil)
if err != nil {
return nil, err
}
defer func() {
err := tx.Rollback()
// If the error is sql.ErrTxDone, it means the transaction already closed, so ignore error.
if err != nil && !errors.Is(err, sql.ErrTxDone) {
// Transaction rollback error should never happen, unless db connection was lost.
retError = fmt.Errorf("transaction rollback failed: %w", retError)
}
}()
result, err = tx.NamedExecContext(ctx, templateInsertWorkflowExecution, finalRow)
if err != nil {
return nil, err
}
_, err = tx.NamedExecContext(ctx, templateInsertCustomSearchAttributes, finalRow)
if err != nil {
return nil, err
}
err = tx.Commit()
if err != nil {
return nil, err
}
return result, nil
}
// ReplaceIntoVisibility replaces an existing row if it exist or creates a new row in visibility table
func (mdb *db) ReplaceIntoVisibility(
ctx context.Context,
row *sqlplugin.VisibilityRow,
) (sql.Result, error) {
switch {
case row.CloseTime != nil && row.HistoryLength != nil:
row.StartTime = mdb.converter.ToMySQLDateTime(row.StartTime)
row.ExecutionTime = mdb.converter.ToMySQLDateTime(row.ExecutionTime)
closeTime := mdb.converter.ToMySQLDateTime(*row.CloseTime)
return mdb.conn.ExecContext(ctx,
templateCreateWorkflowExecutionClosed,
row.NamespaceID,
row.WorkflowID,
row.RunID,
row.StartTime,
row.ExecutionTime,
row.WorkflowTypeName,
closeTime,
row.Status,
*row.HistoryLength,
row.Memo,
row.Encoding,
row.TaskQueue,
)
default:
return nil, errCloseParams
) (result sql.Result, retError error) {
finalRow := mdb.prepareRowForDB(row)
tx, err := mdb.db.BeginTxx(ctx, nil)
if err != nil {
return nil, err
}
defer func() {
err := tx.Rollback()
// If the error is sql.ErrTxDone, it means the transaction already closed, so ignore error.
if err != nil && !errors.Is(err, sql.ErrTxDone) {
// Transaction rollback error should never happen, unless db connection was lost.
retError = fmt.Errorf("transaction rollback failed: %w", retError)
}
}()
result, err = tx.NamedExecContext(ctx, templateUpsertWorkflowExecution, finalRow)
if err != nil {
return nil, err
}
_, err = tx.NamedExecContext(ctx, templateUpsertCustomSearchAttributes, finalRow)
if err != nil {
return nil, err
}
err = tx.Commit()
if err != nil {
return nil, err
}
return result, nil
}
// DeleteFromVisibility deletes a row from visibility table if it exist
func (mdb *db) DeleteFromVisibility(
ctx context.Context,
filter sqlplugin.VisibilityDeleteFilter,
) (sql.Result, error) {
return mdb.conn.ExecContext(ctx,
templateDeleteWorkflowExecution,
filter.NamespaceID,
filter.RunID,
)
) (result sql.Result, retError error) {
tx, err := mdb.db.BeginTxx(ctx, nil)
if err != nil {
return nil, err
}
defer func() {
err := tx.Rollback()
// If the error is sql.ErrTxDone, it means the transaction already closed, so ignore error.
if err != nil && !errors.Is(err, sql.ErrTxDone) {
// Transaction rollback error should never happen, unless db connection was lost.
retError = fmt.Errorf("transaction rollback failed: %w", retError)
}
}()
_, err = mdb.conn.NamedExecContext(ctx, templateDeleteCustomSearchAttributes, filter)
if err != nil {
return nil, err
}
result, err = mdb.conn.NamedExecContext(ctx, templateDeleteWorkflowExecution_v8, filter)
if err != nil {
return nil, err
}
err = tx.Commit()
if err != nil {
return nil, err
}
return result, nil
}
// SelectFromVisibility reads one or more rows from visibility table
@@ -178,103 +191,24 @@ func (mdb *db) SelectFromVisibility(
ctx context.Context,
filter sqlplugin.VisibilitySelectFilter,
) ([]sqlplugin.VisibilityRow, error) {
var err error
if len(filter.Query) == 0 {
// backward compatibility for existing tests
err := sqlplugin.GenerateSelectQuery(&filter, mdb.converter.ToMySQLDateTime)
if err != nil {
return nil, err
}
}
var rows []sqlplugin.VisibilityRow
if filter.MinTime != nil {
*filter.MinTime = mdb.converter.ToMySQLDateTime(*filter.MinTime)
}
if filter.MaxTime != nil {
*filter.MaxTime = mdb.converter.ToMySQLDateTime(*filter.MaxTime)
}
// If filter.Status == 0 (UNSPECIFIED) then only closed workflows will be returned (all excluding 1 (RUNNING)).
switch {
case filter.MinTime == nil && filter.RunID != nil && filter.Status != 1:
var row sqlplugin.VisibilityRow
err = mdb.conn.GetContext(ctx,
&row,
templateGetClosedWorkflowExecution,
filter.NamespaceID,
*filter.RunID,
)
if err == nil {
rows = append(rows, row)
}
case filter.MinTime != nil && filter.MaxTime != nil &&
filter.WorkflowID != nil && filter.RunID != nil && filter.PageSize != nil:
qry := templateGetOpenWorkflowExecutionsByID
if filter.Status != 1 {
qry = templateGetClosedWorkflowExecutionsByID
}
err = mdb.conn.SelectContext(ctx,
&rows,
qry,
*filter.WorkflowID,
filter.NamespaceID,
*filter.MinTime,
*filter.MaxTime,
*filter.RunID,
*filter.MaxTime,
*filter.MaxTime,
*filter.PageSize,
)
case filter.MinTime != nil && filter.MaxTime != nil &&
filter.WorkflowTypeName != nil && filter.RunID != nil && filter.PageSize != nil:
qry := templateGetOpenWorkflowExecutionsByType
if filter.Status != 1 {
qry = templateGetClosedWorkflowExecutionsByType
}
err = mdb.conn.SelectContext(ctx,
&rows,
qry,
*filter.WorkflowTypeName,
filter.NamespaceID,
*filter.MinTime,
*filter.MaxTime,
*filter.RunID,
*filter.MaxTime,
*filter.MaxTime,
*filter.PageSize,
)
case filter.MinTime != nil && filter.MaxTime != nil &&
filter.RunID != nil && filter.PageSize != nil &&
filter.Status != 0 && filter.Status != 1: // 0 is UNSPECIFIED, 1 is RUNNING
err = mdb.conn.SelectContext(ctx,
&rows,
templateGetClosedWorkflowExecutionsByStatus,
filter.Status,
filter.NamespaceID,
*filter.MinTime,
*filter.MaxTime,
*filter.RunID,
*filter.MaxTime,
*filter.MaxTime,
*filter.PageSize,
)
case filter.MinTime != nil && filter.MaxTime != nil &&
filter.RunID != nil && filter.PageSize != nil:
qry := templateGetOpenWorkflowExecutions
if filter.Status != 1 {
qry = templateGetClosedWorkflowExecutions
}
err = mdb.conn.SelectContext(ctx,
&rows,
qry,
filter.NamespaceID,
*filter.MinTime,
*filter.MaxTime,
*filter.RunID,
*filter.MaxTime,
*filter.MaxTime,
*filter.PageSize,
)
default:
return nil, fmt.Errorf("invalid query filter")
}
err := mdb.conn.SelectContext(ctx, &rows, filter.Query, filter.QueryArgs...)
if err != nil {
return nil, err
}
for i := range rows {
mdb.processRowFromDB(&rows[i])
err = mdb.processRowFromDB(&rows[i])
if err != nil {
return nil, err
}
}
return rows, nil
}
@@ -285,16 +219,18 @@ func (mdb *db) GetFromVisibility(
filter sqlplugin.VisibilityGetFilter,
) (*sqlplugin.VisibilityRow, error) {
var row sqlplugin.VisibilityRow
err := mdb.conn.GetContext(ctx,
&row,
templateGetWorkflowExecution,
filter.NamespaceID,
filter.RunID,
)
stmt, err := mdb.conn.PrepareNamedContext(ctx, templateGetWorkflowExecution_v8)
if err != nil {
return nil, err
}
err = stmt.GetContext(ctx, &row, filter)
if err != nil {
return nil, err
}
err = mdb.processRowFromDB(&row)
if err != nil {
return nil, err
}
mdb.processRowFromDB(&row)
return &row, nil
}
@@ -302,21 +238,68 @@ func (mdb *db) CountFromVisibility(
ctx context.Context,
filter sqlplugin.VisibilitySelectFilter,
) (int64, error) {
return 0, store.OperationNotSupportedErr
var count int64
err := mdb.conn.GetContext(ctx, &count, filter.Query, filter.QueryArgs...)
if err != nil {
return 0, err
}
return count, nil
}
func (mdb *db) CountGroupByFromVisibility(
ctx context.Context,
filter sqlplugin.VisibilitySelectFilter,
) ([]sqlplugin.VisibilityCountRow, error) {
return nil, store.OperationNotSupportedErr
rows, err := mdb.db.QueryContext(ctx, filter.Query, filter.QueryArgs...)
if err != nil {
return nil, err
}
defer rows.Close()
return sqlplugin.ParseCountGroupByRows(rows, filter.GroupBy)
}
func (mdb *db) processRowFromDB(row *sqlplugin.VisibilityRow) {
func (mdb *db) prepareRowForDB(row *sqlplugin.VisibilityRow) *sqlplugin.VisibilityRow {
if row == nil {
return nil
}
finalRow := *row
finalRow.StartTime = mdb.converter.ToMySQLDateTime(finalRow.StartTime)
finalRow.ExecutionTime = mdb.converter.ToMySQLDateTime(finalRow.ExecutionTime)
if finalRow.CloseTime != nil {
*finalRow.CloseTime = mdb.converter.ToMySQLDateTime(*finalRow.CloseTime)
}
return &finalRow
}
func (mdb *db) processRowFromDB(row *sqlplugin.VisibilityRow) error {
if row == nil {
return nil
}
row.StartTime = mdb.converter.FromMySQLDateTime(row.StartTime)
row.ExecutionTime = mdb.converter.FromMySQLDateTime(row.ExecutionTime)
if row.CloseTime != nil {
closeTime := mdb.converter.FromMySQLDateTime(*row.CloseTime)
row.CloseTime = &closeTime
}
if row.SearchAttributes != nil {
for saName, saValue := range *row.SearchAttributes {
switch typedSaValue := saValue.(type) {
case []interface{}:
// the only valid type is slice of strings
strSlice := make([]string, len(typedSaValue))
for i, item := range typedSaValue {
switch v := item.(type) {
case string:
strSlice[i] = v
default:
return fmt.Errorf("%w: %T (expected string)", sqlplugin.ErrInvalidKeywordListDataType, v)
}
}
(*row.SearchAttributes)[saName] = strSlice
default:
// no-op
}
}
}
return nil
}

View File

@@ -1,305 +0,0 @@
// The MIT License
//
// Copyright (c) 2020 Temporal Technologies Inc. All rights reserved.
//
// Copyright (c) 2020 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 (
"context"
"database/sql"
"errors"
"fmt"
"strings"
"go.temporal.io/server/common/persistence/sql/sqlplugin"
)
var (
templateInsertWorkflowExecution = fmt.Sprintf(
`INSERT INTO executions_visibility (%s)
VALUES (%s)
ON DUPLICATE KEY UPDATE run_id = VALUES(run_id)`,
strings.Join(sqlplugin.DbFields, ", "),
sqlplugin.BuildNamedPlaceholder(sqlplugin.DbFields...),
)
templateInsertCustomSearchAttributes = `
INSERT INTO custom_search_attributes (
namespace_id, run_id, search_attributes
) VALUES (:namespace_id, :run_id, :search_attributes)
ON DUPLICATE KEY UPDATE run_id = VALUES(run_id)`
templateUpsertWorkflowExecution = fmt.Sprintf(
`INSERT INTO executions_visibility (%s)
VALUES (%s)
%s`,
strings.Join(sqlplugin.DbFields, ", "),
sqlplugin.BuildNamedPlaceholder(sqlplugin.DbFields...),
buildOnDuplicateKeyUpdate(sqlplugin.DbFields...),
)
templateUpsertCustomSearchAttributes = `
INSERT INTO custom_search_attributes (
namespace_id, run_id, search_attributes
) VALUES (:namespace_id, :run_id, :search_attributes)
ON DUPLICATE KEY UPDATE search_attributes = VALUES(search_attributes)`
templateDeleteWorkflowExecution_v8 = `
DELETE FROM executions_visibility
WHERE namespace_id = :namespace_id AND run_id = :run_id`
templateDeleteCustomSearchAttributes = `
DELETE FROM custom_search_attributes
WHERE namespace_id = :namespace_id AND run_id = :run_id`
templateGetWorkflowExecution_v8 = fmt.Sprintf(
`SELECT %s FROM executions_visibility
WHERE namespace_id = :namespace_id AND run_id = :run_id`,
strings.Join(sqlplugin.DbFields, ", "),
)
)
func buildOnDuplicateKeyUpdate(fields ...string) string {
items := make([]string, len(fields))
for i, field := range fields {
items[i] = fmt.Sprintf("%s = VALUES(%s)", field, field)
}
return fmt.Sprintf("ON DUPLICATE KEY UPDATE %s", strings.Join(items, ", "))
}
// InsertIntoVisibility inserts a row into visibility table. If an row already exist,
// its left as such and no update will be made
func (mdb *dbV8) InsertIntoVisibility(
ctx context.Context,
row *sqlplugin.VisibilityRow,
) (result sql.Result, retError error) {
finalRow := mdb.prepareRowForDB(row)
tx, err := mdb.db.db.BeginTxx(ctx, nil)
if err != nil {
return nil, err
}
defer func() {
err := tx.Rollback()
// If the error is sql.ErrTxDone, it means the transaction already closed, so ignore error.
if err != nil && !errors.Is(err, sql.ErrTxDone) {
// Transaction rollback error should never happen, unless db connection was lost.
retError = fmt.Errorf("transaction rollback failed: %w", retError)
}
}()
result, err = tx.NamedExecContext(ctx, templateInsertWorkflowExecution, finalRow)
if err != nil {
return nil, err
}
_, err = tx.NamedExecContext(ctx, templateInsertCustomSearchAttributes, finalRow)
if err != nil {
return nil, err
}
err = tx.Commit()
if err != nil {
return nil, err
}
return result, nil
}
// ReplaceIntoVisibility replaces an existing row if it exist or creates a new row in visibility table
func (mdb *dbV8) ReplaceIntoVisibility(
ctx context.Context,
row *sqlplugin.VisibilityRow,
) (result sql.Result, retError error) {
finalRow := mdb.prepareRowForDB(row)
tx, err := mdb.db.db.BeginTxx(ctx, nil)
if err != nil {
return nil, err
}
defer func() {
err := tx.Rollback()
// If the error is sql.ErrTxDone, it means the transaction already closed, so ignore error.
if err != nil && !errors.Is(err, sql.ErrTxDone) {
// Transaction rollback error should never happen, unless db connection was lost.
retError = fmt.Errorf("transaction rollback failed: %w", retError)
}
}()
result, err = tx.NamedExecContext(ctx, templateUpsertWorkflowExecution, finalRow)
if err != nil {
return nil, err
}
_, err = tx.NamedExecContext(ctx, templateUpsertCustomSearchAttributes, finalRow)
if err != nil {
return nil, err
}
err = tx.Commit()
if err != nil {
return nil, err
}
return result, nil
}
// DeleteFromVisibility deletes a row from visibility table if it exist
func (mdb *dbV8) DeleteFromVisibility(
ctx context.Context,
filter sqlplugin.VisibilityDeleteFilter,
) (result sql.Result, retError error) {
tx, err := mdb.db.db.BeginTxx(ctx, nil)
if err != nil {
return nil, err
}
defer func() {
err := tx.Rollback()
// If the error is sql.ErrTxDone, it means the transaction already closed, so ignore error.
if err != nil && !errors.Is(err, sql.ErrTxDone) {
// Transaction rollback error should never happen, unless db connection was lost.
retError = fmt.Errorf("transaction rollback failed: %w", retError)
}
}()
_, err = mdb.conn.NamedExecContext(ctx, templateDeleteCustomSearchAttributes, filter)
if err != nil {
return nil, err
}
result, err = mdb.conn.NamedExecContext(ctx, templateDeleteWorkflowExecution_v8, filter)
if err != nil {
return nil, err
}
err = tx.Commit()
if err != nil {
return nil, err
}
return result, nil
}
// SelectFromVisibility reads one or more rows from visibility table
func (mdb *dbV8) SelectFromVisibility(
ctx context.Context,
filter sqlplugin.VisibilitySelectFilter,
) ([]sqlplugin.VisibilityRow, error) {
if len(filter.Query) == 0 {
// backward compatibility for existing tests
err := sqlplugin.GenerateSelectQuery(&filter, mdb.converter.ToMySQLDateTime)
if err != nil {
return nil, err
}
}
var rows []sqlplugin.VisibilityRow
err := mdb.conn.SelectContext(ctx, &rows, filter.Query, filter.QueryArgs...)
if err != nil {
return nil, err
}
for i := range rows {
err = mdb.processRowFromDB(&rows[i])
if err != nil {
return nil, err
}
}
return rows, nil
}
// GetFromVisibility reads one row from visibility table
func (mdb *dbV8) GetFromVisibility(
ctx context.Context,
filter sqlplugin.VisibilityGetFilter,
) (*sqlplugin.VisibilityRow, error) {
var row sqlplugin.VisibilityRow
stmt, err := mdb.conn.PrepareNamedContext(ctx, templateGetWorkflowExecution_v8)
if err != nil {
return nil, err
}
err = stmt.GetContext(ctx, &row, filter)
if err != nil {
return nil, err
}
err = mdb.processRowFromDB(&row)
if err != nil {
return nil, err
}
return &row, nil
}
func (mdb *dbV8) CountFromVisibility(
ctx context.Context,
filter sqlplugin.VisibilitySelectFilter,
) (int64, error) {
var count int64
err := mdb.conn.GetContext(ctx, &count, filter.Query, filter.QueryArgs...)
if err != nil {
return 0, err
}
return count, nil
}
func (mdb *dbV8) CountGroupByFromVisibility(
ctx context.Context,
filter sqlplugin.VisibilitySelectFilter,
) ([]sqlplugin.VisibilityCountRow, error) {
rows, err := mdb.db.db.QueryContext(ctx, filter.Query, filter.QueryArgs...)
if err != nil {
return nil, err
}
defer rows.Close()
return sqlplugin.ParseCountGroupByRows(rows, filter.GroupBy)
}
func (mdb *dbV8) prepareRowForDB(row *sqlplugin.VisibilityRow) *sqlplugin.VisibilityRow {
if row == nil {
return nil
}
finalRow := *row
finalRow.StartTime = mdb.converter.ToMySQLDateTime(finalRow.StartTime)
finalRow.ExecutionTime = mdb.converter.ToMySQLDateTime(finalRow.ExecutionTime)
if finalRow.CloseTime != nil {
*finalRow.CloseTime = mdb.converter.ToMySQLDateTime(*finalRow.CloseTime)
}
return &finalRow
}
func (mdb *dbV8) processRowFromDB(row *sqlplugin.VisibilityRow) error {
if row == nil {
return nil
}
row.StartTime = mdb.converter.FromMySQLDateTime(row.StartTime)
row.ExecutionTime = mdb.converter.FromMySQLDateTime(row.ExecutionTime)
if row.CloseTime != nil {
closeTime := mdb.converter.FromMySQLDateTime(*row.CloseTime)
row.CloseTime = &closeTime
}
if row.SearchAttributes != nil {
for saName, saValue := range *row.SearchAttributes {
switch typedSaValue := saValue.(type) {
case []interface{}:
// the only valid type is slice of strings
strSlice := make([]string, len(typedSaValue))
for i, item := range typedSaValue {
switch v := item.(type) {
case string:
strSlice[i] = v
default:
return fmt.Errorf("Unexpected data type in keyword list: %T (expected string)", v)
}
}
(*row.SearchAttributes)[saName] = strSlice
default:
// no-op
}
}
}
return nil
}

View File

@@ -32,7 +32,7 @@ import (
"go.temporal.io/server/common/persistence/schema"
"go.temporal.io/server/common/persistence/sql/sqlplugin"
"go.temporal.io/server/common/persistence/sql/sqlplugin/postgresql/driver"
postgresqlschemaV96 "go.temporal.io/server/schema/postgresql/v96"
postgresqlschemaV12 "go.temporal.io/server/schema/postgresql/v12"
)
func (pdb *db) IsDupEntryError(err error) bool {
@@ -108,7 +108,7 @@ func (pdb *db) Close() error {
// PluginName returns the name of the mysql plugin
func (pdb *db) PluginName() string {
return PluginName
return PluginNameV12
}
// DbName returns the name of the database
@@ -120,9 +120,9 @@ func (pdb *db) DbName() string {
func (pdb *db) ExpectedVersion() string {
switch pdb.dbKind {
case sqlplugin.DbKindMain:
return postgresqlschemaV96.Version
return postgresqlschemaV12.Version
case sqlplugin.DbKindVisibility:
return postgresqlschemaV96.VisibilityVersion
return postgresqlschemaV12.VisibilityVersion
default:
panic(fmt.Sprintf("unknown db kind %v", pdb.dbKind))
}

View File

@@ -1,103 +0,0 @@
// The MIT License
//
// Copyright (c) 2020 Temporal Technologies Inc. All rights reserved.
//
// Copyright (c) 2020 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 postgresql
import (
"context"
"fmt"
"github.com/jmoiron/sqlx"
"go.temporal.io/server/common/persistence/schema"
"go.temporal.io/server/common/persistence/sql/sqlplugin"
"go.temporal.io/server/common/persistence/sql/sqlplugin/postgresql/driver"
postgresqlschemaV12 "go.temporal.io/server/schema/postgresql/v12"
)
// dbV12 represents a logical connection to mysql database
type dbV12 struct {
db
}
var _ sqlplugin.DB = (*dbV12)(nil)
var _ sqlplugin.Tx = (*dbV12)(nil)
// newDB returns an instance of DB, which is a logical
// connection to the underlying postgresql database
func newDBV12(
dbKind sqlplugin.DbKind,
dbName string,
dbDriver driver.Driver,
xdb *sqlx.DB,
tx *sqlx.Tx,
) *dbV12 {
mdb := &dbV12{
db: db{
dbKind: dbKind,
dbName: dbName,
dbDriver: dbDriver,
db: xdb,
tx: tx,
},
}
mdb.conn = xdb
if tx != nil {
mdb.conn = tx
}
mdb.converter = &converter{}
return mdb
}
// BeginTx starts a new transaction and returns a reference to the Tx object
func (pdb *dbV12) BeginTx(ctx context.Context) (sqlplugin.Tx, error) {
xtx, err := pdb.db.db.BeginTxx(ctx, nil)
if err != nil {
return nil, err
}
return newDB(pdb.dbKind, pdb.dbName, pdb.dbDriver, pdb.db.db, xtx), nil
}
// PluginName returns the name of the mysql plugin
func (pdb *dbV12) PluginName() string {
return PluginNameV12
}
// ExpectedVersion returns expected version.
func (pdb *dbV12) ExpectedVersion() string {
switch pdb.dbKind {
case sqlplugin.DbKindMain:
return postgresqlschemaV12.Version
case sqlplugin.DbKindVisibility:
return postgresqlschemaV12.VisibilityVersion
default:
panic(fmt.Sprintf("unknown db kind %v", pdb.dbKind))
}
}
// VerifyVersion verify schema version is up to date
func (pdb *dbV12) VerifyVersion() error {
expectedVersion := pdb.ExpectedVersion()
return schema.VerifyCompatibleVersion(pdb, pdb.dbName, expectedVersion)
}

View File

@@ -41,8 +41,8 @@ import (
const (
// PluginName is the name of the plugin
PluginName = "postgres"
PluginNamePGX = "postgres_pgx"
PluginNameV12 = "postgres12"
PluginNameV12PGX = "postgres12_pgx"
)
var (
@@ -59,8 +59,8 @@ type plugin struct {
var _ sqlplugin.Plugin = (*plugin)(nil)
func init() {
sql.RegisterPlugin(PluginName, &plugin{&driver.PQDriver{}})
sql.RegisterPlugin(PluginNamePGX, &plugin{&driver.PGXDriver{}})
sql.RegisterPlugin(PluginNameV12, &plugin{&driver.PQDriver{}})
sql.RegisterPlugin(PluginNameV12PGX, &plugin{&driver.PGXDriver{}})
}

View File

@@ -1,79 +0,0 @@
// The MIT License
//
// Copyright (c) 2020 Temporal Technologies Inc. All rights reserved.
//
// Copyright (c) 2020 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 postgresql
import (
"go.temporal.io/server/common/config"
"go.temporal.io/server/common/persistence/sql"
"go.temporal.io/server/common/persistence/sql/sqlplugin"
"go.temporal.io/server/common/persistence/sql/sqlplugin/postgresql/driver"
"go.temporal.io/server/common/resolver"
)
const (
// PluginName is the name of the plugin
PluginNameV12 = "postgres12"
PluginNameV12PGX = "postgres12_pgx"
)
type pluginV12 struct {
plugin
}
var _ sqlplugin.Plugin = (*pluginV12)(nil)
func init() {
sql.RegisterPlugin(PluginNameV12, &pluginV12{plugin{&driver.PQDriver{}}})
sql.RegisterPlugin(PluginNameV12PGX, &pluginV12{plugin{&driver.PGXDriver{}}})
}
// CreateDB initialize the db object
func (d *pluginV12) CreateDB(
dbKind sqlplugin.DbKind,
cfg *config.SQL,
r resolver.ServiceResolver,
) (sqlplugin.DB, error) {
conn, err := d.createDBConnection(cfg, r)
if err != nil {
return nil, err
}
db := newDBV12(dbKind, cfg.DatabaseName, d.d, conn, nil)
return db, nil
}
// CreateAdminDB initialize the adminDB object
func (d *pluginV12) CreateAdminDB(
dbKind sqlplugin.DbKind,
cfg *config.SQL,
r resolver.ServiceResolver,
) (sqlplugin.AdminDB, error) {
conn, err := d.createDBConnection(cfg, r)
if err != nil {
return nil, err
}
db := newDBV12(dbKind, cfg.DatabaseName, d.d, conn, nil)
return db, nil
}

View File

@@ -27,109 +27,51 @@ package postgresql
import (
"context"
"database/sql"
"errors"
"fmt"
"strings"
"go.temporal.io/server/common/persistence/sql/sqlplugin"
"go.temporal.io/server/common/persistence/visibility/store"
)
const (
templateCreateWorkflowExecutionStarted = `INSERT INTO executions_visibility (` +
`namespace_id, workflow_id, run_id, start_time, execution_time, workflow_type_name, status, memo, encoding, task_queue) ` +
`VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
ON CONFLICT (namespace_id, run_id) DO NOTHING`
var (
templateInsertWorkflowExecution = fmt.Sprintf(
`INSERT INTO executions_visibility (%s)
VALUES (%s)
ON CONFLICT (namespace_id, run_id) DO NOTHING`,
strings.Join(sqlplugin.DbFields, ", "),
sqlplugin.BuildNamedPlaceholder(sqlplugin.DbFields...),
)
templateCreateWorkflowExecutionClosed = `INSERT INTO executions_visibility (` +
`namespace_id, workflow_id, run_id, start_time, execution_time, workflow_type_name, close_time, status, history_length, memo, encoding, task_queue) ` +
`VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
ON CONFLICT (namespace_id, run_id) DO UPDATE
SET workflow_id = excluded.workflow_id,
start_time = excluded.start_time,
execution_time = excluded.execution_time,
workflow_type_name = excluded.workflow_type_name,
close_time = excluded.close_time,
status = excluded.status,
history_length = excluded.history_length,
memo = excluded.memo,
encoding = excluded.encoding,
task_queue = excluded.task_queue`
templateUpsertWorkflowExecution = fmt.Sprintf(
`INSERT INTO executions_visibility (%s)
VALUES (%s)
%s`,
strings.Join(sqlplugin.DbFields, ", "),
sqlplugin.BuildNamedPlaceholder(sqlplugin.DbFields...),
buildOnDuplicateKeyUpdate(sqlplugin.DbFields...),
)
// RunID condition is needed for correct pagination
templateConditions1 = ` AND namespace_id = $1
AND start_time >= $2
AND start_time <= $3
AND ((run_id > $4 and start_time = $5) OR (start_time < $6))
ORDER BY start_time DESC, run_id
LIMIT $7`
templateDeleteWorkflowExecution_v12 = `
DELETE FROM executions_visibility
WHERE namespace_id = :namespace_id AND run_id = :run_id`
templateConditions2 = ` AND namespace_id = $2
AND start_time >= $3
AND start_time <= $4
AND ((run_id > $5 and start_time = $6) OR (start_time < $7))
ORDER BY start_time DESC, run_id
LIMIT $8`
templateConditionsClosedWorkflow1 = ` AND namespace_id = $1
AND close_time >= $2
AND close_time <= $3
AND ((run_id > $4 and close_time = $5) OR (close_time < $6))
ORDER BY close_time DESC, run_id
LIMIT $7`
templateConditionsClosedWorkflow2 = ` AND namespace_id = $2
AND close_time >= $3
AND close_time <= $4
AND ((run_id > $5 and close_time = $6) OR (close_time < $7))
ORDER BY close_time DESC, run_id
LIMIT $8`
templateOpenFieldNames = `workflow_id, run_id, start_time, execution_time, workflow_type_name, status, memo, encoding, task_queue`
templateOpenSelect = `SELECT ` + templateOpenFieldNames + ` FROM executions_visibility WHERE status = 1 `
templateClosedSelect = `SELECT ` + templateOpenFieldNames + `, close_time, history_length
FROM executions_visibility WHERE status != 1 `
templateGetOpenWorkflowExecutions = templateOpenSelect + templateConditions1
templateGetClosedWorkflowExecutions = templateClosedSelect + templateConditionsClosedWorkflow1
templateGetOpenWorkflowExecutionsByType = templateOpenSelect + `AND workflow_type_name = $1` + templateConditions2
templateGetClosedWorkflowExecutionsByType = templateClosedSelect + `AND workflow_type_name = $1` + templateConditionsClosedWorkflow2
templateGetOpenWorkflowExecutionsByID = templateOpenSelect + `AND workflow_id = $1` + templateConditions2
templateGetClosedWorkflowExecutionsByID = templateClosedSelect + `AND workflow_id = $1` + templateConditionsClosedWorkflow2
templateGetClosedWorkflowExecutionsByStatus = templateClosedSelect + `AND status = $1` + templateConditionsClosedWorkflow2
templateGetClosedWorkflowExecution = `SELECT workflow_id, run_id, start_time, execution_time, memo, encoding, close_time, workflow_type_name, status, history_length, task_queue
FROM executions_visibility
WHERE namespace_id = $1 AND status != 1
AND run_id = $2`
templateGetWorkflowExecution = `
SELECT
workflow_id,
run_id,
start_time,
execution_time,
memo,
encoding,
close_time,
workflow_type_name,
status,
history_length,
task_queue
FROM executions_visibility
WHERE namespace_id = $1 AND run_id = $2`
templateDeleteWorkflowExecution = "DELETE FROM executions_visibility WHERE namespace_id = $1 AND run_id = $2"
templateGetWorkflowExecution_v12 = fmt.Sprintf(
`SELECT %s FROM executions_visibility
WHERE namespace_id = :namespace_id AND run_id = :run_id`,
strings.Join(sqlplugin.DbFields, ", "),
)
)
var errCloseParams = errors.New("missing one of {closeTime, historyLength} params")
func buildOnDuplicateKeyUpdate(fields ...string) string {
items := make([]string, len(fields))
for i, field := range fields {
items[i] = fmt.Sprintf("%s = excluded.%s", field, field)
}
return fmt.Sprintf(
"ON CONFLICT (namespace_id, run_id) DO UPDATE SET %s",
strings.Join(items, ", "),
)
}
// InsertIntoVisibility inserts a row into visibility table. If an row already exist,
// its left as such and no update will be made
@@ -137,21 +79,8 @@ func (pdb *db) InsertIntoVisibility(
ctx context.Context,
row *sqlplugin.VisibilityRow,
) (sql.Result, error) {
row.StartTime = pdb.converter.ToPostgreSQLDateTime(row.StartTime)
row.ExecutionTime = pdb.converter.ToPostgreSQLDateTime(row.ExecutionTime)
return pdb.conn.ExecContext(ctx,
templateCreateWorkflowExecutionStarted,
row.NamespaceID,
row.WorkflowID,
row.RunID,
row.StartTime,
row.ExecutionTime,
row.WorkflowTypeName,
row.Status,
row.Memo,
row.Encoding,
row.TaskQueue,
)
finalRow := pdb.prepareRowForDB(row)
return pdb.conn.NamedExecContext(ctx, templateInsertWorkflowExecution, finalRow)
}
// ReplaceIntoVisibility replaces an existing row if it exist or creates a new row in visibility table
@@ -159,29 +88,8 @@ func (pdb *db) ReplaceIntoVisibility(
ctx context.Context,
row *sqlplugin.VisibilityRow,
) (sql.Result, error) {
switch {
case row.CloseTime != nil && row.HistoryLength != nil:
row.StartTime = pdb.converter.ToPostgreSQLDateTime(row.StartTime)
row.ExecutionTime = pdb.converter.ToPostgreSQLDateTime(row.ExecutionTime)
closeTime := pdb.converter.ToPostgreSQLDateTime(*row.CloseTime)
return pdb.conn.ExecContext(ctx,
templateCreateWorkflowExecutionClosed,
row.NamespaceID,
row.WorkflowID,
row.RunID,
row.StartTime,
row.ExecutionTime,
row.WorkflowTypeName,
closeTime,
row.Status,
*row.HistoryLength,
row.Memo,
row.Encoding,
row.TaskQueue,
)
default:
return nil, errCloseParams
}
finalRow := pdb.prepareRowForDB(row)
return pdb.conn.NamedExecContext(ctx, templateUpsertWorkflowExecution, finalRow)
}
// DeleteFromVisibility deletes a row from visibility table if it exist
@@ -189,11 +97,7 @@ func (pdb *db) DeleteFromVisibility(
ctx context.Context,
filter sqlplugin.VisibilityDeleteFilter,
) (sql.Result, error) {
return pdb.conn.ExecContext(ctx,
templateDeleteWorkflowExecution,
filter.NamespaceID,
filter.RunID,
)
return pdb.conn.NamedExecContext(ctx, templateDeleteWorkflowExecution_v12, filter)
}
// SelectFromVisibility reads one or more rows from visibility table
@@ -201,99 +105,26 @@ func (pdb *db) SelectFromVisibility(
ctx context.Context,
filter sqlplugin.VisibilitySelectFilter,
) ([]sqlplugin.VisibilityRow, error) {
var err error
if len(filter.Query) == 0 {
// backward compatibility for existing tests
err := sqlplugin.GenerateSelectQuery(&filter, pdb.converter.ToPostgreSQLDateTime)
if err != nil {
return nil, err
}
}
// Rebind will replace default placeholder `?` with the right placeholder for PostgreSQL.
filter.Query = pdb.db.Rebind(filter.Query)
var rows []sqlplugin.VisibilityRow
if filter.MinTime != nil {
*filter.MinTime = pdb.converter.ToPostgreSQLDateTime(*filter.MinTime)
}
if filter.MaxTime != nil {
*filter.MaxTime = pdb.converter.ToPostgreSQLDateTime(*filter.MaxTime)
}
// If filter.Status == 0 (UNSPECIFIED) then only closed workflows will be returned (all excluding 1 (RUNNING)).
switch {
case filter.MinTime == nil && filter.RunID != nil && filter.Status != 1:
var row sqlplugin.VisibilityRow
err = pdb.conn.GetContext(ctx,
&row,
templateGetClosedWorkflowExecution,
filter.NamespaceID,
*filter.RunID,
)
if err == nil {
rows = append(rows, row)
}
case filter.MinTime != nil && filter.MaxTime != nil &&
filter.WorkflowID != nil && filter.RunID != nil && filter.PageSize != nil:
qry := templateGetOpenWorkflowExecutionsByID
if filter.Status != 1 {
qry = templateGetClosedWorkflowExecutionsByID
}
err = pdb.conn.SelectContext(ctx,
&rows,
qry,
*filter.WorkflowID,
filter.NamespaceID,
*filter.MinTime,
*filter.MaxTime,
*filter.RunID,
*filter.MaxTime,
*filter.MaxTime,
*filter.PageSize)
case filter.MinTime != nil && filter.MaxTime != nil &&
filter.WorkflowTypeName != nil && filter.RunID != nil && filter.PageSize != nil:
qry := templateGetOpenWorkflowExecutionsByType
if filter.Status != 1 {
qry = templateGetClosedWorkflowExecutionsByType
}
err = pdb.conn.SelectContext(ctx,
&rows,
qry,
*filter.WorkflowTypeName,
filter.NamespaceID,
*filter.MinTime,
*filter.MaxTime,
*filter.RunID,
*filter.MaxTime,
*filter.MaxTime,
*filter.PageSize)
case filter.MinTime != nil && filter.MaxTime != nil &&
filter.RunID != nil && filter.PageSize != nil &&
filter.Status != 0 && filter.Status != 1: // 0 is UNSPECIFIED, 1 is RUNNING
err = pdb.conn.SelectContext(ctx,
&rows,
templateGetClosedWorkflowExecutionsByStatus,
filter.Status,
filter.NamespaceID,
*filter.MinTime,
*filter.MaxTime,
*filter.RunID,
*filter.MaxTime,
*filter.MaxTime,
*filter.PageSize)
case filter.MinTime != nil && filter.MaxTime != nil &&
filter.RunID != nil && filter.PageSize != nil:
qry := templateGetOpenWorkflowExecutions
if filter.Status != 1 {
qry = templateGetClosedWorkflowExecutions
}
err = pdb.conn.SelectContext(ctx,
&rows,
qry,
filter.NamespaceID,
*filter.MinTime,
*filter.MaxTime,
*filter.RunID,
*filter.MaxTime,
*filter.MaxTime,
*filter.PageSize)
default:
return nil, fmt.Errorf("invalid query filter")
}
err := pdb.conn.SelectContext(ctx, &rows, filter.Query, filter.QueryArgs...)
if err != nil {
return nil, err
}
for i := range rows {
pdb.processRowFromDB(&rows[i])
err = pdb.processRowFromDB(&rows[i])
if err != nil {
return nil, err
}
}
return rows, nil
}
@@ -304,16 +135,18 @@ func (pdb *db) GetFromVisibility(
filter sqlplugin.VisibilityGetFilter,
) (*sqlplugin.VisibilityRow, error) {
var row sqlplugin.VisibilityRow
err := pdb.conn.GetContext(ctx,
&row,
templateGetWorkflowExecution,
filter.NamespaceID,
filter.RunID,
)
stmt, err := pdb.conn.PrepareNamedContext(ctx, templateGetWorkflowExecution_v12)
if err != nil {
return nil, err
}
err = stmt.GetContext(ctx, &row, filter)
if err != nil {
return nil, err
}
err = pdb.processRowFromDB(&row)
if err != nil {
return nil, err
}
pdb.processRowFromDB(&row)
return &row, nil
}
@@ -321,24 +154,73 @@ func (pdb *db) CountFromVisibility(
ctx context.Context,
filter sqlplugin.VisibilitySelectFilter,
) (int64, error) {
return 0, store.OperationNotSupportedErr
var count int64
filter.Query = pdb.db.Rebind(filter.Query)
err := pdb.conn.GetContext(ctx, &count, filter.Query, filter.QueryArgs...)
if err != nil {
return 0, err
}
return count, nil
}
func (pdb *db) CountGroupByFromVisibility(
ctx context.Context,
filter sqlplugin.VisibilitySelectFilter,
) ([]sqlplugin.VisibilityCountRow, error) {
return nil, store.OperationNotSupportedErr
filter.Query = pdb.db.Rebind(filter.Query)
rows, err := pdb.db.QueryContext(ctx, filter.Query, filter.QueryArgs...)
if err != nil {
return nil, err
}
defer rows.Close()
return sqlplugin.ParseCountGroupByRows(rows, filter.GroupBy)
}
func (pdb *db) processRowFromDB(row *sqlplugin.VisibilityRow) {
func (pdb *db) prepareRowForDB(row *sqlplugin.VisibilityRow) *sqlplugin.VisibilityRow {
if row == nil {
return nil
}
finalRow := *row
finalRow.StartTime = pdb.converter.ToPostgreSQLDateTime(finalRow.StartTime)
finalRow.ExecutionTime = pdb.converter.ToPostgreSQLDateTime(finalRow.ExecutionTime)
if finalRow.CloseTime != nil {
*finalRow.CloseTime = pdb.converter.ToPostgreSQLDateTime(*finalRow.CloseTime)
}
return &finalRow
}
func (pdb *db) processRowFromDB(row *sqlplugin.VisibilityRow) error {
if row == nil {
return nil
}
row.StartTime = pdb.converter.FromPostgreSQLDateTime(row.StartTime)
row.ExecutionTime = pdb.converter.FromPostgreSQLDateTime(row.ExecutionTime)
if row.CloseTime != nil {
closeTime := pdb.converter.FromPostgreSQLDateTime(*row.CloseTime)
row.CloseTime = &closeTime
}
if row.SearchAttributes != nil {
for saName, saValue := range *row.SearchAttributes {
switch typedSaValue := saValue.(type) {
case []interface{}:
// the only valid type is slice of strings
strSlice := make([]string, len(typedSaValue))
for i, item := range typedSaValue {
switch v := item.(type) {
case string:
strSlice[i] = v
default:
return fmt.Errorf("%w: %T (expected string)", sqlplugin.ErrInvalidKeywordListDataType, v)
}
}
(*row.SearchAttributes)[saName] = strSlice
default:
// no-op
}
}
}
// need to trim the run ID, or otherwise the returned value will
// come with lots of trailing spaces, probably due to the CHAR(64) type
// come with lots of trailing spaces, probably due to the CHAR(64) type
row.RunID = strings.TrimSpace(row.RunID)
return nil
}

View File

@@ -1,226 +0,0 @@
// The MIT License
//
// Copyright (c) 2020 Temporal Technologies Inc. All rights reserved.
//
// Copyright (c) 2020 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 postgresql
import (
"context"
"database/sql"
"fmt"
"strings"
"go.temporal.io/server/common/persistence/sql/sqlplugin"
)
var (
templateInsertWorkflowExecution = fmt.Sprintf(
`INSERT INTO executions_visibility (%s)
VALUES (%s)
ON CONFLICT (namespace_id, run_id) DO NOTHING`,
strings.Join(sqlplugin.DbFields, ", "),
sqlplugin.BuildNamedPlaceholder(sqlplugin.DbFields...),
)
templateUpsertWorkflowExecution = fmt.Sprintf(
`INSERT INTO executions_visibility (%s)
VALUES (%s)
%s`,
strings.Join(sqlplugin.DbFields, ", "),
sqlplugin.BuildNamedPlaceholder(sqlplugin.DbFields...),
buildOnDuplicateKeyUpdate(sqlplugin.DbFields...),
)
templateDeleteWorkflowExecution_v12 = `
DELETE FROM executions_visibility
WHERE namespace_id = :namespace_id AND run_id = :run_id`
templateGetWorkflowExecution_v12 = fmt.Sprintf(
`SELECT %s FROM executions_visibility
WHERE namespace_id = :namespace_id AND run_id = :run_id`,
strings.Join(sqlplugin.DbFields, ", "),
)
)
func buildOnDuplicateKeyUpdate(fields ...string) string {
items := make([]string, len(fields))
for i, field := range fields {
items[i] = fmt.Sprintf("%s = excluded.%s", field, field)
}
return fmt.Sprintf(
"ON CONFLICT (namespace_id, run_id) DO UPDATE SET %s",
strings.Join(items, ", "),
)
}
// InsertIntoVisibility inserts a row into visibility table. If an row already exist,
// its left as such and no update will be made
func (pdb *dbV12) InsertIntoVisibility(
ctx context.Context,
row *sqlplugin.VisibilityRow,
) (sql.Result, error) {
finalRow := pdb.prepareRowForDB(row)
return pdb.conn.NamedExecContext(ctx, templateInsertWorkflowExecution, finalRow)
}
// ReplaceIntoVisibility replaces an existing row if it exist or creates a new row in visibility table
func (pdb *dbV12) ReplaceIntoVisibility(
ctx context.Context,
row *sqlplugin.VisibilityRow,
) (sql.Result, error) {
finalRow := pdb.prepareRowForDB(row)
return pdb.conn.NamedExecContext(ctx, templateUpsertWorkflowExecution, finalRow)
}
// DeleteFromVisibility deletes a row from visibility table if it exist
func (pdb *dbV12) DeleteFromVisibility(
ctx context.Context,
filter sqlplugin.VisibilityDeleteFilter,
) (sql.Result, error) {
return pdb.conn.NamedExecContext(ctx, templateDeleteWorkflowExecution_v12, filter)
}
// SelectFromVisibility reads one or more rows from visibility table
func (pdb *dbV12) SelectFromVisibility(
ctx context.Context,
filter sqlplugin.VisibilitySelectFilter,
) ([]sqlplugin.VisibilityRow, error) {
if len(filter.Query) == 0 {
// backward compatibility for existing tests
err := sqlplugin.GenerateSelectQuery(&filter, pdb.converter.ToPostgreSQLDateTime)
if err != nil {
return nil, err
}
}
// Rebind will replace default placeholder `?` with the right placeholder for PostgreSQL.
filter.Query = pdb.db.db.Rebind(filter.Query)
var rows []sqlplugin.VisibilityRow
err := pdb.conn.SelectContext(ctx, &rows, filter.Query, filter.QueryArgs...)
if err != nil {
return nil, err
}
for i := range rows {
err = pdb.processRowFromDB(&rows[i])
if err != nil {
return nil, err
}
}
return rows, nil
}
// GetFromVisibility reads one row from visibility table
func (pdb *dbV12) GetFromVisibility(
ctx context.Context,
filter sqlplugin.VisibilityGetFilter,
) (*sqlplugin.VisibilityRow, error) {
var row sqlplugin.VisibilityRow
stmt, err := pdb.conn.PrepareNamedContext(ctx, templateGetWorkflowExecution_v12)
if err != nil {
return nil, err
}
err = stmt.GetContext(ctx, &row, filter)
if err != nil {
return nil, err
}
err = pdb.processRowFromDB(&row)
if err != nil {
return nil, err
}
return &row, nil
}
func (pdb *dbV12) CountFromVisibility(
ctx context.Context,
filter sqlplugin.VisibilitySelectFilter,
) (int64, error) {
var count int64
filter.Query = pdb.db.db.Rebind(filter.Query)
err := pdb.conn.GetContext(ctx, &count, filter.Query, filter.QueryArgs...)
if err != nil {
return 0, err
}
return count, nil
}
func (pdb *dbV12) CountGroupByFromVisibility(
ctx context.Context,
filter sqlplugin.VisibilitySelectFilter,
) ([]sqlplugin.VisibilityCountRow, error) {
filter.Query = pdb.db.db.Rebind(filter.Query)
rows, err := pdb.db.db.QueryContext(ctx, filter.Query, filter.QueryArgs...)
if err != nil {
return nil, err
}
defer rows.Close()
return sqlplugin.ParseCountGroupByRows(rows, filter.GroupBy)
}
func (pdb *dbV12) prepareRowForDB(row *sqlplugin.VisibilityRow) *sqlplugin.VisibilityRow {
if row == nil {
return nil
}
finalRow := *row
finalRow.StartTime = pdb.converter.ToPostgreSQLDateTime(finalRow.StartTime)
finalRow.ExecutionTime = pdb.converter.ToPostgreSQLDateTime(finalRow.ExecutionTime)
if finalRow.CloseTime != nil {
*finalRow.CloseTime = pdb.converter.ToPostgreSQLDateTime(*finalRow.CloseTime)
}
return &finalRow
}
func (pdb *dbV12) processRowFromDB(row *sqlplugin.VisibilityRow) error {
if row == nil {
return nil
}
row.StartTime = pdb.converter.FromPostgreSQLDateTime(row.StartTime)
row.ExecutionTime = pdb.converter.FromPostgreSQLDateTime(row.ExecutionTime)
if row.CloseTime != nil {
closeTime := pdb.converter.FromPostgreSQLDateTime(*row.CloseTime)
row.CloseTime = &closeTime
}
if row.SearchAttributes != nil {
for saName, saValue := range *row.SearchAttributes {
switch typedSaValue := saValue.(type) {
case []interface{}:
// the only valid type is slice of strings
strSlice := make([]string, len(typedSaValue))
for i, item := range typedSaValue {
switch v := item.(type) {
case string:
strSlice[i] = v
default:
return fmt.Errorf("Unexpected data type in keyword list: %T (expected string)", v)
}
}
(*row.SearchAttributes)[saName] = strSlice
default:
// no-op
}
}
}
// need to trim the run ID, or otherwise the returned value will
// come with lots of trailing spaces, probably due to the CHAR(64) type
row.RunID = strings.TrimSpace(row.RunID)
return nil
}

View File

@@ -29,6 +29,7 @@ import (
"database/sql"
"database/sql/driver"
"encoding/json"
"errors"
"fmt"
"reflect"
"strings"
@@ -41,6 +42,10 @@ import (
"go.temporal.io/server/common/searchattribute"
)
var (
ErrInvalidKeywordListDataType = errors.New("Unexpected data type in keyword list")
)
type (
// VisibilitySearchAttributes represents the search attributes json
// in executions_visibility table

View File

@@ -145,13 +145,6 @@ func TestMySQLTaskQueueTaskSuite(t *testing.T) {
suite.Run(t, s)
}
func TestMySQLVisibilityPersistenceSuite(t *testing.T) {
s := &VisibilityPersistenceSuite{
TestBase: persistencetests.NewTestBaseWithSQL(persistencetests.GetMySQLTestClusterOption()),
}
suite.Run(t, s)
}
func TestMySQL8VisibilityPersistenceSuite(t *testing.T) {
s := &VisibilityPersistenceSuite{
TestBase: persistencetests.NewTestBaseWithSQL(persistencetests.GetMySQL8TestClusterOption()),
@@ -161,34 +154,6 @@ func TestMySQL8VisibilityPersistenceSuite(t *testing.T) {
// TODO: Merge persistence-tests into the tests directory.
func TestMySQLHistoryV2PersistenceSuite(t *testing.T) {
s := new(persistencetests.HistoryV2PersistenceSuite)
s.TestBase = persistencetests.NewTestBaseWithSQL(persistencetests.GetMySQLTestClusterOption())
s.TestBase.Setup(nil)
suite.Run(t, s)
}
func TestMySQLMetadataPersistenceSuiteV2(t *testing.T) {
s := new(persistencetests.MetadataPersistenceSuiteV2)
s.TestBase = persistencetests.NewTestBaseWithSQL(persistencetests.GetMySQLTestClusterOption())
s.TestBase.Setup(nil)
suite.Run(t, s)
}
func TestMySQLQueuePersistence(t *testing.T) {
s := new(persistencetests.QueuePersistenceSuite)
s.TestBase = persistencetests.NewTestBaseWithSQL(persistencetests.GetMySQLTestClusterOption())
s.TestBase.Setup(nil)
suite.Run(t, s)
}
func TestMySQLClusterMetadataPersistence(t *testing.T) {
s := new(persistencetests.ClusterMetadataManagerSuite)
s.TestBase = persistencetests.NewTestBaseWithSQL(persistencetests.GetMySQLTestClusterOption())
s.TestBase.Setup(nil)
suite.Run(t, s)
}
func TestMySQL8HistoryV2PersistenceSuite(t *testing.T) {
s := new(persistencetests.HistoryV2PersistenceSuite)
s.TestBase = persistencetests.NewTestBaseWithSQL(persistencetests.GetMySQL8TestClusterOption())

View File

@@ -146,13 +146,6 @@ func (p *PostgreSQLSuite) TestPostgreSQLTaskQueueTaskSuite() {
suite.Run(p.T(), s)
}
func (p *PostgreSQLSuite) TestPostgreSQLVisibilityPersistenceSuite() {
s := &VisibilityPersistenceSuite{
TestBase: persistencetests.NewTestBaseWithSQL(persistencetests.GetPostgreSQLTestClusterOption()),
}
suite.Run(p.T(), s)
}
func (p *PostgreSQLSuite) TestPostgreSQL12VisibilityPersistenceSuite() {
s := &VisibilityPersistenceSuite{
TestBase: persistencetests.NewTestBaseWithSQL(persistencetests.GetPostgreSQL12TestClusterOption()),
@@ -162,45 +155,6 @@ func (p *PostgreSQLSuite) TestPostgreSQL12VisibilityPersistenceSuite() {
// TODO: Merge persistence-tests into the tests directory.
func (p *PostgreSQLSuite) TestPostgreSQLHistoryV2PersistenceSuite() {
s := new(persistencetests.HistoryV2PersistenceSuite)
s.TestBase = persistencetests.NewTestBaseWithSQL(persistencetests.GetPostgreSQLTestClusterOption())
s.TestBase.Setup(nil)
suite.Run(p.T(), s)
}
func (p *PostgreSQLSuite) TestPostgreSQLMetadataPersistenceSuiteV2() {
s := new(persistencetests.MetadataPersistenceSuiteV2)
s.TestBase = persistencetests.NewTestBaseWithSQL(persistencetests.GetPostgreSQLTestClusterOption())
s.TestBase.Setup(nil)
suite.Run(p.T(), s)
}
func (p *PostgreSQLSuite) TestPostgreSQLClusterMetadataPersistence() {
s := new(persistencetests.ClusterMetadataManagerSuite)
s.TestBase = persistencetests.NewTestBaseWithSQL(persistencetests.GetPostgreSQLTestClusterOption())
s.TestBase.Setup(nil)
suite.Run(p.T(), s)
}
// TODO flaky test in buildkite
// https://go.temporal.io/server/issues/2877
/*
FAIL: TestPostgreSQLQueuePersistence/TestNamespaceReplicationQueue (0.26s)
queuePersistenceTest.go:102:
Error Trace: queuePersistenceTest.go:102
Error: Not equal:
expected: 99
actual : 98
Test: TestPostgreSQLQueuePersistence/TestNamespaceReplicationQueue
*/
// func (p *PostgreSQLSuite) TestPostgreSQLQueuePersistence() {
// s := new(persistencetests.QueuePersistenceSuite)
// s.TestBase = persistencetests.NewTestBaseWithSQL(persistencetests.GetPostgreSQLTestClusterOption())
// s.TestBase.Setup(nil)
// suite.Run(p.T(), s)
// }
func (p *PostgreSQLSuite) TestPostgreSQL12HistoryV2PersistenceSuite() {
s := new(persistencetests.HistoryV2PersistenceSuite)
s.TestBase = persistencetests.NewTestBaseWithSQL(persistencetests.GetPostgreSQL12TestClusterOption())
@@ -222,6 +176,24 @@ func (p *PostgreSQLSuite) TestPostgreSQL12ClusterMetadataPersistence() {
suite.Run(p.T(), s)
}
// TODO flaky test in buildkite
// https://go.temporal.io/server/issues/2877
/*
FAIL: TestPostgreSQLQueuePersistence/TestNamespaceReplicationQueue (0.26s)
queuePersistenceTest.go:102:
Error Trace: queuePersistenceTest.go:102
Error: Not equal:
expected: 99
actual : 98
Test: TestPostgreSQLQueuePersistence/TestNamespaceReplicationQueue
*/
// func (p *PostgreSQLSuite) TestPostgreSQL12QueuePersistence() {
// s := new(persistencetests.QueuePersistenceSuite)
// s.TestBase = persistencetests.NewTestBaseWithSQL(persistencetests.GetPostgreSQL12TestClusterOption())
// s.TestBase.Setup(nil)
// suite.Run(p.T(), s)
// }
// SQL store tests
func (p *PostgreSQLSuite) TestPostgreSQLNamespaceSuite() {

View File

@@ -45,8 +45,6 @@ import (
"go.temporal.io/server/common/payload"
"go.temporal.io/server/common/persistence"
persistencetests "go.temporal.io/server/common/persistence/persistence-tests"
"go.temporal.io/server/common/persistence/sql/sqlplugin/mysql"
"go.temporal.io/server/common/persistence/sql/sqlplugin/postgresql"
"go.temporal.io/server/common/persistence/visibility"
"go.temporal.io/server/common/persistence/visibility/manager"
"go.temporal.io/server/common/primitives/timestamp"
@@ -780,11 +778,6 @@ func (s *VisibilityPersistenceSuite) TestAdvancedVisibilityPagination() {
}
func (s *VisibilityPersistenceSuite) TestCountWorkflowExecutions() {
switch s.VisibilityMgr.GetStoreNames()[0] {
case mysql.PluginName, postgresql.PluginName, postgresql.PluginNamePGX:
s.T().Skip("Not supported by standard visibility")
}
testNamespaceUUID := namespace.ID(uuid.New())
closeTime := time.Now().UTC()
startTime := closeTime.Add(-5 * time.Second)
@@ -812,11 +805,6 @@ func (s *VisibilityPersistenceSuite) TestCountWorkflowExecutions() {
}
func (s *VisibilityPersistenceSuite) TestCountGroupByWorkflowExecutions() {
switch s.VisibilityMgr.GetStoreNames()[0] {
case mysql.PluginName, postgresql.PluginName, postgresql.PluginNamePGX:
s.T().Skip("Not supported by standard visibility")
}
testNamespaceUUID := namespace.ID(uuid.New())
closeTime := time.Now().UTC()
startTime := closeTime.Add(-5 * time.Second)

View File

@@ -86,9 +86,6 @@ func AllowListForValidation(
case mysql.PluginNameV8, postgresql.PluginNameV12, postgresql.PluginNameV12PGX, sqlite.PluginName:
// Advanced visibility with SQL DB don't support list of values
return dynamicconfig.GetBoolPropertyFnFilteredByNamespace(false)
case mysql.PluginName, postgresql.PluginName, postgresql.PluginNamePGX:
// Standard visibility with SQL DB don't support list of values, but pass validation
return dynamicconfig.GetBoolPropertyFnFilteredByNamespace(true)
default:
// Otherwise (ES), check dynamic config
return allowList

View File

@@ -38,8 +38,6 @@ import (
"go.temporal.io/server/common/persistence/visibility/store/elasticsearch"
esclient "go.temporal.io/server/common/persistence/visibility/store/elasticsearch/client"
"go.temporal.io/server/common/persistence/visibility/store/sql"
"go.temporal.io/server/common/persistence/visibility/store/standard"
standardSql "go.temporal.io/server/common/persistence/visibility/store/standard/sql"
"go.temporal.io/server/common/resolver"
"go.temporal.io/server/common/searchattribute"
)
@@ -256,25 +254,13 @@ func newVisibilityStoreFromDataStoreConfig(
err error
)
if dsConfig.SQL != nil {
switch dsConfig.SQL.PluginName {
case mysql.PluginNameV8, postgresql.PluginNameV12, postgresql.PluginNameV12PGX, sqlite.PluginName:
visStore, err = sql.NewSQLVisibilityStore(
*dsConfig.SQL,
persistenceResolver,
searchAttributesProvider,
searchAttributesMapperProvider,
logger,
)
default:
visStore, err = newStandardVisibilityStore(
dsConfig,
persistenceResolver,
searchAttributesProvider,
searchAttributesMapperProvider,
logger,
metricsHandler,
)
}
visStore, err = sql.NewSQLVisibilityStore(
*dsConfig.SQL,
persistenceResolver,
searchAttributesProvider,
searchAttributesMapperProvider,
logger,
)
} else if dsConfig.Elasticsearch != nil {
visStore = newElasticsearchVisibilityStore(
dsConfig.Elasticsearch.GetVisibilityIndex(),
@@ -298,39 +284,6 @@ func newVisibilityStoreFromDataStoreConfig(
return visStore, err
}
func newStandardVisibilityStore(
dsConfig config.DataStore,
persistenceResolver resolver.ServiceResolver,
searchAttributesProvider searchattribute.Provider,
searchAttributesMapperProvider searchattribute.MapperProvider,
logger log.Logger,
metricsHandler metrics.Handler,
) (store.VisibilityStore, error) {
var (
visStore store.VisibilityStore
err error
)
if dsConfig.SQL != nil {
visStore, err = standardSql.NewSQLVisibilityStore(
*dsConfig.SQL,
persistenceResolver,
logger,
)
}
if err != nil {
return nil, err
}
if visStore == nil {
logger.Fatal("invalid config: sql params must be specified for visibility store")
return nil, nil
}
return standard.NewVisibilityStore(
visStore,
searchAttributesProvider,
searchAttributesMapperProvider,
), nil
}
func newElasticsearchVisibilityStore(
defaultIndexName string,
esClient esclient.Client,

View File

@@ -1,121 +0,0 @@
// The MIT License
//
// Copyright (c) 2021 Temporal Technologies Inc. All rights reserved.
//
// Copyright (c) 2020 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 standard
import (
"errors"
"time"
"github.com/temporalio/sqlparser"
enumspb "go.temporal.io/api/enums/v1"
"go.temporal.io/server/common/namespace"
"go.temporal.io/server/common/persistence/sql/sqlplugin"
"go.temporal.io/server/common/persistence/visibility/store/query"
"go.temporal.io/server/common/searchattribute"
)
var allowedComparisonOperators = map[string]struct{}{
sqlparser.EqualStr: {},
}
type (
converter struct {
*query.Converter
fvInterceptor *valuesInterceptor
}
)
func newQueryConverter(
namespaceName namespace.Name,
searchAttributesTypeMap searchattribute.NameTypeMap,
searchAttributesMapperProvider searchattribute.MapperProvider,
) *converter {
fnInterceptor := newNameInterceptor()
fvInterceptor := newValuesInterceptor(
namespaceName,
searchAttributesTypeMap,
searchAttributesMapperProvider,
)
rangeCond := query.NewRangeCondConverter(fnInterceptor, fvInterceptor, false)
comparisonExpr := query.NewComparisonExprConverter(fnInterceptor, fvInterceptor, allowedComparisonOperators)
whereConverter := &query.WhereConverter{
Or: query.NewNotSupportedExprConverter(),
RangeCond: rangeCond,
ComparisonExpr: comparisonExpr,
Is: query.NewNotSupportedExprConverter(),
}
whereConverter.And = query.NewAndConverter(whereConverter)
return &converter{
Converter: query.NewConverter(fnInterceptor, whereConverter),
fvInterceptor: fvInterceptor,
}
}
func (c *converter) GetFilter(whereOrderBy string) (*sqlplugin.VisibilitySelectFilter, error) {
_, err := c.ConvertWhereOrderBy(whereOrderBy)
if err != nil {
// Convert ConverterError to InvalidArgument and pass through all other errors.
var converterErr *query.ConverterError
if errors.As(err, &converterErr) {
return nil, converterErr.ToInvalidArgument()
}
return nil, err
}
filter := c.fvInterceptor.filter
numPredicates := 0
if filter.WorkflowID != nil {
numPredicates++
}
if filter.WorkflowTypeName != nil {
numPredicates++
}
if filter.Status != int32(enumspb.WORKFLOW_EXECUTION_STATUS_UNSPECIFIED) {
numPredicates++
}
if numPredicates > 1 {
return nil, query.NewConverterError("too many filter conditions specified")
}
if filter.MinTime == nil {
minTime := time.Unix(0, 0)
filter.MinTime = &minTime
}
if filter.MaxTime == nil {
maxTime := time.Now().Add(24 * time.Hour)
filter.MaxTime = &maxTime
}
return filter, nil
}

View File

@@ -1,101 +0,0 @@
// The MIT License
//
// Copyright (c) 2021 Temporal Technologies Inc. All rights reserved.
//
// Copyright (c) 2020 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 standard
import (
"fmt"
"testing"
"time"
"github.com/stretchr/testify/assert"
enumspb "go.temporal.io/api/enums/v1"
"go.temporal.io/server/common/persistence/sql/sqlplugin"
"go.temporal.io/server/common/searchattribute"
"go.temporal.io/server/common/util"
)
var startTimeFrom = time.Now().Add(-time.Hour)
var startTimeTo = time.Now()
var startTimeRangeFilter = fmt.Sprintf(`StartTime BETWEEN "%v" AND "%v"`, startTimeFrom.Format(time.RFC3339Nano), startTimeTo.Format(time.RFC3339Nano))
var supportedQuery = map[string]*sqlplugin.VisibilitySelectFilter{
"": {},
startTimeRangeFilter: {MinTime: &startTimeFrom, MaxTime: &startTimeTo},
`WorkflowId = "abc"`: {WorkflowID: util.Ptr("abc")},
`WorkflowId = "abc" AND ` + startTimeRangeFilter: {WorkflowID: util.Ptr("abc"), MinTime: &startTimeFrom, MaxTime: &startTimeTo},
startTimeRangeFilter + ` AND WorkflowId = "abc"`: {WorkflowID: util.Ptr("abc"), MinTime: &startTimeFrom, MaxTime: &startTimeTo},
`WorkflowType = "abc"`: {WorkflowTypeName: util.Ptr("abc")},
`WorkflowType = "abc" AND ` + startTimeRangeFilter: {WorkflowTypeName: util.Ptr("abc"), MinTime: &startTimeFrom, MaxTime: &startTimeTo},
startTimeRangeFilter + ` AND WorkflowType = "abc"`: {WorkflowTypeName: util.Ptr("abc"), MinTime: &startTimeFrom, MaxTime: &startTimeTo},
`ExecutionStatus = "Running"`: {Status: int32(enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING)},
`ExecutionStatus = "Running" AND ` + startTimeRangeFilter: {Status: int32(enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING), MinTime: &startTimeFrom, MaxTime: &startTimeTo},
startTimeRangeFilter + ` AND ExecutionStatus = "Running"`: {Status: int32(enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING), MinTime: &startTimeFrom, MaxTime: &startTimeTo},
}
// This is not an exhaustive list.
var unsupportedQuery = []string{
fmt.Sprintf(`StartTime NOT BETWEEN "%v" AND "%v"`, startTimeFrom.Format(time.RFC3339Nano), startTimeTo.Format(time.RFC3339Nano)),
"order by WorkflowID",
`WorkflowID = "abc" AND WorkflowType = "xyz"`,
`ExecutionStatus = "Running" AND WorkflowType = "xyz"`,
`WorkflowID = "abc" OR WorkflowType = "xyz"`,
`WorkflowID != "abc"`,
`StartTime < "2022-01-15T05:43:12.74127Z"`,
}
func TestSupportedQueryFilters(t *testing.T) {
for query, expectedFilter := range supportedQuery {
converter := newQueryConverter("test-namespace", searchattribute.TestNameTypeMap, nil)
filter, err := converter.GetFilter(query)
assert.NoError(t, err)
assert.EqualValues(t, expectedFilter.WorkflowID, filter.WorkflowID)
assert.EqualValues(t, expectedFilter.WorkflowTypeName, filter.WorkflowTypeName)
assert.EqualValues(t, expectedFilter.Status, filter.Status)
if expectedFilter.MinTime == nil {
assert.True(t, time.Unix(0, 0).Equal(*filter.MinTime))
} else {
assert.NotNil(t, filter.MinTime)
assert.True(t, expectedFilter.MinTime.Equal(*filter.MinTime))
}
if expectedFilter.MaxTime == nil {
assert.True(t, filter.MaxTime.After(time.Now()))
} else {
assert.NotNil(t, filter.MaxTime)
assert.True(t, expectedFilter.MaxTime.Equal(*filter.MaxTime))
}
}
}
func TestUnsupportedQueryFilters(t *testing.T) {
for _, query := range unsupportedQuery {
converter := newQueryConverter("test-namespace", searchattribute.TestNameTypeMap, nil)
_, err := converter.GetFilter(query)
assert.Error(t, err)
}
}

View File

@@ -1,136 +0,0 @@
// The MIT License
//
// Copyright (c) 2021 Temporal Technologies Inc. All rights reserved.
//
// Copyright (c) 2020 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 standard
import (
"time"
enumspb "go.temporal.io/api/enums/v1"
"go.temporal.io/server/common/namespace"
"go.temporal.io/server/common/persistence/sql/sqlplugin"
"go.temporal.io/server/common/persistence/visibility/store/elasticsearch"
"go.temporal.io/server/common/persistence/visibility/store/query"
"go.temporal.io/server/common/searchattribute"
"go.temporal.io/server/common/util"
)
var allowedFilters = []string{
searchattribute.WorkflowID,
searchattribute.WorkflowType,
searchattribute.ExecutionStatus,
searchattribute.StartTime,
}
type (
nameInterceptor struct{}
valuesInterceptor struct {
filter *sqlplugin.VisibilitySelectFilter
nextInterceptor query.FieldValuesInterceptor
}
)
func newNameInterceptor() *nameInterceptor {
return &nameInterceptor{}
}
func newValuesInterceptor(
namespaceName namespace.Name,
searchAttributesTypeMap searchattribute.NameTypeMap,
searchAttributesMapperProvider searchattribute.MapperProvider,
) *valuesInterceptor {
return &valuesInterceptor{
filter: &sqlplugin.VisibilitySelectFilter{},
nextInterceptor: elasticsearch.NewValuesInterceptor(
namespaceName,
searchAttributesTypeMap,
searchAttributesMapperProvider,
),
}
}
func (ni *nameInterceptor) Name(name string, usage query.FieldNameUsage) (string, error) {
if usage == query.FieldNameSorter {
return "", query.NewConverterError("order by not allowed for standard visibility")
}
for _, filter := range allowedFilters {
if filter == name {
return name, nil
}
}
return "", query.NewConverterError("filter by '%v' not supported for standard visibility", name)
}
func (vi *valuesInterceptor) Values(name string, values ...interface{}) ([]interface{}, error) {
switch name {
case searchattribute.WorkflowID:
values, err := vi.nextInterceptor.Values(name, values...)
if err == nil {
vi.filter.WorkflowID = util.Ptr(values[0].(string))
}
return values, err
case searchattribute.WorkflowType:
values, err := vi.nextInterceptor.Values(name, values...)
if err == nil {
vi.filter.WorkflowTypeName = util.Ptr(values[0].(string))
}
return values, err
case searchattribute.ExecutionStatus:
values, err := vi.nextInterceptor.Values(name, values...)
if err == nil {
statusStr := values[0].(string)
e, err := enumspb.WorkflowExecutionStatusFromString(statusStr)
if err != nil {
return nil, query.NewConverterError("invalid ExecutionStatus %q", statusStr)
}
vi.filter.Status = int32(e)
}
return values, err
case searchattribute.StartTime:
if len(values) != 2 {
return nil, query.NewConverterError("StartTime only supports BETWEEN ... AND ... filter")
}
values, err := vi.nextInterceptor.Values(name, values...)
if err == nil {
minTime, err := time.Parse(time.RFC3339Nano, values[0].(string))
if err != nil {
return nil, query.NewConverterError("invalid StartTime format: %v", minTime)
}
vi.filter.MinTime = &minTime
maxTime, err := time.Parse(time.RFC3339Nano, values[1].(string))
if err != nil {
return nil, query.NewConverterError("invalid StartTime format: %v", maxTime)
}
vi.filter.MaxTime = &maxTime
}
return values, err
default:
return nil, query.NewConverterError("filter by '%v' not supported for standard visibility", name)
}
}

View File

@@ -1,446 +0,0 @@
// The MIT License
//
// Copyright (c) 2020 Temporal Technologies Inc. All rights reserved.
//
// Copyright (c) 2020 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 sql
import (
"context"
"encoding/json"
"fmt"
"time"
enumspb "go.temporal.io/api/enums/v1"
"go.temporal.io/api/serviceerror"
"go.temporal.io/server/common/config"
"go.temporal.io/server/common/log"
"go.temporal.io/server/common/persistence"
persistencesql "go.temporal.io/server/common/persistence/sql"
"go.temporal.io/server/common/persistence/sql/sqlplugin"
"go.temporal.io/server/common/persistence/visibility/manager"
"go.temporal.io/server/common/persistence/visibility/store"
"go.temporal.io/server/common/resolver"
)
type (
visibilityStore struct {
sqlStore persistencesql.SqlStore
}
visibilityPageToken struct {
Time time.Time
RunID string
}
)
var _ store.VisibilityStore = (*visibilityStore)(nil)
// NewSQLVisibilityStore creates an instance of VisibilityStore
func NewSQLVisibilityStore(
cfg config.SQL,
r resolver.ServiceResolver,
logger log.Logger,
) (*visibilityStore, error) {
refDbConn := persistencesql.NewRefCountedDBConn(sqlplugin.DbKindVisibility, &cfg, r)
db, err := refDbConn.Get()
if err != nil {
return nil, err
}
return &visibilityStore{
sqlStore: persistencesql.NewSqlStore(db, logger),
}, nil
}
func (s *visibilityStore) Close() {
s.sqlStore.Close()
}
func (s *visibilityStore) GetName() string {
return s.sqlStore.GetName()
}
func (s *visibilityStore) GetIndexName() string {
// GetIndexName is used to get cluster metadata, which in verstions < v1.20
// were stored in an empty string key.
return ""
}
func (s *visibilityStore) ValidateCustomSearchAttributes(
searchAttributes map[string]any,
) (map[string]any, error) {
return searchAttributes, nil
}
func (s *visibilityStore) RecordWorkflowExecutionStarted(
ctx context.Context,
request *store.InternalRecordWorkflowExecutionStartedRequest,
) error {
_, err := s.sqlStore.Db.InsertIntoVisibility(ctx, &sqlplugin.VisibilityRow{
NamespaceID: request.NamespaceID,
WorkflowID: request.WorkflowID,
RunID: request.RunID,
StartTime: request.StartTime,
ExecutionTime: request.ExecutionTime,
WorkflowTypeName: request.WorkflowTypeName,
Status: int32(enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING), // Underlying value (1) is hardcoded in SQL queries.
Memo: request.Memo.Data,
Encoding: request.Memo.EncodingType.String(),
TaskQueue: request.TaskQueue,
})
return err
}
func (s *visibilityStore) RecordWorkflowExecutionClosed(
ctx context.Context,
request *store.InternalRecordWorkflowExecutionClosedRequest,
) error {
result, err := s.sqlStore.Db.ReplaceIntoVisibility(ctx, &sqlplugin.VisibilityRow{
NamespaceID: request.NamespaceID,
WorkflowID: request.WorkflowID,
RunID: request.RunID,
StartTime: request.StartTime,
ExecutionTime: request.ExecutionTime,
WorkflowTypeName: request.WorkflowTypeName,
CloseTime: &request.CloseTime,
Status: int32(request.Status),
HistoryLength: &request.HistoryLength,
Memo: request.Memo.Data,
Encoding: request.Memo.EncodingType.String(),
TaskQueue: request.TaskQueue,
})
if err != nil {
return err
}
noRowsAffected, err := result.RowsAffected()
if err != nil {
return fmt.Errorf("RecordWorkflowExecutionClosed rowsAffected error: %v", err)
}
if noRowsAffected > 2 { // either adds a new row or deletes old row and adds new row
return fmt.Errorf("RecordWorkflowExecutionClosed unexpected numRows (%v) updated", noRowsAffected)
}
return nil
}
func (s *visibilityStore) UpsertWorkflowExecution(
_ context.Context,
_ *store.InternalUpsertWorkflowExecutionRequest,
) error {
// Not OperationNotSupportedErr!
return nil
}
func (s *visibilityStore) ListOpenWorkflowExecutions(
ctx context.Context,
request *manager.ListWorkflowExecutionsRequest,
) (*store.InternalListWorkflowExecutionsResponse, error) {
return s.listWorkflowExecutions(
"ListOpenWorkflowExecutions",
request.NextPageToken,
request.PageSize,
request.LatestStartTime,
false,
func(readLevel *visibilityPageToken) ([]sqlplugin.VisibilityRow, error) {
return s.sqlStore.Db.SelectFromVisibility(ctx, sqlplugin.VisibilitySelectFilter{
NamespaceID: request.NamespaceID.String(),
MinTime: &request.EarliestStartTime,
MaxTime: &readLevel.Time,
RunID: &readLevel.RunID,
PageSize: &request.PageSize,
Status: int32(enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING),
})
})
}
func (s *visibilityStore) ListClosedWorkflowExecutions(
ctx context.Context,
request *manager.ListWorkflowExecutionsRequest,
) (*store.InternalListWorkflowExecutionsResponse, error) {
return s.listWorkflowExecutions("ListClosedWorkflowExecutions",
request.NextPageToken,
request.PageSize,
request.LatestStartTime,
true,
func(readLevel *visibilityPageToken) ([]sqlplugin.VisibilityRow, error) {
return s.sqlStore.Db.SelectFromVisibility(ctx, sqlplugin.VisibilitySelectFilter{
NamespaceID: request.NamespaceID.String(),
MinTime: &request.EarliestStartTime,
MaxTime: &readLevel.Time,
RunID: &readLevel.RunID,
PageSize: &request.PageSize,
})
})
}
func (s *visibilityStore) ListOpenWorkflowExecutionsByType(
ctx context.Context,
request *manager.ListWorkflowExecutionsByTypeRequest,
) (*store.InternalListWorkflowExecutionsResponse, error) {
return s.listWorkflowExecutions("ListOpenWorkflowExecutionsByType",
request.NextPageToken,
request.PageSize,
request.LatestStartTime,
false,
func(readLevel *visibilityPageToken) ([]sqlplugin.VisibilityRow, error) {
return s.sqlStore.Db.SelectFromVisibility(ctx, sqlplugin.VisibilitySelectFilter{
NamespaceID: request.NamespaceID.String(),
MinTime: &request.EarliestStartTime,
MaxTime: &readLevel.Time,
RunID: &readLevel.RunID,
WorkflowTypeName: &request.WorkflowTypeName,
PageSize: &request.PageSize,
Status: int32(enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING),
})
})
}
func (s *visibilityStore) ListClosedWorkflowExecutionsByType(
ctx context.Context,
request *manager.ListWorkflowExecutionsByTypeRequest,
) (*store.InternalListWorkflowExecutionsResponse, error) {
return s.listWorkflowExecutions("ListClosedWorkflowExecutionsByType",
request.NextPageToken,
request.PageSize,
request.LatestStartTime,
true,
func(readLevel *visibilityPageToken) ([]sqlplugin.VisibilityRow, error) {
return s.sqlStore.Db.SelectFromVisibility(ctx, sqlplugin.VisibilitySelectFilter{
NamespaceID: request.NamespaceID.String(),
MinTime: &request.EarliestStartTime,
MaxTime: &readLevel.Time,
RunID: &readLevel.RunID,
WorkflowTypeName: &request.WorkflowTypeName,
PageSize: &request.PageSize,
})
})
}
func (s *visibilityStore) ListOpenWorkflowExecutionsByWorkflowID(
ctx context.Context,
request *manager.ListWorkflowExecutionsByWorkflowIDRequest,
) (*store.InternalListWorkflowExecutionsResponse, error) {
return s.listWorkflowExecutions("ListOpenWorkflowExecutionsByWorkflowID",
request.NextPageToken,
request.PageSize,
request.LatestStartTime,
false,
func(readLevel *visibilityPageToken) ([]sqlplugin.VisibilityRow, error) {
return s.sqlStore.Db.SelectFromVisibility(ctx, sqlplugin.VisibilitySelectFilter{
NamespaceID: request.NamespaceID.String(),
MinTime: &request.EarliestStartTime,
MaxTime: &readLevel.Time,
RunID: &readLevel.RunID,
WorkflowID: &request.WorkflowID,
PageSize: &request.PageSize,
Status: int32(enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING),
})
})
}
func (s *visibilityStore) ListClosedWorkflowExecutionsByWorkflowID(
ctx context.Context,
request *manager.ListWorkflowExecutionsByWorkflowIDRequest,
) (*store.InternalListWorkflowExecutionsResponse, error) {
return s.listWorkflowExecutions("ListClosedWorkflowExecutionsByWorkflowID",
request.NextPageToken,
request.PageSize,
request.LatestStartTime,
true,
func(readLevel *visibilityPageToken) ([]sqlplugin.VisibilityRow, error) {
return s.sqlStore.Db.SelectFromVisibility(ctx, sqlplugin.VisibilitySelectFilter{
NamespaceID: request.NamespaceID.String(),
MinTime: &request.EarliestStartTime,
MaxTime: &readLevel.Time,
RunID: &readLevel.RunID,
WorkflowID: &request.WorkflowID,
PageSize: &request.PageSize,
})
})
}
func (s *visibilityStore) ListClosedWorkflowExecutionsByStatus(
ctx context.Context,
request *manager.ListClosedWorkflowExecutionsByStatusRequest,
) (*store.InternalListWorkflowExecutionsResponse, error) {
return s.listWorkflowExecutions("ListClosedWorkflowExecutionsByStatus",
request.NextPageToken,
request.PageSize,
request.LatestStartTime,
true,
func(readLevel *visibilityPageToken) ([]sqlplugin.VisibilityRow, error) {
return s.sqlStore.Db.SelectFromVisibility(ctx, sqlplugin.VisibilitySelectFilter{
NamespaceID: request.NamespaceID.String(),
MinTime: &request.EarliestStartTime,
MaxTime: &readLevel.Time,
RunID: &readLevel.RunID,
Status: int32(request.Status),
PageSize: &request.PageSize,
})
})
}
func (s *visibilityStore) DeleteWorkflowExecution(
ctx context.Context,
request *manager.VisibilityDeleteWorkflowExecutionRequest,
) error {
_, err := s.sqlStore.Db.DeleteFromVisibility(ctx, sqlplugin.VisibilityDeleteFilter{
NamespaceID: request.NamespaceID.String(),
RunID: request.RunID,
})
if err != nil {
return serviceerror.NewUnavailable(err.Error())
}
return nil
}
func (s *visibilityStore) ListWorkflowExecutions(
_ context.Context,
_ *manager.ListWorkflowExecutionsRequestV2,
) (*store.InternalListWorkflowExecutionsResponse, error) {
return nil, store.OperationNotSupportedErr
}
func (s *visibilityStore) ScanWorkflowExecutions(
_ context.Context,
_ *manager.ListWorkflowExecutionsRequestV2,
) (*store.InternalListWorkflowExecutionsResponse, error) {
return nil, store.OperationNotSupportedErr
}
func (s *visibilityStore) CountWorkflowExecutions(
_ context.Context,
_ *manager.CountWorkflowExecutionsRequest,
) (*manager.CountWorkflowExecutionsResponse, error) {
return nil, store.OperationNotSupportedErr
}
func (s *visibilityStore) GetWorkflowExecution(
ctx context.Context,
request *manager.GetWorkflowExecutionRequest,
) (*store.InternalGetWorkflowExecutionResponse, error) {
row, err := s.sqlStore.Db.GetFromVisibility(ctx, sqlplugin.VisibilityGetFilter{
NamespaceID: request.NamespaceID.String(),
RunID: request.RunID,
})
if err != nil {
return nil, serviceerror.NewUnavailable(
fmt.Sprintf("GetWorkflowExecution operation failed. Select failed: %v", err))
}
return &store.InternalGetWorkflowExecutionResponse{
Execution: s.rowToInfo(row),
}, nil
}
func (s *visibilityStore) rowToInfo(
row *sqlplugin.VisibilityRow,
) *store.InternalWorkflowExecutionInfo {
if row.ExecutionTime.UnixNano() == 0 {
row.ExecutionTime = row.StartTime
}
info := &store.InternalWorkflowExecutionInfo{
WorkflowID: row.WorkflowID,
RunID: row.RunID,
TypeName: row.WorkflowTypeName,
StartTime: row.StartTime,
ExecutionTime: row.ExecutionTime,
Memo: persistence.NewDataBlob(row.Memo, row.Encoding),
Status: enumspb.WorkflowExecutionStatus(row.Status),
TaskQueue: row.TaskQueue,
}
if row.CloseTime != nil {
info.CloseTime = *row.CloseTime
info.HistoryLength = *row.HistoryLength
}
if row.HistoryLength != nil {
info.HistoryLength = *row.HistoryLength
}
return info
}
func (s *visibilityStore) listWorkflowExecutions(
opName string,
pageToken []byte,
pageSize int,
latestTime time.Time,
closeQuery bool,
selectOp func(readLevel *visibilityPageToken) ([]sqlplugin.VisibilityRow, error),
) (*store.InternalListWorkflowExecutionsResponse, error) {
var readLevel *visibilityPageToken
var err error
if len(pageToken) > 0 {
readLevel, err = s.deserializePageToken(pageToken)
if err != nil {
return nil, err
}
} else {
readLevel = &visibilityPageToken{Time: latestTime, RunID: ""}
}
rows, err := selectOp(readLevel)
if err != nil {
return nil, serviceerror.NewUnavailable(fmt.Sprintf("%v operation failed. Select failed: %v", opName, err))
}
if len(rows) == 0 {
return &store.InternalListWorkflowExecutionsResponse{}, nil
}
var infos = make([]*store.InternalWorkflowExecutionInfo, len(rows))
for i, row := range rows {
infos[i] = s.rowToInfo(&row)
}
var nextPageToken []byte
if len(rows) == pageSize {
lastRow := rows[len(rows)-1]
lastTime := lastRow.StartTime
if closeQuery {
lastTime = *lastRow.CloseTime
}
nextPageToken, err = s.serializePageToken(&visibilityPageToken{
Time: lastTime,
RunID: lastRow.RunID,
})
if err != nil {
return nil, err
}
}
return &store.InternalListWorkflowExecutionsResponse{
Executions: infos,
NextPageToken: nextPageToken,
}, nil
}
func (s *visibilityStore) deserializePageToken(
data []byte,
) (*visibilityPageToken, error) {
var token visibilityPageToken
err := json.Unmarshal(data, &token)
return &token, err
}
func (s *visibilityStore) serializePageToken(
token *visibilityPageToken,
) ([]byte, error) {
data, err := json.Marshal(token)
return data, err
}

View File

@@ -1,401 +0,0 @@
// The MIT License
//
// Copyright (c) 2021 Temporal Technologies Inc. All rights reserved.
//
// Copyright (c) 2020 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 standard
import (
"context"
"encoding/json"
"fmt"
"reflect"
enumspb "go.temporal.io/api/enums/v1"
"go.temporal.io/server/common/persistence/visibility/manager"
"go.temporal.io/server/common/persistence/visibility/store"
"go.temporal.io/server/common/searchattribute"
)
type (
standardStore struct {
store store.VisibilityStore
searchAttributesProvider searchattribute.Provider
searchAttributesMapperProvider searchattribute.MapperProvider
}
// We wrap the token with a boolean to indicate if it is from list open workflows or list closed workflows,
// so we know where to continue from for the next call.
nextPageToken struct {
ForOpenWorkflows bool `json:"isOpen"`
Token []byte
}
listRequest interface {
OverrideToken(token []byte)
GetToken() []byte
OverridePageSize(pageSize int)
GetPageSize() int
}
)
var _ store.VisibilityStore = (*standardStore)(nil)
var _ listRequest = (*manager.ListWorkflowExecutionsRequest)(nil)
func NewVisibilityStore(
visibilityStore store.VisibilityStore,
searchAttributesProvider searchattribute.Provider,
searchAttributesMapperProvider searchattribute.MapperProvider,
) store.VisibilityStore {
return &standardStore{
store: visibilityStore,
searchAttributesProvider: searchAttributesProvider,
searchAttributesMapperProvider: searchAttributesMapperProvider,
}
}
func (s *standardStore) Close() {
s.store.Close()
}
func (s *standardStore) GetName() string {
return s.store.GetName()
}
func (s *standardStore) GetIndexName() string {
// GetIndexName is used to get cluster metadata, which in verstions < v1.20
// were stored in an empty string key.
return ""
}
func (s *standardStore) ValidateCustomSearchAttributes(
searchAttributes map[string]any,
) (map[string]any, error) {
return searchAttributes, nil
}
func (s *standardStore) RecordWorkflowExecutionStarted(
ctx context.Context,
request *store.InternalRecordWorkflowExecutionStartedRequest,
) error {
return s.store.RecordWorkflowExecutionStarted(ctx, request)
}
func (s *standardStore) RecordWorkflowExecutionClosed(
ctx context.Context,
request *store.InternalRecordWorkflowExecutionClosedRequest,
) error {
return s.store.RecordWorkflowExecutionClosed(ctx, request)
}
func (s *standardStore) UpsertWorkflowExecution(
ctx context.Context,
request *store.InternalUpsertWorkflowExecutionRequest,
) error {
return s.store.UpsertWorkflowExecution(ctx, request)
}
func (s *standardStore) DeleteWorkflowExecution(
ctx context.Context,
request *manager.VisibilityDeleteWorkflowExecutionRequest,
) error {
return s.store.DeleteWorkflowExecution(ctx, request)
}
func (s *standardStore) ListOpenWorkflowExecutions(
ctx context.Context,
request *manager.ListWorkflowExecutionsRequest,
) (*store.InternalListWorkflowExecutionsResponse, error) {
return s.store.ListOpenWorkflowExecutions(ctx, request)
}
func (s *standardStore) ListClosedWorkflowExecutions(
ctx context.Context,
request *manager.ListWorkflowExecutionsRequest,
) (*store.InternalListWorkflowExecutionsResponse, error) {
return s.store.ListClosedWorkflowExecutions(ctx, request)
}
func (s *standardStore) ListOpenWorkflowExecutionsByType(
ctx context.Context,
request *manager.ListWorkflowExecutionsByTypeRequest,
) (*store.InternalListWorkflowExecutionsResponse, error) {
return s.store.ListOpenWorkflowExecutionsByType(ctx, request)
}
func (s *standardStore) ListClosedWorkflowExecutionsByType(
ctx context.Context,
request *manager.ListWorkflowExecutionsByTypeRequest,
) (*store.InternalListWorkflowExecutionsResponse, error) {
return s.store.ListClosedWorkflowExecutionsByType(ctx, request)
}
func (s *standardStore) ListOpenWorkflowExecutionsByWorkflowID(
ctx context.Context,
request *manager.ListWorkflowExecutionsByWorkflowIDRequest,
) (*store.InternalListWorkflowExecutionsResponse, error) {
return s.store.ListOpenWorkflowExecutionsByWorkflowID(ctx, request)
}
func (s *standardStore) ListClosedWorkflowExecutionsByWorkflowID(
ctx context.Context,
request *manager.ListWorkflowExecutionsByWorkflowIDRequest,
) (*store.InternalListWorkflowExecutionsResponse, error) {
return s.store.ListClosedWorkflowExecutionsByWorkflowID(ctx, request)
}
func (s *standardStore) ListClosedWorkflowExecutionsByStatus(
ctx context.Context,
request *manager.ListClosedWorkflowExecutionsByStatusRequest,
) (*store.InternalListWorkflowExecutionsResponse, error) {
return s.store.ListClosedWorkflowExecutionsByStatus(ctx, request)
}
func (s *standardStore) ScanWorkflowExecutions(
ctx context.Context,
request *manager.ListWorkflowExecutionsRequestV2,
) (*store.InternalListWorkflowExecutionsResponse, error) {
return s.store.ScanWorkflowExecutions(ctx, request)
}
func (s *standardStore) CountWorkflowExecutions(
ctx context.Context,
request *manager.CountWorkflowExecutionsRequest,
) (*manager.CountWorkflowExecutionsResponse, error) {
return s.store.CountWorkflowExecutions(ctx, request)
}
func (s *standardStore) GetWorkflowExecution(
ctx context.Context,
request *manager.GetWorkflowExecutionRequest,
) (*store.InternalGetWorkflowExecutionResponse, error) {
return s.store.GetWorkflowExecution(ctx, request)
}
func (s *standardStore) ListWorkflowExecutions(
ctx context.Context,
request *manager.ListWorkflowExecutionsRequestV2,
) (*store.InternalListWorkflowExecutionsResponse, error) {
typeMap, err := s.searchAttributesProvider.GetSearchAttributes(s.GetIndexName(), false)
if err != nil {
return nil, err
}
converter := newQueryConverter(request.Namespace, typeMap, s.searchAttributesMapperProvider)
filter, err := converter.GetFilter(request.Query)
if err != nil {
return nil, err
}
baseReq := &manager.ListWorkflowExecutionsRequest{
NamespaceID: request.NamespaceID,
Namespace: request.Namespace,
PageSize: request.PageSize,
NextPageToken: request.NextPageToken,
EarliestStartTime: *filter.MinTime,
LatestStartTime: *filter.MaxTime,
}
// Only a limited query patterns are supported due to the way we set up
// visibility tables in Cassandra.
// Check validation logic in query interceptor for details.
if filter.WorkflowID != nil {
request := &manager.ListWorkflowExecutionsByWorkflowIDRequest{
ListWorkflowExecutionsRequest: baseReq,
WorkflowID: *filter.WorkflowID,
}
return s.listWorkflowExecutionsHelper(
ctx,
request,
s.listOpenWorkflowExecutionsByWorkflowID,
s.listClosedWorkflowExecutionsByWorkflowID)
} else if filter.WorkflowTypeName != nil {
request := &manager.ListWorkflowExecutionsByTypeRequest{
ListWorkflowExecutionsRequest: baseReq,
WorkflowTypeName: *filter.WorkflowTypeName,
}
return s.listWorkflowExecutionsHelper(
ctx,
request,
s.listOpenWorkflowExecutionsByType,
s.listClosedWorkflowExecutionsByType)
} else if filter.Status != int32(enumspb.WORKFLOW_EXECUTION_STATUS_UNSPECIFIED) {
if filter.Status == int32(enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING) {
return s.ListOpenWorkflowExecutions(ctx, baseReq)
} else {
request := &manager.ListClosedWorkflowExecutionsByStatusRequest{
ListWorkflowExecutionsRequest: baseReq,
Status: enumspb.WorkflowExecutionStatus(filter.Status),
}
return s.ListClosedWorkflowExecutionsByStatus(ctx, request)
}
} else {
return s.listWorkflowExecutionsHelper(
ctx,
baseReq,
s.listOpenWorkflowExecutions,
s.listClosedWorkflowExecutions)
}
}
func (s *standardStore) listWorkflowExecutionsHelper(
ctx context.Context,
request listRequest,
listOpenFunc func(ctx context.Context, request listRequest) (*store.InternalListWorkflowExecutionsResponse, error),
listCloseFunc func(ctx context.Context, request listRequest) (*store.InternalListWorkflowExecutionsResponse, error),
) (*store.InternalListWorkflowExecutionsResponse, error) {
var token nextPageToken
if len(request.GetToken()) == 0 {
token = nextPageToken{
ForOpenWorkflows: true,
}
} else {
err := json.Unmarshal(request.GetToken(), &token)
if err != nil {
return nil, fmt.Errorf("invalid next page token: %v", err)
}
request.OverrideToken(token.Token)
}
resp := &store.InternalListWorkflowExecutionsResponse{}
if token.ForOpenWorkflows {
listOpenResp, err := listOpenFunc(ctx, request)
if err != nil {
return nil, err
}
if len(listOpenResp.Executions) > 0 {
request.OverridePageSize(request.GetPageSize() - len(listOpenResp.Executions))
resp.Executions = append(resp.Executions, listOpenResp.Executions...)
}
if request.GetPageSize() == 0 {
token.Token = listOpenResp.NextPageToken
token, err := json.Marshal(token)
if err != nil {
return nil, fmt.Errorf("failed to marshal next page token: %v", err)
}
resp.NextPageToken = token
return resp, nil
} else {
token.ForOpenWorkflows = false
request.OverrideToken(nil)
}
}
listCloseResp, err := listCloseFunc(ctx, request)
if err != nil {
return nil, err
}
resp.Executions = append(resp.Executions, listCloseResp.Executions...)
if listCloseResp.NextPageToken == nil {
resp.NextPageToken = nil
} else {
token.Token = listCloseResp.NextPageToken
token, err := json.Marshal(token)
if err != nil {
return nil, fmt.Errorf("failed to marshal next page token: %v", err)
}
resp.NextPageToken = token
}
return resp, nil
}
func (s *standardStore) listOpenWorkflowExecutionsByWorkflowID(
ctx context.Context,
request listRequest,
) (*store.InternalListWorkflowExecutionsResponse, error) {
actualRequest, ok := request.(*manager.ListWorkflowExecutionsByWorkflowIDRequest)
if !ok {
panic(fmt.Errorf("wrong request type %v for listOpenWorkflowExecutionsByWorkflowID", reflect.TypeOf(request)))
}
return s.ListOpenWorkflowExecutionsByWorkflowID(ctx, actualRequest)
}
func (s *standardStore) listOpenWorkflowExecutionsByType(
ctx context.Context,
request listRequest,
) (*store.InternalListWorkflowExecutionsResponse, error) {
actualRequest, ok := request.(*manager.ListWorkflowExecutionsByTypeRequest)
if !ok {
panic(fmt.Errorf("wrong request type %v for listOpenWorkflowExecutionsByType", reflect.TypeOf(request)))
}
return s.ListOpenWorkflowExecutionsByType(ctx, actualRequest)
}
func (s *standardStore) listOpenWorkflowExecutions(
ctx context.Context,
request listRequest,
) (*store.InternalListWorkflowExecutionsResponse, error) {
actualRequest, ok := request.(*manager.ListWorkflowExecutionsRequest)
if !ok {
panic(fmt.Errorf("wrong request type %v for listOpenWorkflowExecutions", reflect.TypeOf(request)))
}
return s.ListOpenWorkflowExecutions(ctx, actualRequest)
}
func (s *standardStore) listClosedWorkflowExecutionsByWorkflowID(
ctx context.Context,
request listRequest,
) (*store.InternalListWorkflowExecutionsResponse, error) {
actualRequest, ok := request.(*manager.ListWorkflowExecutionsByWorkflowIDRequest)
if !ok {
panic(fmt.Errorf("wrong request type %v for listClosedWorkflowExecutionsByWorkflowID", reflect.TypeOf(request)))
}
return s.ListClosedWorkflowExecutionsByWorkflowID(ctx, actualRequest)
}
func (s *standardStore) listClosedWorkflowExecutionsByType(
ctx context.Context,
request listRequest,
) (*store.InternalListWorkflowExecutionsResponse, error) {
actualRequest, ok := request.(*manager.ListWorkflowExecutionsByTypeRequest)
if !ok {
panic(fmt.Errorf("wrong request type %v for listClosedWorkflowExecutionsByType", reflect.TypeOf(request)))
}
return s.ListClosedWorkflowExecutionsByType(ctx, actualRequest)
}
func (s *standardStore) listClosedWorkflowExecutions(
ctx context.Context,
request listRequest,
) (*store.InternalListWorkflowExecutionsResponse, error) {
actualRequest, ok := request.(*manager.ListWorkflowExecutionsRequest)
if !ok {
panic(fmt.Errorf("wrong request type %v for listClosedWorkflowExecutions", reflect.TypeOf(request)))
}
return s.ListClosedWorkflowExecutions(ctx, actualRequest)
}

View File

@@ -9,7 +9,7 @@ persistence:
datastores:
mysql-default:
sql:
pluginName: "mysql"
pluginName: "mysql8"
databaseName: "temporal"
connectAddr: "127.0.0.1:3306"
connectProtocol: "tcp"

View File

@@ -1,117 +0,0 @@
log:
stdout: true
level: info
persistence:
defaultStore: mysql-default
visibilityStore: mysql-visibility
numHistoryShards: 4
datastores:
mysql-default:
sql:
pluginName: "mysql"
databaseName: "temporal"
connectAddr: "127.0.0.1:3306"
connectProtocol: "tcp"
user: "temporal"
password: "temporal"
maxConns: 20
maxIdleConns: 20
maxConnLifetime: "1h"
mysql-visibility:
sql:
pluginName: "mysql"
databaseName: "temporal_visibility"
connectAddr: "127.0.0.1:3306"
connectProtocol: "tcp"
user: "temporal"
password: "temporal"
maxConns: 2
maxIdleConns: 2
maxConnLifetime: "1h"
global:
membership:
maxJoinDuration: 30s
broadcastAddress: "127.0.0.1"
pprof:
port: 7936
metrics:
prometheus:
# # specify framework to use new approach for initializing metrics and/or use opentelemetry
# framework: "opentelemetry"
framework: "tally"
timerType: "histogram"
listenAddress: "127.0.0.1:8000"
services:
frontend:
rpc:
grpcPort: 7233
membershipPort: 6933
bindOnLocalHost: true
httpPort: 7243
matching:
rpc:
grpcPort: 7235
membershipPort: 6935
bindOnLocalHost: true
history:
rpc:
grpcPort: 7234
membershipPort: 6934
bindOnLocalHost: true
worker:
rpc:
grpcPort: 7239
membershipPort: 6939
bindOnLocalHost: true
clusterMetadata:
enableGlobalNamespace: false
failoverVersionIncrement: 10
masterClusterName: "active"
currentClusterName: "active"
clusterInformation:
active:
enabled: true
initialFailoverVersion: 1
rpcName: "frontend"
rpcAddress: "localhost:7233"
dcRedirectionPolicy:
policy: "noop"
archival:
history:
state: "enabled"
enableRead: true
provider:
filestore:
fileMode: "0666"
dirMode: "0766"
gstorage:
credentialsPath: "/tmp/gcloud/keyfile.json"
visibility:
state: "enabled"
enableRead: true
provider:
filestore:
fileMode: "0666"
dirMode: "0766"
namespaceDefaults:
archival:
history:
state: "disabled"
URI: "file:///tmp/temporal_archival/development"
visibility:
state: "disabled"
URI: "file:///tmp/temporal_vis_archival/development"
dynamicConfigClient:
filepath: "config/dynamicconfig/development-sql.yaml"
pollInterval: "10s"

View File

@@ -9,7 +9,7 @@ persistence:
datastores:
postgres-default:
sql:
pluginName: "postgres"
pluginName: "postgres12"
databaseName: "temporal"
connectAddr: "127.0.0.1:5432"
connectProtocol: "tcp"

View File

@@ -1,117 +0,0 @@
log:
stdout: true
level: info
persistence:
defaultStore: postgres-default
visibilityStore: postgres-visibility
numHistoryShards: 4
datastores:
postgres-default:
sql:
pluginName: "postgres"
databaseName: "temporal"
connectAddr: "127.0.0.1:5432"
connectProtocol: "tcp"
user: "temporal"
password: "temporal"
maxConns: 20
maxIdleConns: 20
maxConnLifetime: "1h"
postgres-visibility:
sql:
pluginName: "postgres"
databaseName: "temporal_visibility"
connectAddr: "127.0.0.1:5432"
connectProtocol: "tcp"
user: "temporal"
password: "temporal"
maxConns: 2
maxIdleConns: 2
maxConnLifetime: "1h"
global:
membership:
maxJoinDuration: 30s
broadcastAddress: "127.0.0.1"
pprof:
port: 7936
metrics:
prometheus:
# # specify framework to use new approach for initializing metrics and/or use opentelemetry
# framework: "opentelemetry"
framework: "tally"
timerType: "histogram"
listenAddress: "127.0.0.1:8000"
services:
frontend:
rpc:
grpcPort: 7233
membershipPort: 6933
bindOnLocalHost: true
httpPort: 7243
matching:
rpc:
grpcPort: 7235
membershipPort: 6935
bindOnLocalHost: true
history:
rpc:
grpcPort: 7234
membershipPort: 6934
bindOnLocalHost: true
worker:
rpc:
grpcPort: 7239
membershipPort: 6939
bindOnLocalHost: true
clusterMetadata:
enableGlobalNamespace: false
failoverVersionIncrement: 10
masterClusterName: "active"
currentClusterName: "active"
clusterInformation:
active:
enabled: true
initialFailoverVersion: 1
rpcName: "frontend"
rpcAddress: "localhost:7233"
dcRedirectionPolicy:
policy: "noop"
archival:
history:
state: "enabled"
enableRead: true
provider:
filestore:
fileMode: "0666"
dirMode: "0766"
gstorage:
credentialsPath: "/tmp/gcloud/keyfile.json"
visibility:
state: "enabled"
enableRead: true
provider:
filestore:
fileMode: "0666"
dirMode: "0766"
namespaceDefaults:
archival:
history:
state: "disabled"
URI: "file:///tmp/temporal_archival/development"
visibility:
state: "disabled"
URI: "file:///tmp/temporal_vis_archival/development"
dynamicConfigClient:
filepath: "config/dynamicconfig/development-sql.yaml"
pollInterval: "10s"

View File

@@ -45,7 +45,7 @@ docker compose run integration-test-cassandra make integration-test-coverage
```
or run integration tests with MySQL:
```bash
docker compose run integration-test-mysql make integration-test-coverage
docker compose run integration-test-mysql8 make integration-test-coverage
```
## Testing the build in Buildkite

View File

@@ -173,27 +173,6 @@ services:
aliases:
- integration-test
integration-test-mysql:
build:
context: ../..
dockerfile: ./develop/buildkite/Dockerfile
environment:
- "MYSQL_SEEDS=mysql"
- "ES_SEEDS=elasticsearch"
- "ES_VERSION=v7"
- "PERSISTENCE_TYPE=sql"
- "PERSISTENCE_DRIVER=mysql"
- "TEMPORAL_VERSION_CHECK_DISABLED=1"
depends_on:
- mysql
- elasticsearch
volumes:
- ../../.testoutput:/temporal/.testoutput
networks:
services-network:
aliases:
- integration-test
integration-test-mysql8:
build:
context: ../..
@@ -212,48 +191,6 @@ services:
aliases:
- integration-test
integration-test-postgresql:
build:
context: ../..
dockerfile: ./develop/buildkite/Dockerfile
environment:
- "POSTGRES_SEEDS=postgresql"
- "ES_SEEDS=elasticsearch"
- "ES_VERSION=v7"
- "PERSISTENCE_TYPE=sql"
- "PERSISTENCE_DRIVER=postgres"
- "TEMPORAL_VERSION_CHECK_DISABLED=1"
depends_on:
- postgresql
- elasticsearch
volumes:
- ../../.testoutput:/temporal/.testoutput
networks:
services-network:
aliases:
- integration-test
integration-test-postgresql-pgx:
build:
context: ../..
dockerfile: ./develop/buildkite/Dockerfile
environment:
- "POSTGRES_SEEDS=postgresql"
- "ES_SEEDS=elasticsearch"
- "ES_VERSION=v7"
- "PERSISTENCE_TYPE=sql"
- "PERSISTENCE_DRIVER=postgres_pgx"
- "TEMPORAL_VERSION_CHECK_DISABLED=1"
depends_on:
- postgresql
- elasticsearch
volumes:
- ../../.testoutput:/temporal/.testoutput
networks:
services-network:
aliases:
- integration-test
integration-test-postgresql12:
build:
context: ../..
@@ -327,28 +264,6 @@ services:
aliases:
- integration-test-xdc
integration-test-xdc-mysql:
build:
context: ../..
dockerfile: ./develop/buildkite/Dockerfile
environment:
- "MYSQL_SEEDS=mysql"
- "ES_SEEDS=elasticsearch"
- "ES_VERSION=v7"
- "PERSISTENCE_TYPE=sql"
- "PERSISTENCE_DRIVER=mysql"
- "TEST_RUN_COUNT=10"
- "TEMPORAL_VERSION_CHECK_DISABLED=1"
depends_on:
- mysql
- elasticsearch
volumes:
- ../../.testoutput:/temporal/.testoutput
networks:
services-network:
aliases:
- integration-test-xdc
integration-test-xdc-mysql8:
build:
context: ../..
@@ -368,50 +283,6 @@ services:
aliases:
- integration-test-xdc
integration-test-xdc-postgresql:
build:
context: ../..
dockerfile: ./develop/buildkite/Dockerfile
environment:
- "POSTGRES_SEEDS=postgresql"
- "ES_SEEDS=elasticsearch"
- "ES_VERSION=v7"
- "PERSISTENCE_TYPE=sql"
- "PERSISTENCE_DRIVER=postgres"
- "TEST_RUN_COUNT=10"
- "TEMPORAL_VERSION_CHECK_DISABLED=1"
depends_on:
- postgresql
- elasticsearch
volumes:
- ../../.testoutput:/temporal/.testoutput
networks:
services-network:
aliases:
- integration-test-xdc
integration-test-xdc-postgresql-pgx:
build:
context: ../..
dockerfile: ./develop/buildkite/Dockerfile
environment:
- "POSTGRES_SEEDS=postgresql"
- "ES_SEEDS=elasticsearch"
- "ES_VERSION=v7"
- "PERSISTENCE_TYPE=sql"
- "PERSISTENCE_DRIVER=postgres_pgx"
- "TEST_RUN_COUNT=10"
- "TEMPORAL_VERSION_CHECK_DISABLED=1"
depends_on:
- postgresql
- elasticsearch
volumes:
- ../../.testoutput:/temporal/.testoutput
networks:
services-network:
aliases:
- integration-test-xdc
integration-test-xdc-postgresql12:
build:
context: ../..

View File

@@ -17,10 +17,7 @@ steps:
- integration-test-cassandra
- integration-test-cassandra-es8
- integration-test-cassandra-opensearch
- integration-test-mysql
- integration-test-mysql8
- integration-test-postgresql
- integration-test-postgresql-pgx
- integration-test-postgresql12
- integration-test-postgresql12-pgx
- integration-test-sqlite
@@ -204,70 +201,6 @@ steps:
mount-buildkite-agent: true
propagate-environment: true
- label: ":golang: functional test with mysql"
agents:
queue: "default"
docker: "*"
command: "make functional-test-coverage"
parallelism: 3
artifact_paths:
- ".testoutput/*"
retry:
automatic:
limit: 1
plugins:
- artifacts#v1.9.0:
download: "develop/buildkite/*"
- ecr#v2.7.0: {login: true}
- docker-compose#v4.14.0:
run: integration-test-mysql
config: ./develop/buildkite/docker-compose.yml
skip-checkout: true
mount-buildkite-agent: true
propagate-environment: true
- label: ":golang: functional xdc test with mysql"
agents:
queue: "default"
docker: "*"
command: "make functional-test-xdc-coverage"
artifact_paths:
- ".testoutput/*"
retry:
automatic:
limit: 1
plugins:
- artifacts#v1.9.0:
download: "develop/buildkite/*"
- ecr#v2.7.0: {login: true}
- docker-compose#v4.14.0:
run: integration-test-xdc-mysql
config: ./develop/buildkite/docker-compose.yml
skip-checkout: true
mount-buildkite-agent: true
propagate-environment: true
- label: ":golang: functional ndc test with mysql"
agents:
queue: "default"
docker: "*"
command: "make functional-test-ndc-coverage"
artifact_paths:
- ".testoutput/*"
retry:
automatic:
limit: 1
plugins:
- artifacts#v1.9.0:
download: "develop/buildkite/*"
- ecr#v2.7.0: {login: true}
- docker-compose#v4.14.0:
run: integration-test-xdc-mysql
config: ./develop/buildkite/docker-compose.yml
skip-checkout: true
mount-buildkite-agent: true
propagate-environment: true
- label: ":golang: functional test with mysql 8"
agents:
queue: "default"
@@ -332,134 +265,6 @@ steps:
mount-buildkite-agent: true
propagate-environment: true
- label: ":golang: functional test with postgresql"
agents:
queue: "default"
docker: "*"
command: "make functional-test-coverage"
parallelism: 3
artifact_paths:
- ".testoutput/*"
retry:
automatic:
limit: 1
plugins:
- artifacts#v1.9.0:
download: "develop/buildkite/*"
- ecr#v2.7.0: {login: true}
- docker-compose#v4.14.0:
run: integration-test-postgresql
config: ./develop/buildkite/docker-compose.yml
skip-checkout: true
mount-buildkite-agent: true
propagate-environment: true
- label: ":golang: functional xdc test with postgresql"
agents:
queue: "default"
docker: "*"
command: "make functional-test-xdc-coverage"
artifact_paths:
- ".testoutput/*"
retry:
automatic:
limit: 1
plugins:
- artifacts#v1.9.0:
download: "develop/buildkite/*"
- ecr#v2.7.0: {login: true}
- docker-compose#v4.14.0:
run: integration-test-xdc-postgresql
config: ./develop/buildkite/docker-compose.yml
skip-checkout: true
mount-buildkite-agent: true
propagate-environment: true
- label: ":golang: functional ndc test with postgresql"
agents:
queue: "default"
docker: "*"
command: "make functional-test-ndc-coverage"
artifact_paths:
- ".testoutput/*"
retry:
automatic:
limit: 1
plugins:
- artifacts#v1.9.0:
download: "develop/buildkite/*"
- ecr#v2.7.0: {login: true}
- docker-compose#v4.14.0:
run: integration-test-xdc-postgresql
config: ./develop/buildkite/docker-compose.yml
skip-checkout: true
mount-buildkite-agent: true
propagate-environment: true
- label: ":golang: functional test with postgresql pgx"
agents:
queue: "default"
docker: "*"
command: "make functional-test-coverage"
parallelism: 3
artifact_paths:
- ".testoutput/*"
retry:
automatic:
limit: 1
plugins:
- artifacts#v1.9.0:
download: "develop/buildkite/*"
- ecr#v2.7.0: {login: true}
- docker-compose#v4.14.0:
run: integration-test-postgresql-pgx
config: ./develop/buildkite/docker-compose.yml
skip-checkout: true
mount-buildkite-agent: true
propagate-environment: true
- label: ":golang: functional xdc test with postgresql pgx"
agents:
queue: "default"
docker: "*"
command: "make functional-test-xdc-coverage"
artifact_paths:
- ".testoutput/*"
retry:
automatic:
limit: 1
plugins:
- artifacts#v1.9.0:
download: "develop/buildkite/*"
- ecr#v2.7.0: {login: true}
- docker-compose#v4.14.0:
run: integration-test-xdc-postgresql-pgx
config: ./develop/buildkite/docker-compose.yml
skip-checkout: true
mount-buildkite-agent: true
propagate-environment: true
- label: ":golang: functional ndc test with postgresql pgx"
agents:
queue: "default"
docker: "*"
command: "make functional-test-ndc-coverage"
artifact_paths:
- ".testoutput/*"
retry:
automatic:
limit: 1
plugins:
- artifacts#v1.9.0:
download: "develop/buildkite/*"
- ecr#v2.7.0: {login: true}
- docker-compose#v4.14.0:
run: integration-test-xdc-postgresql-pgx
config: ./develop/buildkite/docker-compose.yml
skip-checkout: true
mount-buildkite-agent: true
propagate-environment: true
- label: ":golang: functional test with postgresql 12"
agents:
queue: "default"

View File

@@ -40,7 +40,7 @@ persistence:
advertised-hostname: {{ default .Env.CASSANDRA_ADDRESS_TRANSLATOR_OPTIONS "" }}
{{- end }}
{{- end }}
{{- else if eq $db "mysql" "mysql8" }}
{{- else if eq $db "mysql8" }}
default:
sql:
pluginName: "{{ $db }}"
@@ -93,8 +93,7 @@ persistence:
keyFile: {{ default .Env.SQL_CERT_KEY "" }}
enableHostVerification: {{ default .Env.SQL_HOST_VERIFICATION "false" }}
serverName: {{ default .Env.SQL_HOST_NAME "" }}
{{- else if eq $db "postgresql" "postgres" "postgres12" "postgres12_pgx" }}
{{- $db := replace $db "postgresql" "postgres" 1 }}
{{- else if eq $db "postgres12" "postgres12_pgx" }}
default:
sql:
pluginName: "{{ $db }}"

View File

@@ -38,8 +38,6 @@ func TestSchemaDirs(t *testing.T) {
dirs = PathsByDir("mysql")
requireContains(t, []string{
"mysql/v57/temporal",
"mysql/v57/visibility",
"mysql/v8/temporal",
"mysql/v8/visibility",
}, dirs)
@@ -48,8 +46,6 @@ func TestSchemaDirs(t *testing.T) {
requireContains(t, []string{
"postgresql/v12/temporal",
"postgresql/v12/visibility",
"postgresql/v96/temporal",
"postgresql/v96/visibility",
}, dirs)
}

View File

@@ -1 +0,0 @@
CREATE DATABASE temporal character set utf8;

View File

@@ -1,339 +0,0 @@
CREATE TABLE namespaces(
partition_id INT NOT NULL,
id BINARY(16) NOT NULL,
name VARCHAR(255) UNIQUE NOT NULL,
notification_version BIGINT NOT NULL,
--
data MEDIUMBLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
is_global TINYINT(1) NOT NULL,
PRIMARY KEY(partition_id, id)
);
CREATE TABLE namespace_metadata (
partition_id INT NOT NULL,
notification_version BIGINT NOT NULL,
PRIMARY KEY(partition_id)
);
INSERT INTO namespace_metadata (partition_id, notification_version) VALUES (54321, 1);
CREATE TABLE shards (
shard_id INT NOT NULL,
--
range_id BIGINT NOT NULL,
data MEDIUMBLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id)
);
CREATE TABLE executions(
shard_id INT NOT NULL,
namespace_id BINARY(16) NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BINARY(16) NOT NULL,
--
next_event_id BIGINT NOT NULL,
last_write_version BIGINT NOT NULL,
data MEDIUMBLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
state MEDIUMBLOB NOT NULL,
state_encoding VARCHAR(16) NOT NULL,
db_record_version BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id)
);
CREATE TABLE current_executions(
shard_id INT NOT NULL,
namespace_id BINARY(16) NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
--
run_id BINARY(16) NOT NULL,
create_request_id VARCHAR(255) NOT NULL,
state INT NOT NULL,
status INT NOT NULL,
start_version BIGINT NOT NULL DEFAULT 0,
last_write_version BIGINT NOT NULL,
PRIMARY KEY (shard_id, namespace_id, workflow_id)
);
CREATE TABLE buffered_events (
shard_id INT NOT NULL,
namespace_id BINARY(16) NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BINARY(16) NOT NULL,
id BIGINT AUTO_INCREMENT NOT NULL UNIQUE,
--
data MEDIUMBLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id, id)
);
CREATE TABLE tasks (
range_hash INT UNSIGNED NOT NULL,
task_queue_id VARBINARY(272) NOT NULL,
task_id BIGINT NOT NULL,
--
data MEDIUMBLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (range_hash, task_queue_id, task_id)
);
-- Stores ephemeral task queue information such as ack levels and expiry times
CREATE TABLE task_queues (
range_hash INT UNSIGNED NOT NULL,
task_queue_id VARBINARY(272) NOT NULL,
--
range_id BIGINT NOT NULL,
data MEDIUMBLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (range_hash, task_queue_id)
);
-- Stores task queue information such as user provided versioning data
CREATE TABLE task_queue_user_data (
namespace_id BINARY(16) NOT NULL,
task_queue_name VARCHAR(255) NOT NULL,
data MEDIUMBLOB NOT NULL, -- temporal.server.api.persistence.v1.TaskQueueUserData
data_encoding VARCHAR(16) NOT NULL, -- Encoding type used for serialization, in practice this should always be proto3
version BIGINT NOT NULL, -- Version of this row, used for optimistic concurrency
PRIMARY KEY (namespace_id, task_queue_name)
);
-- Stores a mapping between build ids and task queues
CREATE TABLE build_id_to_task_queue (
namespace_id BINARY(16) NOT NULL,
build_id VARCHAR(255) NOT NULL,
task_queue_name VARCHAR(255) NOT NULL,
PRIMARY KEY (namespace_id, build_id, task_queue_name)
);
CREATE TABLE history_immediate_tasks(
shard_id INT NOT NULL,
category_id INT NOT NULL,
task_id BIGINT NOT NULL,
--
data MEDIUMBLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, category_id, task_id)
);
CREATE TABLE history_scheduled_tasks (
shard_id INT NOT NULL,
category_id INT NOT NULL,
visibility_timestamp DATETIME(6) NOT NULL,
task_id BIGINT NOT NULL,
--
data MEDIUMBLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, category_id, visibility_timestamp, task_id)
);
CREATE TABLE transfer_tasks(
shard_id INT NOT NULL,
task_id BIGINT NOT NULL,
--
data MEDIUMBLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, task_id)
);
CREATE TABLE timer_tasks (
shard_id INT NOT NULL,
visibility_timestamp DATETIME(6) NOT NULL,
task_id BIGINT NOT NULL,
--
data MEDIUMBLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, visibility_timestamp, task_id)
);
CREATE TABLE replication_tasks (
shard_id INT NOT NULL,
task_id BIGINT NOT NULL,
--
data MEDIUMBLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, task_id)
);
CREATE TABLE replication_tasks_dlq (
source_cluster_name VARCHAR(255) NOT NULL,
shard_id INT NOT NULL,
task_id BIGINT NOT NULL,
--
data MEDIUMBLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (source_cluster_name, shard_id, task_id)
);
CREATE TABLE visibility_tasks(
shard_id INT NOT NULL,
task_id BIGINT NOT NULL,
--
data MEDIUMBLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, task_id)
);
CREATE TABLE activity_info_maps (
-- each row corresponds to one key of one map<string, ActivityInfo>
shard_id INT NOT NULL,
namespace_id BINARY(16) NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BINARY(16) NOT NULL,
schedule_id BIGINT NOT NULL,
--
data MEDIUMBLOB NOT NULL,
data_encoding VARCHAR(16),
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id, schedule_id)
);
CREATE TABLE timer_info_maps (
shard_id INT NOT NULL,
namespace_id BINARY(16) NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BINARY(16) NOT NULL,
timer_id VARCHAR(255) NOT NULL,
--
data MEDIUMBLOB NOT NULL,
data_encoding VARCHAR(16),
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id, timer_id)
);
CREATE TABLE child_execution_info_maps (
shard_id INT NOT NULL,
namespace_id BINARY(16) NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BINARY(16) NOT NULL,
initiated_id BIGINT NOT NULL,
--
data MEDIUMBLOB NOT NULL,
data_encoding VARCHAR(16),
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id, initiated_id)
);
CREATE TABLE request_cancel_info_maps (
shard_id INT NOT NULL,
namespace_id BINARY(16) NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BINARY(16) NOT NULL,
initiated_id BIGINT NOT NULL,
--
data MEDIUMBLOB NOT NULL,
data_encoding VARCHAR(16),
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id, initiated_id)
);
CREATE TABLE signal_info_maps (
shard_id INT NOT NULL,
namespace_id BINARY(16) NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BINARY(16) NOT NULL,
initiated_id BIGINT NOT NULL,
--
data MEDIUMBLOB NOT NULL,
data_encoding VARCHAR(16),
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id, initiated_id)
);
CREATE TABLE signals_requested_sets (
shard_id INT NOT NULL,
namespace_id BINARY(16) NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BINARY(16) NOT NULL,
signal_id VARCHAR(255) NOT NULL,
--
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id, signal_id)
);
-- history eventsV2: history_node stores history event data
CREATE TABLE history_node (
shard_id INT NOT NULL,
tree_id BINARY(16) NOT NULL,
branch_id BINARY(16) NOT NULL,
node_id BIGINT NOT NULL,
txn_id BIGINT NOT NULL,
--
prev_txn_id BIGINT NOT NULL DEFAULT 0,
data MEDIUMBLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, tree_id, branch_id, node_id, txn_id)
);
-- history eventsV2: history_tree stores branch metadata
CREATE TABLE history_tree (
shard_id INT NOT NULL,
tree_id BINARY(16) NOT NULL,
branch_id BINARY(16) NOT NULL,
--
data MEDIUMBLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, tree_id, branch_id)
);
CREATE TABLE queue (
queue_type INT NOT NULL,
message_id BIGINT NOT NULL,
message_payload MEDIUMBLOB NOT NULL,
message_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY(queue_type, message_id)
);
CREATE TABLE queue_metadata (
queue_type INT NOT NULL,
data MEDIUMBLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
version BIGINT NOT NULL,
PRIMARY KEY(queue_type)
);
CREATE TABLE cluster_metadata_info (
metadata_partition INT NOT NULL,
cluster_name VARCHAR(255) NOT NULL,
data MEDIUMBLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
version BIGINT NOT NULL,
PRIMARY KEY(metadata_partition, cluster_name)
);
CREATE TABLE cluster_membership
(
membership_partition INT NOT NULL,
host_id BINARY(16) NOT NULL,
rpc_address VARCHAR(128) NOT NULL,
rpc_port SMALLINT NOT NULL,
role TINYINT NOT NULL,
session_start TIMESTAMP DEFAULT '1970-01-02 00:00:01',
last_heartbeat TIMESTAMP DEFAULT '1970-01-02 00:00:01',
record_expiry TIMESTAMP DEFAULT '1970-01-02 00:00:01',
INDEX (role, host_id),
INDEX (role, last_heartbeat),
INDEX (rpc_address, role),
INDEX (last_heartbeat),
INDEX (record_expiry),
PRIMARY KEY (membership_partition, host_id)
);
CREATE TABLE queues (
queue_type INT NOT NULL,
queue_name VARCHAR(255) NOT NULL,
metadata_payload MEDIUMBLOB NOT NULL,
metadata_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (queue_type, queue_name)
);
CREATE TABLE queue_messages (
queue_type INT NOT NULL,
queue_name VARCHAR(255) NOT NULL,
queue_partition BIGINT NOT NULL,
message_id BIGINT NOT NULL,
message_payload MEDIUMBLOB NOT NULL,
message_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (
queue_type,
queue_name,
queue_partition,
message_id
)
);

View File

@@ -1,8 +0,0 @@
{
"CurrVersion": "1.0",
"MinCompatibleVersion": "0.1",
"Description": "base version of schema",
"SchemaUpdateCqlFiles": [
"schema.sql"
]
}

View File

@@ -1,260 +0,0 @@
CREATE TABLE namespaces(
partition_id INT NOT NULL,
id BINARY(16) NOT NULL,
name VARCHAR(255) UNIQUE NOT NULL,
notification_version BIGINT NOT NULL,
--
data BLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
is_global TINYINT(1) NOT NULL,
PRIMARY KEY(partition_id, id)
);
CREATE TABLE namespace_metadata (
partition_id INT NOT NULL,
notification_version BIGINT NOT NULL,
PRIMARY KEY(partition_id)
);
INSERT INTO namespace_metadata (partition_id, notification_version) VALUES (54321, 1);
CREATE TABLE shards (
shard_id INT NOT NULL,
--
range_id BIGINT NOT NULL,
data BLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id)
);
CREATE TABLE transfer_tasks(
shard_id INT NOT NULL,
task_id BIGINT NOT NULL,
--
data BLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, task_id)
);
CREATE TABLE executions(
shard_id INT NOT NULL,
namespace_id BINARY(16) NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BINARY(16) NOT NULL,
--
next_event_id BIGINT NOT NULL,
last_write_version BIGINT NOT NULL,
data BLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
state BLOB NOT NULL,
state_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id)
);
CREATE TABLE current_executions(
shard_id INT NOT NULL,
namespace_id BINARY(16) NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
--
run_id BINARY(16) NOT NULL,
create_request_id VARCHAR(64) NOT NULL,
state INT NOT NULL,
status INT NOT NULL,
start_version BIGINT NOT NULL,
last_write_version BIGINT NOT NULL,
PRIMARY KEY (shard_id, namespace_id, workflow_id)
);
CREATE TABLE buffered_events (
shard_id INT NOT NULL,
namespace_id BINARY(16) NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BINARY(16) NOT NULL,
id BIGINT AUTO_INCREMENT NOT NULL UNIQUE,
--
data MEDIUMBLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id, id)
);
CREATE TABLE tasks (
range_hash INT UNSIGNED NOT NULL,
task_queue_id VARBINARY(272) NOT NULL,
task_id BIGINT NOT NULL,
--
data BLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (range_hash, task_queue_id, task_id)
);
CREATE TABLE task_queues (
range_hash INT UNSIGNED NOT NULL,
task_queue_id VARBINARY(272) NOT NULL,
--
range_id BIGINT NOT NULL,
data BLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (range_hash, task_queue_id)
);
CREATE TABLE replication_tasks (
shard_id INT NOT NULL,
task_id BIGINT NOT NULL,
--
data BLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, task_id)
);
CREATE TABLE replication_tasks_dlq (
source_cluster_name VARCHAR(255) NOT NULL,
shard_id INT NOT NULL,
task_id BIGINT NOT NULL,
--
data BLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (source_cluster_name, shard_id, task_id)
);
CREATE TABLE timer_tasks (
shard_id INT NOT NULL,
visibility_timestamp DATETIME(6) NOT NULL,
task_id BIGINT NOT NULL,
--
data BLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, visibility_timestamp, task_id)
);
CREATE TABLE activity_info_maps (
-- each row corresponds to one key of one map<string, ActivityInfo>
shard_id INT NOT NULL,
namespace_id BINARY(16) NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BINARY(16) NOT NULL,
schedule_id BIGINT NOT NULL,
--
data BLOB NOT NULL,
data_encoding VARCHAR(16),
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id, schedule_id)
);
CREATE TABLE timer_info_maps (
shard_id INT NOT NULL,
namespace_id BINARY(16) NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BINARY(16) NOT NULL,
timer_id VARCHAR(255) NOT NULL,
--
data BLOB NOT NULL,
data_encoding VARCHAR(16),
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id, timer_id)
);
CREATE TABLE child_execution_info_maps (
shard_id INT NOT NULL,
namespace_id BINARY(16) NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BINARY(16) NOT NULL,
initiated_id BIGINT NOT NULL,
--
data BLOB NOT NULL,
data_encoding VARCHAR(16),
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id, initiated_id)
);
CREATE TABLE request_cancel_info_maps (
shard_id INT NOT NULL,
namespace_id BINARY(16) NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BINARY(16) NOT NULL,
initiated_id BIGINT NOT NULL,
--
data BLOB NOT NULL,
data_encoding VARCHAR(16),
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id, initiated_id)
);
CREATE TABLE signal_info_maps (
shard_id INT NOT NULL,
namespace_id BINARY(16) NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BINARY(16) NOT NULL,
initiated_id BIGINT NOT NULL,
--
data BLOB NOT NULL,
data_encoding VARCHAR(16),
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id, initiated_id)
);
CREATE TABLE signals_requested_sets (
shard_id INT NOT NULL,
namespace_id BINARY(16) NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BINARY(16) NOT NULL,
signal_id VARCHAR(64) NOT NULL,
--
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id, signal_id)
);
-- history eventsV2: history_node stores history event data
CREATE TABLE history_node (
shard_id INT NOT NULL,
tree_id BINARY(16) NOT NULL,
branch_id BINARY(16) NOT NULL,
node_id BIGINT NOT NULL,
txn_id BIGINT NOT NULL,
--
data MEDIUMBLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, tree_id, branch_id, node_id, txn_id)
);
-- history eventsV2: history_tree stores branch metadata
CREATE TABLE history_tree (
shard_id INT NOT NULL,
tree_id BINARY(16) NOT NULL,
branch_id BINARY(16) NOT NULL,
--
data BLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, tree_id, branch_id)
);
CREATE TABLE queue (
queue_type INT NOT NULL,
message_id BIGINT NOT NULL,
message_payload BLOB NOT NULL,
PRIMARY KEY(queue_type, message_id)
);
CREATE TABLE queue_metadata (
queue_type INT NOT NULL,
data BLOB NOT NULL,
PRIMARY KEY(queue_type)
);
CREATE TABLE cluster_metadata (
metadata_partition INT NOT NULL,
immutable_data BLOB NOT NULL,
immutable_data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY(metadata_partition)
);
CREATE TABLE cluster_membership
(
membership_partition INT NOT NULL,
host_id BINARY(16) NOT NULL,
rpc_address VARCHAR(15) NOT NULL,
rpc_port SMALLINT NOT NULL,
role TINYINT NOT NULL,
session_start TIMESTAMP DEFAULT '1970-01-02 00:00:01',
last_heartbeat TIMESTAMP DEFAULT '1970-01-02 00:00:01',
record_expiry TIMESTAMP DEFAULT '1970-01-02 00:00:01',
INDEX (role, host_id),
INDEX (role, last_heartbeat),
INDEX (rpc_address, role),
INDEX (last_heartbeat),
INDEX (record_expiry),
PRIMARY KEY (membership_partition, host_id)
);

View File

@@ -1,3 +0,0 @@
ALTER TABLE cluster_metadata ADD data BLOB NOT NULL;
ALTER TABLE cluster_metadata ADD data_encoding VARCHAR(16) NOT NULL DEFAULT 'Proto3';
ALTER TABLE cluster_metadata ADD version BIGINT NOT NULL DEFAULT 1;

View File

@@ -1,8 +0,0 @@
{
"CurrVersion": "1.1",
"MinCompatibleVersion": "1.0",
"Description": "schema update for cluster metadata",
"SchemaUpdateCqlFiles": [
"cluster_metadata.sql"
]
}

View File

@@ -1,8 +0,0 @@
{
"CurrVersion": "1.10",
"MinCompatibleVersion": "1.0",
"Description": "add storage for update records and create task_queue_user_data table",
"SchemaUpdateCqlFiles": [
"task_queue_user_data.sql"
]
}

View File

@@ -1,17 +0,0 @@
-- Stores task queue information such as user provided versioning data
CREATE TABLE task_queue_user_data (
namespace_id BINARY(16) NOT NULL,
task_queue_name VARCHAR(255) NOT NULL,
data MEDIUMBLOB NOT NULL, -- temporal.server.api.persistence.v1.TaskQueueUserData
data_encoding VARCHAR(16) NOT NULL, -- Encoding type used for serialization, in practice this should always be proto3
version BIGINT NOT NULL, -- Version of this row, used for optimistic concurrency
PRIMARY KEY (namespace_id, task_queue_name)
);
-- Stores a mapping between build ids and task queues
CREATE TABLE build_id_to_task_queue (
namespace_id BINARY(16) NOT NULL,
build_id VARCHAR(255) NOT NULL,
task_queue_name VARCHAR(255) NOT NULL,
PRIMARY KEY (namespace_id, build_id, task_queue_name)
);

View File

@@ -1,8 +0,0 @@
{
"CurrVersion": "1.11",
"MinCompatibleVersion": "1.0",
"Description": "add queues and queue_messages tables",
"SchemaUpdateCqlFiles": [
"queues.sql"
]
}

View File

@@ -1,22 +0,0 @@
CREATE TABLE queues (
queue_type INT NOT NULL,
queue_name VARCHAR(255) NOT NULL,
metadata_payload MEDIUMBLOB NOT NULL,
metadata_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (queue_type, queue_name)
);
CREATE TABLE queue_messages (
queue_type INT NOT NULL,
queue_name VARCHAR(255) NOT NULL,
queue_partition BIGINT NOT NULL,
message_id BIGINT NOT NULL,
message_payload MEDIUMBLOB NOT NULL,
message_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (
queue_type,
queue_name,
queue_partition,
message_id
)
);

View File

@@ -1,20 +0,0 @@
ALTER TABLE namespaces MODIFY COLUMN data MEDIUMBLOB;
ALTER TABLE shards MODIFY COLUMN data MEDIUMBLOB;
ALTER TABLE transfer_tasks MODIFY COLUMN data MEDIUMBLOB;
ALTER TABLE executions MODIFY COLUMN data MEDIUMBLOB;
ALTER TABLE executions MODIFY COLUMN state MEDIUMBLOB;
ALTER TABLE tasks MODIFY COLUMN data MEDIUMBLOB;
ALTER TABLE task_queues MODIFY COLUMN data MEDIUMBLOB;
ALTER TABLE replication_tasks MODIFY COLUMN data MEDIUMBLOB;
ALTER TABLE replication_tasks_dlq MODIFY COLUMN data MEDIUMBLOB;
ALTER TABLE timer_tasks MODIFY COLUMN data MEDIUMBLOB;
ALTER TABLE activity_info_maps MODIFY COLUMN data MEDIUMBLOB;
ALTER TABLE timer_info_maps MODIFY COLUMN data MEDIUMBLOB;
ALTER TABLE child_execution_info_maps MODIFY COLUMN data MEDIUMBLOB;
ALTER TABLE request_cancel_info_maps MODIFY COLUMN data MEDIUMBLOB;
ALTER TABLE signal_info_maps MODIFY COLUMN data MEDIUMBLOB;
ALTER TABLE history_tree MODIFY COLUMN data MEDIUMBLOB;
ALTER TABLE queue MODIFY COLUMN message_payload MEDIUMBLOB;
ALTER TABLE queue_metadata MODIFY COLUMN data MEDIUMBLOB;
ALTER TABLE cluster_metadata MODIFY COLUMN data MEDIUMBLOB;
ALTER TABLE cluster_metadata MODIFY COLUMN immutable_data MEDIUMBLOB;

View File

@@ -1,9 +0,0 @@
{
"CurrVersion": "1.2",
"MinCompatibleVersion": "1.0",
"Description": "schema update for RPC replication and blob size adjustments",
"SchemaUpdateCqlFiles": [
"queue.sql",
"blob_size.sql"
]
}

View File

@@ -1,2 +0,0 @@
ALTER TABLE queue ADD message_encoding VARCHAR(16) NOT NULL DEFAULT 'Json';
ALTER TABLE queue_metadata ADD data_encoding VARCHAR(16) NOT NULL DEFAULT 'Json';

View File

@@ -1,8 +0,0 @@
{
"CurrVersion": "1.3",
"MinCompatibleVersion": "1.0",
"Description": "schema update for kafka deprecation",
"SchemaUpdateCqlFiles": [
"visibility_tasks.sql"
]
}

View File

@@ -1,8 +0,0 @@
CREATE TABLE visibility_tasks(
shard_id INT NOT NULL,
task_id BIGINT NOT NULL,
--
data MEDIUMBLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, task_id)
);

View File

@@ -1,2 +0,0 @@
ALTER TABLE cluster_metadata DROP immutable_data;
ALTER TABLE cluster_metadata DROP immutable_data_encoding;

View File

@@ -1,8 +0,0 @@
{
"CurrVersion": "1.4",
"MinCompatibleVersion": "1.0",
"Description": "schema update for cluster metadata cleanup",
"SchemaUpdateCqlFiles": [
"cluster_metadata.sql"
]
}

View File

@@ -1 +0,0 @@
ALTER TABLE cluster_membership MODIFY COLUMN rpc_address VARCHAR(128);

View File

@@ -1 +0,0 @@
ALTER TABLE history_node ADD prev_txn_id BIGINT NOT NULL DEFAULT 0;

View File

@@ -1 +0,0 @@
ALTER TABLE executions ADD db_record_version BIGINT NOT NULL DEFAULT 0;

View File

@@ -1,10 +0,0 @@
{
"CurrVersion": "1.5",
"MinCompatibleVersion": "1.0",
"Description": "schema update for cluster_membership, executions and history_node tables",
"SchemaUpdateCqlFiles": [
"event.sql",
"executions.sql",
"cluster_membership.sql"
]
}

View File

@@ -1,8 +0,0 @@
{
"CurrVersion": "1.6",
"MinCompatibleVersion": "1.0",
"Description": "schema update for queue_metadata",
"SchemaUpdateCqlFiles": [
"queue_metadata.sql"
]
}

View File

@@ -1 +0,0 @@
ALTER TABLE queue_metadata ADD version BIGINT NOT NULL DEFAULT 0;

View File

@@ -1,8 +0,0 @@
CREATE TABLE cluster_metadata_info (
metadata_partition INT NOT NULL,
cluster_name VARCHAR(255) NOT NULL,
data MEDIUMBLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
version BIGINT NOT NULL,
PRIMARY KEY(metadata_partition, cluster_name)
);

View File

@@ -1,10 +0,0 @@
{
"CurrVersion": "1.7",
"MinCompatibleVersion": "1.0",
"Description": "create cluster metadata info table to store cluster information and executions to store tiered storage queue",
"SchemaUpdateCqlFiles": [
"cluster_metadata_info.sql",
"no_start_version.sql",
"tiered_storage_tasks.sql"
]
}

View File

@@ -1 +0,0 @@
ALTER TABLE current_executions ALTER COLUMN start_version SET DEFAULT 0;

View File

@@ -1,8 +0,0 @@
CREATE TABLE tiered_storage_tasks (
shard_id INT NOT NULL,
task_id BIGINT NOT NULL,
--
data MEDIUMBLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, task_id)
);

View File

@@ -1,2 +0,0 @@
ALTER TABLE current_executions MODIFY COLUMN create_request_id VARCHAR(255);
ALTER TABLE signals_requested_sets MODIFY COLUMN signal_id VARCHAR(255);

View File

@@ -1 +0,0 @@
DROP TABLE tiered_storage_tasks;

View File

@@ -1,9 +0,0 @@
{
"CurrVersion": "1.8",
"MinCompatibleVersion": "1.0",
"Description": "drop unused tasks table; expand VARCHAR columns governed by maxIDLength to VARCHAR(255)",
"SchemaUpdateCqlFiles": [
"drop_unused_tasks_table.sql",
"alter_columns.sql"
]
}

View File

@@ -1,20 +0,0 @@
CREATE TABLE history_immediate_tasks(
shard_id INT NOT NULL,
category_id INT NOT NULL,
task_id BIGINT NOT NULL,
--
data MEDIUMBLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, category_id, task_id)
);
CREATE TABLE history_scheduled_tasks (
shard_id INT NOT NULL,
category_id INT NOT NULL,
visibility_timestamp DATETIME(6) NOT NULL,
task_id BIGINT NOT NULL,
--
data MEDIUMBLOB NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, category_id, visibility_timestamp, task_id)
);

View File

@@ -1,8 +0,0 @@
{
"CurrVersion": "1.9",
"MinCompatibleVersion": "1.0",
"Description": "add history tasks table",
"SchemaUpdateCqlFiles": [
"history_tasks_table.sql"
]
}

View File

@@ -1,33 +0,0 @@
// The MIT License
//
// Copyright (c) 2020 Temporal Technologies Inc. All rights reserved.
//
// Copyright (c) 2020 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 v57
// NOTE: whenever there is a new database schema update, plz update the following versions
// Version is the MySQL database release version
const Version = "1.11"
// VisibilityVersion is the MySQL visibility database release version
const VisibilityVersion = "1.1"

View File

@@ -1 +0,0 @@
CREATE DATABASE temporal_visibility character set utf8;

View File

@@ -1,24 +0,0 @@
CREATE TABLE executions_visibility (
namespace_id CHAR(64) NOT NULL,
run_id CHAR(64) NOT NULL,
start_time DATETIME(6) NOT NULL,
execution_time DATETIME(6) NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
workflow_type_name VARCHAR(255) NOT NULL,
status INT NOT NULL, -- enum WorkflowExecutionStatus {RUNNING, COMPLETED, FAILED, CANCELED, TERMINATED, CONTINUED_AS_NEW, TIMED_OUT}
close_time DATETIME(6) NULL,
history_length BIGINT,
memo BLOB,
encoding VARCHAR(64) NOT NULL,
task_queue VARCHAR(255) DEFAULT '' NOT NULL,
PRIMARY KEY (namespace_id, run_id)
);
CREATE INDEX by_type_start_time ON executions_visibility (namespace_id, workflow_type_name, status, start_time DESC, run_id);
CREATE INDEX by_workflow_id_start_time ON executions_visibility (namespace_id, workflow_id, status, start_time DESC, run_id);
CREATE INDEX by_status_by_start_time ON executions_visibility (namespace_id, status, start_time DESC, run_id);
CREATE INDEX by_type_close_time ON executions_visibility (namespace_id, workflow_type_name, status, close_time DESC, run_id);
CREATE INDEX by_workflow_id_close_time ON executions_visibility (namespace_id, workflow_id, status, close_time DESC, run_id);
CREATE INDEX by_status_by_close_time ON executions_visibility (namespace_id, status, close_time DESC, run_id);
CREATE INDEX by_close_time_by_status ON executions_visibility (namespace_id, close_time DESC, run_id, status);

View File

@@ -1,8 +0,0 @@
{
"CurrVersion": "1.0",
"MinCompatibleVersion": "0.1",
"Description": "base version of visibility schema",
"SchemaUpdateCqlFiles": [
"schema.sql"
]
}

View File

@@ -1,23 +0,0 @@
CREATE TABLE executions_visibility (
namespace_id CHAR(64) NOT NULL,
run_id CHAR(64) NOT NULL,
start_time DATETIME(6) NOT NULL,
execution_time DATETIME(6) NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
workflow_type_name VARCHAR(255) NOT NULL,
status INT NOT NULL, -- enum WorkflowExecutionStatus {RUNNING, COMPLETED, FAILED, CANCELED, TERMINATED, CONTINUED_AS_NEW, TIMED_OUT}
close_time DATETIME(6) NULL,
history_length BIGINT,
memo BLOB,
encoding VARCHAR(64) NOT NULL,
task_queue VARCHAR(255) DEFAULT '' NOT NULL,
PRIMARY KEY (namespace_id, run_id)
);
CREATE INDEX by_type_start_time ON executions_visibility (namespace_id, workflow_type_name, status, start_time DESC, run_id);
CREATE INDEX by_workflow_id_start_time ON executions_visibility (namespace_id, workflow_id, status, start_time DESC, run_id);
CREATE INDEX by_status_by_start_time ON executions_visibility (namespace_id, status, start_time DESC, run_id);
CREATE INDEX by_type_close_time ON executions_visibility (namespace_id, workflow_type_name, status, close_time DESC, run_id);
CREATE INDEX by_workflow_id_close_time ON executions_visibility (namespace_id, workflow_id, status, close_time DESC, run_id);
CREATE INDEX by_status_by_close_time ON executions_visibility (namespace_id, status, close_time DESC, run_id);

View File

@@ -1 +0,0 @@
CREATE INDEX by_close_time_by_status ON executions_visibility (namespace_id, close_time DESC, run_id, status);

View File

@@ -1,8 +0,0 @@
{
"CurrVersion": "1.1",
"MinCompatibleVersion": "0.1",
"Description": "add close time & status index",
"SchemaUpdateCqlFiles": [
"index.sql"
]
}

View File

@@ -1 +0,0 @@
CREATE DATABASE temporal;

View File

@@ -1,340 +0,0 @@
CREATE TABLE namespaces(
partition_id INTEGER NOT NULL,
id BYTEA NOT NULL,
name VARCHAR(255) UNIQUE NOT NULL,
notification_version BIGINT NOT NULL,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
is_global BOOLEAN NOT NULL,
PRIMARY KEY(partition_id, id)
);
CREATE TABLE namespace_metadata (
partition_id INTEGER NOT NULL,
notification_version BIGINT NOT NULL,
PRIMARY KEY(partition_id)
);
INSERT INTO namespace_metadata (partition_id, notification_version) VALUES (54321, 1);
CREATE TABLE shards (
shard_id INTEGER NOT NULL,
--
range_id BIGINT NOT NULL,
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id)
);
CREATE TABLE executions(
shard_id INTEGER NOT NULL,
namespace_id BYTEA NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BYTEA NOT NULL,
--
next_event_id BIGINT NOT NULL,
last_write_version BIGINT NOT NULL,
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
state BYTEA NOT NULL,
state_encoding VARCHAR(16) NOT NULL,
db_record_version BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id)
);
CREATE TABLE current_executions(
shard_id INTEGER NOT NULL,
namespace_id BYTEA NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
--
run_id BYTEA NOT NULL,
create_request_id VARCHAR(255) NOT NULL,
state INTEGER NOT NULL,
status INTEGER NOT NULL,
start_version BIGINT NOT NULL DEFAULT 0,
last_write_version BIGINT NOT NULL,
PRIMARY KEY (shard_id, namespace_id, workflow_id)
);
CREATE TABLE buffered_events (
shard_id INTEGER NOT NULL,
namespace_id BYTEA NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BYTEA NOT NULL,
id BIGSERIAL NOT NULL UNIQUE,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id, id)
);
CREATE TABLE tasks (
range_hash BIGINT NOT NULL,
task_queue_id BYTEA NOT NULL,
task_id BIGINT NOT NULL,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (range_hash, task_queue_id, task_id)
);
-- Stores ephemeral task queue information such as ack levels and expiry times
CREATE TABLE task_queues (
range_hash BIGINT NOT NULL,
task_queue_id BYTEA NOT NULL,
--
range_id BIGINT NOT NULL,
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (range_hash, task_queue_id)
);
-- Stores task queue information such as user provided versioning data
CREATE TABLE task_queue_user_data (
namespace_id BYTEA NOT NULL,
task_queue_name VARCHAR(255) NOT NULL,
data BYTEA NOT NULL, -- temporal.server.api.persistence.v1.TaskQueueUserData
data_encoding VARCHAR(16) NOT NULL, -- Encoding type used for serialization, in practice this should always be proto3
version BIGINT NOT NULL, -- Version of this row, used for optimistic concurrency
PRIMARY KEY (namespace_id, task_queue_name)
);
-- Stores a mapping between build ids and task queues
CREATE TABLE build_id_to_task_queue (
namespace_id BYTEA NOT NULL,
build_id VARCHAR(255) NOT NULL,
task_queue_name VARCHAR(255) NOT NULL,
PRIMARY KEY (namespace_id, build_id, task_queue_name)
);
CREATE TABLE history_immediate_tasks(
shard_id INTEGER NOT NULL,
category_id INTEGER NOT NULL,
task_id BIGINT NOT NULL,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, category_id, task_id)
);
CREATE TABLE history_scheduled_tasks (
shard_id INTEGER NOT NULL,
category_id INTEGER NOT NULL,
visibility_timestamp TIMESTAMP NOT NULL,
task_id BIGINT NOT NULL,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, category_id, visibility_timestamp, task_id)
);
CREATE TABLE transfer_tasks(
shard_id INTEGER NOT NULL,
task_id BIGINT NOT NULL,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, task_id)
);
CREATE TABLE timer_tasks (
shard_id INTEGER NOT NULL,
visibility_timestamp TIMESTAMP NOT NULL,
task_id BIGINT NOT NULL,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, visibility_timestamp, task_id)
);
CREATE TABLE replication_tasks (
shard_id INTEGER NOT NULL,
task_id BIGINT NOT NULL,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, task_id)
);
CREATE TABLE replication_tasks_dlq (
source_cluster_name VARCHAR(255) NOT NULL,
shard_id INTEGER NOT NULL,
task_id BIGINT NOT NULL,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (source_cluster_name, shard_id, task_id)
);
CREATE TABLE visibility_tasks(
shard_id INTEGER NOT NULL,
task_id BIGINT NOT NULL,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, task_id)
);
CREATE TABLE activity_info_maps (
-- each row corresponds to one key of one map<string, ActivityInfo>
shard_id INTEGER NOT NULL,
namespace_id BYTEA NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BYTEA NOT NULL,
schedule_id BIGINT NOT NULL,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16),
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id, schedule_id)
);
CREATE TABLE timer_info_maps (
shard_id INTEGER NOT NULL,
namespace_id BYTEA NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BYTEA NOT NULL,
timer_id VARCHAR(255) NOT NULL,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16),
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id, timer_id)
);
CREATE TABLE child_execution_info_maps (
shard_id INTEGER NOT NULL,
namespace_id BYTEA NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BYTEA NOT NULL,
initiated_id BIGINT NOT NULL,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16),
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id, initiated_id)
);
CREATE TABLE request_cancel_info_maps (
shard_id INTEGER NOT NULL,
namespace_id BYTEA NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BYTEA NOT NULL,
initiated_id BIGINT NOT NULL,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16),
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id, initiated_id)
);
CREATE TABLE signal_info_maps (
shard_id INTEGER NOT NULL,
namespace_id BYTEA NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BYTEA NOT NULL,
initiated_id BIGINT NOT NULL,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16),
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id, initiated_id)
);
CREATE TABLE signals_requested_sets (
shard_id INTEGER NOT NULL,
namespace_id BYTEA NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BYTEA NOT NULL,
signal_id VARCHAR(255) NOT NULL,
--
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id, signal_id)
);
-- history eventsV2: history_node stores history event data
CREATE TABLE history_node (
shard_id INTEGER NOT NULL,
tree_id BYTEA NOT NULL,
branch_id BYTEA NOT NULL,
node_id BIGINT NOT NULL,
txn_id BIGINT NOT NULL,
--
prev_txn_id BIGINT NOT NULL DEFAULT 0,
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, tree_id, branch_id, node_id, txn_id)
);
-- history eventsV2: history_tree stores branch metadata
CREATE TABLE history_tree (
shard_id INTEGER NOT NULL,
tree_id BYTEA NOT NULL,
branch_id BYTEA NOT NULL,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, tree_id, branch_id)
);
CREATE TABLE queue (
queue_type INTEGER NOT NULL,
message_id BIGINT NOT NULL,
message_payload BYTEA NOT NULL,
message_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY(queue_type, message_id)
);
CREATE TABLE queue_metadata (
queue_type INTEGER NOT NULL,
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
version BIGINT NOT NULL,
PRIMARY KEY(queue_type)
);
CREATE TABLE cluster_metadata_info (
metadata_partition INTEGER NOT NULL,
cluster_name VARCHAR(255) NOT NULL,
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
version BIGINT NOT NULL,
PRIMARY KEY(metadata_partition, cluster_name)
);
CREATE TABLE cluster_membership
(
membership_partition INTEGER NOT NULL,
host_id BYTEA NOT NULL,
rpc_address VARCHAR(128) NOT NULL,
rpc_port SMALLINT NOT NULL,
role SMALLINT NOT NULL,
session_start TIMESTAMP DEFAULT '1970-01-01 00:00:01+00:00',
last_heartbeat TIMESTAMP DEFAULT '1970-01-01 00:00:01+00:00',
record_expiry TIMESTAMP DEFAULT '1970-01-01 00:00:01+00:00',
PRIMARY KEY (membership_partition, host_id)
);
CREATE TABLE queues (
queue_type INT NOT NULL,
queue_name VARCHAR(255) NOT NULL,
metadata_payload BYTEA NOT NULL,
metadata_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (queue_type, queue_name)
);
CREATE TABLE queue_messages (
queue_type INT NOT NULL,
queue_name VARCHAR(255) NOT NULL,
queue_partition BIGINT NOT NULL,
message_id BIGINT NOT NULL,
message_payload BYTEA NOT NULL,
message_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (
queue_type,
queue_name,
queue_partition,
message_id
)
);
CREATE UNIQUE INDEX cm_idx_rolehost ON cluster_membership (role, host_id);
CREATE INDEX cm_idx_rolelasthb ON cluster_membership (role, last_heartbeat);
CREATE INDEX cm_idx_rpchost ON cluster_membership (rpc_address, role);
CREATE INDEX cm_idx_lasthb ON cluster_membership (last_heartbeat);
CREATE INDEX cm_idx_recordexpiry ON cluster_membership (record_expiry);

View File

@@ -1,8 +0,0 @@
{
"CurrVersion": "1.0",
"MinCompatibleVersion": "0.1",
"Description": "base version of schema",
"SchemaUpdateCqlFiles": [
"schema.sql"
]
}

View File

@@ -1,261 +0,0 @@
CREATE TABLE namespaces(
partition_id INTEGER NOT NULL,
id BYTEA NOT NULL,
name VARCHAR(255) UNIQUE NOT NULL,
notification_version BIGINT NOT NULL,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
is_global BOOLEAN NOT NULL,
PRIMARY KEY(partition_id, id)
);
CREATE TABLE namespace_metadata (
partition_id INTEGER NOT NULL,
notification_version BIGINT NOT NULL,
PRIMARY KEY(partition_id)
);
INSERT INTO namespace_metadata (partition_id, notification_version) VALUES (54321, 1);
CREATE TABLE shards (
shard_id INTEGER NOT NULL,
--
range_id BIGINT NOT NULL,
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id)
);
CREATE TABLE transfer_tasks(
shard_id INTEGER NOT NULL,
task_id BIGINT NOT NULL,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, task_id)
);
CREATE TABLE executions(
shard_id INTEGER NOT NULL,
namespace_id BYTEA NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BYTEA NOT NULL,
--
next_event_id BIGINT NOT NULL,
last_write_version BIGINT NOT NULL,
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
state BYTEA NOT NULL,
state_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id)
);
CREATE TABLE current_executions(
shard_id INTEGER NOT NULL,
namespace_id BYTEA NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
--
run_id BYTEA NOT NULL,
create_request_id VARCHAR(64) NOT NULL,
state INTEGER NOT NULL,
status INTEGER NOT NULL,
start_version BIGINT NOT NULL,
last_write_version BIGINT NOT NULL,
PRIMARY KEY (shard_id, namespace_id, workflow_id)
);
CREATE TABLE buffered_events (
shard_id INTEGER NOT NULL,
namespace_id BYTEA NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BYTEA NOT NULL,
id BIGSERIAL NOT NULL UNIQUE,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id, id)
);
CREATE TABLE tasks (
range_hash BIGINT NOT NULL,
task_queue_id BYTEA NOT NULL,
task_id BIGINT NOT NULL,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (range_hash, task_queue_id, task_id)
);
CREATE TABLE task_queues (
range_hash BIGINT NOT NULL,
task_queue_id BYTEA NOT NULL,
--
range_id BIGINT NOT NULL,
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (range_hash, task_queue_id)
);
CREATE TABLE replication_tasks (
shard_id INTEGER NOT NULL,
task_id BIGINT NOT NULL,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, task_id)
);
CREATE TABLE replication_tasks_dlq (
source_cluster_name VARCHAR(255) NOT NULL,
shard_id INTEGER NOT NULL,
task_id BIGINT NOT NULL,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (source_cluster_name, shard_id, task_id)
);
CREATE TABLE timer_tasks (
shard_id INTEGER NOT NULL,
visibility_timestamp TIMESTAMP NOT NULL,
task_id BIGINT NOT NULL,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, visibility_timestamp, task_id)
);
CREATE TABLE activity_info_maps (
-- each row corresponds to one key of one map<string, ActivityInfo>
shard_id INTEGER NOT NULL,
namespace_id BYTEA NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BYTEA NOT NULL,
schedule_id BIGINT NOT NULL,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16),
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id, schedule_id)
);
CREATE TABLE timer_info_maps (
shard_id INTEGER NOT NULL,
namespace_id BYTEA NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BYTEA NOT NULL,
timer_id VARCHAR(255) NOT NULL,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16),
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id, timer_id)
);
CREATE TABLE child_execution_info_maps (
shard_id INTEGER NOT NULL,
namespace_id BYTEA NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BYTEA NOT NULL,
initiated_id BIGINT NOT NULL,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16),
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id, initiated_id)
);
CREATE TABLE request_cancel_info_maps (
shard_id INTEGER NOT NULL,
namespace_id BYTEA NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BYTEA NOT NULL,
initiated_id BIGINT NOT NULL,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16),
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id, initiated_id)
);
CREATE TABLE signal_info_maps (
shard_id INTEGER NOT NULL,
namespace_id BYTEA NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BYTEA NOT NULL,
initiated_id BIGINT NOT NULL,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16),
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id, initiated_id)
);
CREATE TABLE signals_requested_sets (
shard_id INTEGER NOT NULL,
namespace_id BYTEA NOT NULL,
workflow_id VARCHAR(255) NOT NULL,
run_id BYTEA NOT NULL,
signal_id VARCHAR(64) NOT NULL,
--
PRIMARY KEY (shard_id, namespace_id, workflow_id, run_id, signal_id)
);
-- history eventsV2: history_node stores history event data
CREATE TABLE history_node (
shard_id INTEGER NOT NULL,
tree_id BYTEA NOT NULL,
branch_id BYTEA NOT NULL,
node_id BIGINT NOT NULL,
txn_id BIGINT NOT NULL,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, tree_id, branch_id, node_id, txn_id)
);
-- history eventsV2: history_tree stores branch metadata
CREATE TABLE history_tree (
shard_id INTEGER NOT NULL,
tree_id BYTEA NOT NULL,
branch_id BYTEA NOT NULL,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, tree_id, branch_id)
);
CREATE TABLE queue (
queue_type INTEGER NOT NULL,
message_id BIGINT NOT NULL,
message_payload BYTEA NOT NULL,
PRIMARY KEY(queue_type, message_id)
);
CREATE TABLE queue_metadata (
queue_type INTEGER NOT NULL,
data BYTEA NOT NULL,
PRIMARY KEY(queue_type)
);
CREATE TABLE cluster_metadata (
metadata_partition INTEGER NOT NULL,
immutable_data BYTEA NOT NULL,
immutable_data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY(metadata_partition)
);
CREATE TABLE cluster_membership
(
membership_partition INTEGER NOT NULL,
host_id BYTEA NOT NULL,
rpc_address VARCHAR(15) NOT NULL,
rpc_port SMALLINT NOT NULL,
role SMALLINT NOT NULL,
session_start TIMESTAMP DEFAULT '1970-01-01 00:00:01+00:00',
last_heartbeat TIMESTAMP DEFAULT '1970-01-01 00:00:01+00:00',
record_expiry TIMESTAMP DEFAULT '1970-01-01 00:00:01+00:00',
PRIMARY KEY (membership_partition, host_id)
);
CREATE UNIQUE INDEX cm_idx_rolehost ON cluster_membership (role, host_id);
CREATE INDEX cm_idx_rolelasthb ON cluster_membership (role, last_heartbeat);
CREATE INDEX cm_idx_rpchost ON cluster_membership (rpc_address, role);
CREATE INDEX cm_idx_lasthb ON cluster_membership (last_heartbeat);
CREATE INDEX cm_idx_recordexpiry ON cluster_membership (record_expiry);

View File

@@ -1,3 +0,0 @@
ALTER TABLE cluster_metadata ADD data BYTEA NOT NULL DEFAULT '';
ALTER TABLE cluster_metadata ADD data_encoding VARCHAR(16) NOT NULL DEFAULT 'Proto3';
ALTER TABLE cluster_metadata ADD version BIGINT NOT NULL DEFAULT 1;

View File

@@ -1,8 +0,0 @@
{
"CurrVersion": "1.1",
"MinCompatibleVersion": "1.0",
"Description": "schema update for cluster metadata",
"SchemaUpdateCqlFiles": [
"cluster_metadata.sql"
]
}

View File

@@ -1,8 +0,0 @@
{
"CurrVersion": "1.10",
"MinCompatibleVersion": "1.0",
"Description": "add storage for update records and create task_queue_user_data table",
"SchemaUpdateCqlFiles": [
"task_queue_user_data.sql"
]
}

View File

@@ -1,17 +0,0 @@
-- Stores task queue information such as user provided versioning data
CREATE TABLE task_queue_user_data (
namespace_id BYTEA NOT NULL,
task_queue_name VARCHAR(255) NOT NULL,
data BYTEA NOT NULL, -- temporal.server.api.persistence.v1.TaskQueueUserData
data_encoding VARCHAR(16) NOT NULL, -- Encoding type used for serialization, in practice this should always be proto3
version BIGINT NOT NULL, -- Version of this row, used for optimistic concurrency
PRIMARY KEY (namespace_id, task_queue_name)
);
-- Stores a mapping between build ids and task queues
CREATE TABLE build_id_to_task_queue (
namespace_id BYTEA NOT NULL,
build_id VARCHAR(255) NOT NULL,
task_queue_name VARCHAR(255) NOT NULL,
PRIMARY KEY (namespace_id, build_id, task_queue_name)
);

View File

@@ -1,8 +0,0 @@
{
"CurrVersion": "1.11",
"MinCompatibleVersion": "1.0",
"Description": "add queues and queue_messages tables",
"SchemaUpdateCqlFiles": [
"queue_v2.sql"
]
}

View File

@@ -1,22 +0,0 @@
CREATE TABLE queues (
queue_type INT NOT NULL,
queue_name VARCHAR(255) NOT NULL,
metadata_payload BYTEA NOT NULL,
metadata_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (queue_type, queue_name)
);
CREATE TABLE queue_messages (
queue_type INT NOT NULL,
queue_name VARCHAR(255) NOT NULL,
queue_partition BIGINT NOT NULL,
message_id BIGINT NOT NULL,
message_payload BYTEA NOT NULL,
message_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (
queue_type,
queue_name,
queue_partition,
message_id
)
);

View File

@@ -1,8 +0,0 @@
{
"CurrVersion": "1.2",
"MinCompatibleVersion": "1.0",
"Description": "schema update for RPC replication",
"SchemaUpdateCqlFiles": [
"queue.sql"
]
}

View File

@@ -1,2 +0,0 @@
ALTER TABLE queue ADD message_encoding VARCHAR(16) NOT NULL DEFAULT 'Json';
ALTER TABLE queue_metadata ADD data_encoding VARCHAR(16) NOT NULL DEFAULT 'Json';

View File

@@ -1,8 +0,0 @@
{
"CurrVersion": "1.3",
"MinCompatibleVersion": "1.0",
"Description": "schema update for kafka deprecation",
"SchemaUpdateCqlFiles": [
"visibility_tasks.sql"
]
}

View File

@@ -1,8 +0,0 @@
CREATE TABLE visibility_tasks(
shard_id INTEGER NOT NULL,
task_id BIGINT NOT NULL,
--
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
PRIMARY KEY (shard_id, task_id)
);

View File

@@ -1,2 +0,0 @@
ALTER TABLE cluster_metadata DROP immutable_data;
ALTER TABLE cluster_metadata DROP immutable_data_encoding;

View File

@@ -1,8 +0,0 @@
{
"CurrVersion": "1.4",
"MinCompatibleVersion": "1.0",
"Description": "schema update for cluster metadata cleanup",
"SchemaUpdateCqlFiles": [
"cluster_metadata.sql"
]
}

View File

@@ -1 +0,0 @@
ALTER TABLE cluster_membership ALTER COLUMN rpc_address TYPE VARCHAR(128);

View File

@@ -1 +0,0 @@
ALTER TABLE history_node ADD prev_txn_id BIGINT NOT NULL DEFAULT 0;

View File

@@ -1 +0,0 @@
ALTER TABLE executions ADD db_record_version BIGINT NOT NULL DEFAULT 0;

View File

@@ -1,10 +0,0 @@
{
"CurrVersion": "1.5",
"MinCompatibleVersion": "1.0",
"Description": "schema update for cluster_membership, executions and history_node tables",
"SchemaUpdateCqlFiles": [
"event.sql",
"executions.sql",
"cluster_membership.sql"
]
}

View File

@@ -1,8 +0,0 @@
{
"CurrVersion": "1.6",
"MinCompatibleVersion": "1.0",
"Description": "schema update for queue_metadata",
"SchemaUpdateCqlFiles": [
"queue_metadata.sql"
]
}

View File

@@ -1 +0,0 @@
ALTER TABLE queue_metadata ADD version BIGINT NOT NULL DEFAULT 0;

View File

@@ -1,8 +0,0 @@
CREATE TABLE cluster_metadata_info (
metadata_partition INTEGER NOT NULL,
cluster_name VARCHAR(255) NOT NULL,
data BYTEA NOT NULL,
data_encoding VARCHAR(16) NOT NULL,
version BIGINT NOT NULL,
PRIMARY KEY(metadata_partition, cluster_name)
);

Some files were not shown because too many files have changed in this diff Show More