Create & Init Project...

This commit is contained in:
2019-04-22 18:49:16 +08:00
commit fc4fa37393
25440 changed files with 4054998 additions and 0 deletions

View File

@@ -0,0 +1,49 @@
load(
"@io_bazel_rules_go//proto:def.bzl",
"go_proto_library",
)
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
proto_library(
name = "v1_proto",
srcs = ["api.proto"],
tags = ["automanaged"],
)
go_proto_library(
name = "v1_go_proto",
compilers = ["@io_bazel_rules_go//proto:go_proto"],
importpath = "go-common/app/job/live/dao-anchor-job/api/v1",
proto = ":v1_proto",
tags = ["automanaged"],
)
go_library(
name = "go_default_library",
srcs = ["generate.go"],
embed = [":v1_go_proto"],
importpath = "go-common/app/job/live/dao-anchor-job/api/v1",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = ["@com_github_gogo_protobuf//proto:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,33 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: app/job/live/dao-anchor-job/api/v1/api.proto
package v1
import proto "github.com/gogo/protobuf/proto"
import fmt "fmt"
import math "math"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
func init() {
proto.RegisterFile("app/job/live/dao-anchor-job/api/v1/api.proto", fileDescriptor_api_246501f09888d3ec)
}
var fileDescriptor_api_246501f09888d3ec = []byte{
// 89 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x49, 0x2c, 0x28, 0xd0,
0xcf, 0xca, 0x4f, 0xd2, 0xcf, 0xc9, 0x2c, 0x4b, 0xd5, 0x4f, 0x49, 0xcc, 0xd7, 0x4d, 0xcc, 0x4b,
0xce, 0xc8, 0x2f, 0xd2, 0x05, 0x89, 0x25, 0x16, 0x64, 0xea, 0x97, 0x19, 0x82, 0x28, 0xbd, 0x82,
0xa2, 0xfc, 0x92, 0x7c, 0x27, 0x81, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0,
0x48, 0x8e, 0x31, 0x8a, 0xa9, 0xcc, 0x30, 0x89, 0x0d, 0x2c, 0x61, 0x0c, 0x08, 0x00, 0x00, 0xff,
0xff, 0x75, 0x85, 0x9c, 0x41, 0x48, 0x00, 0x00, 0x00,
}

View File

@@ -0,0 +1,16 @@
// 定义项目 API 的 proto 文件 可以同时描述 gRPC 和 HTTP API
// protobuf 文件参考:
// - https://developers.google.com/protocol-buffers/
// - http://info.bilibili.co/display/documentation/gRPC+Proto
// protobuf 生成 HTTP 工具:
// - http://git.bilibili.co/platform/go-common/tree/master/app/tool/protoc-gen-bm
syntax = "proto3";
// package 命名使用 {discovery_id}.{version} 的方式, version 形如 v1, v2, v1beta ..
// NOTE: 不知道的 discovery_id 请询问大佬, 新项目找大佬申请 discovery_id先到先得抢注
// e.g. account.service.v1
// package {discovery_id}.{version}
// NOTE: 最后请删除这些无用的注释 (゜-゜)つロ
option go_package = "v1";

View File

@@ -0,0 +1,4 @@
package v1
// 生成 gRPC 代码
//go:generate $GOPATH/src/go-common/app/tool/warden/protoc.sh

View File

@@ -0,0 +1,44 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
)
go_binary(
name = "cmd",
embed = [":go_default_library"],
tags = ["automanaged"],
)
go_library(
name = "go_default_library",
srcs = ["main.go"],
data = ["test.toml"],
importpath = "go-common/app/job/live/dao-anchor-job/cmd",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/live/dao-anchor-job/internal/conf:go_default_library",
"//app/job/live/dao-anchor-job/internal/server/http:go_default_library",
"//app/job/live/dao-anchor-job/internal/service:go_default_library",
"//library/ecode/tip:go_default_library",
"//library/log:go_default_library",
"//library/net/trace:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,47 @@
package main
import (
"flag"
"os"
"os/signal"
"syscall"
"time"
"go-common/app/job/live/dao-anchor-job/internal/conf"
"go-common/app/job/live/dao-anchor-job/internal/server/http"
"go-common/app/job/live/dao-anchor-job/internal/service"
ecode "go-common/library/ecode/tip"
"go-common/library/log"
"go-common/library/net/trace"
)
func main() {
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
log.Init(conf.Conf.Log)
defer log.Close()
log.Info("dao-anchor-job start")
trace.Init(conf.Conf.Tracer)
defer trace.Close()
ecode.Init(conf.Conf.Ecode)
svc := service.New(conf.Conf)
http.Init(conf.Conf, svc)
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
s := <-c
log.Info("get a signal %s", s.String())
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
svc.Close()
log.Info("dao-anchor-job exit")
time.Sleep(time.Second)
return
case syscall.SIGHUP:
default:
return
}
}
}

