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 | package action | 1 | package action |
2 | 2 | ||
3 | import ( | 3 | import ( |
4 | - "pro2d/common" | ||
5 | "pro2d/common/components" | 4 | "pro2d/common/components" |
6 | "pro2d/common/logger" | 5 | "pro2d/common/logger" |
7 | "pro2d/models" | 6 | "pro2d/models" |
@@ -11,23 +10,9 @@ import ( | @@ -11,23 +10,9 @@ import ( | ||
11 | type GmAction struct { | 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 | logger.Debug(properties) | 14 | logger.Debug(properties) |
27 | exp, _ := strconv.Atoi(properties["exp"].(string)) | 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 | return 0 | 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,13 +65,9 @@ func (s *GmServer) HandlerFuncObj(tvl, obj reflect.Value) gin.HandlerFunc { | ||
65 | role.LoadAll() | 65 | role.LoadAll() |
66 | } | 66 | } |
67 | 67 | ||
68 | - properties["_conn"] = conn | ||
69 | - properties["_role"] = role | ||
70 | - | ||
71 | //func start | 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 | if len(v) != 1 { | 72 | if len(v) != 1 { |
77 | c.JSON(http.StatusNotFound, gin.H{"code": -100, "message": "request param len is error"}) | 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,12 +17,13 @@ type Connection struct { | ||
17 | splitter ISplitter | 17 | splitter ISplitter |
18 | Id uint32 | 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 | messageCallback MessageCallback | 28 | messageCallback MessageCallback |
28 | connectionCallback ConnectionCallback | 29 | connectionCallback ConnectionCallback |
@@ -66,6 +67,9 @@ func (c *Connection) reset() { | @@ -66,6 +67,9 @@ func (c *Connection) reset() { | ||
66 | if c.timerFunc == nil { | 67 | if c.timerFunc == nil { |
67 | c.timerFunc = make(chan func(), 10) | 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 | //c.connectionCallback = c.defaultConnectionCallback | 74 | //c.connectionCallback = c.defaultConnectionCallback |
71 | //c.messageCallback = c.defaultMessageCallback | 75 | //c.messageCallback = c.defaultMessageCallback |
@@ -136,6 +140,10 @@ func (c *Connection) Send(errCode int32, cmd uint32, data []byte) error { | @@ -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 | func (c *Connection) defaultConnectionCallback(conn IConnection) { | 147 | func (c *Connection) defaultConnectionCallback(conn IConnection) { |
140 | } | 148 | } |
141 | 149 | ||
@@ -206,6 +214,8 @@ func (c *Connection) listen() { | @@ -206,6 +214,8 @@ func (c *Connection) listen() { | ||
206 | timerFunc() | 214 | timerFunc() |
207 | case readFunc := <-c.readFunc: | 215 | case readFunc := <-c.readFunc: |
208 | readFunc() | 216 | readFunc() |
217 | + case customizeFunc := <-c.customizeFunc: | ||
218 | + customizeFunc() | ||
209 | case <-c.Quit: | 219 | case <-c.Quit: |
210 | return | 220 | return |
211 | } | 221 | } |
common/components/icompontents.go
@@ -51,6 +51,7 @@ type ( | @@ -51,6 +51,7 @@ type ( | ||
51 | Start() | 51 | Start() |
52 | Stop() | 52 | Stop() |
53 | Send(errCode int32, cmd uint32, b []byte) error | 53 | Send(errCode int32, cmd uint32, b []byte) error |
54 | + CustomChan() chan<- func() | ||
54 | 55 | ||
55 | SetConnectionCallback(ConnectionCallback) | 56 | SetConnectionCallback(ConnectionCallback) |
56 | SetMessageCallback(MessageCallback) | 57 | SetMessageCallback(MessageCallback) |
@@ -149,6 +150,7 @@ type ( | @@ -149,6 +150,7 @@ type ( | ||
149 | 150 | ||
150 | SetProperty(key string, val interface{}) | 151 | SetProperty(key string, val interface{}) |
151 | SetProperties(properties map[string]interface{}) | 152 | SetProperties(properties map[string]interface{}) |
153 | + IncrProperty(key string, val int64) | ||
152 | ParseFields(message protoreflect.Message, properties map[string]interface{}) []int32 | 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,7 +23,7 @@ type RoleModel struct { | ||
23 | func RoleExistByUid(uid string) *RoleModel { | 23 | func RoleExistByUid(uid string) *RoleModel { |
24 | data := &pb.Role{Uid: uid} | 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 | logger.Error("Role not exist err: %v", err) | 27 | logger.Error("Role not exist err: %v", err) |
28 | return nil | 28 | return nil |
29 | } | 29 | } |
@@ -231,3 +231,35 @@ func (m *RoleModel) SaveRoleData(now int64) { | @@ -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,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 | func (s *Schema) ParseFields(message protoreflect.Message, properties map[string]interface{}) []int32 { | 172 | func (s *Schema) ParseFields(message protoreflect.Message, properties map[string]interface{}) []int32 { |
157 | ids := make([]int32, 0, len(properties)) | 173 | ids := make([]int32, 0, len(properties)) |
158 | for k, v := range properties { | 174 | for k, v := range properties { |