You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
94 lines
2.0 KiB
94 lines
2.0 KiB
package balance |
|
|
|
import ( |
|
"github.com/emirpasic/gods/maps/treemap" |
|
"sync" |
|
"sync/atomic" |
|
"texas-poker-bk/internal/dao" |
|
"texas-poker-bk/internal/model/entity" |
|
"texas-poker-bk/tool/async" |
|
) |
|
|
|
var ( |
|
AsyncPersist *balancePersist |
|
) |
|
|
|
func init() { |
|
AsyncPersist = &balancePersist{} |
|
AsyncPersist.init() |
|
} |
|
|
|
// balancePersist 账户金额持久化 |
|
// TODO Persist() 先写log文件后return, 宕机后从log文件恢复 |
|
type balancePersist struct { |
|
// 待持久化用户id列表 |
|
// idQueue []int32 |
|
consuming *atomic.Bool |
|
counter *atomic.Int64 |
|
idQueue *treemap.Map |
|
// accountBalance 存储账户最新金额 |
|
//accountBalance *cache.Cache |
|
balanceMap map[int64]int32 |
|
executor *async.ConcurrentLimiter |
|
lock *sync.RWMutex |
|
} |
|
|
|
func (b *balancePersist) init() { |
|
b.consuming = &atomic.Bool{} |
|
b.counter = &atomic.Int64{} |
|
b.idQueue = treemap.NewWithIntComparator() |
|
//b.accountBalance = cache.New(cache.DefaultExpiration, cache.DefaultExpiration) |
|
b.balanceMap = make(map[int64]int32, 64) |
|
b.executor = async.NewConcurrentLimiter(8, 32) |
|
b.lock = &sync.RWMutex{} |
|
} |
|
|
|
func (b *balancePersist) goConsumer() { |
|
if !b.consuming.CompareAndSwap(false, true) { |
|
return |
|
} |
|
go func() { |
|
for { |
|
accountId, balance := b.next() |
|
if accountId == -1 { |
|
b.consuming.Store(false) |
|
return |
|
} |
|
b.executor.Run(func() { |
|
dao.UserDao.DB.Model(&entity.User{}). |
|
Where("id = ?", accountId). |
|
Update("balance", balance) |
|
}) |
|
} |
|
}() |
|
} |
|
|
|
func (b *balancePersist) Persist(accountId int64, balance int32) { |
|
defer b.goConsumer() |
|
b.lock.Lock() |
|
defer b.lock.Unlock() |
|
|
|
b.idQueue.Put(int(b.counter.Add(1)), accountId) |
|
b.balanceMap[accountId] = balance |
|
} |
|
|
|
func (b *balancePersist) next() (int64, int32) { |
|
b.lock.Lock() |
|
defer b.lock.Unlock() |
|
|
|
k, id := b.idQueue.Min() |
|
if k == 0 || k == nil { |
|
return -1, -1 |
|
} |
|
accountId, ok := id.(int64) |
|
if !ok { |
|
return -1, -1 |
|
} |
|
balance, ok := b.balanceMap[accountId] |
|
if !ok { |
|
return -1, -1 |
|
} |
|
b.idQueue.Remove(k) |
|
delete(b.balanceMap, accountId) |
|
return accountId, balance |
|
}
|
|
|