Version: 0.2.4.dev.260211
perf: 🚀 为获取任务队列中的任务与今日日程一览接口新增缓存 - 为获取任务队列中的任务接口增加缓存机制 ⚡ - 为今日日程一览接口增加缓存机制 📅 - 提升接口访问性能与响应速度 ✅
This commit is contained in:
@@ -52,10 +52,10 @@ func Start() {
|
|||||||
manager := dao.NewManager(db)
|
manager := dao.NewManager(db)
|
||||||
//service 层
|
//service 层
|
||||||
userService := service.NewUserService(userRepo, cacheRepo)
|
userService := service.NewUserService(userRepo, cacheRepo)
|
||||||
taskSv := service.NewTaskService(taskRepo)
|
taskSv := service.NewTaskService(taskRepo, cacheRepo)
|
||||||
courseService := service.NewCourseService(courseRepo, scheduleRepo)
|
courseService := service.NewCourseService(courseRepo, scheduleRepo)
|
||||||
taskClassService := service.NewTaskClassService(taskClassRepo, cacheRepo, scheduleRepo, manager)
|
taskClassService := service.NewTaskClassService(taskClassRepo, cacheRepo, scheduleRepo, manager)
|
||||||
scheduleService := service.NewScheduleService(scheduleRepo, userRepo, taskClassRepo, manager)
|
scheduleService := service.NewScheduleService(scheduleRepo, userRepo, taskClassRepo, manager, cacheRepo)
|
||||||
//api 层
|
//api 层
|
||||||
userApi := api.NewUserHandler(userService)
|
userApi := api.NewUserHandler(userService)
|
||||||
taskApi := api.NewTaskHandler(taskSv)
|
taskApi := api.NewTaskHandler(taskSv)
|
||||||
|
|||||||
@@ -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 {
|
func (d *CacheDAO) ReleaseLock(ctx context.Context, key string) error {
|
||||||
return d.client.Del(ctx, key).Err()
|
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()
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -9,6 +10,7 @@ import (
|
|||||||
"github.com/LoveLosita/smartflow/backend/dao"
|
"github.com/LoveLosita/smartflow/backend/dao"
|
||||||
"github.com/LoveLosita/smartflow/backend/model"
|
"github.com/LoveLosita/smartflow/backend/model"
|
||||||
"github.com/LoveLosita/smartflow/backend/respond"
|
"github.com/LoveLosita/smartflow/backend/respond"
|
||||||
|
"github.com/go-redis/redis/v8"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ScheduleService struct {
|
type ScheduleService struct {
|
||||||
@@ -16,14 +18,16 @@ type ScheduleService struct {
|
|||||||
userDAO *dao.UserDAO
|
userDAO *dao.UserDAO
|
||||||
taskClassDAO *dao.TaskClassDAO
|
taskClassDAO *dao.TaskClassDAO
|
||||||
repoManager *dao.RepoManager // 统一管理多个 DAO 的事务
|
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{
|
return &ScheduleService{
|
||||||
scheduleDAO: scheduleDAO,
|
scheduleDAO: scheduleDAO,
|
||||||
userDAO: userDAO,
|
userDAO: userDAO,
|
||||||
taskClassDAO: taskClassDAO,
|
taskClassDAO: taskClassDAO,
|
||||||
repoManager: repoManager,
|
repoManager: repoManager,
|
||||||
|
cacheDAO: cacheDAO,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,6 +40,16 @@ func (ss *ScheduleService) GetUserTodaySchedule(ctx context.Context, userID int)
|
|||||||
}
|
}
|
||||||
return nil, err
|
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.获取当前日期
|
//2.获取当前日期
|
||||||
/*curTime := time.Now().Format("2006-01-02")*/
|
/*curTime := time.Now().Format("2006-01-02")*/
|
||||||
curTime := "2026-03-02" //测试数据
|
curTime := "2026-03-02" //测试数据
|
||||||
@@ -43,7 +57,6 @@ func (ss *ScheduleService) GetUserTodaySchedule(ctx context.Context, userID int)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
fmt.Println(week, dayOfWeek)
|
|
||||||
//3.查询用户当天的日程安排
|
//3.查询用户当天的日程安排
|
||||||
schedules, err := ss.scheduleDAO.GetUserTodaySchedule(ctx, userID, week, dayOfWeek) //测试数据
|
schedules, err := ss.scheduleDAO.GetUserTodaySchedule(ctx, userID, week, dayOfWeek) //测试数据
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -51,6 +64,8 @@ func (ss *ScheduleService) GetUserTodaySchedule(ctx context.Context, userID int)
|
|||||||
}
|
}
|
||||||
//4.转换为前端需要的格式
|
//4.转换为前端需要的格式
|
||||||
todaySchedules := conv.SchedulesToUserTodaySchedule(schedules)
|
todaySchedules := conv.SchedulesToUserTodaySchedule(schedules)
|
||||||
|
//5.将查询结果存入缓存,设置过期时间为当天结束
|
||||||
|
err = ss.cacheDAO.SetUserTodayScheduleToCache(ctx, userID, todaySchedules)
|
||||||
return todaySchedules, nil
|
return todaySchedules, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,5 +228,11 @@ func (ss *ScheduleService) DeleteScheduleEvent(ctx context.Context, requests []m
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -240,6 +240,12 @@ func (sv *TaskClassService) AddTaskClassItemIntoSchedule(ctx context.Context, re
|
|||||||
// 这里处理最终的错误返回,比如 respond.Error
|
// 这里处理最终的错误返回,比如 respond.Error
|
||||||
return err
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,5 +293,11 @@ func (sv *TaskClassService) DeleteTaskClassItem(ctx context.Context, userID int,
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,22 +2,27 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
|
"log"
|
||||||
|
|
||||||
"github.com/LoveLosita/smartflow/backend/conv"
|
"github.com/LoveLosita/smartflow/backend/conv"
|
||||||
"github.com/LoveLosita/smartflow/backend/dao"
|
"github.com/LoveLosita/smartflow/backend/dao"
|
||||||
"github.com/LoveLosita/smartflow/backend/model"
|
"github.com/LoveLosita/smartflow/backend/model"
|
||||||
"github.com/LoveLosita/smartflow/backend/respond"
|
"github.com/LoveLosita/smartflow/backend/respond"
|
||||||
|
"github.com/go-redis/redis/v8"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TaskService struct {
|
type TaskService struct {
|
||||||
// 伸出手:准备接住 DAO
|
// 伸出手:准备接住 DAO
|
||||||
dao *dao.TaskDAO
|
dao *dao.TaskDAO
|
||||||
|
cache *dao.CacheDAO
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTaskService 创建 TaskService 实例
|
// NewTaskService 创建 TaskService 实例
|
||||||
func NewTaskService(dao *dao.TaskDAO) *TaskService {
|
func NewTaskService(dao *dao.TaskDAO, cache *dao.CacheDAO) *TaskService {
|
||||||
return &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 层进行响应转换
|
//4. 调用 conv 层进行响应转换
|
||||||
response := conv.ModelToUserAddTaskResponse(createdTask)
|
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
|
return response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ts *TaskService) GetUserTasks(ctx context.Context, userID int) ([]model.GetUserTaskResp, error) {
|
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)
|
tasks, err := ts.dao.GetTasksByUserID(userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
//2. 调用 conv 层进行响应转换
|
//3. 调用 conv 层进行响应转换
|
||||||
response := conv.ModelToGetUserTasksResp(tasks)
|
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
|
return response, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user