diff --git a/core/apiimpl.go b/core/apiimpl.go index 13610d2..b784438 100644 --- a/core/apiimpl.go +++ b/core/apiimpl.go @@ -1,7 +1,6 @@ package core import ( - "encoding/json" "net/http" common "repositories.action2quare.com/ayo/gocommon" @@ -84,7 +83,7 @@ func (sub *subTavern) JoinGroup(w http.ResponseWriter, r *http.Request) { } if err == nil { - json.NewEncoder(w).Encode(map[string]string{ + writeBsonDoc(w, map[string]string{ "gid": gidobj.Hex(), "tid": tidobj.Hex(), }) @@ -195,9 +194,6 @@ func (sub *subTavern) AcceptInvitation(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusInternalServerError) return } - - // TODO : full group doc을 내려보냄 - // w.Write([]byte(gidbytes.Hex())) } func (sub *subTavern) DenyInvitation(w http.ResponseWriter, r *http.Request) { @@ -292,7 +288,7 @@ func (sub *subTavern) SearchGroup(w http.ResponseWriter, r *http.Request) { } if err := writeBsonArr(w, result); err != nil { - logger.Error("json marshal failed :", err) + logger.Error("bson marshal failed :", err) w.WriteHeader(http.StatusInternalServerError) return } @@ -369,7 +365,7 @@ func (sub *subTavern) QueryGroup(w http.ResponseWriter, r *http.Request) { } if err := writeBsonDoc(w, result); err != nil { - logger.Error("json marshal failed :", err) + logger.Error("bson marshal failed :", err) w.WriteHeader(http.StatusInternalServerError) return } @@ -486,8 +482,7 @@ func (sub *subTavern) UpdateGroupDocument(w http.ResponseWriter, r *http.Request } var frag bson.M - dec := json.NewDecoder(r.Body) - if err := dec.Decode(&frag); err != nil { + if err := readBsonDoc(r.Body, &frag); err != nil { logger.Error("UpdateGroupDocument failed. readBsonDoc err :", err) w.WriteHeader(http.StatusBadRequest) return @@ -499,3 +494,33 @@ func (sub *subTavern) UpdateGroupDocument(w http.ResponseWriter, r *http.Request return } } + +func (sub *subTavern) QueryGroupMembers(w http.ResponseWriter, r *http.Request) { + typename, _ := common.ReadStringFormValue(r.Form, "type") + group := sub.groups[typename] + if group == nil { + logger.Println("QueryGroupMembers failed. type is missing") + w.WriteHeader(http.StatusBadRequest) + return + } + + gid, ok := common.ReadObjectIDFormValue(r.Form, "gid") + if !ok { + logger.Println("QueryGroupMembers failed. gid is missing") + w.WriteHeader(http.StatusBadRequest) + return + } + + members, err := group.QueryGroupMembers(gid) + if err != nil { + logger.Error("QueryGroupMembers failed. group.QueryGroupMembers returns err :", err) + w.WriteHeader(http.StatusBadRequest) + return + } + + if err := writeBsonDoc(w, members); err != nil { + logger.Error("QueryGroupMembers failed. writeBsonDoc return err :", err) + w.WriteHeader(http.StatusInternalServerError) + return + } +} diff --git a/core/group.go b/core/group.go index 7ccade3..f5c3119 100644 --- a/core/group.go +++ b/core/group.go @@ -38,4 +38,5 @@ type group interface { UpdateMemberDocument(groupID primitive.ObjectID, memberID primitive.ObjectID, doc bson.M) error Dismiss(groupID primitive.ObjectID) error UpdateGroupDocument(groupID primitive.ObjectID, doc bson.M) error + QueryGroupMembers(groupID primitive.ObjectID) (bson.M, error) } diff --git a/core/group_memory.go b/core/group_memory.go index 31ba010..dc60261 100644 --- a/core/group_memory.go +++ b/core/group_memory.go @@ -54,36 +54,45 @@ type memberDoc struct { type InvitationFail bson.M type groupDoc struct { - Body bson.M `json:"_body"` - Members map[string]*memberDoc `json:"_members"` - InCharge string `json:"_incharge"` - Gid string `json:"_gid"` + Members map[string]any `json:"_members"` + InCharge string `json:"_incharge"` + Gid string `json:"_gid"` - rh *RedisonHandler + rh *gocommon.RedisonHandler id groupID } -func (p groupDoc) MarshalJSON() ([]byte, error) { - if len(p.Gid) == 0 { - p.Gid = p.id.Hex() +func (gd *groupDoc) loadMemberFull(tid string) (bson.M, error) { + full, err := gd.rh.JSONGet(gd.strid(), "$._members."+tid) + if err != nil { + return nil, err } - // Turn p into a map - type groupDoc_ groupDoc // prevent recursion - b, _ := json.Marshal(groupDoc_(p)) + bt := []byte(full.(string)) + bt = bt[1 : len(bt)-1] - var m map[string]json.RawMessage - _ = json.Unmarshal(b, &m) - - // Add tags to the map, possibly overriding struct fields - for k, v := range p.Body { - // if overriding struct fields is not acceptable: - // if _, ok := m[k]; ok { continue } - b, _ = json.Marshal(v) - m[k] = b + var doc bson.M + if err = json.Unmarshal(bt, &doc); err != nil { + return nil, err } - return json.Marshal(m) + return doc, nil +} + +func (gd *groupDoc) loadFull() (doc bson.M) { + // 새 멤버에 그룹 전체를 알림 + full, err := gd.rh.JSONGet(gd.strid(), "$") + if err == nil { + bt := []byte(full.(string)) + bt = bt[1 : len(bt)-1] + err = json.Unmarshal(bt, &doc) + if err != nil { + logger.Println("loadFull err :", err) + } + } else { + logger.Println("loadFull err :", err) + } + return } func (gd *groupDoc) strid() string { @@ -160,18 +169,19 @@ func (gd *groupDoc) addInvite(inviteeDoc bson.M, ttl time.Duration, max int) (*m return newdoc, err } -func (gd *groupDoc) addMember(mid accountID, doc bson.M) (*memberDoc, error) { - memdoc := &memberDoc{ - Body: doc, - Invite: false, - InviteExpire: 0, - } +func (gd *groupDoc) addMember(mid accountID, doc bson.M) (bson.M, error) { + tid := gd.tid(mid) + prefix := "$._members." + tid - if _, err := gd.rh.JSONSet(gd.strid(), "$._members."+gd.tid(mid), memdoc, SetOptionXX); err != nil { + if _, err := gd.rh.JSONMerge(gd.strid(), prefix+"._body", doc, gocommon.RedisonSetOptionXX); err != nil { return nil, err } - return memdoc, nil + if err := gd.rh.JSONMDel(gd.strid(), []string{prefix + "._invite", prefix + "._invite_exp"}); err != nil { + return nil, err + } + + return gd.loadMemberFull(tid) } func (gd *groupDoc) removeMember(mid accountID) error { @@ -179,21 +189,41 @@ func (gd *groupDoc) removeMember(mid accountID) error { return err } +func (gd *groupDoc) getMembers() (map[string]any, error) { + res, err := gd.rh.JSONGet(gd.strid(), "$._members") + if err != nil { + return nil, err + } + + var temp []map[string]any + err = json.Unmarshal([]byte(res.(string)), &temp) + if err != nil { + return nil, err + } + + out := make(map[string]any) + for k, v := range temp[0] { + body := v.(map[string]any)["_body"] + out[gd.mid(k).Hex()] = body + } + + return out, nil +} + type groupInMemory struct { *groupConfig sendUpstreamMessage func(*wshandler.UpstreamMessage) sendEnterRoomMessage func(groupID, accountID) sendLeaveRoomMessage func(groupID, accountID) - rh *RedisonHandler + rh *gocommon.RedisonHandler } func (gm *groupInMemory) createGroup(newid groupID, charge accountID, chargeDoc bson.M) (*groupDoc, error) { tid := makeTid(newid, charge) gd := &groupDoc{ - Body: bson.M{}, - Members: map[string]*memberDoc{ - tid: { + Members: map[string]any{ + tid: &memberDoc{ Body: chargeDoc, Invite: false, InviteExpire: 0, @@ -205,7 +235,7 @@ func (gm *groupInMemory) createGroup(newid groupID, charge accountID, chargeDoc id: newid, } - _, err := gm.rh.JSONSet(gd.strid(), "$", gd, SetOptionNX) + _, err := gm.rh.JSONSet(gd.strid(), "$", gd, gocommon.RedisonSetOptionNX) if err != nil { return nil, err } @@ -243,18 +273,36 @@ func (gm *groupInMemory) Candidate(gid groupID, mid accountID, doc bson.M) error var errGroupNotExist = errors.New("group does not exist") func (gm *groupInMemory) Join(gid groupID, mid accountID, doc bson.M) error { - group, err := gm.find(gid) + gd, err := gm.find(gid) if err != nil { return err } - if group == nil { + if gd == nil { // 그룹이 없다. 실패 return errGroupNotExist } // 내 정보 업데이트할 때에도 사용됨 - _, err = group.addMember(mid, doc) + if memdoc, err := gd.addMember(mid, doc); err == nil { + // 기존 유저에게 새 유저 알림 + gm.sendUpstreamMessage(&wshandler.UpstreamMessage{ + Target: "#" + gid.Hex(), + Body: map[string]any{ + gd.tid(mid): memdoc, + }, + Tag: []string{"MemberDocFull"}, + }) + + gm.sendEnterRoomMessage(gid, mid) + + // 새 멤버에 그룹 전체를 알림 + gm.sendUpstreamMessage(&wshandler.UpstreamMessage{ + Target: "@" + mid.Hex(), + Body: gd.loadFull(), + Tag: []string{"GroupDocFull"}, + }) + } return err } @@ -269,7 +317,7 @@ func (gm *groupInMemory) Invite(gid groupID, mid accountID, inviterDoc bson.M, i } // targetid에 초대한 mid가 들어있다. - already, err := gm.rh.Get(gm.rh.ctx, targetid.Hex()).Result() + already, err := gm.rh.Get(context.Background(), targetid.Hex()).Result() if err != nil && err != redis.Nil { return "", err } @@ -313,7 +361,7 @@ 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() + _, err = gm.rh.SetNX(context.Background(), targetid.Hex(), mid.Hex(), time.Duration(gm.InviteExpire)*time.Second).Result() if err != nil { return "", err } @@ -340,9 +388,7 @@ 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() + cnt, err := gm.rh.Del(context.Background(), mid.Hex()).Result() if err != nil { return err } @@ -351,7 +397,7 @@ func (gm *groupInMemory) AcceptInvitation(gid groupID, mid accountID, member bso return errInvitationExpired } - gd := groupDoc{ + gd := &groupDoc{ id: gid, rh: gm.rh, } @@ -366,25 +412,13 @@ func (gm *groupInMemory) AcceptInvitation(gid groupID, mid accountID, member bso }, Tag: []string{"MemberDocFull"}, }) + gm.sendEnterRoomMessage(gid, mid) // 새 멤버에 그룹 전체를 알림 - full, err := gm.rh.JSONGet(gd.strid(), "$") - if err != nil { - return err - } - - var temp []*groupDoc - err = json.Unmarshal([]byte(full.(string)), &temp) - if err != nil { - return err - } - - test, _ := json.Marshal(temp[0]) - logger.Println(string(test)) gm.sendUpstreamMessage(&wshandler.UpstreamMessage{ Target: "@" + mid.Hex(), - Body: temp[0], + Body: gd.loadFull(), Tag: []string{"GroupDocFull"}, }) } @@ -393,8 +427,16 @@ func (gm *groupInMemory) AcceptInvitation(gid groupID, mid accountID, member bso return err } +func (gm *groupInMemory) QueryGroupMembers(gid groupID) (bson.M, error) { + gd := groupDoc{ + id: gid, + rh: gm.rh, + } + return gd.getMembers() +} + func (gm *groupInMemory) DenyInvitation(gid groupID, mid accountID, tid ticketID) error { - gm.rh.Del(gm.rh.ctx, mid.Hex()).Result() + gm.rh.Del(context.Background(), mid.Hex()).Result() gd := groupDoc{ id: gid, rh: gm.rh, @@ -435,10 +477,11 @@ func (gm *groupInMemory) Leave(gid groupID, mid accountID) error { } func (gm *groupInMemory) UpdateMemberDocument(gid groupID, mid accountID, doc bson.M) error { - gd := groupDoc{ + gd := &groupDoc{ id: gid, rh: gm.rh, } + prefixPath := fmt.Sprintf("$._members.%s.", gd.tid(mid)) err := gm.rh.JSONMSetRel(gd.strid(), prefixPath, doc) if err != nil { @@ -494,7 +537,7 @@ func (cfg *groupConfig) prepareInMemory(ctx context.Context, typename string, su // 각 함수에서는 publish gm := &groupInMemory{ groupConfig: cfg, - rh: NewRedisonHandler(ctx, redisClient), + rh: gocommon.NewRedisonHandler(ctx, redisClient), sendUpstreamMessage: func(msg *wshandler.UpstreamMessage) { wsh.SendUpstreamMessage(region, msg) }, diff --git a/core/redison_handler.go b/core/redison_handler.go deleted file mode 100644 index 4e89b8d..0000000 --- a/core/redison_handler.go +++ /dev/null @@ -1,372 +0,0 @@ -package core - -import ( - "context" - "encoding/json" - "fmt" - "strings" - - "github.com/go-redis/redis/v8" -) - -type SetOption = string -type GetOption = [2]any - -const ( - // JSONSET command Options - SetOptionNX SetOption = "NX" - SetOptionXX SetOption = "XX" -) - -var ( - GetOptionSPACE = GetOption{"SPACE", " "} - GetOptionINDENT = GetOption{"INDENT", "\t"} - GetOptionNEWLINE = GetOption{"NEWLINE", "\n"} - GetOptionNOESCAPE = GetOption{"NOESCAPE", ""} -) - -// gocommon으로 옮길 거 -type RedisonHandler struct { - *redis.Client - ctx context.Context -} - -func NewRedisonHandler(ctx context.Context, redisClient *redis.Client) *RedisonHandler { - return &RedisonHandler{ - Client: redisClient, - ctx: ctx, - } -} - -func respToArray[T any](resp any, err error) ([]T, error) { - if err != nil { - return nil, err - } - - resArr := resp.([]any) - v := make([]T, len(resArr)) - for i, e := range resArr { - v[i] = e.(T) - } - return v, nil -} - -func appendArgs[T any](args []any, ext ...T) []any { - for _, e := range ext { - args = append(args, e) - } - return args -} - -func (rh *RedisonHandler) JSONMSetRel(key string, prefixPath string, kv map[string]any) error { - if len(prefixPath) > 0 && !strings.HasSuffix(prefixPath, ".") { - prefixPath += "." - } - - pl := rh.Pipeline() - for path, obj := range kv { - b, err := json.Marshal(obj) - if err != nil { - return err - } - pl.Do(rh.ctx, "JSON.SET", key, prefixPath+path, b) - } - - cmders, err := pl.Exec(rh.ctx) - if err != nil { - return err - } - - for _, cmder := range cmders { - if cmder.Err() != nil { - return cmder.Err() - } - } - return nil -} - -func (rh *RedisonHandler) JSONMSet(key string, kv map[string]any) error { - return rh.JSONMSetRel(key, "", kv) -} - -func (rh *RedisonHandler) JSONSet(key, path string, obj any, opts ...SetOption) (bool, error) { - b, err := json.Marshal(obj) - if err != nil { - return false, err - } - - args := []any{ - "JSON.SET", - key, - path, - b, - } - if len(opts) > 0 { - args = append(args, opts[0]) - } - - res, err := rh.Do(rh.ctx, args...).Result() - if err != nil { - return false, err - } - - return res.(string) == "OK", nil -} - -func (rh *RedisonHandler) JSONGet(key, path string, opts ...GetOption) (res any, err error) { - args := appendArgs[string]([]any{ - "JSON.GET", - key, - }, strings.Split(path, " ")...) - - for _, opt := range opts { - args = append(args, opt[:]...) - } - - return rh.Do(rh.ctx, args...).Result() -} - -func (rh *RedisonHandler) JSONGetString(key, path string) ([]string, error) { - return respToArray[string](rh.JSONResp(key, path)) -} - -func (rh *RedisonHandler) JSONGetInt64(key, path string) ([]int64, error) { - return respToArray[int64](rh.JSONResp(key, path)) -} - -func (rh *RedisonHandler) JSONMGet(path string, keys ...string) (res any, err error) { - args := appendArgs[string]([]any{ - "JSON.MGET", - path, - }, keys...) - return rh.Do(rh.ctx, args...).Result() -} - -func (rh *RedisonHandler) JSONMDel(key string, paths []string) error { - pl := rh.Pipeline() - for _, path := range paths { - args := []any{ - "JSON.DEL", - key, - path, - } - pl.Do(rh.ctx, args...) - } - _, err := pl.Exec(rh.ctx) - return err -} - -func (rh *RedisonHandler) JSONDel(key, path string) (int64, error) { - args := []any{ - "JSON.DEL", - key, - path, - } - resp, err := rh.Do(rh.ctx, args...).Result() - if err != nil { - return 0, err - } - - return resp.(int64), nil -} - -func (rh *RedisonHandler) JSONType(key, path string) ([]string, error) { - args := []any{ - "JSON.TYPE", - key, - path, - } - return respToArray[string](rh.Do(rh.ctx, args...).Result()) -} - -func (rh *RedisonHandler) JSONNumIncrBy(key, path string, number int) ([]any, error) { - args := []any{ - "JSON.NUMINCRBY", - key, - path, - number, - } - resp, err := rh.Do(rh.ctx, args...).Result() - if err != nil { - return nil, err - } - - return resp.([]any), nil -} - -func (rh *RedisonHandler) JSONNumMultBy(key, path string, number int) (res any, err error) { - args := []any{ - "JSON.NUMMULTBY", - key, - path, - number, - } - resp, err := rh.Do(rh.ctx, args...).Result() - if err != nil { - return nil, err - } - - return resp.([]any), nil -} - -func (rh *RedisonHandler) JSONStrAppend(key, path string, jsonstring string) ([]int64, error) { - args := []any{ - "JSON.STRAPPEND", - key, - path, - fmt.Sprintf(`'"%s"'`, jsonstring), - } - return respToArray[int64](rh.Do(rh.ctx, args...).Result()) -} - -func (rh *RedisonHandler) JSONStrLen(key, path string) (res []int64, err error) { - args := []any{ - "JSON.STRLEN", - key, - path, - } - return respToArray[int64](rh.Do(rh.ctx, args...).Result()) -} - -func (rh *RedisonHandler) JSONArrAppend(key, path string, values ...any) (int64, error) { - args := []any{ - "JSON.ARRAPPEND", - key, - path, - } - resp, err := rh.Do(rh.ctx, args...).Result() - if err != nil { - return 0, err - } - - return resp.(int64), nil -} - -func (rh *RedisonHandler) JSONArrLen(key, path string) ([]int64, error) { - args := []any{ - "JSON.ARRLEN", - key, - path, - } - return respToArray[int64](rh.Do(rh.ctx, args...).Result()) -} - -func (rh *RedisonHandler) JSONArrPop(key, path string, index int) (res any, err error) { - args := []any{ - "JSON.ARRPOP", - key, - path, - index, - } - resp, err := rh.Do(rh.ctx, args...).Result() - if err != nil { - return nil, err - } - return resp.([]any)[0], nil -} - -func appendValues(args []any, values ...any) []any { - for _, jsonValue := range values { - switch jsonValue := jsonValue.(type) { - case string: - args = append(args, fmt.Sprintf(`'"%s"'`, jsonValue)) - case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64: - args = append(args, jsonValue) - default: - bt, _ := json.Marshal(jsonValue) - args = append(args, bt) - } - } - return args -} - -func (rh *RedisonHandler) JSONArrIndex(key, path string, jsonValue any, optionalRange ...int) ([]int64, error) { - args := appendValues([]any{ - "JSON.ARRINDEX", - key, - path, - }, jsonValue) - - return respToArray[int64](rh.Do(rh.ctx, args...).Result()) -} - -func (rh *RedisonHandler) JSONArrTrim(key, path string, start, end int) (res any, err error) { - args := []any{ - "JSON.ARRTRIM", - key, - path, - start, - end, - } - return respToArray[int64](rh.Do(rh.ctx, args...).Result()) -} - -func (rh *RedisonHandler) JSONArrInsert(key, path string, index int, values ...any) (res any, err error) { - args := appendValues([]any{ - "JSON.ARRINSERT", - key, - path, - index, - }, values...) - - return respToArray[int64](rh.Do(rh.ctx, args...).Result()) -} - -func (rh *RedisonHandler) JSONObjKeys(key, path string) ([]string, error) { - args := []any{ - "JSON.OBJKEYS", - key, - path, - } - - res, err := rh.Do(rh.ctx, args...).Result() - if err != nil { - return nil, err - } - - resArr := res.([]any) - resArr = resArr[0].([]any) - slc := make([]string, len(resArr)) - - for i, r := range resArr { - slc[i] = r.(string) - } - - return slc, nil -} - -func (rh *RedisonHandler) JSONObjLen(key, path string) ([]int64, error) { - args := []any{ - "JSON.OBJLEN", - key, - } - - if path != "$" { - args = append(args, path) - } - - return respToArray[int64](rh.Do(rh.ctx, args...).Result()) -} - -func (rh *RedisonHandler) JSONDebug(key, path string) (res any, err error) { - args := []any{ - "JSON.DEBUG", - "MEMORY", - key, - path, - } - return rh.Do(rh.ctx, args...).Result() -} - -func (rh *RedisonHandler) JSONForget(key, path string) (int64, error) { - return rh.JSONDel(key, path) -} - -func (rh *RedisonHandler) JSONResp(key, path string) (res any, err error) { - args := []any{ - "JSON.RESP", - key, - path, - } - return rh.Do(rh.ctx, args...).Result() -} diff --git a/core/tavern.go b/core/tavern.go index 7c9cb36..e8ebf2b 100644 --- a/core/tavern.go +++ b/core/tavern.go @@ -9,7 +9,9 @@ import ( "net/http" "reflect" "strings" + "time" + "github.com/go-redis/redis/v8" "repositories.action2quare.com/ayo/gocommon" "repositories.action2quare.com/ayo/gocommon/logger" "repositories.action2quare.com/ayo/gocommon/wshandler" @@ -84,6 +86,7 @@ type Tavern struct { type subTavern struct { mongoClient gocommon.MongoClient + redisClient *redis.Client wsh *wshandler.WebsocketHandler region string groups map[string]group @@ -141,7 +144,7 @@ func (tv *Tavern) Cleanup() { } func (tv *Tavern) prepare(ctx context.Context) error { - for region := range config.RegionStorage { + for region, addr := range config.RegionStorage { var dbconn gocommon.MongoClient var err error var groupinstance group @@ -154,9 +157,15 @@ func (tv *Tavern) prepare(ctx context.Context) error { methods[method.Name] = method } + redisClient, err := gocommon.NewRedisClient(addr.Redis["tavern"]) + if err != nil { + return err + } + sub := &subTavern{ wsh: tv.wsh, mongoClient: dbconn, + redisClient: redisClient, region: region, methods: methods, } @@ -191,7 +200,7 @@ func (tv *Tavern) prepare(ctx context.Context) error { func (tv *Tavern) RegisterHandlers(ctx context.Context, serveMux *http.ServeMux, prefix string) error { for _, sub := range tv.subTaverns { - tv.wsh.RegisterReceiver(sub.region, sub.clientMessageReceived) + tv.wsh.RegisterReceiver(sub.region, sub) var pattern string if sub.region == "default" { pattern = gocommon.MakeHttpHandlerPattern(prefix, "api") @@ -204,11 +213,11 @@ func (tv *Tavern) RegisterHandlers(ctx context.Context, serveMux *http.ServeMux, return nil } -func (sub *subTavern) clientMessageReceived(sender *wshandler.Sender, messageType wshandler.WebSocketMessageType, body io.Reader) { +func (sub *subTavern) OnClientMessageReceived(sender *wshandler.Sender, messageType wshandler.WebSocketMessageType, body io.Reader) { if messageType == wshandler.Connected { - + logger.Println("OnClientMessageReceived : connected ", sender.Accid.Hex()) } else if messageType == wshandler.Disconnected { - + logger.Println("OnClientMessageReceived : disconnected ", sender.Accid.Hex()) } else if messageType == wshandler.BinaryMessage { var msg map[string][]any dec := json.NewDecoder(body) @@ -242,6 +251,20 @@ func (sub *subTavern) clientMessageReceived(sender *wshandler.Sender, messageTyp } } +func (sub *subTavern) OnRoomCreated(region, name string) { + _, err := sub.redisClient.Persist(context.Background(), name).Result() + if err != nil { + logger.Println("OnRoomCreate Persist failed :", err) + } +} + +func (sub *subTavern) OnRoomDestroyed(region, name string) { + _, err := sub.redisClient.Expire(context.Background(), name, 3600*time.Second).Result() + if err != nil { + logger.Println("OnRoomDestroyed Persist failed :", err) + } +} + func (sub *subTavern) api(w http.ResponseWriter, r *http.Request) { defer func() { s := recover() diff --git a/core/tavern_test.go b/core/tavern_test.go index a947d6d..663360c 100644 --- a/core/tavern_test.go +++ b/core/tavern_test.go @@ -3,16 +3,37 @@ package core import ( "context" + "fmt" "testing" + "time" "github.com/go-redis/redis/v8" "go.mongodb.org/mongo-driver/bson/primitive" + "repositories.action2quare.com/ayo/gocommon" "repositories.action2quare.com/ayo/gocommon/logger" ) +func TestPubSub(t *testing.T) { + opt0, _ := redis.ParseURL("redis://192.168.8.94:6380/0") + opt1, _ := redis.ParseURL("redis://192.168.8.94:6380/1") + + rc0 := redis.NewClient(opt0) + rc1 := redis.NewClient(opt1) + + go func() { + time.Sleep(time.Second) + rc1.Publish(context.Background(), "__testchan", "real???") + fmt.Println("published") + }() + + pubsub := rc0.Subscribe(context.Background(), "__testchan") + msg, err := pubsub.ReceiveMessage(context.Background()) + fmt.Println(msg.Payload, err) +} + func TestReJSON(t *testing.T) { rc := redis.NewClient(&redis.Options{Addr: "192.168.8.94:6380"}) - rh := NewRedisonHandler(context.Background(), rc) + rh := gocommon.NewRedisonHandler(context.Background(), rc) testDoc := map[string]any{ "members": map[string]any{ diff --git a/go.mod b/go.mod index f5a45e9..7803b45 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.20 require ( github.com/go-redis/redis/v8 v8.11.5 go.mongodb.org/mongo-driver v1.11.7 - repositories.action2quare.com/ayo/gocommon v0.0.0-20230717084540-29843802ff0e + repositories.action2quare.com/ayo/gocommon v0.0.0-20230719003337-29b2f258507d ) require ( diff --git a/go.sum b/go.sum index f486b47..3b2f437 100644 --- a/go.sum +++ b/go.sum @@ -112,3 +112,23 @@ repositories.action2quare.com/ayo/gocommon v0.0.0-20230716093911-66aea48fb732 h1 repositories.action2quare.com/ayo/gocommon v0.0.0-20230716093911-66aea48fb732/go.mod h1:PdpZ16O1czKKxCxn+0AFNaEX/0kssYwC3G8jR0V7ybw= repositories.action2quare.com/ayo/gocommon v0.0.0-20230717084540-29843802ff0e h1:/eG6tAQzEaN178Aib+/erjHrE/+IjIVLRSmP4gx6D7E= repositories.action2quare.com/ayo/gocommon v0.0.0-20230717084540-29843802ff0e/go.mod h1:PdpZ16O1czKKxCxn+0AFNaEX/0kssYwC3G8jR0V7ybw= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230718004527-4b35e0e6386b h1:K3YQXnVP/W6LzwGzqOxwKmFUD5IrrNPEWYcN/fSinck= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230718004527-4b35e0e6386b/go.mod h1:PdpZ16O1czKKxCxn+0AFNaEX/0kssYwC3G8jR0V7ybw= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230718005518-289af24a8ffa h1:YmzJ1YccK3BxC/NbfB11SEUG1S6Lkz6ejg4kS3q/3Qc= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230718005518-289af24a8ffa/go.mod h1:PdpZ16O1czKKxCxn+0AFNaEX/0kssYwC3G8jR0V7ybw= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230718020415-82abcddb497b h1:baO9csa0Esnp7UW+L8zJW/ygpjGHRve4rU2/1pVvXQg= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230718020415-82abcddb497b/go.mod h1:PdpZ16O1czKKxCxn+0AFNaEX/0kssYwC3G8jR0V7ybw= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230718020838-c21017d2cd8b h1:FqLKDrFji0+giFwAJ3oV6dIOR6Sd/aaay76WgWIEVR8= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230718020838-c21017d2cd8b/go.mod h1:PdpZ16O1czKKxCxn+0AFNaEX/0kssYwC3G8jR0V7ybw= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230718032106-40a603522d40 h1:VyFfS0d6pTX2HbZoDHOxJwag4aVSLOh/LrQXqfSJLBg= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230718032106-40a603522d40/go.mod h1:PdpZ16O1czKKxCxn+0AFNaEX/0kssYwC3G8jR0V7ybw= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230718083804-d724cc84fa94 h1:iQPrRcZ6XfFblpVHxe/CIoWyTj7imF+3edIGSX6ZMM8= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230718083804-d724cc84fa94/go.mod h1:PdpZ16O1czKKxCxn+0AFNaEX/0kssYwC3G8jR0V7ybw= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230718084512-89fa9e4ac585 h1:Wy6qjZ0uHfp02/H688zotRfzYGRPjun7Qay0Z9B/hSg= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230718084512-89fa9e4ac585/go.mod h1:PdpZ16O1czKKxCxn+0AFNaEX/0kssYwC3G8jR0V7ybw= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230718105124-72a683fed2c0 h1:8LmRo2nKaLi4QCmO/agSpNTmCD0EdwFycjHjOweQJp8= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230718105124-72a683fed2c0/go.mod h1:PdpZ16O1czKKxCxn+0AFNaEX/0kssYwC3G8jR0V7ybw= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230719003101-256bfd030c29 h1:ADScrqJgmk/TfyOu/6oXD3WkSH8sh3Bw360O8GKuEV8= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230719003101-256bfd030c29/go.mod h1:PdpZ16O1czKKxCxn+0AFNaEX/0kssYwC3G8jR0V7ybw= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230719003337-29b2f258507d h1:eMzrvVkQfbs5X5dcw80TGGKtJ+6XELl7zNsWiuq4gzs= +repositories.action2quare.com/ayo/gocommon v0.0.0-20230719003337-29b2f258507d/go.mod h1:PdpZ16O1czKKxCxn+0AFNaEX/0kssYwC3G8jR0V7ybw=