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,23 @@
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/service/main/share/api:all-srcs",
"//app/service/main/share/cmd:all-srcs",
"//app/service/main/share/conf:all-srcs",
"//app/service/main/share/dao:all-srcs",
"//app/service/main/share/model:all-srcs",
"//app/service/main/share/server/grpc:all-srcs",
"//app/service/main/share/server/http:all-srcs",
"//app/service/main/share/service:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,58 @@
# share-service
### 1.5.2
1. 更改grpc目录
### 1.5.1
1. 增加播单类型
### 1.5.0
1. 修改pub消息type为archive
### 1.4.9
1. 更改重复举报算法
### 1.4.8
1. 优化
### 1.4.7
1. 增加databus info日志
### 1.4.6
1. pub稿件分享数
### 1.4.5
1. 拜年祭需求增加type类型判断
### 1.4.4
1. 拜年祭多aid对应单aid分享数统计
### 1.4.3
1. 改变生产消息顺序
### 1.4.2
1. databus添加消息
### 1.4.1
1. 稿件分享接入
### 1.3.1
1. 写入mid分享databus
### v1.3.0
1. remote ctx.RemoteIP()
### v1.2.1
1. fix variable name
### v1.2.0
1. 使用 bm verify
### v1.1.0
1. 增加批量接口最大30个
### v1.0.0
1. 分享计数服务
### v1.1.1
1. 添加ut测试用例

View File

@@ -0,0 +1,12 @@
# Owner
haoguanwei
renwei
zhapuyu
zhoushuguang
# Author
zhoushuguang
# Reviewer
haoguanwei
zhapuyu

View File

@@ -0,0 +1,17 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- haoguanwei
- renwei
- zhapuyu
- zhoushuguang
labels:
- main
- service
- service/main/share
options:
no_parent_owners: true
reviewers:
- haoguanwei
- zhapuyu
- zhoushuguang

View File

@@ -0,0 +1,17 @@
# go-common/app/service/share
##### 项目简介
> 1. 提供分享计数功能
##### 编译环境
> 1. 请只用golang v1.7.x以上版本编译执行。
##### 依赖包
> 1. 公共依赖
##### 编译执行
> 1. 启动执行
> 2. 项目文档http://info.bilibili.co/pages/viewpage.action?pageId=1742325
##### 测试
> 1. 执行当前目录下所有测试文件,测试所有功能

View File

