86 lines
2.4 KiB
Go
86 lines
2.4 KiB
Go
// Package service - 会话服务
|
||
// 功能:用户会话管理、状态维护
|
||
package service
|
||
|
||
import (
|
||
"context"
|
||
"customer-server/dao"
|
||
|
||
"gitea.com/red-future/common/jaeger"
|
||
"gitea.com/red-future/common/rabbitmq"
|
||
"gitea.com/red-future/common/redis"
|
||
"github.com/gogf/gf/v2/encoding/gjson"
|
||
"github.com/gogf/gf/v2/os/glog"
|
||
)
|
||
|
||
// sessionService 会话服务(操作 session 表)
|
||
type sessionService struct{}
|
||
|
||
// SessionService 会话服务单例
|
||
var SessionService = new(sessionService)
|
||
|
||
// ============== RabbitMQ 消费者(归档延时消息)==============
|
||
|
||
// SessionArchiveConsumer 会话归档消费者
|
||
type SessionArchiveConsumer struct {
|
||
consumer *rabbitmq.Consumer
|
||
}
|
||
|
||
// NewSessionArchiveConsumer 创建会话归档消费者
|
||
func NewSessionArchiveConsumer(ctx context.Context) *SessionArchiveConsumer {
|
||
queueName := GetConfigString(ctx, "archive.queue")
|
||
return &SessionArchiveConsumer{
|
||
consumer: rabbitmq.NewConsumer(queueName, handleSessionArchive),
|
||
}
|
||
}
|
||
|
||
// Start 启动消费者
|
||
func (c *SessionArchiveConsumer) Start(ctx context.Context) (err error) {
|
||
glog.Info(ctx, "会话归档消费者启动...")
|
||
return c.consumer.Start(ctx)
|
||
}
|
||
|
||
// Stop 停止消费者
|
||
func (c *SessionArchiveConsumer) Stop(ctx context.Context) {
|
||
c.consumer.Stop(ctx)
|
||
}
|
||
|
||
// handleSessionArchive 处理会话归档消息
|
||
func handleSessionArchive(ctx context.Context, body []byte) (err error) {
|
||
ctx, span := jaeger.NewSpan(ctx, "consumer.session.archive")
|
||
defer span.End()
|
||
|
||
var msg redis.ArchiveMessage
|
||
if err = gjson.DecodeTo(body, &msg); err != nil {
|
||
jaeger.RecordError(ctx, err, "解析归档消息失败")
|
||
return
|
||
}
|
||
|
||
glog.Infof(ctx, "收到归档消息 - 用户: %s, Session: %s", msg.UserId, msg.SessionId)
|
||
|
||
// 检查用户是否在归档发送后有活跃(60分钟内)
|
||
isActive, err := redis.IsUserActive(ctx, msg.UserId, int64(redis.GetArchiveDelay()))
|
||
if err != nil {
|
||
jaeger.RecordError(ctx, err, "检查用户活跃状态失败")
|
||
return
|
||
}
|
||
|
||
if isActive {
|
||
glog.Infof(ctx, "用户 %s 在归档期间有活跃,跳过归档", msg.UserId)
|
||
return
|
||
}
|
||
|
||
// 执行归档
|
||
if err = dao.Session.Archive(ctx, msg.UserId, msg.SessionId); err != nil {
|
||
jaeger.RecordError(ctx, err, "归档会话失败")
|
||
return
|
||
}
|
||
|
||
// 清除 Session 缓存(需要tenantId)
|
||
// TODO: ArchiveMessage需要添加TenantId字段
|
||
redis.DelSessionCache(ctx, msg.TenantId, msg.UserId)
|
||
|
||
glog.Infof(ctx, "会话已归档 - 用户: %s, Session: %s", msg.UserId, msg.SessionId)
|
||
return
|
||
}
|