View File

@@ -0,0 +1,22 @@
[httpCli]
key = "fb06a25c6338edbc"
secret = "fd10bd177559780c2e4a44f1fa47fa83"
dial = "100ms"
timeout = "5s"
keepAlive = "60s"
[httpClient.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[coverControl]
CoverCron = "0 */5 * * * *"
pieceSize = 50
[MinuteControl]
MinuteCron = "0 */1 * * * *"
pieceSize = 50
[Minute3Control]
Minute3Cron = "0 */3 * * * *"
pieceSize = 50

View File

@@ -0,0 +1,40 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["conf.go"],
importpath = "go-common/app/job/live/dao-anchor-job/internal/conf",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/conf:go_default_library",
"//library/database/bfs:go_default_library",
"//library/ecode/tip:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/http/blademaster/middleware/verify:go_default_library",
"//library/net/rpc/liverpc:go_default_library",
"//library/net/rpc/warden:go_default_library",
"//library/net/trace:go_default_library",
"//vendor/github.com/BurntSushi/toml:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,105 @@
package conf
import (
"errors"
"flag"
"go-common/library/database/bfs"
"go-common/library/net/rpc/liverpc"
"go-common/library/net/rpc/warden"
"go-common/library/conf"
ecode "go-common/library/ecode/tip"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/verify"
"go-common/library/net/trace"
"github.com/BurntSushi/toml"
)
var (
confPath string
client *conf.Client
// Conf config
Conf = &Config{}
)
// Config .
type Config struct {
Log *log.Config
BM *bm.ServerConfig
Verify *verify.Config
Tracer *trace.Config
Ecode *ecode.Config
LiveRpc map[string]*liverpc.ClientConfig
GrpcCli *warden.ClientConfig
BfsCli *bfs.Config
HttpCli *bm.ClientConfig
CoverControl *CoverControl
Minute3Control *Minute3Control
MinuteControl *MinuteControl
}
type CoverControl struct {
CoverCron string
PieceSize int
}
type Minute3Control struct {
Minute3Cron string
PieceSize int
}
type MinuteControl struct {
MinuteCron string
PieceSize int
}
func init() {
flag.StringVar(&confPath, "conf", "", "default config path")
}
// Init init conf
func Init() error {
if confPath != "" {
return local()
}
return remote()
}
func local() (err error) {
_, err = toml.DecodeFile(confPath, &Conf)
return
}
func remote() (err error) {
if client, err = conf.New(); err != nil {
return
}
if err = load(); err != nil {
return
}
go func() {
for range client.Event() {
log.Info("config reload")
if load() != nil {
log.Error("config reload error (%v)", err)
}
}
}()
return
}
func load() (err error) {
var (
s string
ok bool
tmpConf *Config
)
if s, ok = client.Toml2(); !ok {
return errors.New("load config center error")
}
if _, err = toml.Decode(s, &tmpConf); err != nil {
return errors.New("could not decode config")
}
*Conf = *tmpConf
return
}

View File

@@ -0,0 +1,47 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"av.go",
"bfs.go",
"dao.go",
"daoAnchor.go",
"video.go",
],
importpath = "go-common/app/job/live/dao-anchor-job/internal/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/live/dao-anchor-job/internal/conf:go_default_library",
"//app/service/live/av/api/liverpc:go_default_library",
"//app/service/live/av/api/liverpc/v1:go_default_library",
"//app/service/live/dao-anchor/api/grpc/v0:go_default_library",
"//app/service/live/dao-anchor/api/grpc/v1:go_default_library",
"//app/service/video/stream-mng/api/v1:go_default_library",
"//library/database/bfs:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/rpc/liverpc:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,24 @@
package dao
import (
"context"
"go-common/app/service/live/av/api/liverpc/v1"
"go-common/library/log"
)
// GetFansMedalInfo 获取粉丝勋章信息
func (d *Dao) GetPkStatus(c context.Context, roomId int64) (resp *v1.PkGetPkStatusResp_Data, err error) {
reply, err := d.AvApi.V1Pk.GetPkStatus(c, &v1.PkGetPkStatusReq{RoomId: roomId})
if err != nil {
log.Error("av_GetPkStatus_error:%v", err)
return
}
if reply.Code != 0 {
log.Error("av_GetPkStatus_error:%d,%s,%v", reply.Code, reply.Msg, reply.Data)
return
}
log.Info("av_GetPkStatus:%d,%s,$v", reply.Code, reply.Msg, reply.Data)
resp = reply.Data
return
}