@@ -0,0 +1,70 @@
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",
"go_test",
)
proto_library(
name = "v1_proto",
srcs = ["api.proto"],
tags = ["automanaged"],
deps = ["@gogo_special_proto//github.com/gogo/protobuf/gogoproto"],
)
go_proto_library(
name = "v1_go_proto",
compilers = ["@io_bazel_rules_go//proto:gogofast_grpc"],
importpath = "go-common/app/service/main/share/api",
proto = ":v1_proto",
tags = ["automanaged"],
deps = ["@com_github_gogo_protobuf//gogoproto:go_default_library"],
)
go_library(
name = "go_default_library",
srcs = ["client.go"],
embed = [":v1_go_proto"],
importpath = "go-common/app/service/main/share/api",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/net/rpc/warden: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"],
)
go_test(
name = "go_default_test",
srcs = ["client_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//library/ecode:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)

View File

@@ -0,0 +1,616 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: app/service/main/share/api/api.proto
package v1
import proto "github.com/gogo/protobuf/proto"
import fmt "fmt"
import math "math"
import _ "github.com/gogo/protobuf/gogoproto"
import (
context "golang.org/x/net/context"
grpc "google.golang.org/grpc"
)
import io "io"
// 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
type AddShareRequest struct {
Oid int64 `protobuf:"varint,1,opt,name=oid,proto3" json:"oid,omitempty"`
Mid int64 `protobuf:"varint,2,opt,name=mid,proto3" json:"mid,omitempty"`
Type int32 `protobuf:"varint,3,opt,name=type,proto3" json:"type,omitempty"`
Ip string `protobuf:"bytes,4,opt,name=ip,proto3" json:"ip,omitempty"`
}
func (m *AddShareRequest) Reset() { *m = AddShareRequest{} }
func (m *AddShareRequest) String() string { return proto.CompactTextString(m) }
func (*AddShareRequest) ProtoMessage() {}
func (*AddShareRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_api_84381552fbdb86d8, []int{0}
}
func (m *AddShareRequest) GetOid() int64 {
if m != nil {
return m.Oid
}
return 0
}
func (m *AddShareRequest) GetMid() int64 {
if m != nil {
return m.Mid
}
return 0
}
func (m *AddShareRequest) GetType() int32 {
if m != nil {
return m.Type
}
return 0
}
func (m *AddShareRequest) GetIp() string {
if m != nil {
return m.Ip
}
return ""
}
type AddShareReply struct {
Shares int64 `protobuf:"varint,1,opt,name=shares,proto3" json:"shares,omitempty"`
}
func (m *AddShareReply) Reset() { *m = AddShareReply{} }
func (m *AddShareReply) String() string { return proto.CompactTextString(m) }
func (*AddShareReply) ProtoMessage() {}
func (*AddShareReply) Descriptor() ([]byte, []int) {
return fileDescriptor_api_84381552fbdb86d8, []int{1}
}
func (m *AddShareReply) GetShares() int64 {
if m != nil {
return m.Shares
}
return 0
}
func init() {
proto.RegisterType((*AddShareRequest)(nil), "share.service.v1.AddShareRequest")
proto.RegisterType((*AddShareReply)(nil), "share.service.v1.AddShareReply")
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4
// ShareClient is the client API for Share service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type ShareClient interface {
AddShare(ctx context.Context, in *AddShareRequest, opts ...grpc.CallOption) (*AddShareReply, error)
}
type shareClient struct {
cc *grpc.ClientConn
}
func NewShareClient(cc *grpc.ClientConn) ShareClient {
return &shareClient{cc}
}
func (c *shareClient) AddShare(ctx context.Context, in *AddShareRequest, opts ...grpc.CallOption) (*AddShareReply, error) {
out := new(AddShareReply)
err := c.cc.Invoke(ctx, "/share.service.v1.Share/AddShare", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// ShareServer is the server API for Share service.
type ShareServer interface {
AddShare(context.Context, *AddShareRequest) (*AddShareReply, error)
}
func RegisterShareServer(s *grpc.Server, srv ShareServer) {
s.RegisterService(&_Share_serviceDesc, srv)
}
func _Share_AddShare_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(AddShareRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ShareServer).AddShare(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/share.service.v1.Share/AddShare",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ShareServer).AddShare(ctx, req.(*AddShareRequest))
}
return interceptor(ctx, in, info, handler)
}
var _Share_serviceDesc = grpc.ServiceDesc{
ServiceName: "share.service.v1.Share",
HandlerType: (*ShareServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "AddShare",
Handler: _Share_AddShare_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "app/service/main/share/api/api.proto",
}
func (m *AddShareRequest) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalTo(dAtA)
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *AddShareRequest) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if m.Oid != 0 {
dAtA[i] = 0x8
i++
i = encodeVarintApi(dAtA, i, uint64(m.Oid))
}
if m.Mid != 0 {
dAtA[i] = 0x10
i++
i = encodeVarintApi(dAtA, i, uint64(m.Mid))
}
if m.Type != 0 {
dAtA[i] = 0x18
i++
i = encodeVarintApi(dAtA, i, uint64(m.Type))
}
if len(m.Ip) > 0 {
dAtA[i] = 0x22
i++
i = encodeVarintApi(dAtA, i, uint64(len(m.Ip)))
i += copy(dAtA[i:], m.Ip)
}
return i, nil
}
func (m *AddShareReply) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalTo(dAtA)
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *AddShareReply) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if m.Shares != 0 {
dAtA[i] = 0x8
i++
i = encodeVarintApi(dAtA, i, uint64(m.Shares))
}
return i, nil
}
func encodeVarintApi(dAtA []byte, offset int, v uint64) int {
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return offset + 1
}
func (m *AddShareRequest) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if m.Oid != 0 {
n += 1 + sovApi(uint64(m.Oid))
}
if m.Mid != 0 {
n += 1 + sovApi(uint64(m.Mid))
}
if m.Type != 0 {
n += 1 + sovApi(uint64(m.Type))
}
l = len(m.Ip)
if l > 0 {
n += 1 + l + sovApi(uint64(l))
}
return n
}
func (m *AddShareReply) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if m.Shares != 0 {
n += 1 + sovApi(uint64(m.Shares))
}
return n
}
func sovApi(x uint64) (n int) {
for {
n++
x >>= 7
if x == 0 {
break
}
}
return n
}
func sozApi(x uint64) (n int) {
return sovApi(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *AddShareRequest) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowApi
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: AddShareRequest: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: AddShareRequest: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Oid", wireType)
}
m.Oid = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowApi
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Oid |= (int64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 2:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Mid", wireType)
}
m.Mid = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowApi
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Mid |= (int64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 3:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
}
m.Type = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowApi
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Type |= (int32(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 4:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Ip", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowApi
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthApi
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Ip = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipApi(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthApi
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *AddShareReply) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowApi
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: AddShareReply: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: AddShareReply: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Shares", wireType)
}
m.Shares = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowApi
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Shares |= (int64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
default:
iNdEx = preIndex
skippy, err := skipApi(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthApi
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipApi(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowApi
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowApi
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
return iNdEx, nil
case 1:
iNdEx += 8
return iNdEx, nil
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowApi
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
iNdEx += length
if length < 0 {
return 0, ErrInvalidLengthApi
}
return iNdEx, nil
case 3:
for {
var innerWire uint64
var start int = iNdEx
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowApi
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
innerWire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
innerWireType := int(innerWire & 0x7)
if innerWireType == 4 {
break
}
next, err := skipApi(dAtA[start:])
if err != nil {
return 0, err
}
iNdEx = start + next
}
return iNdEx, nil
case 4:
return iNdEx, nil
case 5:
iNdEx += 4
return iNdEx, nil
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
}
panic("unreachable")
}
var (
ErrInvalidLengthApi = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowApi = fmt.Errorf("proto: integer overflow")
)
func init() {
proto.RegisterFile("app/service/main/share/api/api.proto", fileDescriptor_api_84381552fbdb86d8)
}
var fileDescriptor_api_84381552fbdb86d8 = []byte{
// 256 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x8f, 0x4b, 0x4a, 0xc4, 0x40,
0x10, 0x86, 0xe9, 0x64, 0x66, 0xd0, 0x02, 0x35, 0xf4, 0x42, 0xc2, 0x2c, 0x62, 0x9c, 0x8d, 0x59,
0x68, 0x37, 0xd1, 0x13, 0xe8, 0x01, 0x5c, 0xc4, 0x85, 0xe8, 0x2e, 0x8f, 0x36, 0x53, 0x30, 0xb1,
0xcb, 0xbc, 0x20, 0x37, 0x74, 0xe9, 0x11, 0x24, 0x27, 0x91, 0xd4, 0x44, 0x84, 0x59, 0xb8, 0xfb,
0xff, 0xea, 0xaf, 0x3f, 0xaa, 0xe0, 0x3a, 0x25, 0xd2, 0x8d, 0xa9, 0x7b, 0xcc, 0x8d, 0xae, 0x52,
0x7c, 0xd7, 0xcd, 0x36, 0xad, 0x8d, 0x4e, 0x09, 0x75, 0x59, 0x53, 0xae, 0xfb, 0x78, 0xca, 0x8a,
0x6a, 0xdb, 0x5a, 0xe9, 0xf1, 0xa3, 0x9a, 0x79, 0xd5, 0xc7, 0xeb, 0x9b, 0x12, 0xdb, 0x6d, 0x97,
0xa9, 0xdc, 0x56, 0xba, 0xb4, 0xa5, 0xd5, 0x0c, 0x66, 0xdd, 0x1b, 0x37, 0x2e, 0x9c, 0xf6, 0x82,
0xcd, 0x0b, 0x9c, 0xdd, 0x17, 0xc5, 0xd3, 0x64, 0x49, 0xcc, 0x47, 0x67, 0x9a, 0x56, 0x7a, 0xe0,
0x5a, 0x2c, 0x7c, 0x11, 0x8a, 0xc8, 0x4d, 0xa6, 0x38, 0x4d, 0x2a, 0x2c, 0x7c, 0x67, 0x3f, 0xa9,
0xb0, 0x90, 0x12, 0x16, 0xed, 0x40, 0xc6, 0x77, 0x43, 0x11, 0x2d, 0x13, 0xce, 0xf2, 0x14, 0x1c,
0x24, 0x7f, 0x11, 0x8a, 0xe8, 0x38, 0x71, 0x90, 0x36, 0x57, 0x70, 0xf2, 0xa7, 0xa6, 0xdd, 0x20,
0xcf, 0x61, 0xc5, 0xeb, 0x36, 0xb3, 0x7b, 0x6e, 0xb7, 0xcf, 0xb0, 0x64, 0x4a, 0x3e, 0xc2, 0xd1,
0xef, 0x0f, 0x79, 0xa9, 0x0e, 0x4f, 0x53, 0x07, 0x8b, 0xae, 0x2f, 0xfe, 0x43, 0x68, 0x37, 0x3c,
0x78, 0x9f, 0x63, 0x20, 0xbe, 0xc6, 0x40, 0x7c, 0x8f, 0x81, 0x78, 0x75, 0xfa, 0x38, 0x5b, 0xf1,
0xd5, 0x77, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x3c, 0x7c, 0x30, 0x07, 0x66, 0x01, 0x00, 0x00,
}

View File

@@ -0,0 +1,23 @@
syntax = "proto3";
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
package share.service.v1;
option go_package = "v1";
// Share grpc
service Share {
rpc AddShare(AddShareRequest) returns(AddShareReply);
}
message AddShareRequest{
int64 oid = 1;
int64 mid = 2;
int32 type = 3;
string ip = 4;
}
message AddShareReply {
int64 shares = 1;
}

View File

@@ -0,0 +1,22 @@
package v1
import (
"context"
"go-common/library/net/rpc/warden"
"google.golang.org/grpc"
)
// AppID discovery appid.
const AppID = "main.appsvr.shareservice"
// NewClient new grpc client.
func NewClient(cfg *warden.ClientConfig, opts ...grpc.DialOption) (ShareClient, error) {
client := warden.NewClient(cfg, opts...)
conn, err := client.Dial(context.Background(), "discovery://default/"+AppID)
if err != nil {
return nil, err
}
return NewShareClient(conn), nil
}

View File

@@ -0,0 +1,36 @@
package v1
import (
"context"
"testing"
"go-common/library/ecode"
"github.com/smartystreets/goconvey/convey"
)
var client ShareClient
func init() {
var err error
client, err = NewClient(nil)
if err != nil {
panic(err)
}
}
func TestAddShare(t *testing.T) {
convey.Convey("TestAddShare", t, func(ctx convey.C) {
var c = context.Background()
ctx.Convey("When everything is correct", func(ctx convey.C) {
reply, err := client.AddShare(c, &AddShareRequest{Oid: 22, Mid: 33, Type: 3})
ctx.So(err, convey.ShouldBeNil)
ctx.Printf("%+v\n", reply.Shares)
})
ctx.Convey("When error", func(ctx convey.C) {
reply, err := client.AddShare(c, &AddShareRequest{Oid: 22, Mid: 33, Type: 3})
ctx.So(err, convey.ShouldEqual, ecode.ShareAlreadyAdd)
ctx.So(reply, convey.ShouldBeNil)
})
})
}

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"],
data = ["share-service-test.toml"],
importpath = "go-common/app/service/main/share/cmd",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/share/conf:go_default_library",
"//app/service/main/share/server/grpc:go_default_library",
"//app/service/main/share/server/http:go_default_library",
"//app/service/main/share/service: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,45 @@
package main
import (
"context"
"flag"
"os"
"os/signal"
"syscall"
"go-common/app/service/main/share/conf"
"go-common/app/service/main/share/server/grpc"
"go-common/app/service/main/share/server/http"
"go-common/app/service/main/share/service"
"go-common/library/log"
)
func main() {
flag.Parse()
if err := conf.Init(); err != nil {
log.Error("conf.Init() error(%v)", err)
panic(err)
}
// init log
log.Init(conf.Conf.Xlog)
defer log.Close()
log.Info("share-service start")
svr := service.New(conf.Conf)
grpcSvr := grpc.New(conf.Conf.WardenServer, svr)
http.Init(conf.Conf, svr)
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
s := <-c
log.Info("share-service get a signal %s", s.String())
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
grpcSvr.Shutdown(context.Background())
log.Info("share-service exit")
return
case syscall.SIGHUP:
default:
return
}
}
}

