Commit 8c62bdfa authored by vicotor's avatar vicotor

add moulti routine for handle group

parent e75eaf7e
......@@ -8,10 +8,12 @@ import (
)
type CacheData struct {
rdb *goredislib.Client
pathLru *lru.Cache
ctx context.Context
cancel context.CancelFunc
rdb *goredislib.Client
pathLru *lru.Cache
ctx context.Context
cancel context.CancelFunc
maxRoutine int
taskChan chan QueryParam
taskType model.TaskTypeRepository
userRepo model.UserRepository
......@@ -19,17 +21,33 @@ type CacheData struct {
userAndTaskRepo model.UserLevelTaskTypeRepository
}
func NewCacheData(ctx context.Context, options goredislib.Options) *CacheData {
rdb := goredislib.NewClient(&options)
type RedisConnParam struct {
Addr string
Password string
DbIndex int
}
func NewCacheData(ctx context.Context, options RedisConnParam, mysqlConfig model.DbConfig) *CacheData {
model.DbInit(mysqlConfig)
rdb := goredislib.NewClient(&goredislib.Options{
Addr: options.Addr,
Password: options.Password,
DB: options.DbIndex,
PoolSize: 100,
})
pathLru, _ := lru.New(10000)
cache := &CacheData{
rdb: rdb,
pathLru: pathLru,
taskChan: make(chan QueryParam, 10000),
taskType: model.NewTaskTypeRepository(),
userRepo: model.NewUserRepository(),
userLevel: model.NewUserLevelRepository(),
userAndTaskRepo: model.NewUserLevelTaskTypeRepository(),
}
cache.ctx, cache.cancel = context.WithCancel(ctx)
for i := 0; i < cache.maxRoutine; i++ {
go cache.queryRoutine()
}
return cache
}
......@@ -3,6 +3,7 @@ package cachedata
import "errors"
var (
ErrInvalidParam = errors.New("invalid param")
ErrNotExist = errors.New("not exist")
ErrUserDeleted = errors.New("user is deleted")
ErrWaitLockTimeout = errors.New("wait lock timeout")
......
......@@ -9,6 +9,49 @@ import (
"time"
)
type QueryResult struct {
Task *model.TaskType
Error error
}
type QueryParam struct {
path string
uid int64
result chan QueryResult
}
func (c *CacheData) queryRoutine() {
for {
select {
case <-c.ctx.Done():
return
case param := <-c.taskChan:
c.doQuery(param.path, param.uid, param.result)
}
}
}
func (c *CacheData) MQuery(paths []string, uids []int64) (chan QueryResult, error) {
if len(paths) != len(uids) {
return nil, ErrInvalidParam
}
result := make(chan QueryResult, len(paths))
for i := 0; i < len(paths); i++ {
c.taskChan <- QueryParam{path: paths[i], uid: uids[i]}
}
return result, nil
}
func (c *CacheData) doQuery(path string, uid int64, result chan QueryResult) {
task, err := c.Query(path, uid)
select {
case result <- QueryResult{Task: task, Error: err}:
default:
log.Errorf("failed to send query result to channel")
}
}
func (c *CacheData) Query(path string, uid int64) (*model.TaskType, error) {
locked, release, _ := c.getUserLockWithRetry(uid, USER_INFO_LOCK_DURATION*10)
if !locked {
......@@ -53,7 +96,8 @@ func (c *CacheData) Query(path string, uid int64) (*model.TaskType, error) {
return nil, err
}
if passed {
// todo: cost a free time.
// cost a free time.
c.costFreeTime(uid, user, userLevel, task, userLevelAndTaskType)
return task, nil
}
// b. continue check balance is enough for task.Fee
......@@ -63,7 +107,8 @@ func (c *CacheData) Query(path string, uid int64) (*model.TaskType, error) {
return nil, err
}
if passed {
// todo: cost charge.
// cost charge.
c.costCharge(uid, task.Price)
return task, nil
}
......
......@@ -7,16 +7,16 @@ require (
github.com/go-sql-driver/mysql v1.7.1
github.com/gomodule/redigo v2.0.0+incompatible
github.com/google/uuid v1.5.0
github.com/hashicorp/golang-lru v0.5.4
github.com/redis/go-redis/v9 v9.4.0
github.com/stretchr/testify v1.7.0
github.com/sirupsen/logrus v1.4.2
)
require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/konsorten/go-windows-terminal-sequences v1.0.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
github.com/stretchr/testify v1.7.0 // indirect
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 // indirect
)
......@@ -70,11 +70,11 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/ledisdb/ledisdb v0.0.0-20200510135210-d35789ec47e6/go.mod h1:n931TsDuKuq+uX4v1fulaMbA/7ZLLhjc85h7chZGBCQ=
github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
......@@ -87,7 +87,6 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
......@@ -119,6 +118,7 @@ github.com/siddontang/go v0.0.0-20170517070808-cb568a3e5cc0/go.mod h1:3yhqj7WBBf
github.com/siddontang/goredis v0.0.0-20150324035039-760763f78400/go.mod h1:DDcKzU3qCuvj/tPnimWSsZZzvk9qvkvrIL5naVBPh5s=
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec/go.mod h1:QBvMkMya+gXctz3kmljlUCu/yB3GZ6oee+dUozsezQE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
......@@ -153,6 +153,7 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
......@@ -165,7 +166,6 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
......
This diff is collapsed.
package payment
import (
"context"
"fmt"
"github.com/stretchr/testify/assert"
"testing"
)
func TestPayment(t *testing.T) {
// Initialize a new Payment instance
p := NewPayment(RedisConnParam{
Addr: "127.0.0.1:6379",
Password: "123456",
DbIndex: 0,
})
t.Run("Test Balance", func(t *testing.T) {
// Test IncrBalance
_, err := p.IncrBalance(context.Background(), "testuser", 100)
assert.NoError(t, err)
// Test GetBalance
balance, err := p.GetBalance(context.Background(), "testuser")
assert.NoError(t, err)
assert.Equal(t, int64(100), balance)
// Test DecrBalance
_, err = p.DecrBalance(context.Background(), "testuser", 50)
assert.NoError(t, err)
})
t.Run("Test Charge", func(t *testing.T) {
// Test IncrCharge
_, err := p.IncrCharge(context.Background(), "testuser", 200)
assert.NoError(t, err)
// Test GetCharge
charge, err := p.GetCharge(context.Background(), "testuser")
assert.NoError(t, err)
assert.Equal(t, int64(200), charge)
// Test DecrCharge
_, err = p.DecrCharge(context.Background(), "testuser", 100)
assert.NoError(t, err)
})
t.Run("Test Credits", func(t *testing.T) {
// Test IncrCredits
_, err := p.IncrCredits(context.Background(), "testuser", 300)
assert.NoError(t, err)
// Test GetCredits
credits, err := p.GetCredits(context.Background(), "testuser")
assert.NoError(t, err)
assert.Equal(t, int64(300), credits)
// Test DecrCredits
_, err = p.DecrCredits(context.Background(), "testuser", 150)
assert.NoError(t, err)
})
// Close the Payment instance
err := p.Close()
assert.NoError(t, err)
}
// add benchmark test for IncrBalance
func BenchmarkPaymentIncrBalance(b *testing.B) {
p := NewPayment(RedisConnParam{
Addr: "127.0.0.1:6379",
Password: "123456",
DbIndex: 0,
})
defer p.Close()
// run the IncrBalance function b.N times with different uid
for n := 0; n < b.N; n++ {
uid := fmt.Sprintf("11%d", n)
_, err := p.IncrBalance(context.Background(), uid, 100)
if err != nil {
b.Error(err)
}
}
}
package redisService
import goredislib "github.com/redis/go-redis/v9"
func GetRedis(param goredislib.Options) *goredislib.Client {
return goredislib.NewClient(&param)
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment