github.com/condensat/bank-core@v0.1.0/database/query/batch.go (about) 1 // Copyright 2020 Condensat Tech. All rights reserved. 2 // Use of this source code is governed by a MIT 3 // license that can be found in the LICENSE file. 4 5 package query 6 7 import ( 8 "errors" 9 "time" 10 11 "github.com/condensat/bank-core/database" 12 "github.com/condensat/bank-core/database/model" 13 14 "github.com/jinzhu/gorm" 15 ) 16 17 const ( 18 DefaultBatchExecutionDelay time.Duration = time.Hour 19 DefaultBatchCapacity model.Int = 16 20 ) 21 22 var ( 23 ErrInvalidBatchID = errors.New("Invalid BatchID") 24 ErrInvalidBatchWithdraws = errors.New("Invalid Withdraws") 25 ErrInvalidNetwork = errors.New("Invalid Network") 26 ) 27 28 func AddBatch(db database.Context, network model.BatchNetwork, data model.BatchData, withdraws ...model.WithdrawID) (model.Batch, error) { 29 gdb := db.DB().(*gorm.DB) 30 if db == nil { 31 return model.Batch{}, database.ErrInvalidDatabase 32 } 33 34 if len(network) == 0 { 35 return model.Batch{}, ErrInvalidNetwork 36 } 37 38 timestamp := time.Now().UTC().Truncate(time.Second) 39 result := model.Batch{ 40 Timestamp: timestamp, 41 ExecuteAfter: timestamp.Add(DefaultBatchExecutionDelay), 42 Capacity: DefaultBatchCapacity, 43 Network: network, 44 Data: data, 45 } 46 err := gdb.Create(&result).Error 47 if err != nil { 48 return model.Batch{}, err 49 } 50 51 err = AddWithdrawToBatch(db, result.ID, withdraws...) 52 if err != nil { 53 return model.Batch{}, err 54 } 55 56 return result, nil 57 } 58 59 func GetBatch(db database.Context, ID model.BatchID) (model.Batch, error) { 60 gdb := db.DB().(*gorm.DB) 61 if db == nil { 62 return model.Batch{}, database.ErrInvalidDatabase 63 } 64 65 if ID == 0 { 66 return model.Batch{}, ErrInvalidBatchID 67 } 68 69 var result model.Batch 70 err := gdb. 71 Where(&model.Batch{ID: ID}). 72 First(&result).Error 73 if err != nil { 74 return model.Batch{}, err 75 } 76 77 return result, nil 78 } 79 80 func FetchBatchReady(db database.Context) ([]model.Batch, error) { 81 gdb := db.DB().(*gorm.DB) 82 if gdb == nil { 83 return nil, database.ErrInvalidDatabase 84 } 85 86 subQueryInfo := gdb.Model(&model.BatchInfo{}). 87 Where(model.BatchInfo{ 88 Status: model.BatchStatusCreated, 89 }). 90 SubQuery() 91 92 subQueryLast := gdb.Model(&model.BatchInfo{}). 93 Select("MAX(id)"). 94 Group("batch_id"). 95 SubQuery() 96 97 var list []*model.Batch 98 err := gdb.Model(&model.Batch{}). 99 Joins("JOIN (?) AS i ON batch.id = i.batch_id", subQueryInfo). 100 Where("i.id IN (?)", subQueryLast). 101 Where("batch.execute_after <= ?", time.Now().UTC().Truncate(time.Second)). 102 Order("batch.id ASC"). 103 Find(&list).Error 104 105 if err != nil && err != gorm.ErrRecordNotFound { 106 return nil, err 107 } 108 return convertBatchList(list), nil 109 } 110 111 func FetchBatchByLastStatus(db database.Context, status model.BatchStatus) ([]model.Batch, error) { 112 gdb := db.DB().(*gorm.DB) 113 if gdb == nil { 114 return nil, database.ErrInvalidDatabase 115 } 116 117 if len(status) == 0 { 118 return nil, ErrInvalidBatchStatus 119 } 120 121 subQueryInfo := gdb.Model(&model.BatchInfo{}). 122 Where(model.BatchInfo{ 123 Status: status, 124 }). 125 SubQuery() 126 127 subQueryLast := gdb.Model(&model.BatchInfo{}). 128 Select("MAX(id)"). 129 Group("batch_id"). 130 SubQuery() 131 132 var list []*model.Batch 133 err := gdb.Model(&model.Batch{}). 134 Joins("JOIN (?) AS i ON batch.id = i.batch_id", subQueryInfo). 135 Where("i.id IN (?)", subQueryLast). 136 Order("batch.id ASC"). 137 Find(&list).Error 138 139 if err != nil && err != gorm.ErrRecordNotFound { 140 return nil, err 141 } 142 return convertBatchList(list), nil 143 } 144 145 func ListBatchNetworksByStatus(db database.Context, status model.BatchStatus) ([]model.BatchNetwork, error) { 146 gdb := db.DB().(*gorm.DB) 147 if db == nil { 148 return nil, database.ErrInvalidDatabase 149 } 150 151 if len(status) == 0 { 152 return nil, ErrInvalidWithdrawStatus 153 } 154 155 subQueryInfo := gdb.Model(&model.BatchInfo{}). 156 Where(model.BatchInfo{ 157 Status: status, 158 }). 159 SubQuery() 160 161 var list []*model.Batch 162 err := gdb.Model(&model.Batch{}). 163 Select("network"). 164 Joins("JOIN (?) AS i ON batch.id = i.batch_id", subQueryInfo). 165 Group("network"). 166 Order("batch.id ASC"). 167 Find(&list).Error 168 169 if err != nil && err != gorm.ErrRecordNotFound { 170 return nil, err 171 } 172 173 return convertBatchNetworkList(list), nil 174 } 175 176 type BatchInfos struct { 177 Count int 178 Active int 179 } 180 181 func BatchsInfos(db database.Context) (BatchInfos, error) { 182 gdb := db.DB().(*gorm.DB) 183 if gdb == nil { 184 return BatchInfos{}, database.ErrInvalidDatabase 185 } 186 187 var totalBatchs int64 188 err := gdb.Model(&model.Batch{}). 189 Count(&totalBatchs).Error 190 if err != nil { 191 return BatchInfos{}, err 192 } 193 194 subQueryLast := gdb.Model(&model.BatchInfo{}). 195 Select("MAX(id)"). 196 Group("batch_id"). 197 SubQuery() 198 199 var activeBatchs int64 200 err = gdb.Model(&model.BatchInfo{}). 201 Where("id IN (?)", subQueryLast). 202 Where("status <> ?", model.BatchStatusSettled). 203 Count(&activeBatchs).Error 204 if err != nil { 205 return BatchInfos{}, err 206 } 207 208 return BatchInfos{ 209 Count: int(totalBatchs), 210 Active: int(activeBatchs), 211 }, nil 212 } 213 214 func convertBatchList(list []*model.Batch) []model.Batch { 215 var result []model.Batch 216 for _, curr := range list { 217 if curr != nil { 218 result = append(result, *curr) 219 } 220 } 221 222 return result[:] 223 } 224 225 func convertBatchNetworkList(list []*model.Batch) []model.BatchNetwork { 226 var result []model.BatchNetwork 227 for _, curr := range list { 228 if curr != nil { 229 result = append(result, curr.Network) 230 } 231 } 232 233 return result[:] 234 }