You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
198 lines
4.8 KiB
198 lines
4.8 KiB
package logic |
|
|
|
import ( |
|
"context" |
|
"fmt" |
|
"google.golang.org/grpc" |
|
"google.golang.org/grpc/reflection" |
|
"google.golang.org/protobuf/types/known/emptypb" |
|
"net" |
|
"sonet/api/gen/chat" |
|
"sonet/pkg/config" |
|
"sonet/pkg/grpc/discovery" |
|
"sonet/pkg/grpc/interceptor" |
|
"sonet/pkg/protocol/deliver" |
|
"sonet/pkg/protocol/session" |
|
"sonet/pkg/utils/collect" |
|
"sonet/pkg/utils/logger" |
|
"sonet/pkg/utils/shutdown" |
|
"strconv" |
|
"sync/atomic" |
|
"time" |
|
) |
|
|
|
type ChatServer struct { |
|
chat.UnimplementedChatServer |
|
deliver *deliver.Deliver |
|
deliverGroup *deliver.GroupDeliver |
|
roomId int64 |
|
rooms *collect.ConcurrentMap[string, *chat.Group] |
|
} |
|
|
|
func NewChatServer(deliver *deliver.Deliver, deliverGroup *deliver.GroupDeliver) *ChatServer { |
|
rooms := collect.NewConcurrentMap[string, *chat.Group](32, func(k string) string { return k }) |
|
return &ChatServer{ |
|
deliver: deliver, |
|
deliverGroup: deliverGroup, |
|
roomId: 90000, |
|
rooms: rooms, |
|
} |
|
} |
|
|
|
func (s *ChatServer) Run(conf config.GrpcConfig, registry discovery.Registry) (err error) { |
|
server := grpc.NewServer( |
|
config.GetGrpcOptions( |
|
conf, |
|
grpc.UnaryInterceptor(interceptor.RecoverInterceptor), |
|
)..., |
|
) |
|
if !conf.NoReflection { |
|
// 注册反射服务 |
|
reflection.Register(server) |
|
} |
|
chat.RegisterChatServer(server, s) |
|
listen, err := net.Listen("tcp", conf.Address) |
|
if err != nil { |
|
return |
|
} |
|
|
|
// registry discovery |
|
register := conf.Register |
|
if register.Name == "" { |
|
register.Name = chat.Chat_ServiceDesc.ServiceName |
|
} |
|
if register.Addr == "" { |
|
register.Addr = conf.Address |
|
} |
|
ctx, cancel := context.WithCancel(context.Background()) |
|
err = registry.Registry(ctx, register) |
|
if err != nil { |
|
panic(err) |
|
} |
|
shutdown.AddHook(cancel) |
|
|
|
// run serve |
|
logger.Infof("%s grpc server running %s\n", register.Name, listen.Addr().String()) |
|
err = server.Serve(listen) |
|
return |
|
} |
|
|
|
func (s *ChatServer) Send(ctx context.Context, req *chat.ReqSend) (*chat.ResSend, error) { |
|
subject, err := session.GetSubject(ctx) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
// TODO 消息队列消峰发送,ack 队列重发(可异步发送),asc超时第二次发送时同步判断是否不在线? |
|
|
|
// 投递消息 |
|
message := &chat.ChatMessage{Sender: subject.Uid, Content: req.Content} |
|
_, err = s.deliver.Deliver(ctx, message, req.Receiver) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
return &chat.ResSend{}, nil |
|
} |
|
|
|
func (s *ChatServer) RoomSend(ctx context.Context, req *chat.ReqRoomSend) (res *chat.ResSend, err error) { |
|
subject, err := session.GetSubject(ctx) |
|
if err != nil { |
|
return nil, err |
|
} |
|
gMessage := &chat.ChatMessage{ |
|
Type: 1, |
|
Sender: subject.Uid, |
|
Gid: req.Gid, |
|
Content: req.Message, |
|
} |
|
err = s.deliverGroup.DeliverGroup(ctx, req.Gid, gMessage) |
|
return |
|
} |
|
|
|
func (s *ChatServer) RoomCreate(ctx context.Context, req *chat.ReqRoomCreate) (res *chat.ResRoomCreate, err error) { |
|
subject, err := session.GetSubject(ctx) |
|
if err != nil { |
|
return nil, err |
|
} |
|
logger.Infof("create room: %s", req.Gname) |
|
|
|
group := &chat.Group{ |
|
Gid: strconv.Itoa(int(atomic.AddInt64(&s.roomId, 1))), |
|
MasterUid: subject.Uid, |
|
UserLimit: 10000, |
|
UserNum: 1, |
|
Gname: req.Gname, |
|
CreateUid: subject.Uid, |
|
CreateAt: time.Now().UnixMilli(), |
|
} |
|
|
|
// join postal group |
|
err = s.deliverGroup.GroupJoin(ctx, subject.Uid, []string{group.Gid}) |
|
if err != nil { |
|
return |
|
} |
|
|
|
s.rooms.Store(group.Gid, group) |
|
res = &chat.ResRoomCreate{Group: group} |
|
return |
|
} |
|
|
|
func (s *ChatServer) RoomJoin(ctx context.Context, req *chat.ReqRoomJoin) (_ *emptypb.Empty, err error) { |
|
subject, err := session.GetSubject(ctx) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
room, ok := s.rooms.Load(req.Gid) |
|
if !ok { |
|
err = fmt.Errorf("room %s not exists", req.Gid) |
|
return |
|
} |
|
atomic.AddInt32(&room.UserNum, 1) |
|
|
|
err = s.deliverGroup.GroupJoin(ctx, subject.Uid, []string{req.Gid}) |
|
return |
|
} |
|
|
|
func (s *ChatServer) RoomLeave(ctx context.Context, req *chat.ReqRoomLeave) (_ *emptypb.Empty, err error) { |
|
subject, err := session.GetSubject(ctx) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
room, ok := s.rooms.Load(req.Gid) |
|
if !ok { |
|
err = fmt.Errorf("room %s not exists", req.Gid) |
|
return |
|
} |
|
atomic.AddInt32(&room.UserNum, -1) |
|
|
|
err = s.deliverGroup.GroupLeave(ctx, subject.Uid, []string{req.Gid}) |
|
return |
|
} |
|
|
|
func (s *ChatServer) RoomKickOut(ctx context.Context, req *chat.ReqRoomKickOut) (_ *emptypb.Empty, err error) { |
|
return |
|
} |
|
|
|
func (s *ChatServer) RoomInfo(ctx context.Context, req *chat.ReqRoomInfo) (res *chat.ResRoomInfo, err error) { |
|
room, ok := s.rooms.Load(req.Gid) |
|
if !ok { |
|
err = fmt.Errorf("room %s not exists", req.Gid) |
|
return |
|
} |
|
|
|
res = &chat.ResRoomInfo{Group: room} |
|
return |
|
} |
|
|
|
func (s *ChatServer) RoomList(ctx context.Context, req *chat.ReqRoomList) (res *chat.ResRoomList, err error) { |
|
rooms := make([]*chat.Group, 16) |
|
s.rooms.Range(func(_ string, room *chat.Group) bool { |
|
rooms = append(rooms, room) |
|
return true |
|
}) |
|
res = &chat.ResRoomList{Groups: rooms} |
|
return |
|
}
|
|
|