View File

@@ -0,0 +1,56 @@
package dao
import (
"context"
"errors"
"io/ioutil"
"net/http"
"strconv"
"go-common/library/database/bfs"
"go-common/library/log"
)
const BUCKET = "live"
const FILE_PATH = "/data/www/cover/"
//上传至bfs相关接口
//ImgUpload 上传图片至bfs
func (d *Dao) ImgUpload(ctx context.Context, roomId int64, pic string, file []byte) (resp string, err error) {
log.Info("ImgUpload_start")
fileName := strconv.Itoa(int(roomId)) + ".jpg"
reply, err := d.BfsClient.Upload(ctx, &bfs.Request{
Bucket: BUCKET,
Dir: "",
ContentType: "",
Filename: fileName,
File: []byte(file),
})
if err != nil {
log.Error("ImgUpload_bfs_Upload_failed,err:%v", err)
return
}
resp = reply
return
}
func (d *Dao) ImgDownload(ctx context.Context, pic string) (resp []byte, err error) {
reply, err := http.Get(pic)
if err != nil {
log.Warn("ImgDownload_failed_err:%v", err)
return
}
defer reply.Body.Close()
if reply.StatusCode != 200 {
err = errors.New("curl error http code not equal to 200")
log.Warn("ImgDownload_failed_httpCode:%d", reply.StatusCode)
return
}
resp, err = ioutil.ReadAll(reply.Body)
if err != nil {
log.Warn("ImgDownload_read_err:%v", err)
return
}
return
}

View File

@@ -0,0 +1,70 @@
package dao
import (
"context"
"go-common/app/job/live/dao-anchor-job/internal/conf"
av_api "go-common/app/service/live/av/api/liverpc"
daoAnchor_api_v0 "go-common/app/service/live/dao-anchor/api/grpc/v0"
daoAnchor_api "go-common/app/service/live/dao-anchor/api/grpc/v1"
video_api "go-common/app/service/video/stream-mng/api/v1"
"go-common/library/database/bfs"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/rpc/liverpc"
)
// Dao dao
type Dao struct {
c *conf.Config
AvApi *av_api.Client
daoAnchorApi *daoAnchor_api.Client
VideoApi video_api.StreamClient
BfsClient *bfs.BFS
HttpClient *bm.Client
daoAnchorApiV0 *daoAnchor_api_v0.Client
}
// New init mysql db
func New(c *conf.Config) (dao *Dao) {
dao = &Dao{
c: c,
AvApi: av_api.New(getConf("av")),
BfsClient: bfs.New(c.BfsCli),
HttpClient: bm.NewClient(c.HttpCli),
}
daoAnchorApi, err := daoAnchor_api.NewClient(c.GrpcCli)
if err != nil {
panic(err)
}
dao.daoAnchorApi = daoAnchorApi
videoApi, err := video_api.NewClient(c.GrpcCli)
if err != nil {
panic(err)
}
dao.VideoApi = videoApi
daoAnchorApiV0, err := daoAnchor_api_v0.NewClient(c.GrpcCli)
if err != nil {
panic(err)
}
dao.daoAnchorApiV0 = daoAnchorApiV0
return
}
// Close close the resource.
func (d *Dao) Close() {
}
// Ping dao ping
func (d *Dao) Ping(ctx context.Context) error {
// TODO: add mc,redis... if you use
return nil
}
func getConf(appName string) *liverpc.ClientConfig {
c := conf.Conf.LiveRpc
if c != nil {
return c[appName]
}
return nil
}

