Commit 8aaf28ddf943150f5ba4f972303f6d78ad112419

Authored by zhangqijia
1 parent 92131fd9

fix: 修复gm系统修改role数据带来的数据竞争

cmd/gameserver/action/GmAction.go
1 1 package action
2 2  
3 3 import (
4   - "pro2d/common"
5 4 "pro2d/common/components"
6 5 "pro2d/common/logger"
7 6 "pro2d/models"
... ... @@ -11,23 +10,9 @@ import (
11 10 type GmAction struct {
12 11 }
13 12  
14   -func (gm *GmAction) AddExp(properties map[string]interface{}) int {
15   - r := properties[common.Role_]
16   - c := properties[common.Conn_]
17   -
18   - role := r.(*models.RoleModel)
19   - var conn components.IConnection
20   - if c == nil {
21   - conn = nil
22   - } else {
23   - conn = c.(components.IConnection)
24   - }
25   -
  13 +func (gm *GmAction) AddExp(conn components.IConnection, role *models.RoleModel, properties map[string]interface{}) int {
26 14 logger.Debug(properties)
27 15 exp, _ := strconv.Atoi(properties["exp"].(string))
28   - logger.Debug("update before id: %s, exp: %d", role.Role.Id, role.Role.Exp)
29   - role.Role.Exp += int64(exp)
30   - role.UpdateProperty(conn, "exp", role.Role.Exp, true)
31   - logger.Debug("update after id: %s, exp: %d", role.Role.Id, role.Role.Exp)
  16 + role.IncrPropertyChan(conn, "exp", int64(exp))
32 17 return 0
33 18 }
... ...
cmd/gameserver/service/gm.go
... ... @@ -65,13 +65,9 @@ func (s *GmServer) HandlerFuncObj(tvl, obj reflect.Value) gin.HandlerFunc {
65 65 role.LoadAll()
66 66 }
67 67  
68   - properties["_conn"] = conn
69   - properties["_role"] = role
70   -
71 68 //func start
72   - v := tvl.Call([]reflect.Value{obj, reflect.ValueOf(properties)})
73   -
74   - role.SaveRoleData(0)
  69 + v := tvl.Call([]reflect.Value{obj, reflect.ValueOf(conn), reflect.ValueOf(role), reflect.ValueOf(properties)})
  70 + role.SaveRoleDataChan(conn, 0)
75 71  
76 72 if len(v) != 1 {
77 73 c.JSON(http.StatusNotFound, gin.H{"code": -100, "message": "request param len is error"})
... ...
common/components/conn.go
... ... @@ -17,12 +17,13 @@ type Connection struct {
17 17 splitter ISplitter
18 18 Id uint32
19 19  
20   - scanner *bufio.Scanner
21   - writer *bufio.Writer
22   - WBuffer chan []byte
23   - Quit chan *Connection
24   - readFunc chan func()
25   - timerFunc chan func()
  20 + scanner *bufio.Scanner
  21 + writer *bufio.Writer
  22 + WBuffer chan []byte
  23 + Quit chan *Connection
  24 + readFunc chan func()
  25 + timerFunc chan func()
  26 + customizeFunc chan func()
26 27  
27 28 messageCallback MessageCallback
28 29 connectionCallback ConnectionCallback
... ... @@ -66,6 +67,9 @@ func (c *Connection) reset() {
66 67 if c.timerFunc == nil {
67 68 c.timerFunc = make(chan func(), 10)
68 69 }
  70 + if c.customizeFunc == nil {
  71 + c.customizeFunc = make(chan func(), 10)
  72 + }
69 73  
70 74 //c.connectionCallback = c.defaultConnectionCallback
71 75 //c.messageCallback = c.defaultMessageCallback
... ... @@ -136,6 +140,10 @@ func (c *Connection) Send(errCode int32, cmd uint32, data []byte) error {
136 140 }
137 141 }
138 142  
  143 +func (c *Connection) CustomChan() chan<- func() {
  144 + return c.customizeFunc
  145 +}
  146 +
139 147 func (c *Connection) defaultConnectionCallback(conn IConnection) {
140 148 }
141 149  
... ... @@ -206,6 +214,8 @@ func (c *Connection) listen() {
206 214 timerFunc()
207 215 case readFunc := <-c.readFunc:
208 216 readFunc()
  217 + case customizeFunc := <-c.customizeFunc:
  218 + customizeFunc()
209 219 case <-c.Quit:
210 220 return
211 221 }
... ...
common/components/icompontents.go
... ... @@ -51,6 +51,7 @@ type (
51 51 Start()
52 52 Stop()
53 53 Send(errCode int32, cmd uint32, b []byte) error
  54 + CustomChan() chan<- func()
54 55  
55 56 SetConnectionCallback(ConnectionCallback)
56 57 SetMessageCallback(MessageCallback)
... ... @@ -149,6 +150,7 @@ type (
149 150  
150 151 SetProperty(key string, val interface{})
151 152 SetProperties(properties map[string]interface{})
  153 + IncrProperty(key string, val int64)
152 154 ParseFields(message protoreflect.Message, properties map[string]interface{}) []int32
153 155 }
154 156 )
... ...
models/role.go
... ... @@ -23,7 +23,7 @@ type RoleModel struct {
23 23 func RoleExistByUid(uid string) *RoleModel {
24 24 data := &pb.Role{Uid: uid}
25 25  
26   - if err := mongoproxy.FindOne(mongoproxy.GetBsonM("uid", uid), data); err != nil {
  26 + if err := mongoproxy.FindOne(mongoproxy.GetCollName(data), mongoproxy.GetBsonM("uid", uid), data); err != nil {
27 27 logger.Error("Role not exist err: %v", err)
28 28 return nil
29 29 }
... ... @@ -231,3 +231,35 @@ func (m *RoleModel) SaveRoleData(now int64) {
231 231 }
232 232 }
233 233 }
  234 +
  235 +func (m *RoleModel) IncrPropertyChan(conn components.IConnection, key string, val int64) {
  236 + if conn != nil {
  237 + conn.CustomChan() <- func() {
  238 + m.IncrProperty(key, val)
  239 + }
  240 + } else {
  241 + m.IncrProperty(key, val)
  242 + }
  243 +
  244 +}
  245 +
  246 +func (m *RoleModel) UpdatePropertyChan(conn components.IConnection, key string, val interface{}, notify bool) {
  247 + if conn != nil {
  248 + conn.CustomChan() <- func() {
  249 + m.UpdateProperties(conn, map[string]interface{}{key: val}, notify)
  250 + }
  251 + } else {
  252 + m.UpdateProperties(conn, map[string]interface{}{key: val}, notify)
  253 + }
  254 +}
  255 +
  256 +func (m *RoleModel) SaveRoleDataChan(conn components.IConnection, now int64) {
  257 + if conn != nil {
  258 + conn.CustomChan() <- func() {
  259 + m.SaveRoleData(now)
  260 + }
  261 + } else {
  262 + m.SaveRoleData(now)
  263 + }
  264 +
  265 +}
... ...
models/schema.go
... ... @@ -153,6 +153,22 @@ func (s *Schema) SetProperties(properties map[string]interface{}) {
153 153 }
154 154 }
155 155  
  156 +func (s *Schema) IncrProperty(key string, val int64) {
  157 + idx, ok := s.reflectIndex[strings.ToLower(key)]
  158 + if !ok {
  159 + return
  160 + }
  161 + field := s.reflectValue.Field(idx)
  162 + var v int64
  163 + switch field.Kind() {
  164 + case reflect.Int64:
  165 + v = field.Int() + val
  166 + case reflect.Int:
  167 + v = field.Int() + val
  168 + }
  169 + s.SetProperty(key, v)
  170 +}
  171 +
156 172 func (s *Schema) ParseFields(message protoreflect.Message, properties map[string]interface{}) []int32 {
157 173 ids := make([]int32, 0, len(properties))
158 174 for k, v := range properties {
... ...