Squashed commit of the following:

commit 8e1b232d57
Author: mountain <mountain@action2quare.com>
Date:   Wed Jul 19 09:37:02 2023 +0900

    InMemory 그룹을 redis로 변경

commit 01da5bb3a4
Author: mountain <mountain@action2quare.com>
Date:   Tue Jul 18 01:31:39 2023 +0900

    body를 marshaling하고 클라이언트에서 flatten함

commit ba61a11659
Author: mountain <mountain@action2quare.com>
Date:   Mon Jul 17 17:47:07 2023 +0900

    gob 등록

commit 67cca13326
Author: mountain <mountain@action2quare.com>
Date:   Sun Jul 16 18:41:24 2023 +0900

    모듈 업데이트

commit 272c696c59
Author: mountain <mountain@action2quare.com>
Date:   Sun Jul 16 17:29:21 2023 +0900

    json value 다시 되돌림

commit aa568ec3fa
Author: mountain <mountain@action2quare.com>
Date:   Sun Jul 16 17:26:19 2023 +0900

    SetOption 타입 변경

commit b9c4d8b21b
Author: mountain <mountain@action2quare.com>
Date:   Sun Jul 16 17:15:08 2023 +0900

    objvalue marshalling 수정

commit 99834c1461
Author: mountain <mountain@action2quare.com>
Date:   Sun Jul 16 17:01:06 2023 +0900

    objlen 수정

commit 592112219e
Author: mountain <mountain@action2quare.com>
Date:   Sun Jul 16 16:38:05 2023 +0900

    gocommon 업데이트

commit 62485b6d54
Author: mountain <mountain@action2quare.com>
Date:   Sun Jul 16 15:36:20 2023 +0900

    redis json 마이그레이션 완료

commit d36dd13bb7
Author: mountain <mountain@action2quare.com>
Date:   Sun Jul 16 02:51:41 2023 +0900

    redis stack 사용
This commit is contained in:
2023-07-19 09:37:40 +09:00
parent 454aae5294
commit 8dded8b907
11 changed files with 565 additions and 1419 deletions

View File

