InMemory 그룹을 redis로 변경

This commit is contained in:
2023-07-19 09:37:02 +09:00
parent 01da5bb3a4
commit 8e1b232d57
8 changed files with 209 additions and 448 deletions

View File

@ -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
}
}

View File

@ -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)
}

View File

@ -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"`
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)
},

View File

@ -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()
}

View File

@ -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()

View File

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

2
go.mod
View File

@ -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 (

20
go.sum
View File

@ -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=