github.com/ecodeclub/eorm@v0.0.2-0.20231001112437-dae71da914d0/internal/datasource/transaction/transaction_suite_test.go (about) 1 // Copyright 2021 ecodeclub 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package transaction_test 16 17 import ( 18 "context" 19 "database/sql" 20 "fmt" 21 "testing" 22 23 "github.com/DATA-DOG/go-sqlmock" 24 "github.com/ecodeclub/eorm" 25 "github.com/ecodeclub/eorm/internal/datasource" 26 "github.com/ecodeclub/eorm/internal/datasource/cluster" 27 "github.com/ecodeclub/eorm/internal/datasource/masterslave" 28 "github.com/ecodeclub/eorm/internal/datasource/masterslave/slaves" 29 "github.com/ecodeclub/eorm/internal/datasource/masterslave/slaves/roundrobin" 30 "github.com/ecodeclub/eorm/internal/datasource/shardingsource" 31 "github.com/ecodeclub/eorm/internal/model" 32 "github.com/ecodeclub/eorm/internal/sharding" 33 "github.com/ecodeclub/eorm/internal/sharding/hash" 34 "github.com/ecodeclub/eorm/internal/test" 35 "github.com/stretchr/testify/require" 36 "github.com/stretchr/testify/suite" 37 ) 38 39 type ShardingTransactionSuite struct { 40 shardingKey string 41 shardingDB *eorm.DB 42 algorithm sharding.Algorithm 43 44 suite.Suite 45 datasource.DataSource 46 clusterDB datasource.DataSource 47 mockMaster1DB *sql.DB 48 mockMaster sqlmock.Sqlmock 49 50 mockSlave1DB *sql.DB 51 mockSlave1 sqlmock.Sqlmock 52 53 mockSlave2DB *sql.DB 54 mockSlave2 sqlmock.Sqlmock 55 56 mockSlave3DB *sql.DB 57 mockSlave3 sqlmock.Sqlmock 58 59 mockMaster2DB *sql.DB 60 mockMaster2 sqlmock.Sqlmock 61 62 mockSlave4DB *sql.DB 63 mockSlave4 sqlmock.Sqlmock 64 65 mockSlave5DB *sql.DB 66 mockSlave5 sqlmock.Sqlmock 67 68 mockSlave6DB *sql.DB 69 mockSlave6 sqlmock.Sqlmock 70 } 71 72 func (s *ShardingTransactionSuite) SetupTest() { 73 t := s.T() 74 s.initMock(t) 75 } 76 77 func (s *ShardingTransactionSuite) initMock(t *testing.T) { 78 var err error 79 s.mockMaster1DB, s.mockMaster, err = sqlmock.New() 80 if err != nil { 81 t.Fatal(err) 82 } 83 s.mockSlave1DB, s.mockSlave1, err = sqlmock.New() 84 if err != nil { 85 t.Fatal(err) 86 } 87 s.mockSlave2DB, s.mockSlave2, err = sqlmock.New() 88 if err != nil { 89 t.Fatal(err) 90 } 91 s.mockSlave3DB, s.mockSlave3, err = sqlmock.New() 92 if err != nil { 93 t.Fatal(err) 94 } 95 96 s.mockMaster2DB, s.mockMaster2, err = sqlmock.New() 97 if err != nil { 98 t.Fatal(err) 99 } 100 s.mockSlave4DB, s.mockSlave4, err = sqlmock.New() 101 if err != nil { 102 t.Fatal(err) 103 } 104 s.mockSlave5DB, s.mockSlave5, err = sqlmock.New() 105 if err != nil { 106 t.Fatal(err) 107 } 108 s.mockSlave6DB, s.mockSlave6, err = sqlmock.New() 109 if err != nil { 110 t.Fatal(err) 111 } 112 113 db1 := masterslave.NewMasterSlavesDB(s.mockMaster1DB, masterslave.MasterSlavesWithSlaves( 114 newSlaves(t, s.mockSlave1DB, s.mockSlave2DB, s.mockSlave3DB))) 115 116 db2 := masterslave.NewMasterSlavesDB(s.mockMaster2DB, masterslave.MasterSlavesWithSlaves( 117 newSlaves(t, s.mockSlave4DB, s.mockSlave5DB, s.mockSlave6DB))) 118 119 s.clusterDB = cluster.NewClusterDB(map[string]*masterslave.MasterSlavesDB{ 120 "order_detail_db_0": db1, 121 "order_detail_db_1": db2, 122 }) 123 124 s.DataSource = shardingsource.NewShardingDataSource(map[string]datasource.DataSource{ 125 "0.db.cluster.company.com:3306": s.clusterDB, 126 }) 127 128 r := model.NewMetaRegistry() 129 sk := "OrderId" 130 s.algorithm = &hash.Hash{ 131 ShardingKey: sk, 132 DBPattern: &hash.Pattern{Name: "order_detail_db_%d", Base: 2}, 133 TablePattern: &hash.Pattern{Name: "order_detail_tab_%d", Base: 3}, 134 DsPattern: &hash.Pattern{Name: "0.db.cluster.company.com:3306", NotSharding: true}, 135 } 136 s.shardingKey = sk 137 _, err = r.Register(&test.OrderDetail{}, 138 model.WithTableShardingAlgorithm(s.algorithm)) 139 require.NoError(t, err) 140 db, err := eorm.OpenDS("mysql", s.DataSource, eorm.DBWithMetaRegistry(r)) 141 require.NoError(t, err) 142 s.shardingDB = db 143 } 144 145 func (s *ShardingTransactionSuite) TearDownTest() { 146 _ = s.mockMaster1DB.Close() 147 _ = s.mockSlave1DB.Close() 148 _ = s.mockSlave2DB.Close() 149 _ = s.mockSlave3DB.Close() 150 151 _ = s.mockMaster2DB.Close() 152 _ = s.mockSlave4DB.Close() 153 _ = s.mockSlave5DB.Close() 154 _ = s.mockSlave6DB.Close() 155 } 156 157 func (s *ShardingTransactionSuite) findTgt(t *testing.T, values []*test.OrderDetail) []*test.OrderDetail { 158 od := values[0] 159 pre := eorm.C(s.shardingKey).EQ(od.OrderId) 160 for i := 1; i < len(values); i++ { 161 od = values[i] 162 pre = pre.Or(eorm.C(s.shardingKey).EQ(od.OrderId)) 163 } 164 querySet, err := eorm.NewShardingSelector[test.OrderDetail](s.shardingDB). 165 Where(pre).GetMulti(masterslave.UseMaster(context.Background())) 166 require.NoError(t, err) 167 return querySet 168 } 169 170 func newShardingTransactionSuite() ShardingTransactionSuite { 171 return ShardingTransactionSuite{} 172 } 173 174 func newSlaves(t *testing.T, dbs ...*sql.DB) slaves.Slaves { 175 res, err := roundrobin.NewSlaves(dbs...) 176 require.NoError(t, err) 177 return res 178 } 179 180 func newMockCommitErr(dbName string, err error) error { 181 return fmt.Errorf("masterslave DB name [%s] Commit error: %w", dbName, err) 182 } 183 184 func newMockRollbackErr(dbName string, err error) error { 185 return fmt.Errorf("masterslave DB name [%s] Rollback error: %w", dbName, err) 186 }