View File

@@ -0,0 +1,121 @@
# This is a TOML document. Boom.
version = "1.0.0"
user = "nobody"
pid = "/tmp/share-service.pid"
dir = "./"
perf = "127.0.0.1:6080"
family = "share-service"
RedisExpire = 108000
tick = "5m"
worker = 8
AllowType = [1,2,3]
Target = 2233
Sources = [111,222,333,444,555,666]
[xlog]
dir = "/data/log/share-service/"
[statsd]
project = "share-service"
addr = "172.18.20.15:8200"
chanSize = 10240
[tracer]
proto = "udp"
addr = "172.16.33.46:5140"
tag = "platform/share-service"
[app]
key = "53e2fa226f5ad348"
secret = "3cf6bd1b0ff671021da5f424fea4b04a"
[bm]
addr = "0.0.0.0:6081"
timeout = "1s"
[db]
name = "172.16.33.205:3308"
dsn = "test:test@tcp(172.16.33.205:3308)/bilibili_share?timeout=200ms&readTimeout=200ms&writeTimeout=200ms&parseTime=true&loc=Local&charset=utf8,utf8mb4"
active = 5
idle = 1
idleTimeout ="4h"
queryTimeout = "10s"
execTimeout = "10s"
tranTimeout = "10s"
[db.arc.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[ecode]
domain = "172.16.33.248:6401"
all = "1h"
diff = "5m"
[ecode.clientconfig]
key = "test"
secret = "e6c4c252dc7e3d8a90805eecd7c73396"
dial = "2000ms"
timeout = "2s"
keepAlive = "10s"
timer = 128
[ecode.clientconfig.breaker]
window ="3s"
sleep ="100ms"
bucket = 10
ratio = 0.5
request = 100
[ecode.app]
key = "test"
secret = "e6c4c252dc7e3d8a90805eecd7c73396"
[redis]
name = "share-service/redis"
proto = "tcp"
addr = "172.18.33.61:6889"
idle = 50
active = 100
dialTimeout = "10s"
readTimeout = "10s"
writeTimeout = "10s"
idleTimeout = "80s"
expire = "8h"
[databus]
key = "8e27ab7e39270b59"
secret = "477df6a068d7332a163f95abbad2079c"
group = "ShareMid-MainAppSvr-P"
topic = "ShareMid-T"
action = "pub"
name = "share-service/pub"
proto = "tcp"
addr = "172.18.33.50:6205"
idle = 100
active = 100
dialTimeout = "1s"
readTimeout = "60s"
writeTimeout = "1s"
idleTimeout = "10s"
[archiveDatabus]
key = "8e27ab7e39270b59"
secret = "477df6a068d7332a163f95abbad2079c"
group = "StatShare-MainAppSvr-P"
topic = "StatShare-T"
action = "pub"
name = "archive-service/StatShare"
proto = "tcp"
addr = "172.18.33.50:6205"
idle = 10
active = 50
dialTimeout = "2s"
readTimeout = "2s"
writeTimeout = "2s"
idleTimeout = "80s"

View File

@@ -0,0 +1,42 @@
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/service/main/share/conf",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/cache/redis:go_default_library",
"//library/conf:go_default_library",
"//library/database/sql: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:go_default_library",
"//library/net/rpc/warden:go_default_library",
"//library/net/trace:go_default_library",
"//library/queue/databus: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,96 @@
package conf
import (
"errors"
"flag"
"go-common/library/cache/redis"
"go-common/library/conf"
"go-common/library/database/sql"
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/rpc"
"go-common/library/net/rpc/warden"
"go-common/library/net/trace"
"go-common/library/queue/databus"
"github.com/BurntSushi/toml"
)
var (
// Conf .
Conf = &Config{}
confPath string
client *conf.Client
)
// Config struct
type Config struct {
Xlog *log.Config
Tracer *trace.Config
BM *bm.ServerConfig
DB *sql.Config
Ecode *ecode.Config
Verify *verify.Config
Redis *redis.Config
AllowType []int
RedisExpire int64
Databus *databus.Config
ArchiveDatabus *databus.Config
WardenServer *warden.ServerConfig
ArcRPC *rpc.ClientConfig
Target int64
Sources []int64
Worker int
}
func init() {
flag.StringVar(&confPath, "conf", "", "default config path")
}
// Init init config.
func Init() (err error) {
if confPath != "" {
_, err = toml.DecodeFile(confPath, &Conf)
return
}
err = remote()
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,68 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"dao_test.go",
"databus_test.go",
"mysql_test.go",
"redis_test.go",
"share_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/service/main/share/conf:go_default_library",
"//app/service/main/share/model:go_default_library",
"//library/ecode:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"dao.go",
"databus.go",
"mysql.go",
"redis.go",
"share.go",
],
importpath = "go-common/app/service/main/share/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/share/conf:go_default_library",
"//app/service/main/share/model:go_default_library",
"//library/cache:go_default_library",
"//library/cache/redis:go_default_library",
"//library/database/sql:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/ip:go_default_library",
"//library/queue/databus:go_default_library",
"//vendor/github.com/dgryski/go-farm:go_default_library",
"//vendor/github.com/pkg/errors: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,73 @@
package dao
import (
"context"
"go-common/app/service/main/share/conf"
"go-common/library/cache"
"go-common/library/cache/redis"
"go-common/library/database/sql"
"go-common/library/log"
"go-common/library/queue/databus"
)
// Dao is redis dao.
type Dao struct {
c *conf.Config
db *sql.DB
rds *redis.Pool
// cache chan
cacheCh chan func()
// databus
databus *databus.Databus
// archiveDatabus
archiveDatabus *databus.Databus
// sources
sources map[int64]struct{}
// asyncCache
asyncCache *cache.Cache
}
// New is new redis dao.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
db: sql.NewMySQL(c.DB),
rds: redis.NewPool(c.Redis),
cacheCh: make(chan func(), 1024),
databus: databus.New(c.Databus),
archiveDatabus: databus.New(c.ArchiveDatabus),
sources: make(map[int64]struct{}, len(c.Sources)),
asyncCache: cache.New(c.Worker, 1024),
}
for _, s := range c.Sources {
d.sources[s] = struct{}{}
}
return d
}
// BeginTran begin transcation.
func (d *Dao) BeginTran(c context.Context) (tx *sql.Tx, err error) {
return d.db.Begin(c)
}
// Close close
func (d *Dao) Close() {
d.db.Close()
d.rds.Close()
}
// Ping ping
func (d *Dao) Ping() (err error) {
if err = d.db.Ping(context.Background()); err != nil {
log.Error("d.db.Ping error(%v)", err)
return
}
conn := d.rds.Get(context.Background())
defer conn.Close()
if _, err = conn.Do("SET", "ping", "pong"); err != nil {
log.Error("redis.Set error(%v)", err)
return
}
return
}

