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 { | ... | ... |