Initial commit

This commit is contained in:
Donny
2019-04-22 20:46:32 +08:00
commit 49ab8aadd1
25441 changed files with 4055000 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
### v1.0.0
1. 上线功能xxx

View File

@@ -0,0 +1,6 @@
# Owner
weixuan
# Author
# Reviewer

View File

@@ -0,0 +1,10 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- weixuan
labels:
- live
- service
- service/live/xroom
options:
no_parent_owners: true

View File

@@ -0,0 +1,12 @@
# xroom-service
## 项目简介
1.
## 编译环境
## 依赖包
## 编译执行

View File

@@ -0,0 +1,61 @@
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 = "api_proto",
srcs = ["api.proto"],
tags = ["automanaged"],
deps = ["@gogo_special_proto//github.com/gogo/protobuf/gogoproto"],
)
go_proto_library(
name = "api_go_proto",
compilers = ["@io_bazel_rules_go//proto:gogofast_grpc"],
importpath = "go-common/app/service/live/xroom/api",
proto = ":api_proto",
tags = ["automanaged"],
deps = ["@com_github_gogo_protobuf//gogoproto:go_default_library"],
)
go_library(
name = "go_default_library",
srcs = [
"api.bm.go",
"generate.go",
],
embed = [":api_go_proto"],
importpath = "go-common/app/service/live/xroom/api",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/net/http/blademaster:go_default_library",
"//library/net/http/blademaster/binding:go_default_library",
"@com_github_gogo_protobuf//gogoproto:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@org_golang_google_grpc//:go_default_library",
"@org_golang_x_net//context: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,79 @@
// Code generated by protoc-gen-bm v0.1, DO NOT EDIT.
// source: api.proto
/*
Package api is a generated blademaster stub package.
This code was generated with go-common/app/tool/bmgen/protoc-gen-bm v0.1.
It is generated from these files:
api.proto
*/
package api
import (
"context"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/binding"
)
// to suppressed 'imported but not used warning'
var _ *bm.Context
var _ context.Context
var _ binding.StructValidator
var PathRoomGetMultiple = "/live.xroom.v1.Room/getMultiple"
var PathRoomGetMultipleByUids = "/live.xroom.v1.Room/getMultipleByUids"
var PathRoomIsAnchor = "/live.xroom.v1.Room/isAnchor"
// ==============
// Room Interface
// ==============
type RoomBMServer interface {
// 批量根据room_ids获取房间信息
GetMultiple(ctx context.Context, req *RoomIDsReq) (resp *RoomIDsInfosResp, err error)
// 批量根据uids获取房间信息
GetMultipleByUids(ctx context.Context, req *UIDsReq) (resp *UIDsInfosResp, err error)
// 批量根据uids判断是否是主播如果是返回主播的room_id否则返回0
IsAnchor(ctx context.Context, req *IsAnchorUIDsReq) (resp *IsAnchorUIDsResp, err error)
}
var RoomSvc RoomBMServer
func roomGetMultiple(c *bm.Context) {
p := new(RoomIDsReq)
if err := c.BindWith(p, binding.Default(c.Request.Method, c.Request.Header.Get("Content-Type"))); err != nil {
return
}
resp, err := RoomSvc.GetMultiple(c, p)
c.JSON(resp, err)
}
func roomGetMultipleByUids(c *bm.Context) {
p := new(UIDsReq)
if err := c.BindWith(p, binding.Default(c.Request.Method, c.Request.Header.Get("Content-Type"))); err != nil {
return
}
resp, err := RoomSvc.GetMultipleByUids(c, p)
c.JSON(resp, err)
}
func roomIsAnchor(c *bm.Context) {
p := new(IsAnchorUIDsReq)
if err := c.BindWith(p, binding.Default(c.Request.Method, c.Request.Header.Get("Content-Type"))); err != nil {
return
}
resp, err := RoomSvc.IsAnchor(c, p)
c.JSON(resp, err)
}
// RegisterRoomBMServer Register the blademaster route
func RegisterRoomBMServer(e *bm.Engine, server RoomBMServer) {
RoomSvc = server
e.GET("/live.xroom.v1.Room/getMultiple", roomGetMultiple)
e.GET("/live.xroom.v1.Room/getMultipleByUids", roomGetMultipleByUids)
e.GET("/live.xroom.v1.Room/isAnchor", roomIsAnchor)
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,166 @@
// 定义项目 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
// gRPC Golang Model:
// - http://info.bilibili.co/display/documentation/gRPC+Golang+Model
// gRPC Golang Warden Gen:
// - http://info.bilibili.co/display/documentation/gRPC+Golang+Warden+Gen
// gRPC http 调试工具(无需pb文件):
// - http://info.bilibili.co/pages/viewpage.action?pageId=12877366
// grpc 命令行调试工具(无需pb文件):
// - http://info.bilibili.co/pages/viewpage.action?pageId=11869411
syntax = "proto3";
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
package live.xroom.v1;
option go_package = "api";
option (gogoproto.goproto_getters_all) = false;
service Room {
// 批量根据room_ids获取房间信息
rpc getMultiple (RoomIDsReq) returns (RoomIDsInfosResp);
// 批量根据uids获取房间信息
rpc getMultipleByUids (UIDsReq) returns (UIDsInfosResp);
// 批量根据uids判断是否是主播如果是返回主播的room_id否则返回0
rpc isAnchor (IsAnchorUIDsReq) returns (IsAnchorUIDsResp);
}
message RoomIDsReq {
// room_ids数组长号
repeated int64 room_ids = 1 [(gogoproto.moretags) = 'form:"room_ids" validate:"required,gt=0,dive,gt=0"'];
// 要获取的房间信息维度 status:状态相关 show:展示相关 area:分区相关 anchor:主播相关
repeated string attrs = 2 [(gogoproto.moretags) = 'form:"attrs" validate:"required,gt=0,dive,gt=0"'];
}
message UIDsReq {
// 主播uids
repeated int64 uids = 1 [(gogoproto.moretags) = 'form:"uids" validate:"required,gt=0,dive,gt=0"'];
// 要获取的房间信息维度 status:状态相关 show:展示相关 area:分区相关 anchor:主播相关
repeated string attrs = 2 [(gogoproto.moretags) = 'form:"attrs" validate:"required,gt=0,dive,gt=0"'];
}
message IsAnchorUIDsReq {
// 主播uids
repeated int64 uids = 1 [(gogoproto.moretags) = 'form:"uids" validate:"required,gt=0,dive,gt=0"'];
}
message IsAnchorUIDsResp {
// uid => room_id(长号)room_id=0表示没有创建房间
map<int64, int64> list = 1 [(gogoproto.jsontag) = "list"];
}
// 批量根据room_ids获取房间信息
message RoomIDsInfosResp {
// 主播room_id => 房间维度信息
map<int64, Infos> list = 1 [(gogoproto.jsontag) = "list"];
}
// 批量根据uids获取房间信息
message UIDsInfosResp {
// 主播UID => 房间维度信息
map<int64, Infos> list = 1 [(gogoproto.jsontag) = "list"];
}
message Infos {
// room_id 房间长号
int64 room_id = 1 [(gogoproto.jsontag) = "room_id"];
// uid 主播uid
int64 uid = 2 [(gogoproto.jsontag) = "uid"];
// Model1房间信息状态相关
RoomStatusInfo status = 3 [(gogoproto.jsontag) = "status"];
// Model2房间信息展示相关
RoomShowInfo show = 4 [(gogoproto.jsontag) = "show"];
// Model3房间信息分区相关
RoomAreaInfo area = 5 [(gogoproto.jsontag) = "area"];
// Model4房间信息主播相关
RoomAnchorInfo anchor = 6 [(gogoproto.jsontag) = "anchor"];
}
// 房间信息(状态)
message RoomStatusInfo {
// 直播间状态 0未开播1直播中2轮播中
int64 live_status = 1 [(gogoproto.jsontag) = "live_status"];
// 横竖屏方向 0横屏1竖屏
int64 live_screen_type = 2 [(gogoproto.jsontag) = "live_screen_type"];
// 是否开播过标识
int64 live_mark = 3 [(gogoproto.jsontag) = "live_mark"];
// 封禁状态0未封禁1审核封禁; 2全网封禁
int64 lock_status = 4 [(gogoproto.jsontag) = "lock_status"];
// 封禁时间戳
int64 lock_time = 5 [(gogoproto.jsontag) = "lock_time"];
// 隐藏状态 0不隐藏1隐藏
int64 hidden_status = 6 [(gogoproto.jsontag) = "hidden_status"];
// 隐藏时间戳
int64 hidden_time = 7 [(gogoproto.jsontag) = "hidden_time"];
// 直播类型 0默认 1摄像头直播 2录屏直播 3语音直播
int64 live_type = 8 [(gogoproto.jsontag) = "live_type"];
}
// 房间信息(展示)
message RoomShowInfo {
// short_id 短号
int64 short_id = 1 [(gogoproto.jsontag) = "short_id"];
// 直播间标题
string title = 2 [(gogoproto.jsontag) = "title"];
// 直播间封面
string cover = 3 [(gogoproto.jsontag) = "cover"];
// 直播间标签
string tags = 4 [(gogoproto.jsontag) = "tags"];
// 直播间背景图
string background = 5 [(gogoproto.jsontag) = "background"];
// 直播间简介
string description = 6 [(gogoproto.jsontag) = "description"];
// 关键帧
string keyframe = 7 [(gogoproto.jsontag) = "keyframe"];
// 人气值
int64 popularity_count = 8 [(gogoproto.jsontag) = "popularity_count"];
// 房间tag角标
repeated TagData tag_list = 9 [(gogoproto.jsontag) = "tag_list"];
// 最近一次开播时间戳
int64 live_start_time = 10 [(gogoproto.jsontag) = "live_start_time"];
}
// 房间信息(分区)
message RoomAreaInfo {
// 直播间分区id
int64 area_id = 1 [(gogoproto.jsontag) = "area_id"];
// 直播间分区名称
string area_name = 2 [(gogoproto.jsontag) = "area_name"];
// 直播间父分区id
int64 parent_area_id = 3 [(gogoproto.jsontag) = "parent_area_id"];
// 直播间父分区名称
string parent_area_name = 4 [(gogoproto.jsontag) = "parent_area_name"];
}
// 主播信息(展示)
message RoomAnchorInfo {
// 主播类型
int64 anchor_profile_type = 1 [(gogoproto.jsontag) = "anchor_profile_type"];
// 主播等级
AnchorLevel anchor_level = 2 [(gogoproto.jsontag) = "anchor_level"];
}
// 房间角标、tag
message TagData {
int64 tag_id = 1 [(gogoproto.jsontag) = "tag_id"];
int64 tag_sub_id = 2 [(gogoproto.jsontag) = "tag_sub_id"];
int64 tag_value = 3 [(gogoproto.jsontag) = "tag_value"];
string tag_ext = 4 [(gogoproto.jsontag) = "tag_ext"];
}
// 主播经验定义
message AnchorLevel {
// 等级
int64 level = 1 [(gogoproto.jsontag) = "level"];
// 当前等级颜色
int64 color = 2 [(gogoproto.jsontag) = "color"];
// 当前积分
int64 score = 3 [(gogoproto.jsontag) = "score"];
// 当前等级最小积分
int64 left = 4 [(gogoproto.jsontag) = "left"];
// 下一等级起始积分
int64 right = 5 [(gogoproto.jsontag) = "right"];
// 下一个经验值
int64 max_level = 6 [(gogoproto.jsontag) = "max_level"];
}

View File

@@ -0,0 +1,257 @@
<!-- package=live.xroom.v1 -->
- [/live.xroom.v1.Room/getMultiple](#live.xroom.v1.RoomgetMultiple) 批量根据room_ids获取房间信息
- [/live.xroom.v1.Room/getMultipleByUids](#live.xroom.v1.RoomgetMultipleByUids) 批量根据uids获取房间信息
- [/live.xroom.v1.Room/isAnchor](#live.xroom.v1.RoomisAnchor) 批量根据uids判断是否是主播如果是返回主播的room_id否则返回0
## /live.xroom.v1.Room/getMultiple
### 批量根据room_ids获取房间信息
#### 方法GET
#### 请求参数
|参数名|必选|类型|描述|
|:---|:---|:---|:---|
|room_ids|是|多个integer| room_ids数组长号|
|attrs|是|多个string| 要获取的房间信息维度 status:状态相关 show:展示相关 area:分区相关 anchor:主播相关|
#### 响应
```javascript
{
"code": 0,
"message": "ok",
"data": {
// 主播room_id => 房间维度信息
"list": {
"1": {
// room_id 房间长号
"room_id": 0,
// uid 主播uid
"uid": 0,
// Model1房间信息状态相关
"status": {
// 直播间状态 0未开播1直播中2轮播中
"live_status": 0,
// 横竖屏方向 0横屏1竖屏
"live_screen_type": 0,
// 是否开播过标识
"live_mark": 0,
// 封禁状态0未封禁1审核封禁; 2全网封禁
"lock_status": 0,
// 封禁时间戳
"lock_time": 0,
// 隐藏状态 0不隐藏1隐藏
"hidden_status": 0,
// 隐藏时间戳
"hidden_time": 0,
// 直播类型 0默认 1摄像头直播 2录屏直播 3语音直播
"live_type": 0
},
// Model2房间信息展示相关
"show": {
// short_id 短号
"short_id": 0,
// 直播间标题
"title": "",
// 直播间封面
"cover": "",
// 直播间标签
"tags": "",
// 直播间背景图
"background": "",
// 直播间简介
"description": "",
// 关键帧
"keyframe": "",
// 人气值
"popularity_count": 0,
// 房间tag角标
"tag_list": [
{
"tag_id": 0,
"tag_sub_id": 0,
"tag_value": 0,
"tag_ext": ""
}
],
// 最近一次开播时间戳
"live_start_time": 0
},
// Model3房间信息分区相关
"area": {
// 直播间分区id
"area_id": 0,
// 直播间分区名称
"area_name": "",
// 直播间父分区id
"parent_area_id": 0,
// 直播间父分区名称
"parent_area_name": ""
},
// Model4房间信息主播相关
"anchor": {
// 主播类型
"anchor_profile_type": 0,
// 主播等级
"anchor_level": {
// 等级
"level": 0,
// 当前等级颜色
"color": 0,
// 当前积分
"score": 0,
// 当前等级最小积分
"left": 0,
// 下一等级起始积分
"right": 0,
// 下一个经验值
"max_level": 0
}
}
}
}
}
}
```
## /live.xroom.v1.Room/getMultipleByUids
### 批量根据uids获取房间信息
#### 方法GET
#### 请求参数
|参数名|必选|类型|描述|
|:---|:---|:---|:---|
|uids|是|多个integer| 主播uids|
|attrs|是|多个string| 要获取的房间信息维度 status:状态相关 show:展示相关 area:分区相关 anchor:主播相关|
#### 响应
```javascript
{
"code": 0,
"message": "ok",
"data": {
// 主播UID => 房间维度信息
"list": {
"1": {
// room_id 房间长号
"room_id": 0,
// uid 主播uid
"uid": 0,
// Model1房间信息状态相关
"status": {
// 直播间状态 0未开播1直播中2轮播中
"live_status": 0,
// 横竖屏方向 0横屏1竖屏
"live_screen_type": 0,
// 是否开播过标识
"live_mark": 0,
// 封禁状态0未封禁1审核封禁; 2全网封禁
"lock_status": 0,
// 封禁时间戳
"lock_time": 0,
// 隐藏状态 0不隐藏1隐藏
"hidden_status": 0,
// 隐藏时间戳
"hidden_time": 0,
// 直播类型 0默认 1摄像头直播 2录屏直播 3语音直播
"live_type": 0
},
// Model2房间信息展示相关
"show": {
// short_id 短号
"short_id": 0,
// 直播间标题
"title": "",
// 直播间封面
"cover": "",
// 直播间标签
"tags": "",
// 直播间背景图
"background": "",
// 直播间简介
"description": "",
// 关键帧
"keyframe": "",
// 人气值
"popularity_count": 0,
// 房间tag角标
"tag_list": [
{
"tag_id": 0,
"tag_sub_id": 0,
"tag_value": 0,
"tag_ext": ""
}
],
// 最近一次开播时间戳
"live_start_time": 0
},
// Model3房间信息分区相关
"area": {
// 直播间分区id
"area_id": 0,
// 直播间分区名称
"area_name": "",
// 直播间父分区id
"parent_area_id": 0,
// 直播间父分区名称
"parent_area_name": ""
},
// Model4房间信息主播相关
"anchor": {
// 主播类型
"anchor_profile_type": 0,
// 主播等级
"anchor_level": {
// 等级
"level": 0,
// 当前等级颜色
"color": 0,
// 当前积分
"score": 0,
// 当前等级最小积分
"left": 0,
// 下一等级起始积分
"right": 0,
// 下一个经验值
"max_level": 0
}
}
}
}
}
}
```
## /live.xroom.v1.Room/isAnchor
### 批量根据uids判断是否是主播如果是返回主播的room_id否则返回0
#### 方法GET
#### 请求参数
|参数名|必选|类型|描述|
|:---|:---|:---|:---|
|uids|是|多个integer| 主播uids|
#### 响应
```javascript
{
"code": 0,
"message": "ok",
"data": {
// uid => room_id(长号)room_id=0表示没有创建房间
"list": {
"1": 0
}
}
}
```

View File

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

View File

@@ -0,0 +1,43 @@
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"],
importpath = "go-common/app/service/live/xroom/cmd",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/live/xroom/internal/server/grpc:go_default_library",
"//app/service/live/xroom/internal/server/http:go_default_library",
"//app/service/live/xroom/internal/service:go_default_library",
"//library/conf/paladin:go_default_library",
"//library/ecode/tip:go_default_library",
"//library/log: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,50 @@
package main
import (
"context"
"flag"
"os"
"os/signal"
"syscall"
"time"
"go-common/app/service/live/xroom/internal/server/grpc"
"go-common/app/service/live/xroom/internal/server/http"
"go-common/app/service/live/xroom/internal/service"
"go-common/library/conf/paladin"
ecode "go-common/library/ecode/tip"
"go-common/library/log"
)
func main() {
flag.Parse()
if err := paladin.Init(); err != nil {
panic(err)
}
log.Init(nil) // debug flag: log.dir={path}
defer log.Close()
log.Info("xroom-service start")
ecode.Init(nil)
svc := service.New()
grpcSrv := grpc.New(svc)
httpSrv := http.New(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:
ctx, _ := context.WithTimeout(context.Background(), 35*time.Second)
grpcSrv.Shutdown(ctx)
httpSrv.Shutdown(ctx)
log.Info("xroom-service exit")
svc.Close()
time.Sleep(time.Second)
return
case syscall.SIGHUP:
default:
return
}
}
}

View File

@@ -0,0 +1,2 @@
# This is a TOML document. Boom

View File

@@ -0,0 +1,6 @@
[server]
addr = "0.0.0.0:9000"
timeout = "1s"
[client]
timeout = "1s"

View File

@@ -0,0 +1,4 @@
[server]
addr = "0.0.0.0:8000"
timeout = "1s"

View File

@@ -0,0 +1,13 @@
demoExpire = "24h"
[demo]
name = "xroom"
proto = "tcp"
addr = "127.0.0.1:11211"
active = 50
idle = 10
dialTimeout = "100ms"
readTimeout = "200ms"
writeTimeout = "300ms"
idleTimeout = "80s"

View File

@@ -0,0 +1,11 @@
[demo]
addr = "127.0.0.1:3306"
dsn = "{user}:{password}@tcp(127.0.0.1:3306)/{database}?timeout=1s&readTimeout=1s&writeTimeout=1s&parseTime=true&loc=Local&charset=utf8mb4,utf8"
readDSN = ["{user}:{password}@tcp(127.0.0.2:3306)/{database}?timeout=1s&readTimeout=1s&writeTimeout=1s&parseTime=true&loc=Local&charset=utf8mb4,utf8","{user}:{password}@tcp(127.0.0.3:3306)/{database}?timeout=1s&readTimeout=1s&writeTimeout=1s&parseTime=true&loc=Local&charset=utf8,utf8mb4"]
active = 20
idle = 10
idleTimeout ="4h"
queryTimeout = "200ms"
execTimeout = "300ms"
tranTimeout = "400ms"

View File

@@ -0,0 +1,13 @@
demoExpire = "24h"
[demo]
name = "xroom"
proto = "tcp"
addr = "127.0.0.1:6389"
idle = 10
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"

View File

@@ -0,0 +1,33 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["dao.go"],
importpath = "go-common/app/service/live/xroom/internal/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/cache/memcache:go_default_library",
"//library/cache/redis:go_default_library",
"//library/database/sql: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,92 @@
package dao
import (
"context"
"go-common/library/cache/memcache"
"go-common/library/cache/redis"
"go-common/library/database/sql"
)
// Dao dao.
type Dao struct {
db *sql.DB
redis *redis.Pool
redisExpire int32
mc *memcache.Pool
mcExpire int32
}
func checkErr(err error) {
if err != nil {
panic(err)
}
}
// New new a dao and return.
func New() (dao *Dao) {
var (
// dc struct {
// Demo *sql.Config
// }
// rc struct {
// Demo *redis.Config
// DemoExpire xtime.Duration
// }
// mc struct {
// Demo *memcache.Config
// DemoExpire xtime.Duration
// }
)
// checkErr(paladin.Get("mysql.toml").UnmarshalTOML(&dc))
// checkErr(paladin.Get("redis.toml").UnmarshalTOML(&rc))
// checkErr(paladin.Get("memcache.toml").UnmarshalTOML(&mc))
dao = &Dao{
// // mysql
// db: sql.NewMySQL(dc.Demo),
// // redis
// redis: redis.NewPool(rc.Demo),
// redisExpire: int32(time.Duration(rc.DemoExpire) / time.Second),
// // memcache
// mc: memcache.NewPool(mc.Demo),
// mcExpire: int32(time.Duration(mc.DemoExpire) / time.Second),
}
return
}
// Close close the resource.
func (d *Dao) Close() {
// d.mc.Close()
// d.redis.Close()
// d.db.Close()
}
// Ping ping the resource.
func (d *Dao) Ping(ctx context.Context) (err error) {
// if err = d.pingMC(ctx); err != nil {
// return
// }
// if err = d.pingRedis(ctx); err != nil {
// return
// }
// return d.db.Ping(ctx)
return nil
}
// func (d *Dao) pingMC(ctx context.Context) (err error) {
// conn := d.mc.Get(ctx)
// defer conn.Close()
// if err = conn.Set(&memcache.Item{Key: "ping", Value: []byte("pong"), Expiration: 0}); err != nil {
// log.Error("conn.Set(PING) error(%v)", err)
// }
// return
// }
// func (d *Dao) pingRedis(ctx context.Context) (err error) {
// conn := d.redis.Get(ctx)
// defer conn.Close()
// if _, err = conn.Do("SET", "ping", "pong"); err != nil {
// log.Error("conn.Set(PING) error(%v)", err)
// }
// 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/service/live/xroom/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,34 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["server.go"],
importpath = "go-common/app/service/live/xroom/internal/server/grpc",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/live/xroom/api:go_default_library",
"//app/service/live/xroom/internal/service:go_default_library",
"//library/conf/paladin:go_default_library",
"//library/net/rpc/warden: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,27 @@
package grpc
import (
pb "go-common/app/service/live/xroom/api"
"go-common/app/service/live/xroom/internal/service"
"go-common/library/conf/paladin"
"go-common/library/net/rpc/warden"
)
// New new a grpc server.
func New(svc *service.Service) *warden.Server {
var rc struct {
Server *warden.ServerConfig
}
if err := paladin.Get("grpc.toml").UnmarshalTOML(&rc); err != nil {
if err != paladin.ErrNotExist {
panic(err)
}
}
ws := warden.NewServer(rc.Server)
pb.RegisterRoomServer(ws.Server(), svc)
ws, err := ws.Start()
if err != nil {
panic(err)
}
return ws
}

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/service/live/xroom/internal/server/http",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/live/xroom/internal/service:go_default_library",
"//library/conf/paladin: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,61 @@
package http
import (
"net/http"
"go-common/app/service/live/xroom/internal/service"
"go-common/library/conf/paladin"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/verify"
)
var (
svc *service.Service
)
// New new a bm server.
func New(s *service.Service) (engine *bm.Engine) {
var (
hc struct {
Server *bm.ServerConfig
}
)
if err := paladin.Get("http.toml").UnmarshalTOML(&hc); err != nil {
if err != paladin.ErrNotExist {
panic(err)
}
}
svc = s
engine = bm.DefaultServer(hc.Server)
initRouter(engine, verify.New(nil))
if err := engine.Start(); err != nil {
panic(err)
}
return
}
func initRouter(e *bm.Engine, v *verify.Verify) {
e.Ping(ping)
e.Register(register)
g := e.Group("/x/xroom")
{
g.GET("/start", v.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,40 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"room.go",
"service.go",
],
importpath = "go-common/app/service/live/xroom/internal/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/live/dao-anchor/api/grpc/v1:go_default_library",
"//app/service/live/xroom/api:go_default_library",
"//app/service/live/xroom/internal/dao:go_default_library",
"//library/conf/paladin:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/rpc/warden: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,222 @@
package service
import (
"context"
dav1 "go-common/app/service/live/dao-anchor/api/grpc/v1"
pb "go-common/app/service/live/xroom/api"
"go-common/library/ecode"
"go-common/library/log"
)
type fieldInfo struct {
fields []string
attrs map[string]bool
}
// Model维度Model定义
var (
attrsMap = map[string][]string{
"status": {"live_status", "live_screen_type", "live_mark", "lock_time", "lock_status", "hidden_status", "hidden_time", "live_type"},
"show": {"short_id", "title", "cover", "tags", "background", "description", "keyframe", "popularity_count", "tag_list", "live_start_time"},
"area": {"area_id", "area_name", "parent_area_id", "parent_area_name"},
"anchor": {"anchor_profile_type", "anchor_data"},
}
)
// GetMultiple implementation
// 批量根据room_ids获取房间信息
func (s *Service) GetMultiple(ctx context.Context, req *pb.RoomIDsReq) (resp *pb.RoomIDsInfosResp, err error) {
resp = &pb.RoomIDsInfosResp{
List: map[int64]*pb.Infos{},
}
var fi *fieldInfo
if fi, err = attrsProcess(req.Attrs); err != nil {
return
}
freq := &dav1.RoomByIDsReq{
RoomIds: req.RoomIds,
Fields: fi.fields,
DefaultFields: 0,
}
fresp, ferr := s.daClient.FetchRoomByIDs(ctx, freq)
if ferr != nil {
log.Error("[GetMultiple]FetchRoomByIDs from dao-anchor err:%+v", ferr.Error())
return nil, ferr
}
for k, v := range fresp.RoomDataSet {
resp.List[k] = infoSet(v, len(req.RoomIds), fi.attrs)
}
return resp, nil
}
// GetMultipleByUids implementation
// 批量根据uids获取房间信息
func (s *Service) GetMultipleByUids(ctx context.Context, req *pb.UIDsReq) (resp *pb.UIDsInfosResp, err error) {
resp = &pb.UIDsInfosResp{
List: map[int64]*pb.Infos{},
}
var fi *fieldInfo
if fi, err = attrsProcess(req.Attrs); err != nil {
return
}
freq := &dav1.RoomByIDsReq{
Uids: req.Uids,
Fields: fi.fields,
DefaultFields: 0,
}
fresp, ferr := s.daClient.FetchRoomByIDs(ctx, freq)
if ferr != nil {
log.Error("[GetMultipleByUids]FetchRoomByIDs from dao-anchor err:%+v", ferr.Error())
return resp, ferr
}
for _, v := range fresp.RoomDataSet {
resp.List[v.Uid] = infoSet(v, len(req.Uids), fi.attrs)
}
return
}
// IsAnchor implementation
// 批量根据uids判断是否是主播如果是返回主播的room_id否则返回0
func (s *Service) IsAnchor(ctx context.Context, req *pb.IsAnchorUIDsReq) (resp *pb.IsAnchorUIDsResp, err error) {
resp = &pb.IsAnchorUIDsResp{
List: map[int64]int64{},
}
freq := &dav1.RoomByIDsReq{
Uids: req.Uids,
Fields: []string{"room_id", "uid"},
DefaultFields: 1,
}
fresp, ferr := s.daClient.FetchRoomByIDs(ctx, freq)
if ferr != nil {
log.Error("[IsAnchor] FetchRoomByIDs from dao-anchor err:%+v]", ferr.Error())
return resp, ferr
}
uidMap := make(map[int64]int64)
for _, v := range fresp.RoomDataSet {
uidMap[v.Uid] = v.RoomId
}
for _, v := range req.Uids {
if roomID, ok := uidMap[v]; ok {
resp.List[v] = roomID
continue
}
resp.List[v] = 0
}
return
}
func attrsProcess(attrs []string) (fi *fieldInfo, err error) {
fi = &fieldInfo{
fields: []string{},
attrs: map[string]bool{},
}
tidyFields := make([]string, 0)
fieldsExistMap := make(map[string]bool)
for _, dimension := range attrs {
if fields, ok := attrsMap[dimension]; ok {
for _, field := range fields {
if _, exist := fieldsExistMap[field]; !exist {
tidyFields = append(tidyFields, field)
fieldsExistMap[field] = true
}
}
fi.attrs[dimension] = true
}
}
if len(tidyFields) == 0 {
return nil, ecode.Error(-400, "attrs error value")
}
fi.fields = tidyFields
return fi, nil
}
func tagList(tag []*dav1.TagData, len int) (pbTags []*pb.TagData) {
pbTags = make([]*pb.TagData, 0, len)
for k, v := range tag {
pbTags[k] = &pb.TagData{
TagId: v.GetTagId(),
TagSubId: v.GetTagSubId(),
TagValue: v.GetTagValue(),
TagExt: v.GetTagExt(),
}
}
return nil
}
func infoSet(rs *dav1.RoomData, len int, attrs map[string]bool) (info *pb.Infos) {
infos := &pb.Infos{
RoomId: rs.GetRoomId(),
Uid: rs.GetUid(),
}
if attrs["status"] {
infos.Status = &pb.RoomStatusInfo{
LiveStatus: rs.GetLiveStatus(),
LiveScreenType: rs.GetLiveScreenType(),
LiveMark: rs.GetLiveMark(),
LockTime: rs.GetLockTime(),
LockStatus: rs.GetLockStatus(),
HiddenStatus: rs.GetHiddenStatus(),
HiddenTime: rs.GetHiddenTime(),
LiveType: rs.GetLiveType(),
}
}
if attrs["show"] {
infos.Show = &pb.RoomShowInfo{
ShortId: rs.GetShortId(),
Title: rs.GetTitle(),
Cover: rs.GetCover(),
Tags: rs.GetTags(),
Background: rs.GetBackground(),
Description: rs.GetDescription(),
Keyframe: rs.GetKeyframe(),
PopularityCount: rs.GetPopularityCount(),
TagList: tagList(rs.GetTagList(), len),
LiveStartTime: rs.GetLiveStartTime(),
}
}
if attrs["area"] {
infos.Area = &pb.RoomAreaInfo{
AreaId: rs.GetAreaId(),
AreaName: rs.GetAreaName(),
ParentAreaId: rs.GetParentAreaId(),
ParentAreaName: rs.GetParentAreaName(),
}
}
if attrs["anchor"] {
infos.Anchor = &pb.RoomAnchorInfo{
AnchorProfileType: rs.GetAnchorProfileType(),
AnchorLevel: &pb.AnchorLevel{
Level: rs.GetAnchorLevel().GetLevel(),
Color: rs.GetAnchorLevel().GetColor(),
Score: rs.GetAnchorLevel().GetScore(),
Left: rs.GetAnchorLevel().GetLeft(),
Right: rs.GetAnchorLevel().GetRight(),
MaxLevel: rs.GetAnchorLevel().GetMaxLevel(),
},
}
}
return infos
}

View File

@@ -0,0 +1,63 @@
package service
import (
"context"
dav1 "go-common/app/service/live/dao-anchor/api/grpc/v1"
"go-common/app/service/live/xroom/internal/dao"
"go-common/library/conf/paladin"
"go-common/library/net/rpc/warden"
)
// Service service.
type Service struct {
ac *paladin.Map
appConf *AppConf
dao *dao.Dao
daClient *dav1.Client
}
// AppConf Conf
type AppConf struct {
}
//GrpcConf conf
type GrpcConf struct {
Client *warden.ClientConfig
Server *warden.ServerConfig
}
// New new a service and return.
func New() (s *Service) {
var ac = new(paladin.TOML)
if err := paladin.Watch("application.toml", ac); err != nil {
panic(err)
}
var gConf *GrpcConf
if err := paladin.Get("grpc.toml").UnmarshalTOML(&gConf); err != nil {
panic(err)
}
dClient, err := dav1.NewClient(gConf.Client)
if err != nil {
panic(err)
}
s = &Service{
ac: ac,
dao: dao.New(),
daClient: dClient,
}
return s
}
// Ping ping the resource.
func (s *Service) Ping(ctx context.Context) (err error) {
return s.dao.Ping(ctx)
}
// Close close the resource.
func (s *Service) Close() {
s.dao.Close()
}