View File

@@ -0,0 +1,45 @@
package dao
import (
"flag"
"os"
"testing"
"go-common/app/service/main/share/conf"
"github.com/smartystreets/goconvey/convey"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.app-svr.share-service")
flag.Set("conf_token", "120ed94e23b963fc0564fbdb662916c3")
flag.Set("tree_id", "25960")
flag.Set("conf_version", "docker-1")
flag.Set("deploy_env", "uat")
flag.Set("conf_host", "config.bilibili.co")
flag.Set("conf_path", "/tmp")
flag.Set("region", "sh")
flag.Set("zone", "sh001")
} else {
flag.Set("conf", "../cmd/share-service-test.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
m.Run()
os.Exit(0)
}
func TestPing(t *testing.T) {
convey.Convey("Ping", t, func() {
d.Ping()
})
}

View File

@@ -0,0 +1,31 @@
package dao
import (
"context"
"strconv"
"time"
"go-common/app/service/main/share/model"
)
// PubShare .
func (d *Dao) PubShare(c context.Context, p *model.ShareParams) (err error) {
msg := &model.MIDShare{
OID: p.OID,
MID: p.MID,
TP: p.TP,
Time: time.Now().Unix(),
}
return d.databus.Send(c, strconv.FormatInt(p.MID, 10), &msg)
}
// PubStatShare .
func (d *Dao) PubStatShare(c context.Context, typ string, oid, count int64) (err error) {
msg := &model.ArchiveShare{
Type: typ,
ID: oid,
Count: int(count),
Ts: time.Now().Unix(),
}
return d.archiveDatabus.Send(c, strconv.FormatInt(oid, 10), &msg)
}

View File

@@ -0,0 +1,31 @@
package dao
import (
"context"
"testing"
"go-common/app/service/main/share/model"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoPubShare(t *testing.T) {
convey.Convey("PubShare", t, func(ctx convey.C) {
p := &model.ShareParams{
OID: int64(1),
MID: int64(1),
TP: int(3),
}
err := d.PubShare(context.Background(), p)
convey.So(err, convey.ShouldBeNil)
})
}
func TestDaoPubStatShare(t *testing.T) {
convey.Convey("PubStatShare", t, func(ctx convey.C) {
oid := int64(1)
count := int64(666)
err := d.PubStatShare(context.Background(), model.ArchiveMsgTyp, oid, count)
convey.So(err, convey.ShouldBeNil)
})
}

View File

@@ -0,0 +1,66 @@
package dao
import (
"context"
"fmt"
"go-common/app/service/main/share/model"
"go-common/library/database/sql"
"go-common/library/log"
"github.com/pkg/errors"
)
const (
_shareSQL = "SELECT oid,tp,share FROM %s WHERE oid=? AND tp=?"
_addShareSQL = "INSERT INTO %s(oid,tp,share) VALUES(?,?,1) ON DUPLICATE KEY UPDATE share=share+1"
)
func table(oid int64) string {
return fmt.Sprintf("share_count_%02d", oid%100)
}
// Share get share
func (d *Dao) Share(c context.Context, oid int64, tp int) (share *model.Share, err error) {
row := d.db.QueryRow(c, fmt.Sprintf(_shareSQL, table(oid)), oid, tp)
share = &model.Share{}
if err = row.Scan(&share.OID, &share.Tp, &share.Count); err != nil {
if err == sql.ErrNoRows {
share = nil
err = nil
} else {
err = errors.WithStack(err)
}
return
}
return
}
// AddShare add share
func (d *Dao) AddShare(c context.Context, oid int64, tp int) (err error) {
if _, err = d.db.Exec(c, fmt.Sprintf(_addShareSQL, table(oid)), oid, tp); err != nil {
err = errors.Wrapf(err, "d.db.Exec(%s, %d, %d)", fmt.Sprintf(_addShareSQL, table(oid)), oid, tp)
return
}
if _, ok := d.sources[oid]; ok && tp == model.ArchiveTyp {
if _, err = d.db.Exec(c, fmt.Sprintf(_addShareSQL, table(d.c.Target)), d.c.Target, tp); err != nil {
return
}
var share *model.Share
if share, err = d.Share(c, d.c.Target, tp); err != nil {
return
}
// pub msg
if err = d.PubStatShare(c, model.ArchiveMsgTyp, d.c.Target, share.Count); err != nil {
log.Error("s.dao.PubArchiveShare error(%v)", err)
err = nil
}
d.asyncCache.Save(func() {
if err = d.SetShareCache(context.Background(), d.c.Target, tp, share.Count); err != nil {
log.Error("d.SetShareCache error(%v)", err)
return
}
})
}
return
}

View File

@@ -0,0 +1,50 @@
package dao
import (
"context"
"math/rand"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoTable(t *testing.T) {
var (
oid = int64(0)
)
convey.Convey("table", t, func(ctx convey.C) {
p1 := table(oid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaoShare(t *testing.T) {
var (
c = context.TODO()
oid = int64(0)
tp = int(0)
)
convey.Convey("Share", t, func(ctx convey.C) {
share, err := d.Share(c, oid, tp)
ctx.Convey("Then err should be nil.share should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(share, convey.ShouldNotBeNil)
})
})
}
func TestDaoAddShare(t *testing.T) {
var (
c = context.TODO()
oid = int64(rand.Intn(10000000))
tp = int(3)
)
convey.Convey("AddShare", t, func(ctx convey.C) {
err := d.AddShare(c, oid, tp)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}

View File

@@ -0,0 +1,121 @@
package dao
import (
"context"
"fmt"
"go-common/app/service/main/share/model"
"go-common/library/cache/redis"
"go-common/library/log"
xip "go-common/library/net/ip"
farm "github.com/dgryski/go-farm"
"github.com/pkg/errors"
)
func redisKey(oid int64, tp int) string {
return fmt.Sprintf("%d_%d", oid, tp)
}
func redisValue(p *model.ShareParams) int64 {
return int64(farm.Hash64([]byte(fmt.Sprintf("%d_%d_%d_%s", p.MID, p.OID, p.TP, p.IP))))
}
func shareKey(oid int64, tp int) string {
return fmt.Sprintf("c_%d_%d", oid, tp)
}
// AddShareMember add share
func (d *Dao) AddShareMember(ctx context.Context, p *model.ShareParams) (ok bool, err error) {
var (
conn = d.rds.Get(ctx)
key = redisKey(p.OID, p.TP)
value = (p.MID << 32) | int64(xip.InetAtoN(p.IP))
)
log.Info("oid-%d mid-%d ip-%s tp-%d key-%s value-%d", p.OID, p.MID, p.IP, p.TP, key, value)
defer conn.Close()
if err = conn.Send("SADD", key, value); err != nil {
err = errors.Wrapf(err, "conn.Do(SADD, %s, %d)", key, value)
return
}
if err = conn.Send("EXPIRE", key, d.c.RedisExpire); err != nil {
err = errors.Wrapf(err, "conn.Do(SADD, %s, %d)", key, value)
return
}
if err = conn.Flush(); err != nil {
err = errors.Wrap(err, "conn.Flush")
return
}
if ok, err = redis.Bool(conn.Receive()); err != nil {
log.Error("sadd failed mid(%d) oid(%d) type(%d) ip(%s) key(%s) value(%d)",
p.MID, p.OID, p.TP, p.IP, key, value)
err = errors.Wrap(err, "redis.Bool(conn.Receive)")
return
}
if _, err = conn.Receive(); err != nil {
err = errors.Wrap(err, "conn.Receive")
return
}
return
}
// SetShareCache set share cache
func (d *Dao) SetShareCache(c context.Context, oid int64, tp int, shared int64) (err error) {
var (
conn = d.rds.Get(c)
key = shareKey(oid, tp)
)
defer conn.Close()
if _, err = conn.Do("SET", key, shared); err != nil {
err = errors.WithStack(err)
return
}
return
}
// ShareCache return oid share count
func (d *Dao) ShareCache(c context.Context, oid int64, tp int) (shared int64, err error) {
var (
conn = d.rds.Get(c)
key = shareKey(oid, tp)
)
defer conn.Close()
if shared, err = redis.Int64(conn.Do("GET", key)); err != nil {
if err == redis.ErrNil {
shared = -1
err = nil
} else {
err = errors.WithStack(err)
}
}
return
}
// SharesCache return oids share
func (d *Dao) SharesCache(c context.Context, oids []int64, tp int) (shares map[int64]int64, err error) {
conn := d.rds.Get(c)
defer conn.Close()
for _, oid := range oids {
if err = conn.Send("GET", shareKey(oid, tp)); err != nil {
log.Error("conn.Send(GET, %s) error(%v)", shareKey(oid, tp), err)
return
}
}
if err = conn.Flush(); err != nil {
log.Error("conn.Flush error(%v)", err)
return
}
shares = make(map[int64]int64, len(oids))
for _, oid := range oids {
var cnt int64
if cnt, err = redis.Int64(conn.Receive()); err != nil {
if err == redis.ErrNil {
err = nil
continue
}
return
}
shares[oid] = cnt
}
return
}

View File

@@ -0,0 +1,111 @@
package dao
import (
"context"
"testing"
"go-common/app/service/main/share/model"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoRedisKey(t *testing.T) {
var (
oid = int64(0)
tp = int(0)
)
convey.Convey("redisKey", t, func(ctx convey.C) {
p1 := redisKey(oid, tp)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaoRedisValue(t *testing.T) {
convey.Convey("redisValue", t, func(ctx convey.C) {
p := &model.ShareParams{
OID: 22,
MID: 33,
TP: 2,
IP: "",
}
p1 := redisValue(p)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaoShareKey(t *testing.T) {
var (
oid = int64(0)
tp = int(0)
)
convey.Convey("shareKey", t, func(ctx convey.C) {
p1 := shareKey(oid, tp)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaoAddShareMember(t *testing.T) {
convey.Convey("AddShareMember", t, func(ctx convey.C) {
p := &model.ShareParams{
OID: int64(1),
MID: int64(1),
TP: int(3),
}
ok, err := d.AddShareMember(context.Background(), p)
ctx.Convey("Then err should be nil.ok should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(ok, convey.ShouldNotBeNil)
})
})
}
func TestDaoSetShareCache(t *testing.T) {
var (
c = context.TODO()
oid = int64(0)
tp = int(0)
shared = int64(0)
)
convey.Convey("SetShareCache", t, func(ctx convey.C) {
err := d.SetShareCache(c, oid, tp, shared)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoShareCache(t *testing.T) {
var (
c = context.TODO()
oid = int64(0)
tp = int(0)
)
convey.Convey("ShareCache", t, func(ctx convey.C) {
shared, err := d.ShareCache(c, oid, tp)
ctx.Convey("Then err should be nil.shared should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(shared, convey.ShouldNotBeNil)
})
})
}
func TestDaoSharesCache(t *testing.T) {
var (
c = context.TODO()
oids = []int64{}
tp = int(0)
)
convey.Convey("SharesCache", t, func(ctx convey.C) {
shares, err := d.SharesCache(c, oids, tp)
ctx.Convey("Then err should be nil.shares should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(shares, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,92 @@
package dao
import (
"context"
"go-common/app/service/main/share/model"
"go-common/library/ecode"
"go-common/library/log"
"github.com/pkg/errors"
)
// Shares get shares
func (d *Dao) Shares(ctx context.Context, oids []int64, tp int) (shares map[int64]int64, err error) {
shares, err = d.SharesCache(ctx, oids, tp)
if err != nil {
log.Error("d.SharesCache(%v) tp(%d) error(%v)", oids, tp, err)
err = nil
shares = make(map[int64]int64, len(oids))
}
var missed []int64
for _, oid := range oids {
if _, ok := shares[oid]; !ok {
missed = append(missed, oid)
}
}
if len(missed) == 0 {
return
}
// 最大30个id并且分了100张表用in的优化空间也不大暂时循环单个查
for _, oid := range missed {
cnt, err := d.ShareCount(ctx, oid, tp)
if err != nil {
continue
}
shares[oid] = cnt
}
return
}
// ShareCount get share from cache/db
func (d *Dao) ShareCount(ctx context.Context, oid int64, tp int) (count int64, err error) {
count, err = d.ShareCache(ctx, oid, tp)
if count != -1 && err == nil {
return
}
var share *model.Share
if share, err = d.Share(ctx, oid, tp); err != nil {
err = errors.WithStack(err)
return
}
count = 0
if share != nil {
count = share.Count
}
d.asyncCache.Save(func() {
if err = d.SetShareCache(context.Background(), oid, tp, count); err != nil {
log.Error("%+v", err)
return
}
})
return
}
// Add add share
func (d *Dao) Add(ctx context.Context, p *model.ShareParams) (shared int64, err error) {
var ok bool
if ok, err = d.AddShareMember(ctx, p); err != nil {
return
}
if !ok {
err = ecode.ShareAlreadyAdd
return
}
if err = d.AddShare(ctx, p.OID, p.TP); err != nil {
err = errors.WithStack(err)
return
}
var share *model.Share
if share, err = d.Share(ctx, p.OID, p.TP); err != nil {
err = errors.WithStack(err)
return
}
shared = share.Count
d.asyncCache.Save(func() {
if err = d.SetShareCache(context.Background(), p.OID, p.TP, shared); err != nil {
log.Error("%+v", err)
return
}
})
return
}

View File

@@ -0,0 +1,63 @@
package dao
import (
"context"
"math/rand"
"testing"
"go-common/app/service/main/share/model"
"go-common/library/ecode"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoShares(t *testing.T) {
var (
c = context.TODO()
oids = []int64{1, 2}
tp = int(0)
)
convey.Convey("Shares", t, func(ctx convey.C) {
shares, err := d.Shares(c, oids, tp)
ctx.Convey("Then err should be nil.shares should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(shares, convey.ShouldNotBeNil)
})
})
}
func TestDaoShareCount(t *testing.T) {
var (
c = context.TODO()
oid = int64(rand.Intn(100000000))
tp = int(2)
)
convey.Convey("ShareCount", t, func(ctx convey.C) {
count, err := d.ShareCount(c, oid, tp)
ctx.Convey("Then err should be nil.count should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(count, convey.ShouldNotBeNil)
})
})
}
func TestDaoAdd(t *testing.T) {
convey.Convey("Add", t, func(ctx convey.C) {
oid := rand.Intn(1000000)
mid := rand.Intn(1000000)
p := &model.ShareParams{
OID: int64(oid),
MID: int64(mid),
TP: int(3),
IP: "",
}
shared, err := d.Add(context.Background(), p)
if err == ecode.ShareAlreadyAdd {
err = nil
}
ctx.Convey("Then err should be nil.shared should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(shared, convey.ShouldNotBeNil)
})
})
}

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/main/share/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,51 @@
package model
const (
// BangumiTyp 番剧
BangumiTyp = 1
// ComicTyp 漫画
ComicTyp = 2
// ArchiveTyp 稿件
ArchiveTyp = 3
// PlaylistTyp 播单
PlaylistTyp = 4
// ArchiveMsgTyp .
ArchiveMsgTyp = "archive"
// BangumiMsgTyp .
BangumiMsgTyp = "bangumi_share"
// ComicMsgTyp .
ComicMsgTyp = "comic_share"
// PlaylistMsgTyp .
PlaylistMsgTyp = "playlist"
)
// ShareParams .
type ShareParams struct {
OID int64 `json:"oid" form:"oid" validate:"required,gt=0"`
MID int64 `json:"mid" form:"mid" validate:"required"`
TP int `json:"tp" form:"tp" validate:"required,gt=0"`
IP string `json:"ip"`
}
// Share share item
type Share struct {
OID int64 `json:"oid"`
Tp int `json:"tp"`
Count int64 `json:"count"`
}
// MIDShare .
type MIDShare struct {
OID int64 `json:"oid"`
MID int64 `json:"mid"`
TP int `json:"tp"`
Time int64 `json:"time"`
}
// ArchiveShare .
type ArchiveShare struct {
Type string `json:"type"`
ID int64 `json:"id"`
Count int `json:"count"`
Ts int64 `json:"timestamp"`
}

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/main/share/server/grpc",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/share/api:go_default_library",
"//app/service/main/share/model:go_default_library",
"//app/service/main/share/service: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,45 @@
package grpc
import (
"context"
"go-common/app/service/main/share/api"
"go-common/app/service/main/share/model"
"go-common/app/service/main/share/service"
"go-common/library/net/rpc/warden"
)
// server .
type server struct {
srv *service.Service
}
// New share warden rpc server.
func New(cfg *warden.ServerConfig, srv *service.Service) *warden.Server {
w := warden.NewServer(cfg)
v1.RegisterShareServer(w.Server(), &server{srv: srv})
var err error
w, err = w.Start()
if err != nil {
panic(err)
}
return w
}
// AddShare .
func (s *server) AddShare(ctx context.Context, req *v1.AddShareRequest) (*v1.AddShareReply, error) {
p := &model.ShareParams{
OID: req.Oid,
MID: req.Mid,
TP: int(req.Type),
IP: req.Ip,
}
shares, err := s.srv.Add(ctx, p)
if err != nil {
return nil, err
}
addShareReply := &v1.AddShareReply{
Shares: shares,
}
return addShareReply, nil
}

View File

@@ -0,0 +1,42 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"http.go",
"share.go",
],
importpath = "go-common/app/service/main/share/server/http",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/share/conf:go_default_library",
"//app/service/main/share/model:go_default_library",
"//app/service/main/share/service:go_default_library",
"//library/ecode: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/metadata:go_default_library",
"//library/xstr: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 http
import (
"net/http"
"go-common/app/service/main/share/conf"
"go-common/app/service/main/share/service"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/verify"
)
var (
svr *service.Service
verifySvc *verify.Verify
)
// Init init http router.
func Init(c *conf.Config, s *service.Service) {
svr = s
verifySvc = verify.New(c.Verify)
engine := bm.DefaultServer(c.BM)
route(engine)
if err := engine.Start(); err != nil {
log.Error("engine.Start error(%v)", err)
panic(err)
}
}
func route(e *bm.Engine) {
e.Ping(ping)
e.Register(register)
group := e.Group("/x/internal/share")
{
group.POST("/add", verifySvc.Verify, add)
group.GET("/stat", verifySvc.Verify, stat)
group.GET("/stats", verifySvc.Verify, stats)
}
}
func ping(c *bm.Context) {
if err := svr.Ping(); err != nil {
log.Error("share-service ping error(%v)", err)
c.AbortWithStatus(http.StatusServiceUnavailable)
}
}
func register(c *bm.Context) {
c.JSON(nil, nil)
}

View File

@@ -0,0 +1,60 @@
package http
import (
"strconv"
"go-common/app/service/main/share/model"
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/metadata"
"go-common/library/xstr"
)
func add(ctx *bm.Context) {
p := &model.ShareParams{}
if err := ctx.Bind(p); err != nil {
return
}
p.IP = metadata.String(ctx, metadata.RemoteIP)
ctx.JSON(svr.Add(ctx, p))
}
func stat(ctx *bm.Context) {
var (
oid int64
tp int64
err error
)
params := ctx.Request.Form
oidStr := params.Get("oid")
if oid, err = strconv.ParseInt(oidStr, 10, 64); err != nil || oid <= 0 {
ctx.JSON(nil, ecode.RequestErr)
return
}
tpStr := params.Get("tp")
if tp, err = strconv.ParseInt(tpStr, 10, 64); err != nil || tp <= 0 {
ctx.JSON(nil, ecode.RequestErr)
return
}
ctx.JSON(svr.Stat(ctx, oid, int(tp)))
}
func stats(ctx *bm.Context) {
var (
oids []int64
tp int64
err error
)
params := ctx.Request.Form
oidsStr := params.Get("oids")
if oids, err = xstr.SplitInts(oidsStr); err != nil || len(oids) == 0 || len(oids) > 30 {
ctx.JSON(nil, ecode.RequestErr)
return
}
tpStr := params.Get("tp")
if tp, err = strconv.ParseInt(tpStr, 10, 64); err != nil || tp <= 0 {
ctx.JSON(nil, ecode.RequestErr)
return
}
ctx.JSON(svr.Stats(ctx, oids, int(tp)))
}

View File

@@ -0,0 +1,52 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["service_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/service/main/share/conf:go_default_library",
"//app/service/main/share/model:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"service.go",
"share.go",
],
importpath = "go-common/app/service/main/share/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/share/conf:go_default_library",
"//app/service/main/share/dao:go_default_library",
"//app/service/main/share/model:go_default_library",
"//library/ecode: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,58 @@
package service
import (
"time"
"go-common/app/service/main/share/conf"
"go-common/app/service/main/share/dao"
"go-common/app/service/main/share/model"
)
// Service is service.
type Service struct {
c *conf.Config
dao *dao.Dao
allowType map[int]string
pubMsgType map[int]string
}
// New new a Service and return.
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
dao: dao.New(c),
}
s.allowType = make(map[int]string, len(s.c.AllowType))
s.pubMsgType = map[int]string{
model.BangumiTyp: model.BangumiMsgTyp,
model.ComicTyp: model.ComicMsgTyp,
model.ArchiveTyp: model.ArchiveMsgTyp,
model.PlaylistTyp: model.PlaylistMsgTyp,
}
for _, tp := range s.c.AllowType {
s.allowType[tp] = s.pubMsgType[tp]
}
go s.loadConf()
return
}
func (s *Service) loadConf() {
for {
time.Sleep(10 * time.Second)
allowType := make(map[int]string, len(s.c.AllowType))
for _, tp := range s.c.AllowType {
allowType[tp] = s.pubMsgType[tp]
}
s.allowType = allowType
}
}
// Ping ping
func (s *Service) Ping() (err error) {
return s.dao.Ping()
}
// Close close
func (s *Service) Close() (err error) {
return s.dao.Ping()
}

View File

@@ -0,0 +1,52 @@
package service
import (
"context"
"flag"
"path/filepath"
"testing"
"go-common/app/service/main/share/conf"
"go-common/app/service/main/share/model"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func init() {
dir, _ := filepath.Abs("../cmd/share-service-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
}
func Test_Add(t *testing.T) {
Convey("Add", t, func() {
p := &model.ShareParams{
OID: 1684013,
MID: 100,
TP: 1,
IP: "",
}
share, err := s.Add(context.Background(), p)
Println(share)
Println(err)
})
}
func Test_Stat(t *testing.T) {
Convey("Stat", t, func() {
share, err := s.Stat(context.Background(), 100, 1)
Println(share)
Println(err)
})
}
func Test_Stats(t *testing.T) {
Convey("Stats", t, func() {
s.Stats(context.Background(), []int64{1, 2, 3, 34}, 1)
})
}

View File

@@ -0,0 +1,52 @@
package service
import (
"context"
"go-common/app/service/main/share/model"
"go-common/library/ecode"
"go-common/library/log"
)
// Add add share
func (s *Service) Add(ctx context.Context, p *model.ShareParams) (shared int64, err error) {
typ, ok := s.allowType[p.TP]
if !ok || typ == "" {
log.Error("share type(%d) not support or typ is empty typ(%s)", p.TP, typ)
err = ecode.RequestErr
return
}
if err = s.dao.PubShare(ctx, p); err != nil {
log.Error("s.dao.PubShare oid(%d) mid(%d) error(%v)", p.OID, p.MID, err)
err = nil
}
log.Info("pubshare success: oid(%d) mid(%d) type(%d) ip(%s)", p.OID, p.MID, p.TP, p.IP)
if shared, err = s.dao.Add(ctx, p); err != nil {
log.Error("s.dao.Add mid(%d) oid(%d) tp(%d) ip(%s) error(%v)", p.MID, p.OID, p.TP, p.IP, err)
return
}
if err = s.dao.PubStatShare(ctx, typ, p.OID, shared); err != nil {
log.Error("s.dao.PubArchiveShare oid(%d) error(%v)", p.OID, err)
err = nil
}
log.Info("oid-%d mid-%d type-%d count-%d", p.OID, p.MID, p.TP, shared)
return
}
// Stat return oid shared count
func (s *Service) Stat(ctx context.Context, oid int64, tp int) (shared int64, err error) {
if _, ok := s.allowType[tp]; !ok {
err = ecode.RequestErr
return
}
return s.dao.ShareCount(ctx, oid, tp)
}
// Stats return oids shares
func (s *Service) Stats(ctx context.Context, oids []int64, tp int) (shares map[int64]int64, err error) {
if _, ok := s.allowType[tp]; !ok {
err = ecode.RequestErr
return
}
return s.dao.Shares(ctx, oids, tp)
}