7 Star 2 Fork 2

赵康铭 / tinyTicktok

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
video.go 5.50 KB
一键复制 编辑 原始数据 按行查看 历史
GeminiCx 提交于 2022-06-07 15:58 . 改用jsoniter进行优化
package service
import (
"context"
"fmt"
"github.com/json-iterator/go"
"time"
"gitee.com/zhaokangming/tiny-ticktok/dao"
"gitee.com/zhaokangming/tiny-ticktok/model"
"gitee.com/zhaokangming/tiny-ticktok/pkg/app"
"gitee.com/zhaokangming/tiny-ticktok/public/mock"
)
type FeedResponse struct {
app.Response
VideoList []model.Video `json:"video_list,omitempty"`
NextTime int64 `json:"next_time,omitempty"`
}
// CreateVideo create a single video
func CreateVideo(ctx context.Context, uid int64, video model.Video) error {
return dao.CreateVideo(ctx, dao.Video{
AuthorID: uid,
PlayUrl: video.PlayUrl,
CoverUrl: video.CoverUrl,
Title: video.Title,
})
}
// MGetVideos 返回视频列表
// 根据目前我们这个业务场景来讲取视频一次取30个,并且视频发布不是很频繁的情况下,
// 考虑在第一次查询的时候直接搞30分钟的cache,如果cache不存在的情况下,进行Mysql的读取
func MGetVideos(ctx context.Context, curID, nextTime int64) (*FeedResponse, error) {
res := new(FeedResponse)
res.NextTime = time.Now().Unix()
// 从redis中先判断有无缓存
cache := dao.RDB.Get(ctx, "videosCache").Val()
if cache != "" {
var json = jsoniter.ConfigCompatibleWithStandardLibrary
err := json.Unmarshal([]byte(cache), &res.VideoList)
if err != nil {
// 但凡这边缓存走不通都应该走一边nocache的方式
err := MGetVideosNoCache(ctx, curID, nextTime, res)
if err != nil {
// mysql还走不通直接返回
return nil, err
}
}
return res, nil
}
// 说明无缓存此时进行mysql的读取
err := MGetVideosNoCache(ctx, curID, nextTime, res)
if err != nil {
return nil, err
}
return res, nil
}
// MGetVideosNoCache 没有缓存的情况:从Mysql数据库中获取全部的视频流信息 -> 存入redis缓存
func MGetVideosNoCache(ctx context.Context, curID, nextTime int64, res *FeedResponse) error {
// 从redis中进行获取全部视频数据
videos, err := dao.MGetVideosFromRedis(ctx)
if err != nil {
videos, err = dao.MGetVideos(ctx, nextTime)
if err != nil {
return err
}
}
// 从mysql中填充videos的信息(即res.videoList)
err = FillVideoList(ctx, curID, videos, nil, res)
if err != nil {
return err
}
// json化并存入redis
err = dao.SetEXOfVideos(ctx, res.VideoList, "videosCache", 30*time.Minute)
if err != nil {
return err
}
return nil
}
// MGetVideosByUID 获取某一用户的所有视频列表,同样是判断个人投稿的缓存是否存在 -> 如果没缓存去mysql中寻找
func MGetVideosByUID(ctx context.Context, uid, targetID int64) (*FeedResponse, error) {
res := new(FeedResponse)
// 从redis中先判断有无缓存
cache := dao.RDB.Get(ctx, fmt.Sprintf("videosCache:%d", targetID)).Val()
if cache != "" {
var json = jsoniter.ConfigCompatibleWithStandardLibrary
err := json.Unmarshal([]byte(cache), &res.VideoList)
if err != nil {
// 但凡这边缓存走不通都应该走一边nocache的方式
err := MGetVideosByUIDNoCache(ctx, uid, targetID, res)
if err != nil {
// mysql还走不通直接返回
return nil, err
}
}
return res, nil
}
// 没有cache的情况
err := MGetVideosByUIDNoCache(ctx, uid, targetID, res)
if err != nil {
return nil, err
}
return res, nil
}
// MGetVideosByUIDNoCache 个人视频中没有缓存的情况:从mysql取出来,并进行缓存
func MGetVideosByUIDNoCache(ctx context.Context, uid, targetID int64, res *FeedResponse) error {
// 获取某一用户的所有视频列表
videos, err := dao.MGetVideosByUID(ctx, targetID)
if err != nil {
return err
}
user, err := QueryUser(ctx, uid, targetID)
if err != nil {
return err
}
// 填充视频信息
err = FillVideoList(ctx, uid, videos, user, res)
if err != nil {
return err
}
// json化并存入redis,key值为:videosCacheOf+uid,过期时间为60min(因为个人投稿的频率应该更低)
err = dao.SetEXOfVideos(ctx, res.VideoList, fmt.Sprintf("videosCache:%d", uid), -1)
if err != nil {
return err
}
return nil
}
// FillVideoList 对mysql数据库的查出来的video信息进行填充:Author,id,FavoriteCount,CommentCount
// 传入user的目的是判断调用的接口方是否是查询个人的,如果是个人直接填充
func FillVideoList(ctx context.Context, curID int64, videos []dao.Video, user *model.User, res *FeedResponse) error {
res.VideoList = make([]model.Video, len(videos))
for i, v := range videos {
// 定义错误、以及视频作者变量
var (
err error
userVideo *model.User
)
// user不等于空时说明传进来的是查找个人的,直接赋值
// 这样做的目的是在抽象的结果下个人的查询接口,只需调一次QueryUser(因为作者都相同)
if user != nil {
userVideo = user
} else {
// 从mysql查询作者信息,有error直接return
userVideo, err = QueryUser(ctx, curID, v.AuthorID)
if err != nil {
return err
}
}
// 填充列表
res.VideoList[i].Author = *userVideo
res.VideoList[i].Id = int64(v.ID)
res.VideoList[i].Title = v.Title
res.VideoList[i].FavoriteCount = dao.QueryFavoriteCount(ctx, int64(v.ID))
res.VideoList[i].CommentCount, err = dao.QueryCommentCount(ctx, int64(v.ID))
if err != nil {
return err
}
res.VideoList[i].IsFavorite = dao.QueryIsFavorite(ctx, userVideo.Id, int64(v.ID))
res.VideoList[i].CoverUrl = v.CoverUrl
res.VideoList[i].PlayUrl = v.PlayUrl
}
// 如果视频列表为空进行mock
if len(res.VideoList) == 0 {
res.VideoList = append(res.VideoList, mock.DemoVideos...)
}
return nil
}
Go
1
https://gitee.com/zhaokangming/tiny-ticktok.git
git@gitee.com:zhaokangming/tiny-ticktok.git
zhaokangming
tiny-ticktok
tinyTicktok
dcbaf51081e9

搜索帮助

53164aa7 5694891 3bd8fe86 5694891