Commit 8aaf28ddf943150f5ba4f972303f6d78ad112419
1 parent
92131fd9
fix: 修复gm系统修改role数据带来的数据竞争
Showing
6 changed files
with
71 additions
and
30 deletions
 
Show diff stats
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 { | ... | ... |