From a2da9a2aa4b8421b8f222707275a425d29c9530c Mon Sep 17 00:00:00 2001 From: LoveLosita <2810873701@qq.com> Date: Wed, 11 Feb 2026 17:31:12 +0800 Subject: [PATCH] =?UTF-8?q?Version:=200.2.4.dev.260211=20perf:=20?= =?UTF-8?q?=F0=9F=9A=80=20=E4=B8=BA=E8=8E=B7=E5=8F=96=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E9=98=9F=E5=88=97=E4=B8=AD=E7=9A=84=E4=BB=BB=E5=8A=A1=E4=B8=8E?= =?UTF-8?q?=E4=BB=8A=E6=97=A5=E6=97=A5=E7=A8=8B=E4=B8=80=E8=A7=88=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E6=96=B0=E5=A2=9E=E7=BC=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 为获取任务队列中的任务接口增加缓存机制 ⚡ - 为今日日程一览接口增加缓存机制 📅 - 提升接口访问性能与响应速度 ✅ --- backend/cmd/start.go | 4 +-- backend/dao/cache.go | 51 +++++++++++++++++++++++++++++++++++ backend/service/schedule.go | 25 +++++++++++++++-- backend/service/task-class.go | 12 +++++++++ backend/service/task.go | 37 +++++++++++++++++++++---- 5 files changed, 120 insertions(+), 9 deletions(-) diff --git a/backend/cmd/start.go b/backend/cmd/start.go index 0430751..793cd00 100644 --- a/backend/cmd/start.go +++ b/backend/cmd/start.go @@ -52,10 +52,10 @@ func Start() { manager := dao.NewManager(db) //service 层 userService := service.NewUserService(userRepo, cacheRepo) - taskSv := service.NewTaskService(taskRepo) + taskSv := service.NewTaskService(taskRepo, cacheRepo) courseService := service.NewCourseService(courseRepo, scheduleRepo) taskClassService := service.NewTaskClassService(taskClassRepo, cacheRepo, scheduleRepo, manager) - scheduleService := service.NewScheduleService(scheduleRepo, userRepo, taskClassRepo, manager) + scheduleService := service.NewScheduleService(scheduleRepo, userRepo, taskClassRepo, manager, cacheRepo) //api 层 userApi := api.NewUserHandler(userService) taskApi := api.NewTaskHandler(taskSv) diff --git a/backend/dao/cache.go b/backend/dao/cache.go index 1d0397f..5c0085b 100644 --- a/backend/dao/cache.go +++ b/backend/dao/cache.go @@ -85,3 +85,54 @@ func (d *CacheDAO) AcquireLock(ctx context.Context, key string, ttl time.Duratio func (d *CacheDAO) ReleaseLock(ctx context.Context, key string) error { return d.client.Del(ctx, key).Err() } + +func (d *CacheDAO) GetUserTasksFromCache(ctx context.Context, userID int) ([]model.GetUserTaskResp, error) { + key := fmt.Sprintf("smartflow:tasks:%d", userID) + var tasks []model.GetUserTaskResp + val, err := d.client.Get(ctx, key).Result() + if err != nil { + return nil, err // 注意:如果是 redis.Nil,交给 Service 层处理查库逻辑 + } + err = json.Unmarshal([]byte(val), &tasks) + return tasks, err +} + +func (d *CacheDAO) SetUserTasksToCache(ctx context.Context, userID int, tasks []model.GetUserTaskResp) error { + key := fmt.Sprintf("smartflow:tasks:%d", userID) + data, err := json.Marshal(tasks) + if err != nil { + return err + } + return d.client.Set(ctx, key, data, 24*time.Hour).Err() +} + +func (d *CacheDAO) DeleteUserTasksFromCache(ctx context.Context, userID int) error { + key := fmt.Sprintf("smartflow:tasks:%d", userID) + return d.client.Del(ctx, key).Err() +} + +func (d *CacheDAO) GetUserTodayScheduleFromCache(ctx context.Context, userID int) ([]model.UserTodaySchedule, error) { + key := fmt.Sprintf("smartflow:today_schedule:%d", userID) + var schedules []model.UserTodaySchedule + val, err := d.client.Get(ctx, key).Result() + if err != nil { + return nil, err // 注意:如果是 redis.Nil,交给 Service 层处理查库逻辑 + } + err = json.Unmarshal([]byte(val), &schedules) + return schedules, err +} + +func (d *CacheDAO) SetUserTodayScheduleToCache(ctx context.Context, userID int, schedules []model.UserTodaySchedule) error { + key := fmt.Sprintf("smartflow:today_schedule:%d", userID) + data, err := json.Marshal(schedules) + if err != nil { + return err + } + // 设置过期时间为当天剩余的时间,确保每天更新一次缓存 + return d.client.Set(ctx, key, data, time.Until(time.Date(time.Now().Year(), time.Now().Month(), time.Now().Day()+1, 0, 0, 0, 0, time.Now().Location()))).Err() +} + +func (d *CacheDAO) DeleteUserTodayScheduleFromCache(ctx context.Context, userID int) error { + key := fmt.Sprintf("smartflow:today_schedule:%d", userID) + return d.client.Del(ctx, key).Err() +} diff --git a/backend/service/schedule.go b/backend/service/schedule.go index 01b506c..1657fd9 100644 --- a/backend/service/schedule.go +++ b/backend/service/schedule.go @@ -2,6 +2,7 @@ package service import ( "context" + "errors" "fmt" "time" @@ -9,6 +10,7 @@ import ( "github.com/LoveLosita/smartflow/backend/dao" "github.com/LoveLosita/smartflow/backend/model" "github.com/LoveLosita/smartflow/backend/respond" + "github.com/go-redis/redis/v8" ) type ScheduleService struct { @@ -16,14 +18,16 @@ type ScheduleService struct { userDAO *dao.UserDAO taskClassDAO *dao.TaskClassDAO repoManager *dao.RepoManager // 统一管理多个 DAO 的事务 + cacheDAO *dao.CacheDAO // 需要在 ScheduleService 中使用缓存 } -func NewScheduleService(scheduleDAO *dao.ScheduleDAO, userDAO *dao.UserDAO, taskClassDAO *dao.TaskClassDAO, repoManager *dao.RepoManager) *ScheduleService { +func NewScheduleService(scheduleDAO *dao.ScheduleDAO, userDAO *dao.UserDAO, taskClassDAO *dao.TaskClassDAO, repoManager *dao.RepoManager, cacheDAO *dao.CacheDAO) *ScheduleService { return &ScheduleService{ scheduleDAO: scheduleDAO, userDAO: userDAO, taskClassDAO: taskClassDAO, repoManager: repoManager, + cacheDAO: cacheDAO, } } @@ -36,6 +40,16 @@ func (ss *ScheduleService) GetUserTodaySchedule(ctx context.Context, userID int) } return nil, err }*/ + //1.先尝试从缓存获取数据 + cachedResp, err := ss.cacheDAO.GetUserTodayScheduleFromCache(ctx, userID) + if err == nil { + // 缓存命中,直接返回 + return cachedResp, nil + } + // 如果是 redis.Nil 错误,说明缓存未命中,我们继续查库 + if !errors.Is(err, redis.Nil) { + return nil, err + } //2.获取当前日期 /*curTime := time.Now().Format("2006-01-02")*/ curTime := "2026-03-02" //测试数据 @@ -43,7 +57,6 @@ func (ss *ScheduleService) GetUserTodaySchedule(ctx context.Context, userID int) if err != nil { return nil, err } - fmt.Println(week, dayOfWeek) //3.查询用户当天的日程安排 schedules, err := ss.scheduleDAO.GetUserTodaySchedule(ctx, userID, week, dayOfWeek) //测试数据 if err != nil { @@ -51,6 +64,8 @@ func (ss *ScheduleService) GetUserTodaySchedule(ctx context.Context, userID int) } //4.转换为前端需要的格式 todaySchedules := conv.SchedulesToUserTodaySchedule(schedules) + //5.将查询结果存入缓存,设置过期时间为当天结束 + err = ss.cacheDAO.SetUserTodayScheduleToCache(ctx, userID, todaySchedules) return todaySchedules, nil } @@ -213,5 +228,11 @@ func (ss *ScheduleService) DeleteScheduleEvent(ctx context.Context, requests []m if err != nil { return err } + //4.删除成功后,清除相关缓存(如果有的话),以保证数据一致性 + err = ss.cacheDAO.DeleteUserTodayScheduleFromCache(ctx, userID) + if err != nil { + // 缓存删除失败,记录日志但不影响正常返回数据 + fmt.Printf("Failed to delete user today schedule cache for userID %d: %v\n", userID, err) + } return nil } diff --git a/backend/service/task-class.go b/backend/service/task-class.go index b81794b..1839e24 100644 --- a/backend/service/task-class.go +++ b/backend/service/task-class.go @@ -240,6 +240,12 @@ func (sv *TaskClassService) AddTaskClassItemIntoSchedule(ctx context.Context, re // 这里处理最终的错误返回,比如 respond.Error return err } + //6.事务提交成功后,清除相关缓存(如果有的话),以保证数据一致性 + err = sv.cacheRepo.DeleteTaskClassList(ctx, userID) + if err != nil { + // 缓存删除失败,记录日志但不影响正常返回数据 + log.Printf("Failed to delete task class list cache for userID %d: %v", userID, err) + } return nil } @@ -287,5 +293,11 @@ func (sv *TaskClassService) DeleteTaskClassItem(ctx context.Context, userID int, }); err != nil { return err } + //3.事务提交成功后,清除相关缓存(如果有的话),以保证数据一致性 + err = sv.cacheRepo.DeleteUserTodayScheduleFromCache(ctx, userID) + if err != nil { + // 缓存删除失败,记录日志但不影响正常返回数据 + log.Printf("Failed to delete task class list cache for userID %d: %v", userID, err) + } return nil } diff --git a/backend/service/task.go b/backend/service/task.go index 6e85953..d9f934d 100644 --- a/backend/service/task.go +++ b/backend/service/task.go @@ -2,22 +2,27 @@ package service import ( "context" + "errors" + "log" "github.com/LoveLosita/smartflow/backend/conv" "github.com/LoveLosita/smartflow/backend/dao" "github.com/LoveLosita/smartflow/backend/model" "github.com/LoveLosita/smartflow/backend/respond" + "github.com/go-redis/redis/v8" ) type TaskService struct { // 伸出手:准备接住 DAO - dao *dao.TaskDAO + dao *dao.TaskDAO + cache *dao.CacheDAO } // NewTaskService 创建 TaskService 实例 -func NewTaskService(dao *dao.TaskDAO) *TaskService { +func NewTaskService(dao *dao.TaskDAO, cache *dao.CacheDAO) *TaskService { return &TaskService{ - dao: dao, + dao: dao, + cache: cache, } } @@ -35,16 +40,38 @@ func (ts *TaskService) AddTask(ctx context.Context, req *model.UserAddTaskReques } //4. 调用 conv 层进行响应转换 response := conv.ModelToUserAddTaskResponse(createdTask) + //5. 添加成功后,清除相关缓存(如果有的话),以保证数据一致性 + err = ts.cache.DeleteUserTasksFromCache(ctx, userID) + if err != nil { + // 缓存删除失败,记录日志但不影响正常返回数据 + log.Printf("Failed to delete user tasks cache for userID %d: %v", userID, err) + } return response, nil } func (ts *TaskService) GetUserTasks(ctx context.Context, userID int) ([]model.GetUserTaskResp, error) { - //1. 调用 courseDAO 层获取数据 + //1. 先尝试从缓存获取数据 + cachedResp, err := ts.cache.GetUserTasksFromCache(ctx, userID) + if err == nil { + // 缓存命中,直接返回 + return cachedResp, nil + } + // 如果是 redis.Nil 错误,说明缓存未命中,我们继续查库 + if !errors.Is(err, redis.Nil) { + return nil, err // 其他错误,返回错误 + } + //2. 调用 courseDAO 层获取数据 tasks, err := ts.dao.GetTasksByUserID(userID) if err != nil { return nil, err } - //2. 调用 conv 层进行响应转换 + //3. 调用 conv 层进行响应转换 response := conv.ModelToGetUserTasksResp(tasks) + //4. 将结果存入缓存,设置合理的过期时间(24h) + err = ts.cache.SetUserTasksToCache(ctx, userID, response) + if err != nil { + // 缓存写入失败,记录日志但不影响正常返回数据 + log.Printf("Failed to cache user tasks for userID %d: %v", userID, err) + } return response, nil }