Files
tavern/core/tavern.go

248 lines
6.6 KiB
Go
Raw Normal View History

2023-05-24 16:10:00 +09:00
package core
import (
"context"
"errors"
"io"
"net"
"net/http"
"strings"
Squashed commit of the following: commit 8e1b232d57801c12edb94d02038b663d19c67b9b Author: mountain <mountain@action2quare.com> Date: Wed Jul 19 09:37:02 2023 +0900 InMemory 그룹을 redis로 변경 commit 01da5bb3a4b2c1857ce73d5722add85d347c976d Author: mountain <mountain@action2quare.com> Date: Tue Jul 18 01:31:39 2023 +0900 body를 marshaling하고 클라이언트에서 flatten함 commit ba61a11659eb790d98d41ce61d38dd001ccfa56c Author: mountain <mountain@action2quare.com> Date: Mon Jul 17 17:47:07 2023 +0900 gob 등록 commit 67cca13326aa517ba0de396b8d5bce736c1c86d8 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 18:41:24 2023 +0900 모듈 업데이트 commit 272c696c59652452da45e2704eabebc1e5f587a8 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 17:29:21 2023 +0900 json value 다시 되돌림 commit aa568ec3fa0016b4a1a43b29c578720ff65883c1 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 17:26:19 2023 +0900 SetOption 타입 변경 commit b9c4d8b21bbe47733f3bc061973743de06ce3b64 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 17:15:08 2023 +0900 objvalue marshalling 수정 commit 99834c146182cf51cbe4a24915f14c91208be994 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 17:01:06 2023 +0900 objlen 수정 commit 592112219ec5333031b56949d85e91ce5e46bf20 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 16:38:05 2023 +0900 gocommon 업데이트 commit 62485b6d54e7f8394272b1b80778f677b0fc5996 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 15:36:20 2023 +0900 redis json 마이그레이션 완료 commit d36dd13bb7b5c70825cae3ca5ea4d3cb62506ab6 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 02:51:41 2023 +0900 redis stack 사용
2023-07-19 09:37:40 +09:00
"time"
2023-05-24 16:10:00 +09:00
Squashed commit of the following: commit 8e1b232d57801c12edb94d02038b663d19c67b9b Author: mountain <mountain@action2quare.com> Date: Wed Jul 19 09:37:02 2023 +0900 InMemory 그룹을 redis로 변경 commit 01da5bb3a4b2c1857ce73d5722add85d347c976d Author: mountain <mountain@action2quare.com> Date: Tue Jul 18 01:31:39 2023 +0900 body를 marshaling하고 클라이언트에서 flatten함 commit ba61a11659eb790d98d41ce61d38dd001ccfa56c Author: mountain <mountain@action2quare.com> Date: Mon Jul 17 17:47:07 2023 +0900 gob 등록 commit 67cca13326aa517ba0de396b8d5bce736c1c86d8 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 18:41:24 2023 +0900 모듈 업데이트 commit 272c696c59652452da45e2704eabebc1e5f587a8 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 17:29:21 2023 +0900 json value 다시 되돌림 commit aa568ec3fa0016b4a1a43b29c578720ff65883c1 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 17:26:19 2023 +0900 SetOption 타입 변경 commit b9c4d8b21bbe47733f3bc061973743de06ce3b64 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 17:15:08 2023 +0900 objvalue marshalling 수정 commit 99834c146182cf51cbe4a24915f14c91208be994 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 17:01:06 2023 +0900 objlen 수정 commit 592112219ec5333031b56949d85e91ce5e46bf20 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 16:38:05 2023 +0900 gocommon 업데이트 commit 62485b6d54e7f8394272b1b80778f677b0fc5996 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 15:36:20 2023 +0900 redis json 마이그레이션 완료 commit d36dd13bb7b5c70825cae3ca5ea4d3cb62506ab6 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 02:51:41 2023 +0900 redis stack 사용
2023-07-19 09:37:40 +09:00
"github.com/go-redis/redis/v8"
2023-07-06 00:53:53 +09:00
"repositories.action2quare.com/ayo/gocommon"
2023-08-12 15:26:32 +09:00
"repositories.action2quare.com/ayo/gocommon/flagx"
2023-05-24 16:10:00 +09:00
"repositories.action2quare.com/ayo/gocommon/logger"
2023-08-31 21:17:51 +09:00
"repositories.action2quare.com/ayo/gocommon/session"
2023-05-24 16:10:00 +09:00
"repositories.action2quare.com/ayo/gocommon/wshandler"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/bsonrw"
)
2023-08-12 15:26:32 +09:00
var devflag = flagx.Bool("dev", false, "")
2023-05-24 16:10:00 +09:00
func writeBsonDoc[T any](w io.Writer, src T) error {
rw, err := bsonrw.NewBSONValueWriter(w)
if err != nil {
return err
}
enc, err := bson.NewEncoder(rw)
if err != nil {
return err
}
return enc.Encode(src)
}
type TavernConfig struct {
2023-08-31 21:17:51 +09:00
session.SessionConfig `json:",inline"`
2023-09-08 11:37:50 +09:00
Group map[string]configDocument `json:"tavern_group_types"`
MaingateApiToken string `json:"maingate_api_token"`
RedisURL string `json:"tavern_redis_url"`
macAddr string
2023-05-24 16:10:00 +09:00
}
var config TavernConfig
type Tavern struct {
2023-09-08 11:37:50 +09:00
wsh *wshandler.WebsocketHandler
mongoClient gocommon.MongoClient
redison *gocommon.RedisonHandler
httpApiBorker gocommon.HttpApiHandlerContainer
2023-05-24 16:10:00 +09:00
}
func getMacAddr() (string, error) {
ifas, err := net.Interfaces()
if err != nil {
return "", err
}
for _, ifa := range ifas {
a := ifa.HardwareAddr.String()
if a != "" {
a = strings.ReplaceAll(a, ":", "")
return a, nil
}
}
return "", errors.New("no net interface")
}
// New :
2023-09-08 11:37:50 +09:00
func New(context context.Context, wsh *wshandler.WebsocketHandler) (*Tavern, error) {
if err := gocommon.LoadConfig(&config); err != nil {
return nil, err
2023-05-24 16:10:00 +09:00
}
macaddr, err := getMacAddr()
if err != nil {
return nil, err
}
config.macAddr = macaddr
2023-07-10 15:39:56 +09:00
tv := &Tavern{
2023-05-24 16:10:00 +09:00
wsh: wsh,
}
if err = tv.prepare(context); err != nil {
logger.Println("tavern prepare() failed :", err)
return nil, err
}
2023-07-10 15:39:56 +09:00
return tv, nil
2023-05-24 16:10:00 +09:00
}
2023-07-10 15:39:56 +09:00
func (tv *Tavern) Cleanup() {
2023-08-31 21:02:19 +09:00
tv.mongoClient.Close()
2023-05-24 16:10:00 +09:00
}
func (tv *Tavern) prepare(ctx context.Context) error {
2023-09-08 11:37:50 +09:00
redisClient, err := gocommon.NewRedisClient(config.RedisURL)
2023-08-31 21:02:19 +09:00
if err != nil {
return err
}
2023-05-24 16:10:00 +09:00
2023-08-31 21:02:19 +09:00
tv.redison = gocommon.NewRedisonHandler(redisClient.Context(), redisClient)
2023-09-08 11:37:50 +09:00
tv.wsh.RegisterApiHandler(wshandler.MakeWebsocketApiHandler(tv, "tv"))
Squashed commit of the following: commit 8e1b232d57801c12edb94d02038b663d19c67b9b Author: mountain <mountain@action2quare.com> Date: Wed Jul 19 09:37:02 2023 +0900 InMemory 그룹을 redis로 변경 commit 01da5bb3a4b2c1857ce73d5722add85d347c976d Author: mountain <mountain@action2quare.com> Date: Tue Jul 18 01:31:39 2023 +0900 body를 marshaling하고 클라이언트에서 flatten함 commit ba61a11659eb790d98d41ce61d38dd001ccfa56c Author: mountain <mountain@action2quare.com> Date: Mon Jul 17 17:47:07 2023 +0900 gob 등록 commit 67cca13326aa517ba0de396b8d5bce736c1c86d8 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 18:41:24 2023 +0900 모듈 업데이트 commit 272c696c59652452da45e2704eabebc1e5f587a8 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 17:29:21 2023 +0900 json value 다시 되돌림 commit aa568ec3fa0016b4a1a43b29c578720ff65883c1 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 17:26:19 2023 +0900 SetOption 타입 변경 commit b9c4d8b21bbe47733f3bc061973743de06ce3b64 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 17:15:08 2023 +0900 objvalue marshalling 수정 commit 99834c146182cf51cbe4a24915f14c91208be994 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 17:01:06 2023 +0900 objlen 수정 commit 592112219ec5333031b56949d85e91ce5e46bf20 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 16:38:05 2023 +0900 gocommon 업데이트 commit 62485b6d54e7f8394272b1b80778f677b0fc5996 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 15:36:20 2023 +0900 redis json 마이그레이션 완료 commit d36dd13bb7b5c70825cae3ca5ea4d3cb62506ab6 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 02:51:41 2023 +0900 redis stack 사용
2023-07-19 09:37:40 +09:00
2023-09-05 17:14:07 +09:00
if cfg, ok := config.Group["chat"]; ok {
chat := new(groupChat)
if err := chat.Initialize(tv, cfg); err != nil {
return err
2023-05-24 16:10:00 +09:00
}
2023-09-08 11:37:50 +09:00
tv.httpApiBorker.RegisterApiHandler(gocommon.MakeHttpApiHandler(chat, "chat"))
tv.wsh.RegisterApiHandler(wshandler.MakeWebsocketApiHandler(chat, "chat"))
2023-09-05 17:14:07 +09:00
}
2023-05-24 16:10:00 +09:00
2023-09-05 17:14:07 +09:00
if cfg, ok := config.Group["party"]; ok {
party := new(groupParty)
if err := party.Initialize(tv, cfg); err != nil {
2023-08-31 21:02:19 +09:00
return err
}
2023-09-08 11:37:50 +09:00
tv.httpApiBorker.RegisterApiHandler(gocommon.MakeHttpApiHandler(party, "party"))
tv.wsh.RegisterApiHandler(wshandler.MakeWebsocketApiHandler(party, "party"))
2023-05-24 16:10:00 +09:00
}
2023-08-31 21:02:19 +09:00
2023-05-24 16:10:00 +09:00
return nil
}
func (tv *Tavern) RegisterHandlers(ctx context.Context, serveMux *http.ServeMux, prefix string) error {
2023-09-08 11:37:50 +09:00
// tv.wsh.RegisterReceiver(tv)
2023-08-31 21:02:19 +09:00
pattern := gocommon.MakeHttpHandlerPattern(prefix, "api")
serveMux.HandleFunc(pattern, tv.api)
2023-05-24 16:10:00 +09:00
return nil
}
2023-09-08 11:37:50 +09:00
func (tv *Tavern) EnterChannel(ctx wshandler.ApiCallContext) {
tv.wsh.EnterRoom(ctx.Arguments[0].(string), ctx.CallBy.Accid)
}
2023-09-08 11:37:50 +09:00
func (tv *Tavern) LeaveChannel(ctx wshandler.ApiCallContext) {
tv.wsh.LeaveRoom(ctx.Arguments[0].(string), ctx.CallBy.Accid)
}
func (tv *Tavern) ClientConnected(ctx wshandler.ApiCallContext) {
logger.Println("ClientConnected :", ctx.CallBy.Alias)
tv.redison.Del(tv.redison.Context(), ctx.CallBy.Accid.Hex())
_, err := tv.redison.JSONSet(ctx.CallBy.Accid.Hex(), "$", bson.M{"_ts": time.Now().UTC().Unix()})
if err != nil {
logger.Println("OnClientMessageReceived HSet error :", err)
2023-07-10 15:39:56 +09:00
}
}
2023-09-08 11:37:50 +09:00
func (tv *Tavern) ClientDisconnected(ctx wshandler.ApiCallContext) {
tv.redison.Del(tv.redison.Context(), ctx.CallBy.Accid.Hex()).Result()
logger.Println("ClientDisconnected :", ctx.CallBy.Alias)
}
// func (tv *Tavern) OnClientMessageReceived(sender *wshandler.Sender, messageType wshandler.WebSocketMessageType, body io.Reader) {
// if messageType == wshandler.Connected {
// logger.Println("OnClientMessageReceived : connected ", sender.Accid.Hex())
// tv.redison.Del(tv.redison.Context(), sender.Accid.Hex())
// _, err := tv.redison.JSONSet(sender.Accid.Hex(), "$", bson.M{"_ts": time.Now().UTC().Unix()})
// if err != nil {
// logger.Println("OnClientMessageReceived HSet error :", err)
// }
// } else if messageType == wshandler.Disconnected {
// // TODO : 알려줘야하나???
// var rooms []string
// dec := json.NewDecoder(body)
// if err := dec.Decode(&rooms); err == nil {
// for _, gt := range tv.groups {
// gt.ClientMessageReceived(sender, messageType, rooms)
// }
// }
// tv.redison.Del(tv.redison.Context(), sender.Accid.Hex()).Result()
// logger.Println("OnClientMessageReceived : disconnected ", sender.Accid.Hex())
// } else if messageType == wshandler.BinaryMessage {
// var commandline []any
// dec := json.NewDecoder(body)
// if err := dec.Decode(&commandline); err == nil {
// cmd := commandline[0].(string)
// args := commandline[1:]
// switch cmd {
// case "EnterChannel":
// tv.wsh.EnterRoom(args[0].(string), sender.Accid)
// case "LeaveChannel":
// tv.wsh.LeaveRoom(args[0].(string), sender.Accid)
// }
// }
// }
// }
2023-08-31 21:02:19 +09:00
func (tv *Tavern) OnRoomCreated(name string) {
cnt, err := tv.redison.IncrBy(tv.redison.Context(), "_ref_"+name, 1).Result()
2023-08-12 15:26:32 +09:00
if err != nil && !errors.Is(err, redis.Nil) {
logger.Println("OnRoomCreated JSONSet failed :", err)
return
}
2023-08-14 14:44:56 +09:00
if cnt == 1 {
2023-08-31 21:02:19 +09:00
tv.redison.JSONSet(name, "$", map[string]any{}, gocommon.RedisonSetOptionNX)
2023-08-12 15:26:32 +09:00
}
Squashed commit of the following: commit 8e1b232d57801c12edb94d02038b663d19c67b9b Author: mountain <mountain@action2quare.com> Date: Wed Jul 19 09:37:02 2023 +0900 InMemory 그룹을 redis로 변경 commit 01da5bb3a4b2c1857ce73d5722add85d347c976d Author: mountain <mountain@action2quare.com> Date: Tue Jul 18 01:31:39 2023 +0900 body를 marshaling하고 클라이언트에서 flatten함 commit ba61a11659eb790d98d41ce61d38dd001ccfa56c Author: mountain <mountain@action2quare.com> Date: Mon Jul 17 17:47:07 2023 +0900 gob 등록 commit 67cca13326aa517ba0de396b8d5bce736c1c86d8 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 18:41:24 2023 +0900 모듈 업데이트 commit 272c696c59652452da45e2704eabebc1e5f587a8 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 17:29:21 2023 +0900 json value 다시 되돌림 commit aa568ec3fa0016b4a1a43b29c578720ff65883c1 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 17:26:19 2023 +0900 SetOption 타입 변경 commit b9c4d8b21bbe47733f3bc061973743de06ce3b64 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 17:15:08 2023 +0900 objvalue marshalling 수정 commit 99834c146182cf51cbe4a24915f14c91208be994 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 17:01:06 2023 +0900 objlen 수정 commit 592112219ec5333031b56949d85e91ce5e46bf20 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 16:38:05 2023 +0900 gocommon 업데이트 commit 62485b6d54e7f8394272b1b80778f677b0fc5996 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 15:36:20 2023 +0900 redis json 마이그레이션 완료 commit d36dd13bb7b5c70825cae3ca5ea4d3cb62506ab6 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 02:51:41 2023 +0900 redis stack 사용
2023-07-19 09:37:40 +09:00
}
2023-08-31 21:02:19 +09:00
func (tv *Tavern) OnRoomDestroyed(name string) {
cnt, err := tv.redison.IncrBy(tv.redison.Context(), "_ref_"+name, -1).Result()
2023-08-14 14:44:56 +09:00
if err != nil {
2023-08-12 15:26:32 +09:00
logger.Println("OnRoomDestroyed JSONNumIncrBy failed :", err)
2023-08-14 14:44:56 +09:00
} else if cnt == 0 {
2023-08-31 21:02:19 +09:00
tv.redison.Del(tv.redison.Context(), "_ref_"+name)
tv.redison.JSONDel(name, "$")
2023-08-12 15:26:32 +09:00
}
Squashed commit of the following: commit 8e1b232d57801c12edb94d02038b663d19c67b9b Author: mountain <mountain@action2quare.com> Date: Wed Jul 19 09:37:02 2023 +0900 InMemory 그룹을 redis로 변경 commit 01da5bb3a4b2c1857ce73d5722add85d347c976d Author: mountain <mountain@action2quare.com> Date: Tue Jul 18 01:31:39 2023 +0900 body를 marshaling하고 클라이언트에서 flatten함 commit ba61a11659eb790d98d41ce61d38dd001ccfa56c Author: mountain <mountain@action2quare.com> Date: Mon Jul 17 17:47:07 2023 +0900 gob 등록 commit 67cca13326aa517ba0de396b8d5bce736c1c86d8 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 18:41:24 2023 +0900 모듈 업데이트 commit 272c696c59652452da45e2704eabebc1e5f587a8 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 17:29:21 2023 +0900 json value 다시 되돌림 commit aa568ec3fa0016b4a1a43b29c578720ff65883c1 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 17:26:19 2023 +0900 SetOption 타입 변경 commit b9c4d8b21bbe47733f3bc061973743de06ce3b64 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 17:15:08 2023 +0900 objvalue marshalling 수정 commit 99834c146182cf51cbe4a24915f14c91208be994 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 17:01:06 2023 +0900 objlen 수정 commit 592112219ec5333031b56949d85e91ce5e46bf20 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 16:38:05 2023 +0900 gocommon 업데이트 commit 62485b6d54e7f8394272b1b80778f677b0fc5996 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 15:36:20 2023 +0900 redis json 마이그레이션 완료 commit d36dd13bb7b5c70825cae3ca5ea4d3cb62506ab6 Author: mountain <mountain@action2quare.com> Date: Sun Jul 16 02:51:41 2023 +0900 redis stack 사용
2023-07-19 09:37:40 +09:00
}
2023-08-31 21:02:19 +09:00
func (tv *Tavern) api(w http.ResponseWriter, r *http.Request) {
2023-05-24 16:10:00 +09:00
defer func() {
s := recover()
if s != nil {
logger.Error(s)
}
io.Copy(io.Discard, r.Body)
r.Body.Close()
}()
// 서버에서 오는 요청만 처리
apitoken := r.Header.Get("MG-X-API-TOKEN")
if apitoken != config.MaingateApiToken {
// 서버가 보내는 쿼리만 허용
logger.Println("MG-X-API-TOKEN is missing")
w.WriteHeader(http.StatusBadRequest)
return
}
2023-09-05 17:14:07 +09:00
funcname := r.URL.Query().Get("call")
if len(funcname) == 0 {
logger.Println("query param 'call' is missing")
2023-05-24 16:10:00 +09:00
w.WriteHeader(http.StatusBadRequest)
return
}
2023-09-08 11:37:50 +09:00
tv.httpApiBorker.Call(funcname, w, r)
2023-05-24 16:10:00 +09:00
}