View File

@@ -0,0 +1,146 @@
package dao
import (
"context"
"time"
"go-common/library/ecode"
"fmt"
daoAnchorV0 "go-common/app/service/live/dao-anchor/api/grpc/v0"
"go-common/app/service/live/dao-anchor/api/grpc/v1"
"go-common/library/log"
)
//LIVE_OPEN 开播
const LIVE_OPEN = 1
//LIVE_CLOSE 关播
const LIVE_CLOSE = 0
//LIVE_ROUND 轮播
const LIVE_ROUND = 2
//PAGE_SIZE 分页数据量
const PAGE_SIZE = 100
//RETRY_TIME 接口充实次数
const RETRY_TIME = 3
//GetAllLiveRoom 获取在播列表
func (d *Dao) GetAllLiveRoom(c context.Context, fields []string) (resp map[int64]*v1.RoomData, err error) {
page := 0
resp = map[int64]*v1.RoomData{}
retry := 1
for true {
reply, err := d.daoAnchorApi.RoomOnlineList(c, &v1.RoomOnlineListReq{Fields: fields, Page: int64(page), PageSize: PAGE_SIZE})
if err != nil {
if retry >= RETRY_TIME {
break
}
retry++
time.Sleep(time.Second * 3)
log.Errorw(c, "log", fmt.Sprintf("getAllLiveRoom_RoomOnlineList_error:page=%d;err=%v", page, err))
continue
}
if len(reply.RoomDataList) <= 0 {
break
}
page = page + 1
roomDataList := reply.RoomDataList
for roomId, info := range roomDataList {
v := info
resp[roomId] = v
}
time.Sleep(time.Millisecond)
}
return
}
//GetAllLiveRoomIds 获取在播列表
func (d *Dao) GetAllLiveRoomIds(c context.Context) (resp []int64, err error) {
page := 0
reply, err := d.daoAnchorApi.RoomOnlineListByArea(c, &v1.RoomOnlineListByAreaReq{})
if err != nil {
log.Errorw(c, "log", fmt.Sprintf("GetAllLiveRoomIds_RoomOnlineList_error:page=%d;err=%v", page, err))
return
}
if len(reply.RoomIds) <= 0 {
return
}
resp = reply.RoomIds
return
}
//GetInfosByRoomIds 获取主播房间信息
func (d *Dao) GetInfosByRoomIds(c context.Context, roomIds []int64, fields []string) (resp map[int64]*v1.RoomData, err error) {
if roomIds == nil {
err = ecode.InvalidParam
log.Errorw(c, "log", fmt.Sprintf("getInfosByRoomIds_params_error:%v", roomIds))
return
}
reply, err := d.daoAnchorApi.FetchRoomByIDs(c, &v1.RoomByIDsReq{RoomIds: roomIds, Fields: fields})
if err != nil {
log.Errorw(c, "log", fmt.Sprintf("getInfosByRoomIds_FetchRoomByIDs_error:reply=%v;err=%v", reply, err))
return
}
if reply == nil {
err = ecode.CallDaoAnchorError
log.Errorw(c, "log", "getInfosByRoomIds_FetchRoomByIDs_error")
return
}
resp = reply.RoomDataSet
return
}
//UpdateRoomEx ...
func (d *Dao) UpdateRoomEx(c context.Context, roomId int64, fields []string, keyFrame string) (resp int64, err error) {
if roomId < 0 {
err = ecode.InvalidParam
log.Errorw(c, "log", fmt.Sprintf("updateRoom_params_error:%v", roomId))
return
}
reply, err := d.daoAnchorApi.RoomExtendUpdate(c, &v1.RoomExtendUpdateReq{Fields: fields, RoomId: roomId, Keyframe: keyFrame})
if err != nil {
log.Errorw(c, "log", fmt.Sprintf("updateRoom_RoomUpdate_error:reply=%v;err=%v", reply, err))
return
}
resp = reply.AffectedRows
return
}
func (d *Dao) CreateCacheList(c context.Context, roomIds []int64, content string) (err error) {
if len(roomIds) <= 0 || content == "" {
log.Errorw(c, "log", fmt.Sprintf("CreateCacheList_params_error:room_id=%v;content=%s", roomIds, content))
return
}
reply, err := d.daoAnchorApiV0.CreateLiveCacheList(c, &daoAnchorV0.CreateLiveCacheListReq{RoomIds: roomIds, Content: content})
if err != nil {
log.Errorw(c, "log", fmt.Sprintf("CreateCacheList_error:reply=%v;err=%v", reply, err))
return
}
log.Info("CreateCacheList_info:roomIds=%v;content=%s;reply=%v", roomIds, content, reply)
return
}
func (d *Dao) GetContentMap(c context.Context) (resp map[string]int64, err error) {
reply, err := d.daoAnchorApiV0.GetContentMap(c, &daoAnchorV0.GetContentMapReq{})
if err != nil {
log.Errorw(c, "log", fmt.Sprintf("GetContentMap_error:reply=%v;err=%v", reply, err))
return
}
resp = reply.List
return
}
func (d *Dao) CreateDBData(c context.Context, roomIds []int64, content string) (err error) {
if len(roomIds) <= 0 || content == "" {
log.Errorw(c, "log", fmt.Sprintf("CreateCacheList_params_error:room_id=%v;content=%s", roomIds, content))
return
}
reply, err := d.daoAnchorApiV0.CreateDBData(c, &daoAnchorV0.CreateDBDataReq{RoomIds: roomIds, Content: content})
if err != nil {
log.Errorw(c, "log", fmt.Sprintf("CreateCacheList_error:reply=%v;err=%v", reply, err))
return
}
return
}

