gob 등록

This commit is contained in:
2023-07-17 17:47:07 +09:00
parent 67cca13326
commit ba61a11659
7 changed files with 125 additions and 39 deletions

View File

@ -2,7 +2,10 @@ package core
import (
"context"
"encoding/gob"
"encoding/json"
"errors"
"fmt"
"net/url"
"time"
@ -18,6 +21,11 @@ import (
type accountID = primitive.ObjectID
type ticketID = primitive.ObjectID
type groupID = primitive.ObjectID
type Body = bson.M
func init() {
gob.Register(memberDoc{})
}
func makeTid(gid groupID, in accountID) string {
var out primitive.ObjectID
@ -28,32 +36,36 @@ func makeTid(gid groupID, in accountID) string {
}
type Invitation struct {
GroupID groupID `json:"gid"`
TicketID string `json:"tid"`
Inviter bson.M `json:"inviter"`
ExpireAtUTC int64 `json:"expire_at_utc"`
GroupID groupID `json:"_gid"`
TicketID string `json:"_tid"`
Inviter bson.M `json:"_inviter"` // memberDoc.Body
ExpireAtUTC int64 `json:"_expire_at_utc"`
}
// 플레이어한테 공유하는 멤버 정보
type memberDoc struct {
Body bson.M `json:"body"`
Invite bool `json:"invite"`
InviteExpire int64 `json:"invite_exp"`
Body `json:",inline"`
Invite bool `json:"_invite"`
InviteExpire int64 `json:"_invite_exp"`
}
type GroupDocBody = bson.M
type InvitationFail bson.M
type groupDoc struct {
Body GroupDocBody `json:"body"`
Members map[string]*memberDoc `json:"members"`
InCharge string `json:"incharge"`
Body `json:",inline"`
Members map[string]*memberDoc `json:"_members"`
InCharge string `json:"_incharge"`
rh *RedisonHandler
id groupID
idhex string
}
type groupDocWithId struct {
*groupDoc `json:",inline"`
Gid string `json:"_gid"`
}
func (gd *groupDoc) strid() string {
if len(gd.idhex) == 0 {
gd.idhex = gd.id.Hex()
@ -75,11 +87,11 @@ func (gd *groupDoc) mid(tid string) accountID {
}
func (gd *groupDoc) addInvite(inviteeDoc bson.M, ttl time.Duration, max int) (*memberDoc, error) {
mid := inviteeDoc["_mid"].(accountID)
body := inviteeDoc["body"].(bson.M)
targetmid := inviteeDoc["_mid"].(accountID)
targetbody := inviteeDoc["body"].(bson.M)
// 초대 가능한 빈 자리가 있나
tids, err := gd.rh.JSONObjKeys(gd.strid(), "$.members")
tids, err := gd.rh.JSONObjKeys(gd.strid(), "$._members")
if err != nil {
return nil, err
}
@ -87,19 +99,21 @@ func (gd *groupDoc) addInvite(inviteeDoc bson.M, ttl time.Duration, max int) (*m
now := time.Now().UTC()
createNewDoc := func() *memberDoc {
return &memberDoc{
Body: body,
Body: targetbody,
Invite: true,
InviteExpire: now.Add(ttl).Unix(),
}
}
newtid := gd.tid(targetmid)
if len(tids) < max {
// 빈자리를 찾았다.
newdoc := createNewDoc()
_, err := gd.rh.JSONSet(gd.strid(), "$.members."+gd.tid(mid), newdoc)
_, err := gd.rh.JSONSet(gd.strid(), "$._members."+newtid, newdoc)
return newdoc, err
}
expires, err := gd.rh.JSONGetInt64(gd.strid(), "$.members..invite_exp")
expires, err := gd.rh.JSONGetInt64(gd.strid(), "$._members.._invite_exp")
if err != nil {
return nil, err
}
@ -108,7 +122,7 @@ func (gd *groupDoc) addInvite(inviteeDoc bson.M, ttl time.Duration, max int) (*m
for i, expire := range expires {
if expire < now.Unix() {
// 만료된 초대가 있네? 지우자
delpaths = append(delpaths, "$.members."+tids[i])
delpaths = append(delpaths, "$._members."+tids[i])
}
}
@ -122,18 +136,18 @@ func (gd *groupDoc) addInvite(inviteeDoc bson.M, ttl time.Duration, max int) (*m
}
newdoc := createNewDoc()
_, err = gd.rh.JSONSet(gd.strid(), "$.members."+mid.Hex(), newdoc)
_, err = gd.rh.JSONSet(gd.strid(), "$._members."+newtid, newdoc)
return newdoc, err
}
func (gd *groupDoc) addMember(mid accountID, doc bson.M) (*memberDoc, error) {
memdoc := &memberDoc{
Body: doc,
Invite: false,
InviteExpire: 0,
Body: doc,
}
if _, err := gd.rh.JSONSet(gd.strid(), "$.members."+gd.tid(mid), memdoc, SetOptionXX); err != nil {
if _, err := gd.rh.JSONSet(gd.strid(), "$._members."+gd.tid(mid), memdoc, SetOptionXX); err != nil {
return nil, err
}
@ -141,7 +155,7 @@ func (gd *groupDoc) addMember(mid accountID, doc bson.M) (*memberDoc, error) {
}
func (gd *groupDoc) removeMember(mid accountID) error {
_, err := gd.rh.JSONDel(gd.strid(), "$.members."+gd.tid(mid))
_, err := gd.rh.JSONDel(gd.strid(), "$._members."+gd.tid(mid))
return err
}
@ -265,6 +279,15 @@ func (gm *groupInMemory) Invite(gid groupID, mid accountID, inviterDoc bson.M, i
}
// 내가 wshandler room에 입장
gm.sendEnterRoomMessage(gid, mid)
gm.sendUpstreamMessage(&wshandler.UpstreamMessage{
Target: "@" + mid.Hex(),
Body: groupDocWithId{
groupDoc: gd,
Gid: gd.strid(),
},
Tag: []string{"GroupDocFull"},
})
}
newdoc, err := gd.addInvite(inviteeDoc, time.Duration(gm.InviteExpire+1)*time.Second, gm.MaxMember)
@ -273,10 +296,11 @@ func (gm *groupInMemory) Invite(gid groupID, mid accountID, inviterDoc bson.M, i
}
// 초대 중 표시
_, err = gm.rh.SetNX(gm.rh.ctx, targetid.Hex(), mid.Hex(), time.Duration(gm.InviteExpire)*time.Second).Result()
success, err := gm.rh.SetNX(gm.rh.ctx, targetid.Hex(), mid.Hex(), time.Duration(gm.InviteExpire)*time.Second).Result()
if err != nil {
return "", err
}
logger.Println("invitation key :", targetid.Hex(), success)
// invitee에게 알림
gm.sendUpstreamMessage(&wshandler.UpstreamMessage{
@ -300,6 +324,8 @@ func (gm *groupInMemory) CancelInvitation(gid groupID, tid ticketID) error {
var errInvitationExpired = errors.New("invitation is already expired")
func (gm *groupInMemory) AcceptInvitation(gid groupID, mid accountID, member bson.M) error {
logger.Println("accept invitation key :", mid.Hex())
cnt, err := gm.rh.Del(gm.rh.ctx, mid.Hex()).Result()
if err != nil {
return err
@ -314,9 +340,39 @@ func (gm *groupInMemory) AcceptInvitation(gid groupID, mid accountID, member bso
rh: gm.rh,
}
_, err = gd.addMember(mid, member)
memberDoc, err := gd.addMember(mid, member)
if err == nil {
// 기존 멤버에게 새 멤버를 알림
gm.sendUpstreamMessage(&wshandler.UpstreamMessage{
Target: "#" + gid.Hex(),
Body: map[string]any{
gd.tid(mid): memberDoc,
},
Tag: []string{"MemberDocFull"},
})
gm.sendEnterRoomMessage(gid, mid)
// 새 멤버에 그룹 전체를 알림
full, err := gm.rh.JSONGet(gd.strid(), "$")
if err != nil {
return err
}
logger.Println(full)
var temp []groupDoc
err = json.Unmarshal([]byte(full.(string)), &temp)
if err != nil {
return err
}
gm.sendUpstreamMessage(&wshandler.UpstreamMessage{
Target: "@" + mid.Hex(),
Body: groupDocWithId{
groupDoc: &temp[0],
Gid: gd.strid(),
},
Tag: []string{"GroupDocFull"},
})
}
// 실패
@ -353,11 +409,11 @@ func (gm *groupInMemory) Leave(gid groupID, mid accountID) error {
return err
}
// 나한테는 빈 FullGroupDoc을 보낸다.
// 나한테는 빈 GroupDocFull을 보낸다. 그러면 지워짐
gm.sendUpstreamMessage(&wshandler.UpstreamMessage{
Target: "@" + mid.Hex(),
Body: bson.M{"gid": gid},
Tag: []string{"FullGroupDoc", gid.Hex()},
Tag: []string{"GroupDocFull", gid.Hex()},
})
gm.sendLeaveRoomMessage(gid, mid)
@ -369,7 +425,8 @@ func (gm *groupInMemory) UpdateMemberDocument(gid groupID, mid accountID, doc bs
id: gid,
rh: gm.rh,
}
_, err := gm.rh.JSONSet(gd.strid(), "$.members."+gd.tid(mid)+".body", doc, SetOptionXX)
prefixPath := fmt.Sprintf("$._members.%s.", gd.tid(mid))
err := gm.rh.JSONMSetRel(gd.strid(), prefixPath, doc)
if err != nil {
return err
}
@ -379,7 +436,7 @@ func (gm *groupInMemory) UpdateMemberDocument(gid groupID, mid accountID, doc bs
Body: map[string]any{
gd.tid(mid): doc,
},
Tag: []string{"GroupDocBody"},
Tag: []string{"MemberDocFragment"},
})
return nil
@ -389,13 +446,24 @@ func (gm *groupInMemory) Dismiss(gid groupID) error {
return nil
}
func (gm *groupInMemory) UpdateGroupDocument(gid groupID, body []byte) error {
func (gm *groupInMemory) UpdateGroupDocument(gid groupID, frag bson.M) error {
gd := groupDoc{
id: gid,
rh: gm.rh,
}
_, err := gm.rh.JSONSet(gd.strid(), "$.members.body", body, SetOptionXX)
return err
if err := gm.rh.JSONMSetRel(gd.strid(), "$.", frag); err != nil {
return err
}
// 업데이트 알림
gm.sendUpstreamMessage(&wshandler.UpstreamMessage{
Target: "#" + gid.Hex(),
Body: frag,
Tag: []string{"GroupDocFragment"},
})
return nil
}
func (cfg *groupConfig) prepareInMemory(ctx context.Context, typename string, sub *subTavern) (group, error) {