hertz接入minio作为存储-1 | 青训营笔记

97 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 14 天

在本项目中,我们使用hertz调用视频微服务来进行视频信息的保存和维护。视频内容和封面则存储到minio,构造得到自由的url之后,保存到视频微服务。

在介绍hertz接入minio之前,本篇我们需要简单的介绍下与它联动的模块videomicro的实现。

idl如下:首先是基础模型

image.png

然后是一些定义的方法:

image.png

使用client里面的代码对数据表进行生成。 cd cmd/migrateSchema/ && go run migrate.go

然后使用gorm-gen中的代码生成query代码。 cd cmd/gormGen && go run gen.go

同usermicro的实现一样,我们在dal层中注册下数据库:

image.png

接下来看下各个服务的实现逻辑

创建视频的逻辑:根据请求传来的参数进行对象的创建。

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。