View File

@@ -0,0 +1,26 @@
package dao
import (
"context"
"time"
"go-common/app/service/video/stream-mng/api/v1"
"go-common/library/log"
)
//视频云接口调用
//GetPicsByRoomId 根据房间id获取当前关键帧
func (d *Dao) GetPicsByRoomId(c context.Context, roomId int64, startTime time.Time, endTime time.Time) (resp []string, err error) {
reply, err := d.VideoApi.GetSingleScreeShot(c, &v1.GetSingleScreeShotReq{RoomId: roomId, StartTime: startTime.Format("2006-01-02 15:04:05"), EndTime: endTime.Format("2006-01-02 15:04:05")})
if err != nil {
log.Error("getPicsByRoomId_GetSingleScreeShot_error:reply:%v;err=%v", reply, err)
return
}
if reply == nil {
log.Error("getPicsByRoomId_GetSingleScreeShot_error")
return
}
resp = reply.List
return
}

View File

@@ -0,0 +1,28 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["model.go"],
importpath = "go-common/app/job/live/dao-anchor-job/internal/model",
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1 @@
package model

View File

@@ -0,0 +1,35 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["http.go"],
importpath = "go-common/app/job/live/dao-anchor-job/internal/server/http",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/live/dao-anchor-job/internal/conf:go_default_library",
"//app/job/live/dao-anchor-job/internal/service:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/http/blademaster/middleware/verify:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,53 @@
package http
import (
"net/http"
"go-common/app/job/live/dao-anchor-job/internal/conf"
"go-common/app/job/live/dao-anchor-job/internal/service"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/verify"
)
var (
vfy *verify.Verify
svc *service.Service
)
// Init init
func Init(c *conf.Config, s *service.Service) {
svc = s
vfy = verify.New(c.Verify)
engine := bm.DefaultServer(c.BM)
route(engine)
if err := engine.Start(); err != nil {
log.Error("bm Start error(%v)", err)
panic(err)
}
}
func route(e *bm.Engine) {
e.Ping(ping)
e.Register(register)
g := e.Group("/x/dao-anchor-job")
{
g.GET("/start", vfy.Verify, howToStart)
}
}
func ping(ctx *bm.Context) {
if err := svc.Ping(ctx); err != nil {
log.Error("ping error(%v)", err)
ctx.AbortWithStatus(http.StatusServiceUnavailable)
}
}
func register(c *bm.Context) {
c.JSON(map[string]interface{}{}, nil)
}
// example for http request handler
func howToStart(c *bm.Context) {
c.String(0, "Golang 大法好 !!!")
}

