go_dreamfactory/modules/gateway/agentmgr_comp.go
2023-06-06 09:52:44 +08:00

226 lines
6.9 KiB
Go

package gateway
import (
"context"
"fmt"
"go_dreamfactory/comm"
"go_dreamfactory/pb"
"go_dreamfactory/sys/db"
"sync"
"go_dreamfactory/lego/base"
"go_dreamfactory/lego/core"
"go_dreamfactory/lego/core/cbase"
"go_dreamfactory/lego/sys/log"
"google.golang.org/protobuf/proto"
)
/*
用户代理对象管理组件
*/
type AgentMgrComp struct {
cbase.ModuleCompBase
options *Options
service base.IRPCXService
module *Gateway
agents *sync.Map
}
func (this *AgentMgrComp) Init(service core.IService, module core.IModule, comp core.IModuleComp, options core.IModuleOptions) (err error) {
err = this.ModuleCompBase.Init(service, module, comp, options)
this.options = options.(*Options)
this.service = service.(base.IRPCXService)
this.module = module.(*Gateway)
this.agents = new(sync.Map)
return
}
func (this *AgentMgrComp) Start() (err error) {
err = this.ModuleCompBase.Start()
return
}
// Connect 加入新的用户
func (this *AgentMgrComp) Connect(a IAgent) {
this.agents.Store(a.SessionId(), a)
}
// DisConnect 移除断开的用户
func (this *AgentMgrComp) DisConnect(a IAgent) {
this.agents.Delete(a.SessionId())
if a.UserId() != "" { //登录用户 通知业务服务处理玩家离线相关
if _, err := this.service.RpcGo(context.Background(), fmt.Sprintf("%s/%s", comm.Service_Worker, a.WorkerId()), string(comm.Rpc_GatewayNoticeUserClose), &pb.NoticeUserCloseReq{
Ip: a.IP(),
ServiceTag: this.service.GetTag(),
GatewayServiceId: this.service.GetId(),
UserSessionId: a.SessionId(),
UserId: a.UserId(),
}, nil); err != nil {
log.Errorf("uId:%s Rpc_NoticeUserClose err:%v", a.UserId(), err)
}
//通知运维服务器 处理用户离线数据同步
if _, err := this.service.RpcGo(context.Background(), comm.Service_Mainte, string(comm.Rpc_GatewayNoticeUserClose), &pb.NoticeUserCloseReq{
Ip: a.IP(),
ServiceTag: this.service.GetTag(),
GatewayServiceId: this.service.GetId(),
UserSessionId: a.SessionId(),
UserId: a.UserId(),
}, nil); err != nil {
log.Errorf("uId:%s Rpc_NoticeUserClose err:%v", a.UserId(), err)
}
// if this.options.SpanServiceTag != "" {
//推送跨服集群处理
if _, err := this.service.AcrossClusterRpcGo(context.Background(), db.CrossTag(), comm.Service_Worker, string(comm.Rpc_GatewayNoticeUserClose), &pb.NoticeUserCloseReq{
Ip: a.IP(),
ServiceTag: this.service.GetTag(),
GatewayServiceId: this.service.GetId(),
UserSessionId: a.SessionId(),
UserId: a.UserId(),
}, nil); err != nil {
log.Errorf("uId:%s Rpc_NoticeUserClose err:%v", a.UserId(), err)
}
// }
}
}
// Bind 用户绑定Id
func (this *AgentMgrComp) Bind(ctx context.Context, args *pb.AgentBuildReq, reply *pb.RPCMessageReply) error {
if a, ok := this.agents.Load(args.UserSessionId); ok {
agent := a.(IAgent)
agent.Bind(args.UserId, args.WorkerId)
// if this.options.SpanServiceTag != "" { //跨服集群配置存在 推送通知过去
//推送跨服集群处理
if _, err := this.service.AcrossClusterRpcGo(context.Background(), db.CrossTag(), comm.Service_Worker, string(comm.Rpc_GatewayNoticeUserLogin), &pb.NoticeUserLoginReq{
Ip: agent.IP(),
ServiceTag: this.service.GetTag(),
GatewayServiceId: this.service.GetId(),
UserSessionId: agent.SessionId(),
UserId: agent.UserId(),
}, nil); err != nil {
log.Errorf("uId:%s clusterTag:%s Rpc_NoticeUserLogin err:%v", agent.UserId(), db.CrossTag(), err)
}
// }
} else {
reply.ErrorData = &pb.ErrorData{
Code: pb.ErrorCode_UserSessionNobeing,
Title: pb.ErrorCode_UserSessionNobeing.ToString(),
Message: fmt.Sprintf("绑定uid:%s失败!", args.WorkerId),
}
}
return nil
}
// UnBind 用户解绑Id
func (this *AgentMgrComp) UnBind(ctx context.Context, args *pb.AgentUnBuildReq, reply *pb.RPCMessageReply) error {
if a, ok := this.agents.Load(args.UserSessionId); ok {
a.(IAgent).UnBind()
} else {
reply.ErrorData = &pb.ErrorData{
Code: pb.ErrorCode_UserSessionNobeing,
Title: pb.ErrorCode_UserSessionNobeing.ToString(),
Message: fmt.Sprintf("解绑SessionId:%s失败!", args.UserSessionId),
}
}
return nil
}
// SendMsgToAgent 向用户发送消息
func (this *AgentMgrComp) SendMsgToAgent(ctx context.Context, args *pb.AgentSendMessageReq, reply *pb.RPCMessageReply) error {
this.module.Debugf("SendMsgToAgent: agent:%s msg:%v", args.UserSessionId, args.Reply)
if a, ok := this.agents.Load(args.UserSessionId); ok {
for _, v := range args.Reply {
a.(IAgent).WriteMsg(v)
}
} else {
reply.ErrorData = &pb.ErrorData{
Code: pb.ErrorCode_UserSessionNobeing,
Title: pb.ErrorCode_UserSessionNobeing.ToString(),
Message: fmt.Sprintf("解绑SessionId:%s失败!", args.UserSessionId),
}
}
return nil
}
// SendMsgToAgents 向多个户发送消息
func (this *AgentMgrComp) SendMsgToAgents(ctx context.Context, args *pb.BatchMessageReq, reply *pb.RPCMessageReply) (err error) {
var (
data []byte
)
msg := &pb.UserMessage{
MainType: args.MainType,
SubType: args.SubType,
Data: args.Data,
}
this.module.Debugf("SendMsgToAgents: agents:%v msg:%v", args.UserSessionIds, msg)
if data, err = proto.Marshal(msg); err != nil {
return
}
for _, v := range args.UserSessionIds {
if a, ok := this.agents.Load(v); ok {
agent := a.(IAgent)
if agent.UserId() != "" { //自发送登录用户
if err = agent.WriteBytes(data); err != nil {
this.module.Errorln(err)
}
}
}
}
return nil
}
// SendMsgToAllAgent 向所有户发送消息
func (this *AgentMgrComp) SendMsgToAllAgent(ctx context.Context, args *pb.BroadCastMessageReq, reply *pb.RPCMessageReply) (err error) {
var (
data []byte
)
msg := &pb.UserMessage{
MainType: args.MainType,
SubType: args.SubType,
Data: args.Data,
}
this.module.Debugf("SendMsgToAllAgent: msg:%v", msg)
if data, err = proto.Marshal(msg); err != nil {
return
}
this.agents.Range(func(key, value any) bool {
agent := value.(IAgent)
if agent.UserId() != "" { //只发送登录用户
agent.WriteBytes(data)
}
return true
})
return
}
// CloseAgent 关闭某个用户
func (this *AgentMgrComp) CloseAgent(ctx context.Context, args *pb.AgentCloseeReq, reply *pb.RPCMessageReply) error {
if a, ok := this.agents.Load(args.UserSessionId); ok {
a.(IAgent).Close()
} else {
reply.ErrorData = &pb.ErrorData{
Code: pb.ErrorCode_UserSessionNobeing,
Title: pb.ErrorCode_UserSessionNobeing.ToString(),
Message: fmt.Sprintf("解绑SessionId:%s失败!", args.UserSessionId),
}
}
return nil
}
// 用户代理心跳 维护session表对象
func (this *AgentMgrComp) agentsHeartbeat() {
// var (
// loadpipe *pipe.RedisPipe
// loadpipe *pipe.RedisPipe
// )
// this.agents.Range(func(key, value any) bool {
// agent := value.(IAgent)
// if agent.UserId() != "" { //只发送登录用户
// }
// return true
// })
}