这是我参与「第五届青训营 」伴学笔记创作活动的第 14 天
在本项目中,我们使用hertz调用视频微服务来进行视频信息的保存和维护。视频内容和封面则存储到minio,构造得到自由的url之后,保存到视频微服务。
在介绍hertz接入minio之前,本篇我们需要简单的介绍下与它联动的模块videomicro的实现。
idl如下:首先是基础模型
然后是一些定义的方法:
使用client里面的代码对数据表进行生成。
cd cmd/migrateSchema/ && go run migrate.go
然后使用gorm-gen中的代码生成query代码。
cd cmd/gormGen && go run gen.go
同usermicro的实现一样,我们在dal层中注册下数据库:
接下来看下各个服务的实现逻辑
创建视频的逻辑:根据请求传来的参数进行对象的创建。
func (s *VideoServiceImpl) CreateVideoMethod(ctx context.Context, request *videomicro.CreateVideoReq) (resp *videomicro.CreateVideoResp, err error) {
// TODO: Your code here...
v := query.Video
video := &model.Video{
Title: request.Title,
Author_id: request.AuthorId,
Cover_url: request.CoverUrl,
Play_url: request.PlayUrl,
Favorite_count: 0,
Comment_count: 0,
}
err = v.Create(video)
if err != nil {
return &videomicro.CreateVideoResp{
Status: false,
}, err
}
return &videomicro.CreateVideoResp{
Status: true,
}, nil
}
获取视频的逻辑:根据请求的视频id查询视频。这里有需要进一步改进的点,现在的数据转换是放到了handler里面,其实这部分内容是属于数据层的东西,应该在dal中进行把数据库模型转化为服务需要的服务模型。
// GetVideoMethod implements the VideoServiceImpl interface.
func (s *VideoServiceImpl) GetVideoMethod(ctx context.Context, request *videomicro.GetVideoReq) (resp *videomicro.GetVideoResp, err error) {
// TODO: Your code here...
v := query.Video
video, err := v.Where(v.ID.Eq(uint(request.Id))).First()
if err != nil {
return &videomicro.GetVideoResp{
Status: false,
}, err
}
return &videomicro.GetVideoResp{
Status: true,
Video: &videomicro.Video{
Id: int64(video.ID),
Title: video.Title,
AuthorId: video.Author_id,
PlayUrl: video.Play_url,
CoverUrl: video.Cover_url,
FavoriteCount: video.Favorite_count,
CommentCount: video.Comment_count,
},
}, nil
}
通过作者id批量的获取视频。
func (s *VideoServiceImpl) GetVideosByAuthorIdMethod(ctx context.Context, request *videomicro.GetVideosByAuthorIdReq) (resp *videomicro.GetVideosByAuthorIdResp, err error) {
// TODO: Your code here...
v := query.Video
// return all video by this user, desc
videolist, err := v.Where(v.Author_id.Eq(request.AuthorId)).Order(v.CreatedAt.Desc()).Find()
if err != nil {
return &videomicro.GetVideosByAuthorIdResp{
Status: true,
}, err
}
respvideolist := make([]*videomicro.Video, len(videolist))
for index, video := range videolist {
respvideolist[index] = &videomicro.Video{
Id: int64(video.ID),
Title: video.Title,
AuthorId: video.Author_id,
PlayUrl: video.Play_url,
CoverUrl: video.Cover_url,
FavoriteCount: video.Favorite_count,
CommentCount: video.Comment_count,
}
}
return &videomicro.GetVideosByAuthorIdResp{
Status: true,
VideoList: respvideolist,
}, nil
}
视频feed流的获取逻辑,现在只是简单的根据时间戳和limit获取视频切片。
func (s *VideoServiceImpl) GetVideosFeedMethod(ctx context.Context, request *videomicro.GetVideosFeedReq) (resp *videomicro.GetVideosFeedResp, err error) {
// TODO: Your code here...
v := query.Video
// Desc 倒序查询
startTime := time.Unix(0, request.LatestTime)
videolist, err := v.Where(v.CreatedAt.Lt(startTime)).Limit(int(request.Limit)).Order(v.CreatedAt.Desc()).Find()
if err != nil {
return &videomicro.GetVideosFeedResp{
Status: true,
}, err
}
respvideolist := make([]*videomicro.Video, len(videolist))
for index, video := range videolist {
respvideolist[index] = &videomicro.Video{
Id: int64(video.ID),
Title: video.Title,
AuthorId: video.Author_id,
PlayUrl: video.Play_url,
CoverUrl: video.Cover_url,
FavoriteCount: video.Favorite_count,
CommentCount: video.Comment_count,
}
}
var endTimeUnix = request.LatestTime // 没有条目,则时间还是之前的,交由hertz端处理
if len(videolist) >= 1 { // 搜到条目,则更新时间
endTimeUnix = videolist[len(videolist)-1].CreatedAt.UnixNano()
}
return &videomicro.GetVideosFeedResp{
Status: true,
NextTime: &endTimeUnix,
VideoList: respvideolist,
}, nil
}
删除视频的逻辑
func (s *VideoServiceImpl) DeleteVideoMethod(ctx context.Context, request *videomicro.DeleteVideoReq) (resp *videomicro.DeleteVideoResp, err error) {
// TODO: Your code here...
v := query.Video
_, err = v.Where(v.ID.Eq(uint(request.Id))).Delete(&model.Video{}) // 软删除
if err != nil {
return &videomicro.DeleteVideoResp{
Status: false,
}, err
}
return &videomicro.DeleteVideoResp{
Status: true,
}, err
}
更新视频的逻辑
func (s *VideoServiceImpl) UpdateVideoMethod(ctx context.Context, request *videomicro.UpdateVideoReq) (resp *videomicro.UpdateVideoResp, err error) {
// TODO: Your code here...
v := query.Video
video := v.Where(v.ID.Eq(uint(request.Id)))
if request.Title != nil {
_, err := video.Update(v.Title, request.Title)
if err != nil {
return &videomicro.UpdateVideoResp{
Status: false,
}, err
}
}
return &videomicro.UpdateVideoResp{
Status: true,
}, err
}
编写客户端
和前面几篇文章介绍的usermicro的思路类似,使用kitex与gorm开发微服务-7 | 青训营笔记 - 掘金 (juejin.cn),在自己写的kitex_server层去维护微服务和api的交互逻辑。
这样的我们就搭好了一个基础的视频微服务,下一篇,就正式介绍如何在hertz中使用minio。