View File

@@ -0,0 +1,55 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"cover_test.go",
"data_test.go",
],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = [
"//app/job/live/dao-anchor-job/internal/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"cover.go",
"data.go",
"service.go",
],
importpath = "go-common/app/job/live/dao-anchor-job/internal/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/live/dao-anchor-job/internal/conf:go_default_library",
"//app/job/live/dao-anchor-job/internal/dao:go_default_library",
"//library/log:go_default_library",
"//library/net/trace:go_default_library",
"//library/sync/errgroup:go_default_library",
"//vendor/github.com/robfig/cron:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,112 @@
package service
import (
"context"
"strings"
"time"
"go-common/app/job/live/dao-anchor-job/internal/dao"
"go-common/library/sync/errgroup"
"go-common/library/log"
)
//封面图/关键帧相关脚本
const ROOM_LEN_KEY_FRAME = 500
//updateKeyFrame 更新关键帧
func (s *Service) updateKeyFrame() {
ctx := context.TODO()
ctx, cancel := context.WithTimeout(ctx, time.Minute*5)
defer cancel()
log.Info("updateKeyFrame_start")
//获取全量开播房间
allLiveingRoom, err := s.dao.GetAllLiveRoomIds(ctx)
if allLiveingRoom == nil || err != nil {
log.Error("updateKeyFrame_allLiveingRoom_error:reply=%v;err=%v", allLiveingRoom, err)
return
}
slice := make([]int64, 0)
eg := errgroup.Group{}
for i := 0; i < len(allLiveingRoom); {
end := ROOM_LEN_KEY_FRAME + i
if (ROOM_LEN_KEY_FRAME + i) >= len(allLiveingRoom) {
end = len(allLiveingRoom)
}
slice = allLiveingRoom[i:end]
if len(slice) <= 0 {
break
} else {
eg.Go(func(sliceParam []int64) func() error {
return func() (err error) {
for _, roomId := range sliceParam {
coverUrl, err := s.dealKeyFrame(ctx, roomId)
if err != nil {
time.Sleep(time.Second)
log.Error("updateKeyFrame_deal_error:roomId=%d;ketFrame=%s", roomId, coverUrl)
continue
}
if coverUrl == "" {
continue
}
//更新关键帧
coverUrlArr := strings.Split(coverUrl, "?")
coverUrl = coverUrlArr[0] + "?" + time.Now().Format("01021504")
s.dao.UpdateRoomEx(ctx, roomId, []string{"keyframe"}, coverUrl)
time.Sleep(time.Millisecond * 10)
}
return
}
}(slice))
}
i = end
}
eg.Wait()
log.Info("updateKeyFrame_end")
return
}
func (s *Service) dealKeyFrame(ctx context.Context, roomId int64) (coverUrl string, err error) {
//二次确认是否关播,关播不再做
roomInfos, err := s.dao.GetInfosByRoomIds(ctx, []int64{roomId}, []string{"live_status"})
if err != nil {
log.Error("updateKeyFrame_GetInfosByRoomIds_error:room_id=%d;err=%v", roomId, err)
return
}
roomInfo := roomInfos[roomId]
//未开播,不更新关键帧
if roomInfo == nil || roomInfo.LiveStatus != dao.LIVE_OPEN {
return
}
//判断是否为pk房间,pk房间不更新关键帧
pkReply, err := s.dao.GetPkStatus(ctx, roomId)
if err != nil {
log.Error("updateKeyFrame_GetPkStatus_error:room_id=%d", roomId)
return
}
if pkReply.PkStatus > 0 {
return
}
//获取关键帧
startTime := time.Now().Add(-time.Minute)
endTime := time.Now()
pics, err := s.dao.GetPicsByRoomId(ctx, roomId, startTime, endTime)
if err != nil || pics == nil || pics[0] == "" {
log.Warn("updateKeyFrame_GetPicsByRoomId_error:room_id=%d;pics=%v;err=%v", roomId, pics, err)
return
}
//上传至bfs
reply, err := s.dao.ImgDownload(ctx, pics[0])
if err != nil || reply == nil {
log.Warn("updateKeyFrame_ImgDownload_error:room_id=%d;pic=%s;err=%v;reply=%v", roomId, pics[0], err, reply)
return
}
coverUrl, err = s.dao.ImgUpload(ctx, roomId, pics[0], reply)
if err != nil || coverUrl == "" {
log.Error("updateKeyFrame_ImgUploadBfs_error:room_id=%d;pic=%s", roomId, pics[0])
return
}
return
}

