| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318 |
- package service
-
- import (
- "context"
- "errors"
- "time"
-
- "git.x2erp.com/qdy/go-base/logger"
- "git.x2erp.com/qdy/go-db/factory/mongodb"
- "git.x2erp.com/qdy/go-svc-code/internal/model"
- "go.mongodb.org/mongo-driver/bson"
- "go.mongodb.org/mongo-driver/bson/primitive"
- )
-
- // SessionStore 会话存储服务
- type SessionStore struct {
- mongoFactory *mongodb.MongoDBFactory
- }
-
- // NewSessionStore 创建新的会话存储服务
- func NewSessionStore(factory *mongodb.MongoDBFactory) *SessionStore {
- return &SessionStore{mongoFactory: factory}
- }
-
- // Create 创建会话
- func (s *SessionStore) Create(ctx context.Context, session *model.Session) error {
- if session.ID == "" {
- return errors.New("session ID cannot be empty")
- }
- if session.Title == "" {
- return errors.New("session title cannot be empty")
- }
- if session.AgentName == "" {
- return errors.New("agent name cannot be empty")
- }
-
- // 设置时间戳
- now := time.Now()
- if session.CreatedAt.IsZero() {
- session.CreatedAt = now
- }
- if session.UpdatedAt.IsZero() {
- session.UpdatedAt = now
- }
-
- // 设置默认状态为需求文档
- if session.Status == "" {
- session.Status = model.StatusRequirementDocument
- }
-
- // 插入到MongoDB
- _, success := s.mongoFactory.InsertOneWithResult(model.Session{}.CollectionName(), session)
- if !success {
- logger.Error("创建会话失败", "session_id", session.ID, "title", session.Title)
- return errors.New("failed to create session")
- }
-
- logger.Debug("创建会话成功", "session_id", session.ID, "title", session.Title)
- return nil
- }
-
- // GetByID 根据ID获取会话
- func (s *SessionStore) GetByID(ctx context.Context, id string) (*model.Session, error) {
- if id == "" {
- return nil, errors.New("session ID cannot be empty")
- }
-
- filter := bson.M{"_id": id}
- var result model.Session
-
- err := s.mongoFactory.FindOne(model.Session{}.CollectionName(), filter, &result)
- if err != nil {
- if err.Error() == "mongo: no documents in result" {
- return nil, nil // 未找到会话
- }
- logger.Error("根据ID查询会话失败", "session_id", id, "error", err)
- return nil, err
- }
-
- return &result, nil
- }
-
- // GetByUser 根据用户ID获取会话
- func (s *SessionStore) GetByUser(ctx context.Context, userID string) ([]*model.Session, error) {
- if userID == "" {
- return nil, errors.New("user ID cannot be empty")
- }
-
- filter := bson.M{"user_id": userID}
- var sessions []*model.Session
-
- err := s.mongoFactory.Find(model.Session{}.CollectionName(), filter, &sessions)
- if err != nil {
- logger.Error("根据用户查询会话失败", "user_id", userID, "error", err)
- return nil, err
- }
-
- return sessions, nil
- }
-
- // Update 更新会话(状态和标题)
- func (s *SessionStore) Update(ctx context.Context, id string, title, status string) error {
- if id == "" {
- return errors.New("session ID cannot be empty")
- }
-
- // 检查会话是否存在
- session, err := s.GetByID(ctx, id)
- if err != nil {
- return err
- }
- if session == nil {
- return errors.New("session not found")
- }
-
- // 已发布的会话不能修改
- if session.Status == model.StatusRelease {
- return errors.New("released session cannot be modified")
- }
-
- // 构建更新内容
- update := bson.M{
- "updated_at": time.Now(),
- }
- if title != "" {
- update["title"] = title
- }
- if status != "" {
- // 验证状态值
- if !model.IsValidStatus(status) {
- return errors.New("invalid status value")
- }
- update["status"] = status
- }
-
- filter := bson.M{"_id": id}
- success, _ := s.mongoFactory.UpdateOne(model.Session{}.CollectionName(), filter, update)
- if !success {
- logger.Error("更新会话失败", "session_id", id)
- return errors.New("failed to update session")
- }
-
- logger.Debug("更新会话成功", "session_id", id)
- return nil
- }
-
- // Delete 删除会话
- func (s *SessionStore) Delete(ctx context.Context, id string) error {
- if id == "" {
- return errors.New("session ID cannot be empty")
- }
-
- // 检查会话是否存在
- session, err := s.GetByID(ctx, id)
- if err != nil {
- return err
- }
- if session == nil {
- return errors.New("session not found")
- }
-
- // 已发布的会话不能删除
- if session.Status == model.StatusRelease {
- return errors.New("released session cannot be deleted")
- }
-
- filter := bson.M{"_id": id}
- success, deletedCount := s.mongoFactory.DeleteOne(model.Session{}.CollectionName(), filter)
- if !success {
- logger.Error("删除会话失败", "session_id", id)
- return errors.New("failed to delete session")
- }
-
- logger.Debug("删除会话成功", "session_id", id, "deleted_count", deletedCount)
- return nil
- }
-
- // ListQuery 列表查询参数
- type ListQuery struct {
- Page int `form:"page" binding:"min=1"` // 页码,从1开始
- PageSize int `form:"pageSize" binding:"min=1,max=100"` // 每页大小,最大100
- Title string `form:"title,omitempty"` // 标题搜索(模糊匹配)
- Status string `form:"status,omitempty"` // 状态筛选
- UserID string // 用户ID(从上下文中获取)
- TenantID string // 租户ID(从上下文中获取)
- }
-
- // ListResult 列表查询结果
- type ListResult struct {
- Sessions []*model.Session `json:"sessions"`
- TotalCount int64 `json:"total_count"`
- Page int `json:"page"`
- PageSize int `json:"page_size"`
- TotalPages int `json:"total_pages"`
- }
-
- // List 分页查询会话列表
- func (s *SessionStore) List(ctx context.Context, query *ListQuery) (*ListResult, error) {
- // 构建查询条件
- filter := bson.M{
- "user_id": query.UserID,
- "tenant_id": query.TenantID,
- }
-
- // 标题模糊匹配
- if query.Title != "" {
- filter["title"] = bson.M{"$regex": primitive.Regex{Pattern: query.Title, Options: "i"}}
- }
-
- // 状态筛选
- if query.Status != "" {
- filter["status"] = query.Status
- }
-
- // 查询所有匹配的记录(TODO: 优化为分页查询)
- var allSessions []*model.Session
- err := s.mongoFactory.Find(model.Session{}.CollectionName(), filter, &allSessions)
- if err != nil {
- logger.Error("查询会话列表失败", "error", err)
- return nil, err
- }
-
- // 按创建时间倒序排序
- // 由于MongoDB驱动可能已经按_id排序,我们需要手动排序
- // 这里简单反转切片(假设Find返回的顺序是插入顺序)
- // 实际应该使用聚合管道排序,但当前MongoDB工厂不支持
- logger.Warn("会话列表查询使用内存分页,数据量大时性能可能受影响", "count", len(allSessions))
-
- // 计算分页
- if query.Page < 1 {
- query.Page = 1
- }
- if query.PageSize < 1 {
- query.PageSize = 20
- } else if query.PageSize > 100 {
- query.PageSize = 100
- }
-
- totalCount := int64(len(allSessions))
- skip := (query.Page - 1) * query.PageSize
-
- // 计算分页切片
- var sessions []*model.Session
- if skip < len(allSessions) {
- end := skip + query.PageSize
- if end > len(allSessions) {
- end = len(allSessions)
- }
- sessions = allSessions[skip:end]
- }
-
- // 计算总页数
- totalPages := int(totalCount) / query.PageSize
- if int(totalCount)%query.PageSize > 0 {
- totalPages++
- }
-
- result := &ListResult{
- Sessions: sessions,
- TotalCount: totalCount,
- Page: query.Page,
- PageSize: query.PageSize,
- TotalPages: totalPages,
- }
-
- return result, nil
- }
-
- // EnsureIndexes 确保集合索引
- func (s *SessionStore) EnsureIndexes(ctx context.Context) error {
- // 主键索引(_id)已自动创建
-
- // 用户ID索引(常用查询条件)
- userIDIndexKeys := bson.D{{Key: "user_id", Value: 1}}
- userIDSuccess := s.mongoFactory.CreateIndex(model.Session{}.CollectionName(), userIDIndexKeys)
- if !userIDSuccess {
- logger.Error("创建用户ID索引失败")
- return errors.New("failed to create user_id index")
- }
-
- // 租户ID索引
- tenantIDIndexKeys := bson.D{{Key: "tenant_id", Value: 1}}
- tenantIDSuccess := s.mongoFactory.CreateIndex(model.Session{}.CollectionName(), tenantIDIndexKeys)
- if !tenantIDSuccess {
- logger.Error("创建租户ID索引失败")
- return errors.New("failed to create tenant_id index")
- }
-
- // 状态索引(用于筛选)
- statusIndexKeys := bson.D{{Key: "status", Value: 1}}
- statusSuccess := s.mongoFactory.CreateIndex(model.Session{}.CollectionName(), statusIndexKeys)
- if !statusSuccess {
- logger.Error("创建状态索引失败")
- return errors.New("failed to create status index")
- }
-
- // 创建时间索引(用于排序)
- createdAtIndexKeys := bson.D{{Key: "created_at", Value: -1}}
- createdAtSuccess := s.mongoFactory.CreateIndex(model.Session{}.CollectionName(), createdAtIndexKeys)
- if !createdAtSuccess {
- logger.Error("创建创建时间索引失败")
- return errors.New("failed to create created_at index")
- }
-
- // 复合索引:用户ID + 创建时间(常用查询组合)
- userCreatedIndexKeys := bson.D{
- {Key: "user_id", Value: 1},
- {Key: "created_at", Value: -1},
- }
- userCreatedSuccess := s.mongoFactory.CreateIndex(model.Session{}.CollectionName(), userCreatedIndexKeys)
- if !userCreatedSuccess {
- logger.Error("创建用户-创建时间复合索引失败")
- return errors.New("failed to create user_id-created_at index")
- }
-
- logger.Debug("会话集合索引创建成功")
- return nil
- }
|