From bc605ce6bc529baf996ea7e1fb3b70721bf99a88 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 13 Dec 2024 22:11:24 +0800 Subject: [PATCH 1/6] support auto refresh table mate cache --- .../sql/datasource/base/meta_cache.go | 26 +- .../sql/datasource/base/meta_cache_test.go | 154 ++++++++++ .../sql/datasource/mysql/meta_cache.go | 6 +- .../sql/datasource/mysql/trigger.go | 12 +- .../sql/datasource/mysql/trigger_test.go | 290 ++++++++++++++++++ pkg/datasource/sql/driver.go | 2 +- .../sql/exec/at/multi_update_excutor_test.go | 4 +- .../sql/exec/at/update_executor_test.go | 2 +- 8 files changed, 484 insertions(+), 12 deletions(-) create mode 100644 pkg/datasource/sql/datasource/base/meta_cache_test.go create mode 100644 pkg/datasource/sql/datasource/mysql/trigger_test.go diff --git a/pkg/datasource/sql/datasource/base/meta_cache.go b/pkg/datasource/sql/datasource/base/meta_cache.go index 859157e2b..c4694d8b7 100644 --- a/pkg/datasource/sql/datasource/base/meta_cache.go +++ b/pkg/datasource/sql/datasource/base/meta_cache.go @@ -24,6 +24,8 @@ import ( "sync" "time" + "github.com/go-sql-driver/mysql" + "seata.apache.org/seata-go/pkg/datasource/sql/types" ) @@ -32,7 +34,7 @@ type ( trigger interface { LoadOne(ctx context.Context, dbName string, table string, conn *sql.Conn) (*types.TableMeta, error) - LoadAll() ([]types.TableMeta, error) + LoadAll(ctx context.Context, dbName string, conn *sql.Conn, tables ...string) ([]types.TableMeta, error) } entry struct { @@ -50,10 +52,12 @@ type BaseTableMetaCache struct { cache map[string]*entry cancel context.CancelFunc trigger trigger + db *sql.DB + cfg *mysql.Config } // NewBaseCache -func NewBaseCache(capity int32, expireDuration time.Duration, trigger trigger) *BaseTableMetaCache { +func NewBaseCache(capity int32, expireDuration time.Duration, trigger trigger, db *sql.DB, cfg *mysql.Config) *BaseTableMetaCache { ctx, cancel := context.WithCancel(context.Background()) c := &BaseTableMetaCache{ @@ -64,6 +68,8 @@ func NewBaseCache(capity int32, expireDuration time.Duration, trigger trigger) * cache: map[string]*entry{}, cancel: cancel, trigger: trigger, + cfg: cfg, + db: db, } c.Init(ctx) @@ -82,7 +88,19 @@ func (c *BaseTableMetaCache) Init(ctx context.Context) error { // refresh func (c *BaseTableMetaCache) refresh(ctx context.Context) { f := func() { - v, err := c.trigger.LoadAll() + if c.db == nil || c.cfg == nil || c.cache == nil || len(c.cache) == 0 { + return + } + + tables := make([]string, 0, len(c.cache)) + for table := range c.cache { + tables = append(tables, table) + } + conn, err := c.db.Conn(ctx) + if err != nil { + return + } + v, err := c.trigger.LoadAll(ctx, c.cfg.DBName, conn, tables...) if err != nil { return } @@ -92,7 +110,7 @@ func (c *BaseTableMetaCache) refresh(ctx context.Context) { for i := range v { tm := v[i] - if _, ok := c.cache[tm.TableName]; !ok { + if _, ok := c.cache[tm.TableName]; ok { c.cache[tm.TableName] = &entry{ value: tm, } diff --git a/pkg/datasource/sql/datasource/base/meta_cache_test.go b/pkg/datasource/sql/datasource/base/meta_cache_test.go new file mode 100644 index 000000000..247c96456 --- /dev/null +++ b/pkg/datasource/sql/datasource/base/meta_cache_test.go @@ -0,0 +1,154 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package base + +import ( + "context" + "database/sql" + "sync" + "testing" + "time" + + "github.com/agiledragon/gomonkey/v2" + "github.com/go-sql-driver/mysql" + "github.com/stretchr/testify/assert" + "seata.apache.org/seata-go/pkg/datasource/sql/types" +) + +var ( + capacity int32 = 1024 + EexpireTime = 15 * time.Minute + tableMetaOnce sync.Once +) + +type mockTrigger struct { +} + +func (m *mockTrigger) LoadOne(ctx context.Context, dbName string, table string, conn *sql.Conn) (*types.TableMeta, error) { + return nil, nil +} + +func (m *mockTrigger) LoadAll(ctx context.Context, dbName string, conn *sql.Conn, tables ...string) ([]types.TableMeta, error) { + return nil, nil +} + +func TestBaseTableMetaCache_refresh(t *testing.T) { + type fields struct { + lock sync.RWMutex + expireDuration time.Duration + capity int32 + size int32 + cache map[string]*entry + cancel context.CancelFunc + trigger trigger + db *sql.DB + cfg *mysql.Config + } + type args struct { + ctx context.Context + } + ctx, cancel := context.WithCancel(context.Background()) + tests := []struct { + name string + fields fields + args args + want types.TableMeta + }{ + {name: "test-1", + fields: fields{ + lock: sync.RWMutex{}, + capity: capacity, + size: 0, + expireDuration: EexpireTime, + cache: map[string]*entry{ + "test": &entry{ + value: types.TableMeta{}, + lastAccess: time.Now(), + }, + }, + cancel: cancel, + trigger: &mockTrigger{}, + cfg: &mysql.Config{}, + db: &sql.DB{}, + }, args: args{ctx: ctx}, + want: types.TableMeta{ + TableName: "test", + Columns: map[string]types.ColumnMeta{ + "id": { + ColumnName: "id", + }, + "name": { + ColumnName: "name", + }, + }, + Indexs: map[string]types.IndexMeta{ + "": { + ColumnName: "id", + IType: types.IndexTypePrimaryKey, + Columns: []types.ColumnMeta{ + { + ColumnName: "id", + DatabaseType: types.GetSqlDataType("BIGINT"), + }, + { + ColumnName: "id", + }, + }, + }, + }, + ColumnNames: []string{ + "id", + "name", + }, + }}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + + connStub := gomonkey.ApplyMethodFunc(tt.fields.db, "Conn", + func(_ context.Context) (*sql.Conn, error) { + return &sql.Conn{}, nil + }) + + defer connStub.Reset() + + loadAllStub := gomonkey.ApplyMethodFunc(tt.fields.trigger, "LoadAll", + func(_ context.Context, _ string, _ *sql.Conn, _ ...string) ([]types.TableMeta, error) { + return []types.TableMeta{tt.want}, nil + }) + + defer loadAllStub.Reset() + + c := &BaseTableMetaCache{ + lock: tt.fields.lock, + expireDuration: tt.fields.expireDuration, + capity: tt.fields.capity, + size: tt.fields.size, + cache: tt.fields.cache, + cancel: tt.fields.cancel, + trigger: tt.fields.trigger, + db: tt.fields.db, + cfg: tt.fields.cfg, + } + go c.refresh(tt.args.ctx) + time.Sleep(time.Second * 3) + + assert.Equal(t, c.cache["test"].value, tt.want) + }) + } +} diff --git a/pkg/datasource/sql/datasource/mysql/meta_cache.go b/pkg/datasource/sql/datasource/mysql/meta_cache.go index 82ac0fbc7..2b0a45ea3 100644 --- a/pkg/datasource/sql/datasource/mysql/meta_cache.go +++ b/pkg/datasource/sql/datasource/mysql/meta_cache.go @@ -24,6 +24,8 @@ import ( "sync" "time" + "github.com/go-sql-driver/mysql" + "seata.apache.org/seata-go/pkg/datasource/sql/datasource/base" "seata.apache.org/seata-go/pkg/datasource/sql/types" ) @@ -39,9 +41,9 @@ type TableMetaCache struct { db *sql.DB } -func NewTableMetaInstance(db *sql.DB) *TableMetaCache { +func NewTableMetaInstance(db *sql.DB, cfg *mysql.Config) *TableMetaCache { tableMetaInstance := &TableMetaCache{ - tableMetaCache: base.NewBaseCache(capacity, EexpireTime, NewMysqlTrigger()), + tableMetaCache: base.NewBaseCache(capacity, EexpireTime, NewMysqlTrigger(), db, cfg), db: db, } return tableMetaInstance diff --git a/pkg/datasource/sql/datasource/mysql/trigger.go b/pkg/datasource/sql/datasource/mysql/trigger.go index 689ad2c73..adbbb2f79 100644 --- a/pkg/datasource/sql/datasource/mysql/trigger.go +++ b/pkg/datasource/sql/datasource/mysql/trigger.go @@ -79,8 +79,16 @@ func (m *mysqlTrigger) LoadOne(ctx context.Context, dbName string, tableName str } // LoadAll -func (m *mysqlTrigger) LoadAll() ([]types.TableMeta, error) { - return []types.TableMeta{}, nil +func (m *mysqlTrigger) LoadAll(ctx context.Context, dbName string, conn *sql.Conn, tables ...string) ([]types.TableMeta, error) { + var tableMetas []types.TableMeta + for _, tableName := range tables { + tableMeta, err := m.LoadOne(ctx, dbName, tableName, conn) + if err != nil { + continue + } + tableMetas = append(tableMetas, *tableMeta) + } + return tableMetas, nil } // getColumnMetas get tableMeta column diff --git a/pkg/datasource/sql/datasource/mysql/trigger_test.go b/pkg/datasource/sql/datasource/mysql/trigger_test.go new file mode 100644 index 000000000..313cc285c --- /dev/null +++ b/pkg/datasource/sql/datasource/mysql/trigger_test.go @@ -0,0 +1,290 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package mysql + +import ( + "context" + "database/sql" + "testing" + + "github.com/agiledragon/gomonkey/v2" + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" + + "seata.apache.org/seata-go/pkg/datasource/sql/mock" + "seata.apache.org/seata-go/pkg/datasource/sql/types" + "seata.apache.org/seata-go/pkg/protocol/branch" + "seata.apache.org/seata-go/pkg/rm" +) + +func Test_mysqlTrigger_LoadOne(t *testing.T) { + + type args struct { + ctx context.Context + dbName string + tableName string + conn *sql.Conn + } + tests := []struct { + name string + args args + columnMeta []types.ColumnMeta + indexMeta []types.IndexMeta + wantTableMeta *types.TableMeta + }{ + { + name: "1", + args: args{ctx: context.Background(), dbName: "dbName", tableName: "test", conn: nil}, + indexMeta: []types.IndexMeta{ + { + + IType: types.IndexTypePrimaryKey, + ColumnName: "id", + Columns: []types.ColumnMeta{ + { + ColumnName: "id", + DatabaseType: types.GetSqlDataType("BIGINT"), + }, + }, + }, + }, + columnMeta: []types.ColumnMeta{ + { + ColumnName: "id", + }, + { + ColumnName: "name", + }, + }, + wantTableMeta: &types.TableMeta{ + TableName: "test", + Columns: map[string]types.ColumnMeta{ + "id": { + ColumnName: "id", + }, + "name": { + ColumnName: "name", + }, + }, + Indexs: map[string]types.IndexMeta{ + "": { + ColumnName: "id", + IType: types.IndexTypePrimaryKey, + Columns: []types.ColumnMeta{ + { + ColumnName: "id", + DatabaseType: int32(types.JDBCTypeBigInt), + }, + { + ColumnName: "id", + }, + }, + }, + }, + ColumnNames: []string{ + "id", + "name", + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + m := &mysqlTrigger{} + + getColumnMetasStub := gomonkey.ApplyPrivateMethod(m, "getColumnMetas", + func(_ *mysqlTrigger, ctx context.Context, dbName string, table string, conn *sql.Conn) ([]types.ColumnMeta, error) { + return tt.columnMeta, nil + }) + + defer getColumnMetasStub.Reset() + + getIndexesStub := gomonkey.ApplyPrivateMethod(m, "getIndexes", + func(_ *mysqlTrigger, ctx context.Context, dbName string, tableName string, conn *sql.Conn) ([]types.IndexMeta, error) { + return tt.indexMeta, nil + }) + + defer getIndexesStub.Reset() + + got, err := m.LoadOne(tt.args.ctx, tt.args.dbName, tt.args.tableName, tt.args.conn) + if err != nil { + t.Errorf("LoadOne() error = %v", err) + return + } + + assert.Equal(t, tt.wantTableMeta, got) + }) + } +} + +func initMockResourceManager(branchType branch.BranchType, ctrl *gomock.Controller) *mock.MockDataSourceManager { + mockResourceMgr := mock.NewMockDataSourceManager(ctrl) + mockResourceMgr.SetBranchType(branchType) + mockResourceMgr.EXPECT().BranchRegister(gomock.Any(), gomock.Any()).AnyTimes().Return(int64(0), nil) + rm.GetRmCacheInstance().RegisterResourceManager(mockResourceMgr) + mockResourceMgr.EXPECT().RegisterResource(gomock.Any()).AnyTimes().Return(nil) + mockResourceMgr.EXPECT().CreateTableMetaCache(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(nil, nil) + return mockResourceMgr +} + +func Test_mysqlTrigger_LoadAll(t *testing.T) { + sql.Register("seata-at-mysql", &mock.MockTestDriver{}) + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockMgr := initMockResourceManager(branch.BranchTypeAT, ctrl) + _ = mockMgr + + conn := sql.Conn{} + type args struct { + ctx context.Context + dbName string + conn *sql.Conn + tables []string + } + tests := []struct { + name string + args args + columnMeta []types.ColumnMeta + indexMeta []types.IndexMeta + want []types.TableMeta + }{ + { + name: "test-01", + args: args{ + ctx: nil, + dbName: "dbName", + conn: &conn, + tables: []string{ + "test_01", + "test_02", + }, + }, + indexMeta: []types.IndexMeta{ + { + IType: types.IndexTypePrimaryKey, + ColumnName: "id", + Columns: []types.ColumnMeta{ + { + ColumnName: "id", + DatabaseType: types.GetSqlDataType("BIGINT"), + }, + }, + }, + }, + columnMeta: []types.ColumnMeta{ + { + ColumnName: "id", + }, + { + ColumnName: "name", + }, + }, + want: []types.TableMeta{ + { + TableName: "test_01", + Columns: map[string]types.ColumnMeta{ + "id": { + ColumnName: "id", + }, + "name": { + ColumnName: "name", + }, + }, + Indexs: map[string]types.IndexMeta{ + "": { + ColumnName: "id", + IType: types.IndexTypePrimaryKey, + Columns: []types.ColumnMeta{ + { + ColumnName: "id", + DatabaseType: types.GetSqlDataType("BIGINT"), + }, + { + ColumnName: "id", + }, + }, + }, + }, + ColumnNames: []string{ + "id", + "name", + }, + }, + { + TableName: "test_02", + Columns: map[string]types.ColumnMeta{ + "id": { + ColumnName: "id", + }, + "name": { + ColumnName: "name", + }, + }, + Indexs: map[string]types.IndexMeta{ + "": { + ColumnName: "id", + IType: types.IndexTypePrimaryKey, + Columns: []types.ColumnMeta{ + { + ColumnName: "id", + DatabaseType: types.GetSqlDataType("BIGINT"), + }, + { + ColumnName: "id", + }, + }, + }, + }, + ColumnNames: []string{ + "id", + "name", + }, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + m := &mysqlTrigger{} + + getColumnMetasStub := gomonkey.ApplyPrivateMethod(m, "getColumnMetas", + func(_ *mysqlTrigger, ctx context.Context, dbName string, table string, conn *sql.Conn) ([]types.ColumnMeta, error) { + return tt.columnMeta, nil + }) + + defer getColumnMetasStub.Reset() + + getIndexesStub := gomonkey.ApplyPrivateMethod(m, "getIndexes", + func(_ *mysqlTrigger, ctx context.Context, dbName string, tableName string, conn *sql.Conn) ([]types.IndexMeta, error) { + return tt.indexMeta, nil + }) + + defer getIndexesStub.Reset() + + got, err := m.LoadAll(tt.args.ctx, tt.args.dbName, tt.args.conn, tt.args.tables...) + if err != nil { + t.Errorf("LoadAll() error = %v", err) + return + } + + assert.Equal(t, tt.want, got) + }) + } +} diff --git a/pkg/datasource/sql/driver.go b/pkg/datasource/sql/driver.go index a4b511100..905d81d39 100644 --- a/pkg/datasource/sql/driver.go +++ b/pkg/datasource/sql/driver.go @@ -155,7 +155,7 @@ func (d *seataDriver) getOpenConnectorProxy(connector driver.Connector, dbType t log.Errorf("create new resource: %w", err) return nil, err } - datasource.RegisterTableCache(types.DBTypeMySQL, mysql2.NewTableMetaInstance(db)) + datasource.RegisterTableCache(types.DBTypeMySQL, mysql2.NewTableMetaInstance(db, cfg)) if err = datasource.GetDataSourceManager(d.branchType).RegisterResource(res); err != nil { log.Errorf("regisiter resource: %w", err) return nil, err diff --git a/pkg/datasource/sql/exec/at/multi_update_excutor_test.go b/pkg/datasource/sql/exec/at/multi_update_excutor_test.go index 9207346dd..21ef2e309 100644 --- a/pkg/datasource/sql/exec/at/multi_update_excutor_test.go +++ b/pkg/datasource/sql/exec/at/multi_update_excutor_test.go @@ -34,7 +34,7 @@ import ( func TestBuildSelectSQLByMultiUpdate(t *testing.T) { undo.InitUndoConfig(undo.Config{OnlyCareUpdateColumns: true}) - datasource.RegisterTableCache(types.DBTypeMySQL, mysql.NewTableMetaInstance(nil)) + datasource.RegisterTableCache(types.DBTypeMySQL, mysql.NewTableMetaInstance(nil, nil)) tests := []struct { name string @@ -101,7 +101,7 @@ func TestBuildSelectSQLByMultiUpdate(t *testing.T) { func TestBuildSelectSQLByMultiUpdateAllColumns(t *testing.T) { undo.InitUndoConfig(undo.Config{OnlyCareUpdateColumns: false}) - datasource.RegisterTableCache(types.DBTypeMySQL, mysql.NewTableMetaInstance(nil)) + datasource.RegisterTableCache(types.DBTypeMySQL, mysql.NewTableMetaInstance(nil, nil)) tests := []struct { name string diff --git a/pkg/datasource/sql/exec/at/update_executor_test.go b/pkg/datasource/sql/exec/at/update_executor_test.go index 770f21688..a6ffc9bef 100644 --- a/pkg/datasource/sql/exec/at/update_executor_test.go +++ b/pkg/datasource/sql/exec/at/update_executor_test.go @@ -38,7 +38,7 @@ import ( func TestBuildSelectSQLByUpdate(t *testing.T) { undo.InitUndoConfig(undo.Config{OnlyCareUpdateColumns: true}) - datasource.RegisterTableCache(types.DBTypeMySQL, mysql.NewTableMetaInstance(nil)) + datasource.RegisterTableCache(types.DBTypeMySQL, mysql.NewTableMetaInstance(nil, nil)) stub := gomonkey.ApplyMethod(reflect.TypeOf(datasource.GetTableCache(types.DBTypeMySQL)), "GetTableMeta", func(_ *mysql.TableMetaCache, ctx context.Context, dbName, tableName string) (*types.TableMeta, error) { return &types.TableMeta{ From d602569167b59cca952374b9dc3b5e96363192d0 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 13 Dec 2024 22:29:03 +0800 Subject: [PATCH 2/6] fix test --- pkg/datasource/sql/exec/at/insert_executor_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/datasource/sql/exec/at/insert_executor_test.go b/pkg/datasource/sql/exec/at/insert_executor_test.go index 742249bc4..ecf37392c 100644 --- a/pkg/datasource/sql/exec/at/insert_executor_test.go +++ b/pkg/datasource/sql/exec/at/insert_executor_test.go @@ -114,7 +114,7 @@ func TestBuildSelectSQLByInsert(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - datasource.RegisterTableCache(types.DBTypeMySQL, mysql.NewTableMetaInstance(nil)) + datasource.RegisterTableCache(types.DBTypeMySQL, mysql.NewTableMetaInstance(nil, nil)) stub := gomonkey.ApplyMethod(reflect.TypeOf(datasource.GetTableCache(types.DBTypeMySQL)), "GetTableMeta", func(_ *mysql.TableMetaCache, ctx context.Context, dbName, tableName string) (*types.TableMeta, error) { return &test.metaData, nil @@ -629,7 +629,7 @@ func TestMySQLInsertUndoLogBuilder_getPkValuesByColumn(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - datasource.RegisterTableCache(types.DBTypeMySQL, mysql.NewTableMetaInstance(nil)) + datasource.RegisterTableCache(types.DBTypeMySQL, mysql.NewTableMetaInstance(nil, nil)) stub := gomonkey.ApplyMethod(reflect.TypeOf(datasource.GetTableCache(types.DBTypeMySQL)), "GetTableMeta", func(_ *mysql.TableMetaCache, ctx context.Context, dbName, tableName string) (*types.TableMeta, error) { return &tt.args.meta, nil @@ -731,7 +731,7 @@ func TestMySQLInsertUndoLogBuilder_getPkValuesByAuto(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - datasource.RegisterTableCache(types.DBTypeMySQL, mysql.NewTableMetaInstance(nil)) + datasource.RegisterTableCache(types.DBTypeMySQL, mysql.NewTableMetaInstance(nil, nil)) stub := gomonkey.ApplyMethod(reflect.TypeOf(datasource.GetTableCache(types.DBTypeMySQL)), "GetTableMeta", func(_ *mysql.TableMetaCache, ctx context.Context, dbName, tableName string) (*types.TableMeta, error) { return &tt.args.meta, nil @@ -824,7 +824,7 @@ func TestMySQLInsertUndoLogBuilder_autoGeneratePks(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - datasource.RegisterTableCache(types.DBTypeMySQL, mysql.NewTableMetaInstance(nil)) + datasource.RegisterTableCache(types.DBTypeMySQL, mysql.NewTableMetaInstance(nil, nil)) stub := gomonkey.ApplyMethod(reflect.TypeOf(datasource.GetTableCache(types.DBTypeMySQL)), "GetTableMeta", func(_ *mysql.TableMetaCache, ctx context.Context, dbName, tableName string) (*types.TableMeta, error) { return &tt.args.meta, nil From 684656180ea68e885911872b78c48d713c9e30e7 Mon Sep 17 00:00:00 2001 From: FengZhang Date: Sun, 15 Dec 2024 22:16:09 +0800 Subject: [PATCH 3/6] Refactor the code to address the issue of duplicate definitions --- .../sql/datasource/mysql/trigger_test.go | 113 ++++++++---------- 1 file changed, 52 insertions(+), 61 deletions(-) diff --git a/pkg/datasource/sql/datasource/mysql/trigger_test.go b/pkg/datasource/sql/datasource/mysql/trigger_test.go index 313cc285c..710ba069b 100644 --- a/pkg/datasource/sql/datasource/mysql/trigger_test.go +++ b/pkg/datasource/sql/datasource/mysql/trigger_test.go @@ -32,6 +32,48 @@ import ( "seata.apache.org/seata-go/pkg/rm" ) +func initMockIndexMeta() []types.IndexMeta{ + return []types.IndexMeta{ + { + IType: types.IndexTypePrimaryKey, + ColumnName: "id", + Columns: []types.ColumnMeta{ + { + ColumnName: "id", + DatabaseType: types.GetSqlDataType("BIGINT"), + }, + }, + }, + } +} + +func initMockColumnMeta() []types.ColumnMeta{ + return []types.ColumnMeta{ + { + ColumnName: "id", + }, + { + ColumnName: "name", + }, + } +} + +func initGetIndexesStub(m *mysqlTrigger,indexMeta []types.IndexMeta) *gomonkey.Patches { + getIndexesStub := gomonkey.ApplyPrivateMethod(m, "getIndexes", + func(_ *mysqlTrigger, ctx context.Context, dbName string, tableName string, conn *sql.Conn) ([]types.IndexMeta, error) { + return indexMeta, nil + }) + return getIndexesStub +} + +func initGetColumnMetasStub(m *mysqlTrigger, columnMeta []types.ColumnMeta) *gomonkey.Patches { + getColumnMetasStub := gomonkey.ApplyPrivateMethod(m, "getColumnMetas", + func(_ *mysqlTrigger, ctx context.Context, dbName string, table string, conn *sql.Conn) ([]types.ColumnMeta, error) { + return columnMeta, nil + }) + return getColumnMetasStub +} + func Test_mysqlTrigger_LoadOne(t *testing.T) { type args struct { @@ -50,27 +92,8 @@ func Test_mysqlTrigger_LoadOne(t *testing.T) { { name: "1", args: args{ctx: context.Background(), dbName: "dbName", tableName: "test", conn: nil}, - indexMeta: []types.IndexMeta{ - { - - IType: types.IndexTypePrimaryKey, - ColumnName: "id", - Columns: []types.ColumnMeta{ - { - ColumnName: "id", - DatabaseType: types.GetSqlDataType("BIGINT"), - }, - }, - }, - }, - columnMeta: []types.ColumnMeta{ - { - ColumnName: "id", - }, - { - ColumnName: "name", - }, - }, + indexMeta: initMockIndexMeta(), + columnMeta: initMockColumnMeta(), wantTableMeta: &types.TableMeta{ TableName: "test", Columns: map[string]types.ColumnMeta{ @@ -107,18 +130,10 @@ func Test_mysqlTrigger_LoadOne(t *testing.T) { t.Run(tt.name, func(t *testing.T) { m := &mysqlTrigger{} - getColumnMetasStub := gomonkey.ApplyPrivateMethod(m, "getColumnMetas", - func(_ *mysqlTrigger, ctx context.Context, dbName string, table string, conn *sql.Conn) ([]types.ColumnMeta, error) { - return tt.columnMeta, nil - }) - + getColumnMetasStub := initGetColumnMetasStub(m, tt.columnMeta) defer getColumnMetasStub.Reset() - getIndexesStub := gomonkey.ApplyPrivateMethod(m, "getIndexes", - func(_ *mysqlTrigger, ctx context.Context, dbName string, tableName string, conn *sql.Conn) ([]types.IndexMeta, error) { - return tt.indexMeta, nil - }) - + getIndexesStub := initGetIndexesStub(m, tt.indexMeta) defer getIndexesStub.Reset() got, err := m.LoadOne(tt.args.ctx, tt.args.dbName, tt.args.tableName, tt.args.conn) @@ -132,6 +147,8 @@ func Test_mysqlTrigger_LoadOne(t *testing.T) { } } + + func initMockResourceManager(branchType branch.BranchType, ctrl *gomock.Controller) *mock.MockDataSourceManager { mockResourceMgr := mock.NewMockDataSourceManager(ctrl) mockResourceMgr.SetBranchType(branchType) @@ -176,26 +193,8 @@ func Test_mysqlTrigger_LoadAll(t *testing.T) { "test_02", }, }, - indexMeta: []types.IndexMeta{ - { - IType: types.IndexTypePrimaryKey, - ColumnName: "id", - Columns: []types.ColumnMeta{ - { - ColumnName: "id", - DatabaseType: types.GetSqlDataType("BIGINT"), - }, - }, - }, - }, - columnMeta: []types.ColumnMeta{ - { - ColumnName: "id", - }, - { - ColumnName: "name", - }, - }, + indexMeta: initMockIndexMeta(), + columnMeta: initMockColumnMeta(), want: []types.TableMeta{ { TableName: "test_01", @@ -264,18 +263,10 @@ func Test_mysqlTrigger_LoadAll(t *testing.T) { t.Run(tt.name, func(t *testing.T) { m := &mysqlTrigger{} - getColumnMetasStub := gomonkey.ApplyPrivateMethod(m, "getColumnMetas", - func(_ *mysqlTrigger, ctx context.Context, dbName string, table string, conn *sql.Conn) ([]types.ColumnMeta, error) { - return tt.columnMeta, nil - }) - + getColumnMetasStub := initGetColumnMetasStub(m, tt.columnMeta) defer getColumnMetasStub.Reset() - getIndexesStub := gomonkey.ApplyPrivateMethod(m, "getIndexes", - func(_ *mysqlTrigger, ctx context.Context, dbName string, tableName string, conn *sql.Conn) ([]types.IndexMeta, error) { - return tt.indexMeta, nil - }) - + getIndexesStub := initGetIndexesStub(m, tt.indexMeta) defer getIndexesStub.Reset() got, err := m.LoadAll(tt.args.ctx, tt.args.dbName, tt.args.conn, tt.args.tables...) From 84b80797487dc9c21201cd737c1fd628bdeb331d Mon Sep 17 00:00:00 2001 From: FengZhang Date: Sun, 15 Dec 2024 23:29:18 +0800 Subject: [PATCH 4/6] Refactor the code to address the issue of duplicate definitions --- .../sql/datasource/mysql/trigger_test.go | 112 +++++++----------- 1 file changed, 41 insertions(+), 71 deletions(-) diff --git a/pkg/datasource/sql/datasource/mysql/trigger_test.go b/pkg/datasource/sql/datasource/mysql/trigger_test.go index 710ba069b..144a358cd 100644 --- a/pkg/datasource/sql/datasource/mysql/trigger_test.go +++ b/pkg/datasource/sql/datasource/mysql/trigger_test.go @@ -32,7 +32,7 @@ import ( "seata.apache.org/seata-go/pkg/rm" ) -func initMockIndexMeta() []types.IndexMeta{ +func initMockIndexMeta() []types.IndexMeta { return []types.IndexMeta{ { IType: types.IndexTypePrimaryKey, @@ -47,7 +47,7 @@ func initMockIndexMeta() []types.IndexMeta{ } } -func initMockColumnMeta() []types.ColumnMeta{ +func initMockColumnMeta() []types.ColumnMeta { return []types.ColumnMeta{ { ColumnName: "id", @@ -58,7 +58,7 @@ func initMockColumnMeta() []types.ColumnMeta{ } } -func initGetIndexesStub(m *mysqlTrigger,indexMeta []types.IndexMeta) *gomonkey.Patches { +func initGetIndexesStub(m *mysqlTrigger, indexMeta []types.IndexMeta) *gomonkey.Patches { getIndexesStub := gomonkey.ApplyPrivateMethod(m, "getIndexes", func(_ *mysqlTrigger, ctx context.Context, dbName string, tableName string, conn *sql.Conn) ([]types.IndexMeta, error) { return indexMeta, nil @@ -90,9 +90,9 @@ func Test_mysqlTrigger_LoadOne(t *testing.T) { wantTableMeta *types.TableMeta }{ { - name: "1", - args: args{ctx: context.Background(), dbName: "dbName", tableName: "test", conn: nil}, - indexMeta: initMockIndexMeta(), + name: "1", + args: args{ctx: context.Background(), dbName: "dbName", tableName: "test", conn: nil}, + indexMeta: initMockIndexMeta(), columnMeta: initMockColumnMeta(), wantTableMeta: &types.TableMeta{ TableName: "test", @@ -147,8 +147,6 @@ func Test_mysqlTrigger_LoadOne(t *testing.T) { } } - - func initMockResourceManager(branchType branch.BranchType, ctrl *gomock.Controller) *mock.MockDataSourceManager { mockResourceMgr := mock.NewMockDataSourceManager(ctrl) mockResourceMgr.SetBranchType(branchType) @@ -159,6 +157,39 @@ func initMockResourceManager(branchType branch.BranchType, ctrl *gomock.Controll return mockResourceMgr } +func initLoadAllWant(tableName string) types.TableMeta { + return types.TableMeta{ + TableName: tableName, + Columns: map[string]types.ColumnMeta{ + "id": { + ColumnName: "id", + }, + "name": { + ColumnName: "name", + }, + }, + Indexs: map[string]types.IndexMeta{ + "": { + ColumnName: "id", + IType: types.IndexTypePrimaryKey, + Columns: []types.ColumnMeta{ + { + ColumnName: "id", + DatabaseType: types.GetSqlDataType("BIGINT"), + }, + { + ColumnName: "id", + }, + }, + }, + }, + ColumnNames: []string{ + "id", + "name", + }, + } +} + func Test_mysqlTrigger_LoadAll(t *testing.T) { sql.Register("seata-at-mysql", &mock.MockTestDriver{}) @@ -193,70 +224,9 @@ func Test_mysqlTrigger_LoadAll(t *testing.T) { "test_02", }, }, - indexMeta: initMockIndexMeta(), + indexMeta: initMockIndexMeta(), columnMeta: initMockColumnMeta(), - want: []types.TableMeta{ - { - TableName: "test_01", - Columns: map[string]types.ColumnMeta{ - "id": { - ColumnName: "id", - }, - "name": { - ColumnName: "name", - }, - }, - Indexs: map[string]types.IndexMeta{ - "": { - ColumnName: "id", - IType: types.IndexTypePrimaryKey, - Columns: []types.ColumnMeta{ - { - ColumnName: "id", - DatabaseType: types.GetSqlDataType("BIGINT"), - }, - { - ColumnName: "id", - }, - }, - }, - }, - ColumnNames: []string{ - "id", - "name", - }, - }, - { - TableName: "test_02", - Columns: map[string]types.ColumnMeta{ - "id": { - ColumnName: "id", - }, - "name": { - ColumnName: "name", - }, - }, - Indexs: map[string]types.IndexMeta{ - "": { - ColumnName: "id", - IType: types.IndexTypePrimaryKey, - Columns: []types.ColumnMeta{ - { - ColumnName: "id", - DatabaseType: types.GetSqlDataType("BIGINT"), - }, - { - ColumnName: "id", - }, - }, - }, - }, - ColumnNames: []string{ - "id", - "name", - }, - }, - }, + want: []types.TableMeta{initLoadAllWant("test_01"), initLoadAllWant("test_02")}, }, } for _, tt := range tests { From a54a9d9e99b05c7eee03107d4d455551840fd166 Mon Sep 17 00:00:00 2001 From: FengZhang Date: Mon, 16 Dec 2024 22:49:49 +0800 Subject: [PATCH 5/6] Refactor the code to address the issue of duplicate definitions --- .../sql/datasource/base/meta_cache_test.go | 34 ++---------- .../sql/datasource/mysql/trigger_test.go | 42 +++------------ testdata/meta_cache.go | 53 +++++++++++++++++++ 3 files changed, 63 insertions(+), 66 deletions(-) create mode 100644 testdata/meta_cache.go diff --git a/pkg/datasource/sql/datasource/base/meta_cache_test.go b/pkg/datasource/sql/datasource/base/meta_cache_test.go index 247c96456..48138970b 100644 --- a/pkg/datasource/sql/datasource/base/meta_cache_test.go +++ b/pkg/datasource/sql/datasource/base/meta_cache_test.go @@ -28,6 +28,7 @@ import ( "github.com/go-sql-driver/mysql" "github.com/stretchr/testify/assert" "seata.apache.org/seata-go/pkg/datasource/sql/types" + "seata.apache.org/seata-go/testdata" ) var ( @@ -76,7 +77,7 @@ func TestBaseTableMetaCache_refresh(t *testing.T) { size: 0, expireDuration: EexpireTime, cache: map[string]*entry{ - "test": &entry{ + "test": { value: types.TableMeta{}, lastAccess: time.Now(), }, @@ -86,36 +87,7 @@ func TestBaseTableMetaCache_refresh(t *testing.T) { cfg: &mysql.Config{}, db: &sql.DB{}, }, args: args{ctx: ctx}, - want: types.TableMeta{ - TableName: "test", - Columns: map[string]types.ColumnMeta{ - "id": { - ColumnName: "id", - }, - "name": { - ColumnName: "name", - }, - }, - Indexs: map[string]types.IndexMeta{ - "": { - ColumnName: "id", - IType: types.IndexTypePrimaryKey, - Columns: []types.ColumnMeta{ - { - ColumnName: "id", - DatabaseType: types.GetSqlDataType("BIGINT"), - }, - { - ColumnName: "id", - }, - }, - }, - }, - ColumnNames: []string{ - "id", - "name", - }, - }}, + want: testdata.MockWantTypesMeta()}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/pkg/datasource/sql/datasource/mysql/trigger_test.go b/pkg/datasource/sql/datasource/mysql/trigger_test.go index 144a358cd..a1fd5e9b5 100644 --- a/pkg/datasource/sql/datasource/mysql/trigger_test.go +++ b/pkg/datasource/sql/datasource/mysql/trigger_test.go @@ -25,6 +25,7 @@ import ( "github.com/agiledragon/gomonkey/v2" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" + "seata.apache.org/seata-go/testdata" "seata.apache.org/seata-go/pkg/datasource/sql/mock" "seata.apache.org/seata-go/pkg/datasource/sql/types" @@ -75,7 +76,7 @@ func initGetColumnMetasStub(m *mysqlTrigger, columnMeta []types.ColumnMeta) *gom } func Test_mysqlTrigger_LoadOne(t *testing.T) { - + wantTableMeta := testdata.MockWantTypesMeta() type args struct { ctx context.Context dbName string @@ -90,40 +91,11 @@ func Test_mysqlTrigger_LoadOne(t *testing.T) { wantTableMeta *types.TableMeta }{ { - name: "1", - args: args{ctx: context.Background(), dbName: "dbName", tableName: "test", conn: nil}, - indexMeta: initMockIndexMeta(), - columnMeta: initMockColumnMeta(), - wantTableMeta: &types.TableMeta{ - TableName: "test", - Columns: map[string]types.ColumnMeta{ - "id": { - ColumnName: "id", - }, - "name": { - ColumnName: "name", - }, - }, - Indexs: map[string]types.IndexMeta{ - "": { - ColumnName: "id", - IType: types.IndexTypePrimaryKey, - Columns: []types.ColumnMeta{ - { - ColumnName: "id", - DatabaseType: int32(types.JDBCTypeBigInt), - }, - { - ColumnName: "id", - }, - }, - }, - }, - ColumnNames: []string{ - "id", - "name", - }, - }, + name: "1", + args: args{ctx: context.Background(), dbName: "dbName", tableName: "test", conn: nil}, + indexMeta: initMockIndexMeta(), + columnMeta: initMockColumnMeta(), + wantTableMeta: &wantTableMeta, }, } for _, tt := range tests { diff --git a/testdata/meta_cache.go b/testdata/meta_cache.go new file mode 100644 index 000000000..2fa84b48a --- /dev/null +++ b/testdata/meta_cache.go @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package testdata + +import "seata.apache.org/seata-go/pkg/datasource/sql/types" + +func MockWantTypesMeta() types.TableMeta { + return types.TableMeta{ + TableName: "test", + Columns: map[string]types.ColumnMeta{ + "id": { + ColumnName: "id", + }, + "name": { + ColumnName: "name", + }, + }, + Indexs: map[string]types.IndexMeta{ + "": { + ColumnName: "id", + IType: types.IndexTypePrimaryKey, + Columns: []types.ColumnMeta{ + { + ColumnName: "id", + DatabaseType: types.GetSqlDataType("BIGINT"), + }, + { + ColumnName: "id", + }, + }, + }, + }, + ColumnNames: []string{ + "id", + "name", + }, + } +} From dbce868b0e0b3431d777acbbd0909917c93ec9c9 Mon Sep 17 00:00:00 2001 From: FengZhang Date: Mon, 16 Dec 2024 23:02:33 +0800 Subject: [PATCH 6/6] Refactor the code to address the issue of duplicate definitions --- .../sql/datasource/base/meta_cache_test.go | 2 +- .../sql/datasource/mysql/trigger_test.go | 37 +------------------ testdata/meta_cache.go | 4 +- 3 files changed, 5 insertions(+), 38 deletions(-) diff --git a/pkg/datasource/sql/datasource/base/meta_cache_test.go b/pkg/datasource/sql/datasource/base/meta_cache_test.go index 48138970b..570674e1a 100644 --- a/pkg/datasource/sql/datasource/base/meta_cache_test.go +++ b/pkg/datasource/sql/datasource/base/meta_cache_test.go @@ -87,7 +87,7 @@ func TestBaseTableMetaCache_refresh(t *testing.T) { cfg: &mysql.Config{}, db: &sql.DB{}, }, args: args{ctx: ctx}, - want: testdata.MockWantTypesMeta()}, + want: testdata.MockWantTypesMeta("test")}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/pkg/datasource/sql/datasource/mysql/trigger_test.go b/pkg/datasource/sql/datasource/mysql/trigger_test.go index a1fd5e9b5..4c8bc8bc9 100644 --- a/pkg/datasource/sql/datasource/mysql/trigger_test.go +++ b/pkg/datasource/sql/datasource/mysql/trigger_test.go @@ -76,7 +76,7 @@ func initGetColumnMetasStub(m *mysqlTrigger, columnMeta []types.ColumnMeta) *gom } func Test_mysqlTrigger_LoadOne(t *testing.T) { - wantTableMeta := testdata.MockWantTypesMeta() + wantTableMeta := testdata.MockWantTypesMeta("test") type args struct { ctx context.Context dbName string @@ -129,39 +129,6 @@ func initMockResourceManager(branchType branch.BranchType, ctrl *gomock.Controll return mockResourceMgr } -func initLoadAllWant(tableName string) types.TableMeta { - return types.TableMeta{ - TableName: tableName, - Columns: map[string]types.ColumnMeta{ - "id": { - ColumnName: "id", - }, - "name": { - ColumnName: "name", - }, - }, - Indexs: map[string]types.IndexMeta{ - "": { - ColumnName: "id", - IType: types.IndexTypePrimaryKey, - Columns: []types.ColumnMeta{ - { - ColumnName: "id", - DatabaseType: types.GetSqlDataType("BIGINT"), - }, - { - ColumnName: "id", - }, - }, - }, - }, - ColumnNames: []string{ - "id", - "name", - }, - } -} - func Test_mysqlTrigger_LoadAll(t *testing.T) { sql.Register("seata-at-mysql", &mock.MockTestDriver{}) @@ -198,7 +165,7 @@ func Test_mysqlTrigger_LoadAll(t *testing.T) { }, indexMeta: initMockIndexMeta(), columnMeta: initMockColumnMeta(), - want: []types.TableMeta{initLoadAllWant("test_01"), initLoadAllWant("test_02")}, + want: []types.TableMeta{testdata.MockWantTypesMeta("test_01"), testdata.MockWantTypesMeta("test_02")}, }, } for _, tt := range tests { diff --git a/testdata/meta_cache.go b/testdata/meta_cache.go index 2fa84b48a..38c2e6433 100644 --- a/testdata/meta_cache.go +++ b/testdata/meta_cache.go @@ -19,9 +19,9 @@ package testdata import "seata.apache.org/seata-go/pkg/datasource/sql/types" -func MockWantTypesMeta() types.TableMeta { +func MockWantTypesMeta(tableName string) types.TableMeta { return types.TableMeta{ - TableName: "test", + TableName: tableName, Columns: map[string]types.ColumnMeta{ "id": { ColumnName: "id",