View File

@@ -0,0 +1,26 @@
package service
import (
"flag"
"testing"
. "github.com/smartystreets/goconvey/convey"
"go-common/app/job/live/dao-anchor-job/internal/conf"
)
var s *Service
func init() {
flag.Set("conf", "../../cmd/test.toml")
if err := conf.Init(); err != nil {
panic(err)
}
s = New(conf.Conf)
}
func TestCover(t *testing.T) {
Convey("testCover", t, func() {
s.updateKeyFrame()
})
}

View File

@@ -0,0 +1,95 @@
package service
import (
"context"
"fmt"
"time"
"go-common/library/log"
"go-common/library/sync/errgroup"
)
const ROOM_LEN = 300
//实时数据处理逻辑,生成list
func (s *Service) minuteDataToCacheList() {
ctx := context.TODO()
ctx, cancel := context.WithTimeout(ctx, time.Minute*5)
defer cancel()
ctx = GetTraceLogCtx(ctx, "minuteDataToCacheList")
log.Infow(ctx, "log", "minuteDataToCacheList_start")
//获取需要生成的数据的content列表
contentMap, err := s.dao.GetContentMap(ctx)
if err != nil {
log.Errorw(ctx, "log", fmt.Sprintf("minuteDataToCacheList_GetContentMap_error:reply=%v;err=%v", contentMap, err))
return
}
//获取全量开播房间
allLiveingRoomIds, err := s.dao.GetAllLiveRoomIds(ctx)
if allLiveingRoomIds == nil || err != nil {
log.Errorw(ctx, "log", fmt.Sprintf("minuteDataToCacheList_allLiveingRoomIds_error:reply=%v;err=%v", allLiveingRoomIds, err))
return
}
eg := errgroup.Group{}
for content := range contentMap {
log.Infow(ctx, fmt.Sprintf("minuteDataToCacheList_start:%s", content))
eg.Go(func(contentParam string) func() error {
slice := make([]int64, 0)
for i := 0; i < len(allLiveingRoomIds); {
end := ROOM_LEN + i
if ROOM_LEN+i >= len(allLiveingRoomIds) {
end = len(allLiveingRoomIds)
}
slice = allLiveingRoomIds[i:end]
if len(slice) <= 0 {
break
} else {
s.dao.CreateCacheList(ctx, slice, contentParam)
}
i = end
}
log.Infow(ctx, "log", fmt.Sprintf("minuteDataToCacheList_end_content=%s;err=%v", contentParam, err))
return nil
}(content))
}
eg.Wait()
log.Infow(ctx, "log", "minuteDataToCacheList_end")
return
}
func (s *Service) minuteDataToDB() {
ctx := context.TODO()
ctx, cancel := context.WithTimeout(ctx, time.Minute*3)
defer cancel()
ctx = GetTraceLogCtx(ctx, "minuteDataToDB")
log.Infow(ctx, "log", "minuteDataToDB_start")
//获取需要生成的数据的content列表
contentMap, err := s.dao.GetContentMap(ctx)
if err != nil {
log.Errorw(ctx, "log", fmt.Sprintf("data_allLiveingRoomIds_error:reply=%v;err=%v", contentMap, err))
return
}
//获取全量开播房间
allLiveingRoomIds, err := s.dao.GetAllLiveRoomIds(ctx)
if allLiveingRoomIds == nil || err != nil {
log.Errorw(ctx, "log", fmt.Sprintf("data_allLiveingRoomIds_error:reply=%v;err=%v", allLiveingRoomIds, err))
return
}
eg := errgroup.Group{}
for content := range contentMap {
log.Info("minuteDataToCacheList_start:" + content)
eg.Go(func(contentParam string) func() error {
return func() (err error) {
for _, roomId := range allLiveingRoomIds {
s.dao.CreateDBData(ctx, []int64{int64(roomId)}, contentParam)
}
log.Infow(ctx, "log", fmt.Sprintf("minuteDataToCacheList_end_content=%s;err=%v", contentParam, err))
return
}
}(content))
}
eg.Wait()
log.Infow(ctx, "log", fmt.Sprintf("minuteDataToDB_end"))
return
}

