github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/infura/engine.go (about) 1 package infura 2 3 import ( 4 "errors" 5 "fmt" 6 7 "github.com/fibonacci-chain/fbc/libs/tendermint/libs/log" 8 "github.com/fibonacci-chain/fbc/x/infura/types" 9 "gorm.io/driver/mysql" 10 "gorm.io/gorm" 11 "gorm.io/gorm/logger" 12 ) 13 14 const batchSize = 1000 15 16 func newStreamEngine(cfg *types.Config, logger log.Logger) (types.IStreamEngine, error) { 17 if cfg.MysqlUrl == "" { 18 return nil, errors.New("infura.mysql-url is empty") 19 } 20 return newMySQLEngine(cfg.MysqlUrl, cfg.MysqlUser, cfg.MysqlPass, cfg.MysqlDB, logger) 21 } 22 23 type MySQLEngine struct { 24 db *gorm.DB 25 logger log.Logger 26 } 27 28 func newMySQLEngine(url, user, pass, dbName string, l log.Logger) (types.IStreamEngine, error) { 29 dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", 30 user, pass, url, dbName) 31 32 db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{ 33 SkipDefaultTransaction: true, 34 Logger: logger.Default.LogMode(logger.Info), 35 }) 36 if err != nil { 37 return nil, err 38 } 39 db.AutoMigrate(&types.TransactionReceipt{}, &types.TransactionLog{}, 40 &types.LogTopic{}, &types.Block{}, &types.Transaction{}, &types.ContractCode{}) 41 return &MySQLEngine{ 42 db: db, 43 logger: l, 44 }, nil 45 } 46 47 func (e *MySQLEngine) Write(streamData types.IStreamData) bool { 48 e.logger.Debug("Begin MySqlEngine write") 49 data := streamData.ConvertEngineData() 50 trx := e.db.Begin() 51 // write TransactionReceipts 52 for i := 0; i < len(data.TransactionReceipts); i += batchSize { 53 end := i + batchSize 54 if end > len(data.TransactionReceipts) { 55 end = len(data.TransactionReceipts) 56 } 57 ret := trx.CreateInBatches(data.TransactionReceipts[i:end], len(data.TransactionReceipts[i:end])) 58 if ret.Error != nil { 59 return e.rollbackWithError(trx, ret.Error) 60 } 61 } 62 63 // write Block 64 ret := trx.Omit("Transactions").Create(data.Block) 65 if ret.Error != nil { 66 return e.rollbackWithError(trx, ret.Error) 67 } 68 69 // write Transactions 70 for i := 0; i < len(data.Block.Transactions); i += batchSize { 71 end := i + batchSize 72 if end > len(data.Block.Transactions) { 73 end = len(data.Block.Transactions) 74 } 75 ret := trx.CreateInBatches(data.Block.Transactions[i:end], len(data.Block.Transactions[i:end])) 76 if ret.Error != nil { 77 return e.rollbackWithError(trx, ret.Error) 78 } 79 } 80 81 // write contract code 82 for _, code := range data.ContractCodes { 83 ret := trx.Create(code) 84 if ret.Error != nil { 85 return e.rollbackWithError(trx, ret.Error) 86 } 87 } 88 89 trx.Commit() 90 e.logger.Debug("End MySqlEngine write") 91 return true 92 } 93 94 func (e *MySQLEngine) rollbackWithError(trx *gorm.DB, err error) bool { 95 trx.Rollback() 96 e.logger.Error(err.Error()) 97 return false 98 }