@ -1,15 +1,11 @@
package core
import (
"context"
"encoding/json"
"io"
"net/http"
common "repositories.action2quare.com/ayo/gocommon"
"repositories.action2quare.com/ayo/gocommon/logger"
"github.com/go-redis/redis/v8"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
@ -83,11 +79,11 @@ func (sub *subTavern) JoinGroup(w http.ResponseWriter, r *http.Request) {
if candidate, ok := common.ReadBoolFormValue(r.Form, "candidate"); ok && candidate {
err = group.Candidate(gidobj, midobj, doc)
} else {
tidobj, err = group.Join(gidobj, midobj, tidobj, doc)
err = group.Join(gidobj, midobj, doc)
}
if err == nil {
json.NewEncoder(w).Encode(map[string]string{
writeBsonDoc(w, map[string]string{
"gid": gidobj.Hex(),
"tid": tidobj.Hex(),
})
@ -131,14 +127,14 @@ func (sub *subTavern) Invite(w http.ResponseWriter, r *http.Request) {
Invitee bson.M `bson:"invitee"`
}
if err := readBsonDoc(r.Body, &reqdoc); err != nil {
logger.Error("Invite failed. readBsonDoc returns err :", err)
logger.Println("Invite failed. readBsonDoc returns err :", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
result, err := group.Invite(gid, mid, reqdoc.Inviter, reqdoc.Invitee)
if err != nil {
logger.Error("Invite failed. group.Invite returns err :", err)
logger.Println("Invite failed. group.Invite returns err :", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
@ -184,12 +180,6 @@ func (sub *subTavern) AcceptInvitation(w http.ResponseWriter, r *http.Request) {
gid, _ := common.ReadObjectIDFormValue(r.Form, "gid")
mid, _ := common.ReadObjectIDFormValue(r.Form, "mid")
tid, ok := common.ReadObjectIDFormValue(r.Form, "tid")
if !ok {
logger.Println("CancelInvitation failed. form value 'tid' is missing")
w.WriteHeader(http.StatusBadRequest)
return
}
var member bson.M
if err := readBsonDoc(r.Body, &member); err != nil {
@ -198,14 +188,12 @@ func (sub *subTavern) AcceptInvitation(w http.ResponseWriter, r *http.Request) {
return
}
gidbytes, err := group.AcceptInvitation(gid, mid, tid, member)
err := group.AcceptInvitation(gid, mid, member)
if err != nil {
logger.Error("AcceptInvitation failed. group.AcceptInvitation returns err :", err)
logger.Println("AcceptInvitation failed. group.AcceptInvitation returns err :", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Write([]byte(gidbytes.Hex()))
}
func (sub *subTavern) DenyInvitation(w http.ResponseWriter, r *http.Request) {
@ -270,49 +258,6 @@ func (sub *subTavern) QueryInvitations(w http.ResponseWriter, r *http.Request) {
}
}
func (sub *subTavern) QueryOnlineGroup(w http.ResponseWriter, r *http.Request) {
typename, _ := common.ReadStringFormValue(r.Form, "type")
group := sub.groups[typename]
if group == nil {
logger.Println("QueryOnlineGroup failed. group type is missing :", r.Form)
w.WriteHeader(http.StatusBadRequest)
return
}
var cmd *redis.StringSliceCmd
scoreStart, _ := common.ReadStringFormValue(r.Form, "score_start")
scoreStop, _ := common.ReadStringFormValue(r.Form, "score_stop")
if len(scoreStart) > 0 || len(scoreStop) > 0 {
if len(scoreStart) == 0 {
scoreStart = "-inf"
}
if len(scoreStop) == 0 {
scoreStop = "+inf"
}
cmd = sub.wsh.RedisSync.ZRangeArgs(context.Background(), redis.ZRangeArgs{
Key: onlineGroupQueryKey(typename),
ByScore: true,
Start: scoreStart,
Stop: scoreStop,
Rev: true,
Count: 1,
})
} else {
// 아무거나
cmd = sub.wsh.RedisSync.ZRandMember(context.Background(), onlineGroupQueryKey(typename), 1, false)
}
result, err := cmd.Result()
if err != nil {
logger.Error("QueryOnlineGroup failed. redid.ZRandMember returns err :", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
writeBsonDoc(w, bson.M{"r": result})
}
func (sub *subTavern) SearchGroup(w http.ResponseWriter, r *http.Request) {
typename, _ := common.ReadStringFormValue(r.Form, "type")
group := sub.groups[typename]
@ -343,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
}
@ -420,96 +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)
w.WriteHeader(http.StatusInternalServerError)
return
}
}
// QueryGroupMembers : 그룹내 멤버 조회
// - type : 그룹 타입
// - 그룹 타입에 맞는 키(주로 _id)
// - projection : select할 필드. ,로 구분
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. group type is missing :", r.Form)
w.WriteHeader(http.StatusBadRequest)
return
}
gidobj, ok := common.ReadObjectIDFormValue(r.Form, "gid")
if !ok {
logger.Println("QueryGroupMembers failed. _id is missing :", r.Form)
w.WriteHeader(http.StatusBadRequest)
return
}
midobj, _ := common.ReadObjectIDFormValue(r.Form, "mid")
var after primitive.Timestamp
if ts, ok := common.ReadStringFormValue(r.Form, "after"); ok && ts != "0.0" {
after = common.DotStringToTimestamp(ts)
}
projection, _ := common.ReadStringFormValue(r.Form, "projection")
result, err := group.QueryMembers(gidobj, midobj, projection, after)
if err != nil {
logger.Error("QueryGroupMembers failed. FindAll err :", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
if result == nil {
return
}
if err := writeBsonDoc(w, result); err != nil {
logger.Error("QueryGroupMembers failed. writeBsonArr err :", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
}
func (sub *subTavern) QueryGroupMember(w http.ResponseWriter, r *http.Request) {
typename, _ := common.ReadStringFormValue(r.Form, "type")
group := sub.groups[typename]
if group == nil {
logger.Println("QueryGroupMember failed. group type is missing :", r.Form)
w.WriteHeader(http.StatusBadRequest)
return
}
gid, ok := common.ReadObjectIDFormValue(r.Form, "gid")
if !ok {
logger.Println("QueryGroupMember failed. gid is missing :", r.Form)
w.WriteHeader(http.StatusBadRequest)
return
}
mid, midok := common.ReadObjectIDFormValue(r.Form, "mid")
tid, tidok := common.ReadObjectIDFormValue(r.Form, "tid")
if !midok && !tidok {
// 둘 중 하나는 있어야지
logger.Println("QueryGroupMember failed. tid and mid are both missing")
w.WriteHeader(http.StatusBadRequest)
return
}
projection, _ := common.ReadStringFormValue(r.Form, "projection")
result, err := group.QueryMember(gid, mid, tid, projection)
if err != nil {
logger.Println("QueryGroupMember failed. group.QueryMember returns err :", err)
w.WriteHeader(http.StatusBadRequest)
return
}
if result == nil {
return
}
if err := writeBsonDoc(w, result); err != nil {
logger.Error("QueryGroupMember failed. writeBsonDoc err :", err)
logger.Error("bson marshal failed :", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
@ -535,15 +391,14 @@ func (sub *subTavern) LeaveGroup(w http.ResponseWriter, r *http.Request) {
return
}
mid, midok := common.ReadObjectIDFormValue(r.Form, "mid")
tid, tidok := common.ReadObjectIDFormValue(r.Form, "tid")
if !midok && !tidok {
// 둘 중 하나는 있어야지
logger.Println("LeaveGroup failed. tid and mid are both missing")
if !midok {
logger.Println("LeaveGroup failed. mid is missing")
w.WriteHeader(http.StatusBadRequest)
return
}
if err := group.Leave(gid, mid, tid); err != nil {
if err := group.Leave(gid, mid); err != nil {
// 둘 중 하나는 있어야지
logger.Println("LeaveGroup failed. group.Leave returns err :", err)
w.WriteHeader(http.StatusBadRequest)
@ -626,125 +481,46 @@ func (sub *subTavern) UpdateGroupDocument(w http.ResponseWriter, r *http.Request
return
}
body, err := io.ReadAll(r.Body)
if err != nil {
var frag bson.M
if err := readBsonDoc(r.Body, &frag); err != nil {
logger.Error("UpdateGroupDocument failed. readBsonDoc err :", err)
w.WriteHeader(http.StatusBadRequest)
return
}
if err := group.UpdateGroupDocument(gid, body); err != nil {
if err := group.UpdateGroupDocument(gid, frag); err != nil {
logger.Error("UpdateGroupDocument failed. group.UpdateGroupDocument returns err :", err)
w.WriteHeader(http.StatusBadRequest)
return
}
}
func (sub *subTavern) PauseGroupMember(w http.ResponseWriter, r *http.Request) {
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("DismissGroup failed. type is missing")
w.WriteHeader(http.StatusBadRequest)
return
}
midobj, ok := common.ReadObjectIDFormValue(r.Form, "mid")
if !ok {
logger.Println("UpdateMemberDocument failed. member_id is missing")
w.WriteHeader(http.StatusBadRequest)
return
}
gidobj, ok := common.ReadObjectIDFormValue(r.Form, "gid")
if !ok {
logger.Println("UpdateMemberDocument failed. _id is missing")
w.WriteHeader(http.StatusBadRequest)
return
}
group.PauseMember(gidobj, midobj)
}
func (sub *subTavern) DropPausedMember(w http.ResponseWriter, r *http.Request) {
typename, _ := common.ReadStringFormValue(r.Form, "type")
group := sub.groups[typename]
if group == nil {
logger.Println("DropDeadMember failed. type is missing")
logger.Println("QueryGroupMembers failed. type is missing")
w.WriteHeader(http.StatusBadRequest)
return
}
gid, ok := common.ReadObjectIDFormValue(r.Form, "gid")
if !ok {
logger.Println("DropDeadMember failed. gid is missing")
logger.Println("QueryGroupMembers failed. gid is missing")
w.WriteHeader(http.StatusBadRequest)
return
}
mid, ok := common.ReadObjectIDFormValue(r.Form, "mid")
if !ok {
logger.Println("DropDeadMember failed. mid is missing")
members, err := group.QueryGroupMembers(gid)
if err != nil {
logger.Error("QueryGroupMembers failed. group.QueryGroupMembers returns err :", err)
w.WriteHeader(http.StatusBadRequest)
return
}
if err := group.DropPausedMember(gid, mid); err != nil {
logger.Error("DropDeadMember failed. group.DropDeadMember returns err :", err)
w.WriteHeader(http.StatusBadRequest)
if err := writeBsonDoc(w, members); err != nil {
logger.Error("QueryGroupMembers failed. writeBsonDoc return err :", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
}
// func (sub *subTavern) deliveryMessageHandler(deliveryChan <-chan wshandler.DeliveryMessage) {
// defer func() {
// r := recover()
// if r != nil {
// logger.Error(r)
// }
// }()
// redisSync := sub.wsh.RedisSync
// for msg := range deliveryChan {
// mid := msg.Alias
// if msg.Body != nil {
// buffer := msg.Body
// var channame string
// for i, ch := range buffer {
// if ch == 0 {
// channame = string(buffer[:i])
// buffer = buffer[i+1:]
// break
// }
// }
// if len(channame) == 0 {
// continue
// }
// buffer = append(mid[:], buffer...)
// _, err := redisSync.Publish(context.Background(), channame, buffer).Result()
// if err != nil {
// logger.Error(err)
// }
// }
// if len(msg.Command) > 0 {
// switch msg.Command {
// case "pause":
// gidtype := msg.Conn.GetTag("gid")
// if len(gidtype) > 0 {
// tokens := strings.SplitN(gidtype, "@", 2)
// gidobj, _ := primitive.ObjectIDFromHex(tokens[0])
// gtype := tokens[1]
// group := sub.groups[gtype]
// if group != nil {
// group.PauseMember(gidobj, msg.Alias, msg.Conn)
// }
// }
// }
// }
// }
// logger.Println("delivery chan fin")
// }