View File

@@ -0,0 +1,30 @@
package service
import (
"flag"
"testing"
. "github.com/smartystreets/goconvey/convey"
"go-common/app/job/live/dao-anchor-job/internal/conf"
)
func init() {
flag.Set("conf", "../../cmd/test.toml")
if err := conf.Init(); err != nil {
panic(err)
}
s = New(conf.Conf)
}
func TestMinuteDataToCacheList(t *testing.T) {
Convey("testMinuteDataToCacheList", t, func() {
s.minuteDataToCacheList()
})
}
func TestMinuteDataToDB(t *testing.T) {
Convey("TestMinuteDataToDB", t, func() {
s.minuteDataToDB()
})
}

View File

@@ -0,0 +1,61 @@
package service
import (
"context"
"go-common/library/net/trace"
"go-common/library/log"
"github.com/robfig/cron"
"go-common/app/job/live/dao-anchor-job/internal/conf"
"go-common/app/job/live/dao-anchor-job/internal/dao"
)
// Service struct
type Service struct {
c *conf.Config
dao *dao.Dao
cron *cron.Cron
}
// New init
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
dao: dao.New(c),
cron: cron.New(),
}
if err := s.cron.AddFunc(s.c.CoverControl.CoverCron, s.updateKeyFrame); err != nil {
panic(err)
}
if err := s.cron.AddFunc(s.c.Minute3Control.Minute3Cron, s.minuteDataToDB); err != nil {
panic(err)
}
if err := s.cron.AddFunc(s.c.MinuteControl.MinuteCron, s.minuteDataToCacheList); err != nil {
panic(err)
}
s.cron.Start()
return s
}
// Ping Service
func (s *Service) Ping(ctx context.Context) (err error) {
return s.dao.Ping(ctx)
}
// Close Service
func (s *Service) Close() {
log.Info("Crontab Closed!")
s.cron.Stop()
log.Info("Physical Dao Closed!")
s.dao.Close()
log.Info("tv-job has been closed.")
}
func GetTraceLogCtx(ctx context.Context, title string) (ctxNew context.Context) {
t := trace.New(title)
ctxNew = trace.NewContext(ctx, t)
return
}