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
majiayi
# Author
# Reviewer

View File

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

View File

@@ -0,0 +1,12 @@
# zeus-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 = "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/live/zeus/api/v1",
proto = ":v1_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 = [":v1_go_proto"],
importpath = "go-common/app/service/live/zeus/api/v1",
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,55 @@
// Code generated by protoc-gen-bm v0.1, DO NOT EDIT.
// source: api.proto
/*
Package v1 is a generated blademaster stub package.
This code was generated with go-common/app/tool/bmgen/protoc-gen-bm v0.1.
package 命名使用 {discovery_id}.{version} 的方式, version 形如 v1, v2, v1beta ..
NOTE: 不知道的 discovery_id 请询问大佬, 新项目找大佬申请 discovery_id先到先得抢注
e.g. account.service.v1
It is generated from these files:
api.proto
*/
package v1
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 PathZeusMatch = "/live.zeus.v1.Zeus/Match"
// ==============
// Zeus Interface
// ==============
type ZeusBMServer interface {
// `method:"POST"`
Match(ctx context.Context, req *MatchRequest) (resp *MatchResponse, err error)
}
var v1ZeusSvc ZeusBMServer
func zeusMatch(c *bm.Context) {
p := new(MatchRequest)
if err := c.BindWith(p, binding.Default(c.Request.Method, c.Request.Header.Get("Content-Type"))); err != nil {
return
}
resp, err := v1ZeusSvc.Match(c, p)
c.JSON(resp, err)
}
// RegisterZeusBMServer Register the blademaster route
func RegisterZeusBMServer(e *bm.Engine, server ZeusBMServer) {
v1ZeusSvc = server
e.POST("/live.zeus.v1.Zeus/Match", zeusMatch)
}

View File

@@ -0,0 +1,861 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: app/service/live/zeus/api/v1/api.proto
package v1
/*
package 命名使用 {discovery_id}.{version} 的方式, version 形如 v1, v2, v1beta ..
NOTE: 不知道的 discovery_id 请询问大佬, 新项目找大佬申请 discovery_id先到先得抢注
e.g. account.service.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 MatchRequest struct {
Group string `protobuf:"bytes,1,opt,name=group,proto3" json:"group"`
Platform string `protobuf:"bytes,2,opt,name=platform,proto3" json:"platform"`
Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version"`
Build uint64 `protobuf:"varint,4,opt,name=build,proto3" json:"build"`
Buvid string `protobuf:"bytes,5,opt,name=buvid,proto3" json:"buvid"`
Uid uint64 `protobuf:"varint,6,opt,name=uid,proto3" json:"uid"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *MatchRequest) Reset() { *m = MatchRequest{} }
func (m *MatchRequest) String() string { return proto.CompactTextString(m) }
func (*MatchRequest) ProtoMessage() {}
func (*MatchRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_api_c648a0d3cea95155, []int{0}
}
func (m *MatchRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *MatchRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_MatchRequest.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalTo(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (dst *MatchRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_MatchRequest.Merge(dst, src)
}
func (m *MatchRequest) XXX_Size() int {
return m.Size()
}
func (m *MatchRequest) XXX_DiscardUnknown() {
xxx_messageInfo_MatchRequest.DiscardUnknown(m)
}
var xxx_messageInfo_MatchRequest proto.InternalMessageInfo
func (m *MatchRequest) GetGroup() string {
if m != nil {
return m.Group
}
return ""
}
func (m *MatchRequest) GetPlatform() string {
if m != nil {
return m.Platform
}
return ""
}
func (m *MatchRequest) GetVersion() string {
if m != nil {
return m.Version
}
return ""
}
func (m *MatchRequest) GetBuild() uint64 {
if m != nil {
return m.Build
}
return 0
}
func (m *MatchRequest) GetBuvid() string {
if m != nil {
return m.Buvid
}
return ""
}
func (m *MatchRequest) GetUid() uint64 {
if m != nil {
return m.Uid
}
return 0
}
type MatchResponse struct {
IsMatch bool `protobuf:"varint,1,opt,name=is_match,json=isMatch,proto3" json:"is_match"`
Extend string `protobuf:"bytes,2,opt,name=extend,proto3" json:"extend"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *MatchResponse) Reset() { *m = MatchResponse{} }
func (m *MatchResponse) String() string { return proto.CompactTextString(m) }
func (*MatchResponse) ProtoMessage() {}
func (*MatchResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_api_c648a0d3cea95155, []int{1}
}
func (m *MatchResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *MatchResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_MatchResponse.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalTo(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (dst *MatchResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_MatchResponse.Merge(dst, src)
}
func (m *MatchResponse) XXX_Size() int {
return m.Size()
}
func (m *MatchResponse) XXX_DiscardUnknown() {
xxx_messageInfo_MatchResponse.DiscardUnknown(m)
}
var xxx_messageInfo_MatchResponse proto.InternalMessageInfo
func (m *MatchResponse) GetIsMatch() bool {
if m != nil {
return m.IsMatch
}
return false
}
func (m *MatchResponse) GetExtend() string {
if m != nil {
return m.Extend
}
return ""
}
func init() {
proto.RegisterType((*MatchRequest)(nil), "live.zeus.v1.MatchRequest")
proto.RegisterType((*MatchResponse)(nil), "live.zeus.v1.MatchResponse")
}
// 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
// ZeusClient is the client API for Zeus service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type ZeusClient interface {
// `method:"POST"`
Match(ctx context.Context, in *MatchRequest, opts ...grpc.CallOption) (*MatchResponse, error)
}
type zeusClient struct {
cc *grpc.ClientConn
}
func NewZeusClient(cc *grpc.ClientConn) ZeusClient {
return &zeusClient{cc}
}
func (c *zeusClient) Match(ctx context.Context, in *MatchRequest, opts ...grpc.CallOption) (*MatchResponse, error) {
out := new(MatchResponse)
err := c.cc.Invoke(ctx, "/live.zeus.v1.Zeus/Match", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// ZeusServer is the server API for Zeus service.
type ZeusServer interface {
// `method:"POST"`
Match(context.Context, *MatchRequest) (*MatchResponse, error)
}
func RegisterZeusServer(s *grpc.Server, srv ZeusServer) {
s.RegisterService(&_Zeus_serviceDesc, srv)
}
func _Zeus_Match_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(MatchRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ZeusServer).Match(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/live.zeus.v1.Zeus/Match",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ZeusServer).Match(ctx, req.(*MatchRequest))
}
return interceptor(ctx, in, info, handler)
}
var _Zeus_serviceDesc = grpc.ServiceDesc{
ServiceName: "live.zeus.v1.Zeus",
HandlerType: (*ZeusServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Match",
Handler: _Zeus_Match_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "app/service/live/zeus/api/v1/api.proto",
}
func (m *MatchRequest) 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 *MatchRequest) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if len(m.Group) > 0 {
dAtA[i] = 0xa
i++
i = encodeVarintApi(dAtA, i, uint64(len(m.Group)))
i += copy(dAtA[i:], m.Group)
}
if len(m.Platform) > 0 {
dAtA[i] = 0x12
i++
i = encodeVarintApi(dAtA, i, uint64(len(m.Platform)))
i += copy(dAtA[i:], m.Platform)
}
if len(m.Version) > 0 {
dAtA[i] = 0x1a
i++
i = encodeVarintApi(dAtA, i, uint64(len(m.Version)))
i += copy(dAtA[i:], m.Version)
}
if m.Build != 0 {
dAtA[i] = 0x20
i++
i = encodeVarintApi(dAtA, i, uint64(m.Build))
}
if len(m.Buvid) > 0 {
dAtA[i] = 0x2a
i++
i = encodeVarintApi(dAtA, i, uint64(len(m.Buvid)))
i += copy(dAtA[i:], m.Buvid)
}
if m.Uid != 0 {
dAtA[i] = 0x30
i++
i = encodeVarintApi(dAtA, i, uint64(m.Uid))
}
if m.XXX_unrecognized != nil {
i += copy(dAtA[i:], m.XXX_unrecognized)
}
return i, nil
}
func (m *MatchResponse) 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 *MatchResponse) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if m.IsMatch {
dAtA[i] = 0x8
i++
if m.IsMatch {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i++
}
if len(m.Extend) > 0 {
dAtA[i] = 0x12
i++
i = encodeVarintApi(dAtA, i, uint64(len(m.Extend)))
i += copy(dAtA[i:], m.Extend)
}
if m.XXX_unrecognized != nil {
i += copy(dAtA[i:], m.XXX_unrecognized)
}
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 *MatchRequest) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.Group)
if l > 0 {
n += 1 + l + sovApi(uint64(l))
}
l = len(m.Platform)
if l > 0 {
n += 1 + l + sovApi(uint64(l))
}
l = len(m.Version)
if l > 0 {
n += 1 + l + sovApi(uint64(l))
}
if m.Build != 0 {
n += 1 + sovApi(uint64(m.Build))
}
l = len(m.Buvid)
if l > 0 {
n += 1 + l + sovApi(uint64(l))
}
if m.Uid != 0 {
n += 1 + sovApi(uint64(m.Uid))
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
return n
}
func (m *MatchResponse) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if m.IsMatch {
n += 2
}
l = len(m.Extend)
if l > 0 {
n += 1 + l + sovApi(uint64(l))
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
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 *MatchRequest) 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: MatchRequest: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: MatchRequest: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Group", 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.Group = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Platform", 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.Platform = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Version", 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.Version = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 4:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Build", wireType)
}
m.Build = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowApi
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Build |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 5:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Buvid", 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.Buvid = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 6:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Uid", wireType)
}
m.Uid = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowApi
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Uid |= (uint64(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
}
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *MatchResponse) 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: MatchResponse: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: MatchResponse: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field IsMatch", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowApi
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
m.IsMatch = bool(v != 0)
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Extend", 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.Extend = 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
}
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
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/live/zeus/api/v1/api.proto", fileDescriptor_api_c648a0d3cea95155)
}
var fileDescriptor_api_c648a0d3cea95155 = []byte{
// 338 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x91, 0xbf, 0x4e, 0xc3, 0x30,
0x10, 0xc6, 0xe5, 0xfe, 0xaf, 0x29, 0x12, 0xf2, 0x14, 0x8a, 0xd4, 0x54, 0x95, 0x80, 0x2e, 0xc4,
0x2a, 0xbc, 0x00, 0xea, 0xc4, 0xc2, 0xe2, 0xb1, 0x42, 0x42, 0x49, 0xe3, 0xa6, 0x96, 0xda, 0xda,
0xc4, 0xb1, 0x85, 0x78, 0x42, 0x46, 0x5e, 0x80, 0x08, 0x75, 0xcc, 0x53, 0x20, 0x9f, 0xd3, 0xd2,
0x81, 0x25, 0xdf, 0xdd, 0xef, 0xee, 0x93, 0xef, 0x72, 0xf8, 0x26, 0x56, 0x8a, 0x6a, 0x9e, 0x5b,
0xb1, 0xe4, 0x74, 0x23, 0x2c, 0xa7, 0x1f, 0xdc, 0x68, 0x1a, 0x2b, 0x41, 0xed, 0xcc, 0x49, 0xa4,
0x72, 0x59, 0x48, 0x32, 0x70, 0xb5, 0xc8, 0xd5, 0x22, 0x3b, 0x1b, 0xde, 0x65, 0xa2, 0x58, 0x9b,
0x24, 0x5a, 0xca, 0x2d, 0xcd, 0x64, 0x26, 0x29, 0x34, 0x25, 0x66, 0x05, 0x19, 0x24, 0x10, 0x79,
0xf3, 0xe4, 0x1b, 0xe1, 0xc1, 0x73, 0x5c, 0x2c, 0xd7, 0x8c, 0xbf, 0x19, 0xae, 0x0b, 0x12, 0xe2,
0x76, 0x96, 0x4b, 0xa3, 0x02, 0x34, 0x46, 0xd3, 0xfe, 0xbc, 0x5f, 0x95, 0xa1, 0x07, 0xcc, 0x0b,
0x99, 0xe2, 0x9e, 0xda, 0xc4, 0xc5, 0x4a, 0xe6, 0xdb, 0xa0, 0x01, 0x3d, 0x83, 0xaa, 0x0c, 0x8f,
0x8c, 0x1d, 0x23, 0x72, 0x8d, 0xbb, 0x96, 0xe7, 0x5a, 0xc8, 0x5d, 0xd0, 0x84, 0xc6, 0xb3, 0xaa,
0x0c, 0x0f, 0x88, 0x1d, 0x02, 0xf7, 0x62, 0x62, 0xc4, 0x26, 0x0d, 0x5a, 0x63, 0x34, 0x6d, 0xf9,
0x17, 0x01, 0x30, 0x2f, 0xbe, 0xc1, 0x8a, 0x34, 0x68, 0xff, 0x8d, 0x04, 0x80, 0x79, 0x21, 0x97,
0xb8, 0x69, 0x44, 0x1a, 0x74, 0xc0, 0xdf, 0xad, 0xca, 0xd0, 0xa5, 0xcc, 0x7d, 0x26, 0x2f, 0xf8,
0xbc, 0x5e, 0x4f, 0x2b, 0xb9, 0xd3, 0x9c, 0xdc, 0xe2, 0x9e, 0xd0, 0xaf, 0x5b, 0xc7, 0x60, 0xc5,
0x9e, 0x1f, 0xff, 0xc0, 0x58, 0x57, 0x68, 0x30, 0x90, 0x09, 0xee, 0xf0, 0xf7, 0x82, 0xef, 0xd2,
0x7a, 0x4b, 0x5c, 0x95, 0x61, 0x4d, 0x58, 0xad, 0xf7, 0x4f, 0xb8, 0xb5, 0xe0, 0x46, 0x93, 0x47,
0xdc, 0xf6, 0xa6, 0x61, 0x74, 0x7a, 0x8c, 0xe8, 0xf4, 0xcf, 0x0e, 0xaf, 0xfe, 0xad, 0xf9, 0xb1,
0xe6, 0x17, 0x9f, 0xfb, 0x11, 0xfa, 0xda, 0x8f, 0xd0, 0xcf, 0x7e, 0x84, 0x16, 0x0d, 0x3b, 0x4b,
0x3a, 0x70, 0xa0, 0x87, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x8c, 0x92, 0x06, 0x64, 0x07, 0x02,
0x00, 0x00,
}

View File

@@ -0,0 +1,37 @@
// 定义项目 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 live.zeus.v1;
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
// NOTE: 最后请删除这些无用的注释 (゜-゜)つロ
option go_package = "v1";
service Zeus {
// `method:"POST"`
rpc Match(MatchRequest) returns (MatchResponse);
}
message MatchRequest {
string group = 1 [(gogoproto.jsontag) = "group"];
string platform = 2 [(gogoproto.jsontag) = "platform"];
string version = 3 [(gogoproto.jsontag) = "version"];
uint64 build = 4 [(gogoproto.jsontag) = "build"];
string buvid = 5 [(gogoproto.jsontag) = "buvid"];
uint64 uid = 6 [(gogoproto.jsontag) = "uid"];
}
message MatchResponse {
bool is_match = 1 [(gogoproto.jsontag) = "is_match"];
string extend = 2 [(gogoproto.jsontag) = "extend"];
}

View File

@@ -0,0 +1,32 @@
<!-- package=live.zeus.v1 -->
- [/live.zeus.v1.Zeus/Match](#live.zeus.v1.ZeusMatch)
## /live.zeus.v1.Zeus/Match
### 无标题
#### 方法POST
#### 请求参数
|参数名|必选|类型|描述|
|:---|:---|:---|:---|
|group|否|string||
|platform|否|string||
|version|否|string||
|build|否|integer||
|buvid|否|string||
|uid|否|integer||
#### 响应
```javascript
{
"code": 0,
"message": "ok",
"data": {
"is_match": true,
"extend": ""
}
}
```

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,46 @@
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 = ["zeus.toml"],
importpath = "go-common/app/service/live/zeus/cmd",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/live/zeus/internal/conf:go_default_library",
"//app/service/live/zeus/internal/server/grpc:go_default_library",
"//app/service/live/zeus/internal/server/http:go_default_library",
"//app/service/live/zeus/internal/service:go_default_library",
"//app/service/live/zeus/internal/service/v1: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,53 @@
package main
import (
"context"
"flag"
"os"
"os/signal"
"syscall"
"time"
"go-common/app/service/live/zeus/internal/conf"
"go-common/app/service/live/zeus/internal/server/grpc"
"go-common/app/service/live/zeus/internal/server/http"
"go-common/app/service/live/zeus/internal/service"
ecode "go-common/library/ecode/tip"
"go-common/library/log"
"go-common/library/net/trace"
v1srv "go-common/app/service/live/zeus/internal/service/v1"
)
func main() {
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
log.Init(conf.Conf.Log)
defer log.Close()
log.Info("zeus-service start")
trace.Init(conf.Conf.Tracer)
defer trace.Close()
ecode.Init(conf.Conf.Ecode)
svc := service.New(conf.Conf)
zeus := v1srv.NewZeusService(conf.Conf)
grpcServer := grpc.New(conf.Conf, zeus)
defer grpcServer.Shutdown(context.Background())
http.Init(conf.Conf, svc, zeus)
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("zeus-service exit")
time.Sleep(time.Second)
return
case syscall.SIGHUP:
default:
return
}
}
}

View File

@@ -0,0 +1,25 @@
[log]
#dir = "/data/log/broadcast-proxy"
vlevel = 100
stdout = true
[redis]
name = "zeus-service"
proto = "tcp"
addr = ""
idle = 10
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "1m"
[sven]
treeID="80142"
zone="sh001"
env="dev"
build="docker-1"
token="e4c1cb219c08daca79a0e6cf55dc0d8c"
[index]
matcher="matcher.json"

View File

@@ -0,0 +1,41 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["expr_test.go"],
embed = [":go_default_library"],
tags = ["automanaged"],
)
go_library(
name = "go_default_library",
srcs = [
"ast.go",
"check.go",
"eval.go",
"expr.go",
],
importpath = "go-common/app/service/live/zeus/expr",
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,306 @@
package expr
import (
"bytes"
"fmt"
"strconv"
"strings"
"text/scanner"
"unicode"
)
const (
TokenEOF = -(iota + 1)
TokenIdent
TokenInt
TokenFloat
TokenString
TokenOperator
)
type lexer struct {
scan scanner.Scanner
token rune
text string
}
func (lex *lexer) getToken() rune {
return lex.token
}
func (lex *lexer) getText() string {
return lex.text
}
func (lex *lexer) next() {
token := lex.scan.Scan()
text := lex.scan.TokenText()
switch token {
case scanner.EOF:
lex.token = TokenEOF
lex.text = text
case scanner.Ident:
lex.token = TokenIdent
lex.text = text
case scanner.Int:
lex.token = TokenInt
lex.text = text
case scanner.Float:
lex.token = TokenFloat
lex.text = text
case scanner.RawString:
fallthrough
case scanner.String:
lex.token = TokenString
if len(text) >= 2 && ((text[0] == '`' && text[len(text)-1] == '`') || (text[0] == '"' && text[len(text)-1] == '"')) {
lex.text = text[1 : len(text)-1]
} else {
msg := fmt.Sprintf("got illegal string:%s", text)
panic(lexPanic(msg))
}
case '+', '-', '*', '/', '%', '~':
lex.token = TokenOperator
lex.text = text
case '&', '|', '=':
var buffer bytes.Buffer
lex.token = TokenOperator
buffer.WriteRune(token)
next := lex.scan.Peek()
if next == token {
buffer.WriteRune(next)
lex.scan.Scan()
}
lex.text = buffer.String()
case '>', '<', '!':
var buffer bytes.Buffer
lex.token = TokenOperator
buffer.WriteRune(token)
next := lex.scan.Peek()
if next == '=' {
buffer.WriteRune(next)
lex.scan.Scan()
}
lex.text = buffer.String()
default:
if token >= 0 {
lex.token = token
lex.text = text
} else {
msg := fmt.Sprintf("got unknown token:%d, text:%s", lex.token, lex.text)
panic(lexPanic(msg))
}
}
}
type lexPanic string
// describe returns a string describing the current token, for use in errors.
func (lex *lexer) describe() string {
switch lex.token {
case TokenEOF:
return "end of file"
case TokenIdent:
return fmt.Sprintf("identifier:%s", lex.getText())
case TokenInt, TokenFloat:
return fmt.Sprintf("number:%s", lex.getText())
case TokenString:
return fmt.Sprintf("string:%s", lex.getText())
}
return fmt.Sprintf("token:%d", rune(lex.getToken())) // any other rune
}
func precedence(token rune, text string) int {
if token == TokenOperator {
switch text {
case "~", "!":
return 9
case "*", "/", "%":
return 8
case "+", "-":
return 7
case ">", ">=", "<", "<=":
return 6
case "!=", "==", "=":
return 5
case "&":
return 4
case "|":
return 3
case "&&":
return 2
case "||":
return 1
default:
msg := fmt.Sprintf("unknown operator:%s", text)
panic(lexPanic(msg))
}
}
return 0
}
// ---- parser ----
type ExpressionParser struct {
expression Expr
variable map[string]struct{}
}
func NewExpressionParser() *ExpressionParser {
return &ExpressionParser{
expression: nil,
variable: make(map[string]struct{}),
}
}
// Parse parses the input string as an arithmetic expression.
//
// expr = num a literal number, e.g., 3.14159
// | id a variable name, e.g., x
// | id '(' expr ',' ... ')' a function call
// | '-' expr a unary operator ( + - ! )
// | expr '+' expr a binary operator ( + - * / && & || | == )
//
func (parser *ExpressionParser) Parse(input string) (err error) {
defer func() {
switch x := recover().(type) {
case nil:
// no panic
case lexPanic:
err = fmt.Errorf("%s", x)
default:
// unexpected panic: resume state of panic.
panic(x)
}
}()
lex := new(lexer)
lex.scan.Init(strings.NewReader(input))
lex.scan.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanFloats | scanner.ScanStrings | scanner.ScanRawStrings
lex.scan.IsIdentRune = parser.isIdentRune
lex.next() // initial lookahead
parser.expression = nil
parser.variable = make(map[string]struct{})
e := parser.parseExpr(lex)
if lex.token != scanner.EOF {
return fmt.Errorf("unexpected %s", lex.describe())
}
parser.expression = e
return nil
}
func (parser *ExpressionParser) GetExpr() Expr {
return parser.expression
}
func (parser *ExpressionParser) GetVariable() []string {
variable := make([]string, 0, len(parser.variable))
for v := range parser.variable {
if v != "true" && v != "false" {
variable = append(variable, v)
}
}
return variable
}
func (parser *ExpressionParser) isIdentRune(ch rune, i int) bool {
return ch == '$' || ch == '_' || ch == '?' || unicode.IsLetter(ch) || unicode.IsDigit(ch) && i > 0
}
func (parser *ExpressionParser) parseExpr(lex *lexer) Expr {
return parser.parseBinary(lex, 1)
}
// binary = unary ('+' binary)*
// parseBinary stops when it encounters an
// operator of lower precedence than prec1.
func (parser *ExpressionParser) parseBinary(lex *lexer, prec1 int) Expr {
lhs := parser.parseUnary(lex)
for prec := precedence(lex.getToken(), lex.getText()); prec >= prec1; prec-- {
for precedence(lex.getToken(), lex.getText()) == prec {
op := lex.getText()
lex.next() // consume operator
rhs := parser.parseBinary(lex, prec+1)
lhs = binary{op, lhs, rhs}
}
}
return lhs
}
// unary = '+' expr | primary
func (parser *ExpressionParser) parseUnary(lex *lexer) Expr {
if lex.getToken() == TokenOperator {
op := lex.getText()
if op == "+" || op == "-" || op == "~" || op == "!" {
lex.next()
return unary{op, parser.parseUnary(lex)}
} else {
msg := fmt.Sprintf("unary got unknown operator:%s", lex.getText())
panic(lexPanic(msg))
}
}
return parser.parsePrimary(lex)
}
// primary = id
// | id '(' expr ',' ... ',' expr ')'
// | num
// | '(' expr ')'
func (parser *ExpressionParser) parsePrimary(lex *lexer) Expr {
switch lex.token {
case TokenIdent:
id := lex.getText()
lex.next()
if lex.token != '(' {
parser.variable[id] = struct{}{}
return Var(id)
}
lex.next() // consume '('
var args []Expr
if lex.token != ')' {
for {
args = append(args, parser.parseExpr(lex))
if lex.token != ',' {
break
}
lex.next() // consume ','
}
if lex.token != ')' {
msg := fmt.Sprintf("got %q, want ')'", lex.token)
panic(lexPanic(msg))
}
}
lex.next() // consume ')'
return call{id, args}
case TokenFloat:
f, err := strconv.ParseFloat(lex.getText(), 64)
if err != nil {
panic(lexPanic(err.Error()))
}
lex.next()
return literal{value: f}
case TokenInt:
i, err := strconv.ParseInt(lex.getText(), 10, 64)
if err != nil {
panic(lexPanic(err.Error()))
}
lex.next()
return literal{value: i}
case TokenString:
s := lex.getText()
lex.next()
return literal{value: s}
case '(':
lex.next() // consume '('
e := parser.parseExpr(lex)
if lex.token != ')' {
msg := fmt.Sprintf("got %s, want ')'", lex.describe())
panic(lexPanic(msg))
}
lex.next() // consume ')'
return e
}
msg := fmt.Sprintf("unexpected %s", lex.describe())
panic(lexPanic(msg))
}

View File

@@ -0,0 +1,49 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
package expr
import (
"fmt"
)
//!+Check
func (v Var) Check(vars map[Var]interface{}) error {
vars[v] = true
return nil
}
func (literal) Check(vars map[Var]interface{}) error {
return nil
}
func (u unary) Check(vars map[Var]interface{}) error {
return u.x.Check(vars)
}
func (b binary) Check(vars map[Var]interface{}) error {
if err := b.x.Check(vars); err != nil {
return err
}
return b.y.Check(vars)
}
func (c call) Check(vars map[Var]interface{}) error {
arity, ok := exprFuncParams[c.fn]
if !ok {
return fmt.Errorf("unknown function %q", c.fn)
}
if len(c.args) != arity {
return fmt.Errorf("call to %s has %d args, want %d",
c.fn, len(c.args), arity)
}
for _, arg := range c.args {
if err := arg.Check(vars); err != nil {
return err
}
}
return nil
}
//!-Check

View File

@@ -0,0 +1,602 @@
package expr
import (
"fmt"
"hash/crc32"
"math"
"math/rand"
"reflect"
"strings"
)
const kEpsilon = 1e-7
type Env map[Var]interface{}
type runtimePanic string
func EvalBool(expr Expr, env Env) (value bool, err error) {
defer func() {
switch x := recover().(type) {
case nil:
// no panic
case runtimePanic:
value = false
err = fmt.Errorf("%s", x)
default:
// unexpected panic: resume state of panic.
panic(x)
}
}()
if expr == nil {
return false, nil
}
value = ConvertToBool(expr.Eval(env))
return
}
func EvalInt(expr Expr, env Env) (value int64, err error) {
defer func() {
switch x := recover().(type) {
case nil:
// no panic
case runtimePanic:
value = 0
err = fmt.Errorf("%s", x)
default:
// unexpected panic: resume state of panic.
panic(x)
}
}()
if expr == nil {
return 0, nil
}
value = ConvertToInt(expr.Eval(env))
return
}
func (v Var) Eval(env Env) reflect.Value {
switch v {
case "true":
return reflect.ValueOf(true)
case "false":
return reflect.ValueOf(false)
default:
if i, ok := env[v]; ok {
return reflect.ValueOf(i)
}
panic(runtimePanic(fmt.Sprintf("undefined variable: %s", v)))
}
}
func (l literal) Eval(_ Env) reflect.Value {
return reflect.ValueOf(l.value)
}
func (u unary) Eval(env Env) reflect.Value {
switch u.op {
case "+":
return unaryPlus(u.x.Eval(env))
case "-":
return unaryMinus(u.x.Eval(env))
case "!":
return logicalNegation(u.x.Eval(env))
case "~":
return bitwiseComplement(u.x.Eval(env))
}
panic(runtimePanic(fmt.Sprintf("unsupported unary operator: %q", u.op)))
}
func (b binary) Eval(env Env) reflect.Value {
switch b.op {
case "+":
return addition(b.x.Eval(env), b.y.Eval(env))
case "-":
return subtraction(b.x.Eval(env), b.y.Eval(env))
case "*":
return multiplication(b.x.Eval(env), b.y.Eval(env))
case "/":
return division(b.x.Eval(env), b.y.Eval(env))
case "%":
return modulus(b.x.Eval(env), b.y.Eval(env))
case "&":
return bitwiseAnd(b.x.Eval(env), b.y.Eval(env))
case "&&":
return logicalAnd(b.x.Eval(env), b.y.Eval(env))
case "|":
return bitwiseOr(b.x.Eval(env), b.y.Eval(env))
case "||":
return logicalOr(b.x.Eval(env), b.y.Eval(env))
case "=", "==":
return comparisonEqual(b.x.Eval(env), b.y.Eval(env))
case ">":
return comparisonGreater(b.x.Eval(env), b.y.Eval(env))
case ">=":
return comparisonGreaterOrEqual(b.x.Eval(env), b.y.Eval(env))
case "<":
return comparisonLess(b.x.Eval(env), b.y.Eval(env))
case "<=":
return comparisonLessOrEqual(b.x.Eval(env), b.y.Eval(env))
case "!=":
return comparisonNotEqual(b.x.Eval(env), b.y.Eval(env))
}
panic(runtimePanic(fmt.Sprintf("unsupported binary operator: %q", b.op)))
}
func (c call) Eval(env Env) reflect.Value {
switch c.fn {
case "pow":
return reflect.ValueOf(math.Pow(ConvertToFloat(c.args[0].Eval(env)), ConvertToFloat(c.args[1].Eval(env))))
case "sin":
return reflect.ValueOf(math.Sin(ConvertToFloat(c.args[0].Eval(env))))
case "sqrt":
v := ConvertToFloat(c.args[0].Eval(env))
if v < 0 {
panic(runtimePanic(fmt.Sprintf("function call: %s only accept normal number", c.fn)))
}
return reflect.ValueOf(math.Sqrt(v))
case "rand":
return reflect.ValueOf(rand.Float64())
case "log":
v := ConvertToFloat(c.args[0].Eval(env))
if v < 0 {
panic(runtimePanic(fmt.Sprintf("function call: %s only accept normal number", c.fn)))
}
return reflect.ValueOf(math.Log10(v))
case "to_upper":
v := c.args[0].Eval(env)
if v.Kind() != reflect.String {
panic(runtimePanic(fmt.Sprintf("function call: %s only accept string", c.fn)))
}
return reflect.ValueOf(strings.ToUpper(v.String()))
case "to_lower":
v := c.args[0].Eval(env)
if v.Kind() != reflect.String {
panic(runtimePanic(fmt.Sprintf("function call: %s only accept string", c.fn)))
}
return reflect.ValueOf(strings.ToLower(v.String()))
case "crc32":
v := c.args[0].Eval(env)
if v.Kind() != reflect.String {
panic(runtimePanic(fmt.Sprintf("function call: %s only accept string", c.fn)))
}
return reflect.ValueOf(crc32.ChecksumIEEE([]byte(v.String())))
}
panic(runtimePanic(fmt.Sprintf("unsupported function call: %s", c.fn)))
}
func ConvertToBool(v reflect.Value) bool {
switch v.Kind() {
case reflect.Bool:
return v.Bool()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return v.Int() != 0
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return v.Uint() != 0
case reflect.Float32, reflect.Float64:
return v.Float() != 0
case reflect.String:
return v.String() != ""
default:
panic(runtimePanic(fmt.Sprintf("cannot convert data type: %s to bool", v.Kind().String())))
}
}
func ConvertToInt(v reflect.Value) int64 {
switch v.Kind() {
case reflect.Bool:
if v.Bool() {
return 1
} else {
return 0
}
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return v.Int()
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return int64(v.Uint())
case reflect.Float32, reflect.Float64:
return int64(v.Float())
default:
panic(runtimePanic(fmt.Sprintf("cannot convert data type: %s to int", v.Kind().String())))
}
}
func ConvertToUint(v reflect.Value) uint64 {
switch v.Kind() {
case reflect.Bool:
if v.Bool() {
return 1
} else {
return 0
}
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return uint64(v.Int())
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return v.Uint()
case reflect.Float32, reflect.Float64:
return uint64(v.Float())
default:
panic(runtimePanic(fmt.Sprintf("cannot convert data type: %s to uint", v.Kind().String())))
}
}
func ConvertToFloat(v reflect.Value) float64 {
switch v.Kind() {
case reflect.Bool:
if v.Bool() {
return 1
} else {
return 0
}
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return float64(v.Int())
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return float64(v.Uint())
case reflect.Float32, reflect.Float64:
return v.Float()
default:
panic(runtimePanic(fmt.Sprintf("cannot convert data type: %s to float", v.Kind().String())))
}
}
func unaryPlus(v reflect.Value) reflect.Value {
return v
}
func unaryMinus(v reflect.Value) reflect.Value {
switch v.Kind() {
case reflect.Bool:
return v
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return reflect.ValueOf(-v.Int())
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return reflect.ValueOf(-v.Uint())
case reflect.Float32, reflect.Float64:
return reflect.ValueOf(-v.Float())
default:
panic(runtimePanic(fmt.Sprintf("%v(%s) not support unary minus", v.Interface(), v.Kind().String())))
}
}
func logicalNegation(v reflect.Value) reflect.Value {
return reflect.ValueOf(!ConvertToBool(v))
}
func bitwiseComplement(v reflect.Value) reflect.Value {
switch v.Kind() {
case reflect.Bool:
return reflect.ValueOf(!v.Bool())
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return reflect.ValueOf(^v.Int())
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return reflect.ValueOf(^v.Uint())
case reflect.Float32, reflect.Float64:
panic(runtimePanic("cannot eval ~ for float"))
default:
panic(runtimePanic(fmt.Sprintf("%v(%s) not support bitwise complement", v.Interface(), v.Kind().String())))
}
}
func typeLevel(k reflect.Kind) int {
switch k {
case reflect.String:
return 5
case reflect.Float32, reflect.Float64:
return 4
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return 3
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return 2
case reflect.Bool:
return 1
default:
return 0
}
}
func typeAscend(a reflect.Kind, b reflect.Kind) reflect.Kind {
if typeLevel(a) >= typeLevel(b) {
return a
} else {
return b
}
}
func addition(left reflect.Value, right reflect.Value) reflect.Value {
k := typeAscend(left.Kind(), right.Kind())
switch k {
case reflect.Float32, reflect.Float64:
r := ConvertToFloat(left) + ConvertToFloat(right)
return reflect.ValueOf(r)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
r := ConvertToUint(left) + ConvertToUint(right)
return reflect.ValueOf(r)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
r := ConvertToInt(left) + ConvertToInt(right)
return reflect.ValueOf(r)
case reflect.Bool:
r := ConvertToInt(left) + ConvertToInt(right)
return reflect.ValueOf(r != 0)
default:
panic(runtimePanic(fmt.Sprintf("%v(%s) and %v(%s) not support addition",
left.Interface(), left.Kind().String(), right.Interface(), right.Kind().String())))
}
}
func subtraction(left reflect.Value, right reflect.Value) reflect.Value {
k := typeAscend(left.Kind(), right.Kind())
switch k {
case reflect.Float32, reflect.Float64:
r := ConvertToFloat(left) - ConvertToFloat(right)
return reflect.ValueOf(r)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
r := ConvertToUint(left) - ConvertToUint(right)
return reflect.ValueOf(r)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
r := ConvertToInt(left) - ConvertToInt(right)
return reflect.ValueOf(r)
case reflect.Bool:
r := ConvertToInt(left) - ConvertToInt(right)
return reflect.ValueOf(r != 0)
default:
panic(runtimePanic(fmt.Sprintf("%v(%s) and %v(%s) not support subtraction",
left.Interface(), left.Kind().String(), right.Interface(), right.Kind().String())))
}
}
func multiplication(left reflect.Value, right reflect.Value) reflect.Value {
k := typeAscend(left.Kind(), right.Kind())
switch k {
case reflect.Float32, reflect.Float64:
r := ConvertToFloat(left) * ConvertToFloat(right)
return reflect.ValueOf(r)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
r := ConvertToUint(left) * ConvertToUint(right)
return reflect.ValueOf(r)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
r := ConvertToInt(left) * ConvertToInt(right)
return reflect.ValueOf(r)
case reflect.Bool:
r := ConvertToInt(left) * ConvertToInt(right)
return reflect.ValueOf(r != 0)
default:
panic(runtimePanic(fmt.Sprintf("%v(%s) and %v(%s) not support multiplication",
left.Interface(), left.Kind().String(), right.Interface(), right.Kind().String())))
}
}
func division(left reflect.Value, right reflect.Value) reflect.Value {
k := typeAscend(left.Kind(), right.Kind())
switch k {
case reflect.Float32, reflect.Float64:
lv := ConvertToFloat(left)
rv := ConvertToFloat(right)
if math.Abs(rv) < kEpsilon {
panic(runtimePanic(fmt.Sprintf("%f div %f, divide by zero", lv, rv)))
}
return reflect.ValueOf(lv / rv)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
lv := ConvertToUint(left)
rv := ConvertToUint(right)
if rv == 0 {
panic(runtimePanic(fmt.Sprintf("%d div %d, divide by zero", lv, rv)))
}
return reflect.ValueOf(lv / rv)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
lv := ConvertToInt(left)
rv := ConvertToInt(right)
if rv == 0 {
panic(runtimePanic(fmt.Sprintf("%d div %d, divide by zero", lv, rv)))
}
return reflect.ValueOf(lv / rv)
case reflect.Bool:
lv := ConvertToInt(left)
rv := ConvertToInt(right)
if rv == 0 {
panic(runtimePanic(fmt.Sprintf("%d div %d, divide by zero", lv, rv)))
}
return reflect.ValueOf(lv/rv != 0)
default:
panic(runtimePanic(fmt.Sprintf("%v(%s) and %v(%s) not support division",
left.Interface(), left.Kind().String(), right.Interface(), right.Kind().String())))
}
}
func modulus(left reflect.Value, right reflect.Value) reflect.Value {
k := typeAscend(left.Kind(), right.Kind())
switch k {
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
r := ConvertToUint(left) % ConvertToUint(right)
return reflect.ValueOf(r)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
r := ConvertToInt(left) % ConvertToInt(right)
return reflect.ValueOf(r)
case reflect.Bool:
r := ConvertToInt(left) % ConvertToInt(right)
return reflect.ValueOf(r != 0)
default:
panic(runtimePanic(fmt.Sprintf("%v(%s) and %v(%s) not support division",
left.Interface(), left.Kind().String(), right.Interface(), right.Kind().String())))
}
}
func bitwiseAnd(left reflect.Value, right reflect.Value) reflect.Value {
k := typeAscend(left.Kind(), right.Kind())
switch k {
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
r := ConvertToUint(left) & ConvertToUint(right)
return reflect.ValueOf(r)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
r := ConvertToInt(left) & ConvertToInt(right)
return reflect.ValueOf(r)
case reflect.Bool:
r := ConvertToBool(left) && ConvertToBool(right)
return reflect.ValueOf(r)
default:
panic(runtimePanic(fmt.Sprintf("%v(%s) and %v(%s) not support bitwise and",
left.Interface(), left.Kind().String(), right.Interface(), right.Kind().String())))
}
}
func bitwiseOr(left reflect.Value, right reflect.Value) reflect.Value {
k := typeAscend(left.Kind(), right.Kind())
switch k {
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
r := ConvertToUint(left) | ConvertToUint(right)
return reflect.ValueOf(r)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
r := ConvertToInt(left) | ConvertToInt(right)
return reflect.ValueOf(r)
case reflect.Bool:
r := ConvertToBool(left) || ConvertToBool(right)
return reflect.ValueOf(r)
default:
panic(runtimePanic(fmt.Sprintf("%v(%s) and %v(%s) not support bitwise or",
left.Interface(), left.Kind().String(), right.Interface(), right.Kind().String())))
}
}
func logicalAnd(left reflect.Value, right reflect.Value) reflect.Value {
r := ConvertToBool(left) && ConvertToBool(right)
return reflect.ValueOf(r)
}
func logicalOr(left reflect.Value, right reflect.Value) reflect.Value {
r := ConvertToBool(left) || ConvertToBool(right)
return reflect.ValueOf(r)
}
func comparisonEqual(left reflect.Value, right reflect.Value) reflect.Value {
k := typeAscend(left.Kind(), right.Kind())
switch k {
case reflect.String:
if left.Kind() != reflect.String || right.Kind() != reflect.String {
panic(runtimePanic(fmt.Sprintf("%v(%s) and %v(%s) not support comparison equal",
left.Interface(), left.Kind().String(), right.Interface(), right.Kind().String())))
}
r := strings.Compare(left.String(), right.String()) == 0
return reflect.ValueOf(r)
case reflect.Float32, reflect.Float64:
r := ConvertToFloat(left) == ConvertToFloat(right)
return reflect.ValueOf(r)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
r := ConvertToUint(left) == ConvertToUint(right)
return reflect.ValueOf(r)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
r := ConvertToInt(left) == ConvertToInt(right)
return reflect.ValueOf(r)
case reflect.Bool:
r := ConvertToInt(left) == ConvertToInt(right)
return reflect.ValueOf(r)
default:
panic(runtimePanic(fmt.Sprintf("%v(%s) and %v(%s) not support comparison equal",
left.Interface(), left.Kind().String(), right.Interface(), right.Kind().String())))
}
}
func comparisonNotEqual(left reflect.Value, right reflect.Value) reflect.Value {
k := typeAscend(left.Kind(), right.Kind())
switch k {
case reflect.String:
if left.Kind() != reflect.String || right.Kind() != reflect.String {
panic(runtimePanic(fmt.Sprintf("%v(%s) and %v(%s) not support comparison equal",
left.Interface(), left.Kind().String(), right.Interface(), right.Kind().String())))
}
r := strings.Compare(left.String(), right.String()) != 0
return reflect.ValueOf(r)
case reflect.Float32, reflect.Float64:
r := ConvertToFloat(left) != ConvertToFloat(right)
return reflect.ValueOf(r)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
r := ConvertToUint(left) != ConvertToUint(right)
return reflect.ValueOf(r)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
r := ConvertToInt(left) != ConvertToInt(right)
return reflect.ValueOf(r)
case reflect.Bool:
r := ConvertToInt(left) != ConvertToInt(right)
return reflect.ValueOf(r)
default:
panic(runtimePanic(fmt.Sprintf("type %s and %s not support comparison not equal", left.Kind().String(), right.Kind().String())))
}
}
func comparisonGreater(left reflect.Value, right reflect.Value) reflect.Value {
k := typeAscend(left.Kind(), right.Kind())
switch k {
case reflect.Float32, reflect.Float64:
r := ConvertToFloat(left) > ConvertToFloat(right)
return reflect.ValueOf(r)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
r := ConvertToUint(left) > ConvertToUint(right)
return reflect.ValueOf(r)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
r := ConvertToInt(left) > ConvertToInt(right)
return reflect.ValueOf(r)
case reflect.Bool:
r := ConvertToInt(left) > ConvertToInt(right)
return reflect.ValueOf(r)
default:
panic(runtimePanic(fmt.Sprintf("type %s and %s not support comparison greater", left.Kind().String(), right.Kind().String())))
}
}
func comparisonGreaterOrEqual(left reflect.Value, right reflect.Value) reflect.Value {
k := typeAscend(left.Kind(), right.Kind())
switch k {
case reflect.Float32, reflect.Float64:
r := ConvertToFloat(left) >= ConvertToFloat(right)
return reflect.ValueOf(r)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
r := ConvertToUint(left) >= ConvertToUint(right)
return reflect.ValueOf(r)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
r := ConvertToInt(left) >= ConvertToInt(right)
return reflect.ValueOf(r)
case reflect.Bool:
r := ConvertToInt(left) >= ConvertToInt(right)
return reflect.ValueOf(r)
default:
panic(runtimePanic(fmt.Sprintf("type %s and %s not support comparison greater or equal", left.Kind().String(), right.Kind().String())))
}
}
func comparisonLess(left reflect.Value, right reflect.Value) reflect.Value {
k := typeAscend(left.Kind(), right.Kind())
switch k {
case reflect.Float32, reflect.Float64:
r := ConvertToFloat(left) < ConvertToFloat(right)
return reflect.ValueOf(r)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
r := ConvertToUint(left) < ConvertToUint(right)
return reflect.ValueOf(r)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
r := ConvertToInt(left) < ConvertToInt(right)
return reflect.ValueOf(r)
case reflect.Bool:
r := ConvertToInt(left) < ConvertToInt(right)
return reflect.ValueOf(r)
default:
panic(runtimePanic(fmt.Sprintf("type %s and %s not support comparison less", left.Kind().String(), right.Kind().String())))
}
}
func comparisonLessOrEqual(left reflect.Value, right reflect.Value) reflect.Value {
k := typeAscend(left.Kind(), right.Kind())
switch k {
case reflect.Float32, reflect.Float64:
r := ConvertToFloat(left) <= ConvertToFloat(right)
return reflect.ValueOf(r)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
r := ConvertToUint(left) <= ConvertToUint(right)
return reflect.ValueOf(r)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
r := ConvertToInt(left) <= ConvertToInt(right)
return reflect.ValueOf(r)
case reflect.Bool:
r := ConvertToInt(left) <= ConvertToInt(right)
return reflect.ValueOf(r)
default:
panic(runtimePanic(fmt.Sprintf("type %s and %s not support comparison less or equal", left.Kind().String(), right.Kind().String())))
}
}

View File

@@ -0,0 +1,48 @@
package expr
import "reflect"
// A Var identifies a variable, e.g., x.
type Var string
// A literal is a numeric constant, e.g., 3.141.
type literal struct {
value interface{}
}
// An Expr is an arithmetic expression.
type Expr interface {
// Eval returns the value of this Expr in the environment env.
Eval(env Env) reflect.Value
// Check reports errors in this Expr and adds its Vars to the set.
Check(vars map[Var]interface{}) error
}
// A unary represents a unary operator expression, e.g., -x.
type unary struct {
op string // one of '+', '-', '!', '~'
x Expr
}
// A binary represents a binary operator expression, e.g., x+y.
type binary struct {
op string
x, y Expr
}
// A call represents a function call expression, e.g., sin(x).
type call struct {
fn string
args []Expr
}
var exprFuncParams = map[string]int{
"pow": 2,
"sin": 1,
"sqrt": 1,
"rand": 0,
"log": 1,
"to_upper": 1,
"to_lower": 1,
"crc32": 1,
}

View File

@@ -0,0 +1,60 @@
package expr
import (
"fmt"
"testing"
)
func TestExpr(t *testing.T) {
defer func() {
switch x := recover().(type) {
case nil:
// no panic
case runtimePanic:
fmt.Println(x)
panic(x)
default:
// unexpected panic: resume state of panic.
panic(x)
}
}()
tests := []struct {
expr string
env Env
want string
}{
{`$x == "android"`, Env{"$x": "android"}, "true"},
{"$x == `android`", Env{"$x": "android"}, "true"},
{"to_lower($x) == `android`", Env{"$x": "AnDroId"}, "true"},
{"to_lower($x) == `android`", Env{"$x": "iOS"}, "false"},
{"log($1 + 9 * $1)", Env{"$1": 100}, "3"},
{"$1 > 80 && $2 <9", Env{"$1": 100, "$2": 2}, "true"},
{"pow(x, false) + pow(y, false)", Env{"x": 12, "y": 1}, "2"},
{"pow(x, 3) + pow(y, 3)", Env{"x": 9, "y": 10}, "1729"},
{"9 * (F - 32)/5", Env{"F": -40}, "-129"},
{"-1 + -x", Env{"x": 1}, "-2"},
{"-1 - x", Env{"x": 1}, "-2"},
{"a >= 10", Env{"a": 15}, "true"},
{"b >= sin(10) && a < 1", Env{"a": 9, "b": 10}, "false"},
{"!!!true", Env{"a": 9, "b": 10}, "false"},
}
var prevExpr string
parser := NewExpressionParser()
for _, test := range tests {
// Print expr only when it changes.
if test.expr != prevExpr {
t.Logf("\n%s\n", test.expr)
prevExpr = test.expr
}
if err := parser.Parse(test.expr); err != nil {
t.Error(err) // parse error
continue
}
got := fmt.Sprintf("%v", parser.GetExpr().Eval(test.env))
t.Logf("%s\t%v => %s\n", test.expr, test.env, got)
if got != test.want {
t.Errorf("%s.Eval() in %v = %q, want %q\n",
test.expr, test.env, got, test.want)
}
}
}

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/service/live/zeus/internal/conf",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/cache/memcache:go_default_library",
"//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/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,103 @@
package conf
import (
"errors"
"flag"
"go-common/library/cache/memcache"
"go-common/library/cache/redis"
"go-common/library/database/sql"
"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{}
)
type IndexConfig struct {
Matcher string
}
type SvenConfig struct {
TreeID string
Zone string
Env string
Build string
Token string
}
// Config .
type Config struct {
Log *log.Config
BM *bm.ServerConfig
Verify *verify.Config
Tracer *trace.Config
Redis *redis.Config
Memcache *memcache.Config
MySQL *sql.Config
Ecode *ecode.Config
Sven *SvenConfig
Index *IndexConfig
}
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() {
// Stupid code !
//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,34 @@
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/zeus/internal/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/live/zeus/internal/conf:go_default_library",
"//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,42 @@
package dao
import (
"context"
"go-common/app/service/live/zeus/internal/conf"
"go-common/library/cache/memcache"
"go-common/library/cache/redis"
xsql "go-common/library/database/sql"
)
// Dao dao
type Dao struct {
c *conf.Config
mc *memcache.Pool
redis *redis.Pool
db *xsql.DB
}
// New init mysql db
func New(c *conf.Config) (dao *Dao) {
dao = &Dao{
c: c,
//mc: memcache.NewPool(c.Memcache),
//redis: redis.NewPool(c.Redis),
//db: xsql.NewMySQL(c.MySQL),
}
return
}
// Close close the resource.
func (d *Dao) Close() {
//d.mc.Close()
//d.redis.Close()
//d.db.Close()
}
// Ping dao ping
func (d *Dao) Ping(ctx context.Context) error {
// TODO: add mc,redis... if you use
return d.db.Ping(ctx)
}

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 = [
"matcher.go",
"model.go",
],
importpath = "go-common/app/service/live/zeus/internal/model",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/live/zeus/expr: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,80 @@
package model
import (
"encoding/json"
"errors"
"fmt"
"go-common/app/service/live/zeus/expr"
"go-common/library/log"
)
type Matcher struct {
Group map[string][]*MatcherBucket `json:"group"`
VariableWhitelist []string `json:"variable_whitelist"`
}
type MatcherBucket struct {
RuleExpr string `json:"expr"`
Extend interface{} `json:"extend"`
expr expr.Expr
variable []string
config string
}
func NewMatcher(config string) (*Matcher, error) {
matcher := &Matcher{}
if err := json.Unmarshal([]byte(config), matcher); err != nil {
return nil, err
}
whitelist := make(map[string]struct{}, len(matcher.VariableWhitelist))
for _, v := range matcher.VariableWhitelist {
whitelist[v] = struct{}{}
}
parser := expr.NewExpressionParser()
for _, bucket := range matcher.Group {
for _, b := range bucket {
if e := parser.Parse(b.RuleExpr); e != nil {
msg := fmt.Sprintf("zeus compile error, rule:%s error:%s", b.RuleExpr, e.Error())
return nil, errors.New(msg)
}
b.expr = parser.GetExpr()
b.variable = parser.GetVariable()
for _, v := range b.variable {
if _, ok := whitelist[v]; !ok {
msg := fmt.Sprintf("zeus check error, rule:%s error: variable %s not in whitelist", b.RuleExpr, v)
return nil, errors.New(msg)
}
}
if config, e := json.Marshal(b.Extend); e != nil {
msg := fmt.Sprintf("zeus parse config error, rule:%s error:%s", b.RuleExpr, e.Error())
return nil, errors.New(msg)
} else {
b.config = string(config)
}
}
}
return matcher, nil
}
func (m *Matcher) Match(group string, env expr.Env) (bool, string, error) {
var bucket []*MatcherBucket
var ok bool
if bucket, ok = m.Group[group]; !ok {
return false, "", errors.New("group not found")
}
isMatch := false
extend := ""
for _, b := range bucket {
result, err := expr.EvalBool(b.expr, env)
if err != nil {
log.Error("zeus eval error, group:%s expr:%s error:%s", group, b.RuleExpr, err.Error())
continue
}
if result {
isMatch = true
extend = b.config
break
}
}
return isMatch, extend, nil
}

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 = ["grpc.go"],
importpath = "go-common/app/service/live/zeus/internal/server/grpc",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/live/zeus/api/v1:go_default_library",
"//app/service/live/zeus/internal/conf:go_default_library",
"//app/service/live/zeus/internal/service/v1: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,18 @@
package grpc
import (
v1pb "go-common/app/service/live/zeus/api/v1"
"go-common/app/service/live/zeus/internal/conf"
v1srv "go-common/app/service/live/zeus/internal/service/v1"
"go-common/library/net/rpc/warden"
)
func New(c *conf.Config, s *v1srv.ZeusService) *warden.Server {
ws := warden.NewServer(nil)
v1pb.RegisterZeusServer(ws.Server(), s)
ws, err := ws.Start()
if err != nil {
panic(err)
}
return ws
}

View File

@@ -0,0 +1,37 @@
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/zeus/internal/server/http",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/live/zeus/api/v1:go_default_library",
"//app/service/live/zeus/internal/conf:go_default_library",
"//app/service/live/zeus/internal/service:go_default_library",
"//app/service/live/zeus/internal/service/v1: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,56 @@
package http
import (
"net/http"
v1pb "go-common/app/service/live/zeus/api/v1"
"go-common/app/service/live/zeus/internal/conf"
"go-common/app/service/live/zeus/internal/service"
v1srv "go-common/app/service/live/zeus/internal/service/v1"
"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, zeus *v1srv.ZeusService) {
svc = s
vfy = verify.New(c.Verify)
engine := bm.DefaultServer(c.BM)
route(engine, zeus)
if err := engine.Start(); err != nil {
log.Error("bm Start error(%v)", err)
panic(err)
}
}
func route(e *bm.Engine, zeus *v1srv.ZeusService) {
e.Ping(ping)
e.Register(register)
g := e.Group("/x/zeus")
{
g.GET("/start", vfy.Verify, howToStart)
}
v1pb.RegisterZeusBMServer(e, zeus)
}
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,41 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"match.go",
"service.go",
],
importpath = "go-common/app/service/live/zeus/internal/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/live/zeus/expr:go_default_library",
"//app/service/live/zeus/internal/conf:go_default_library",
"//app/service/live/zeus/internal/dao:go_default_library",
"//app/service/live/zeus/internal/model: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",
"//app/service/live/zeus/internal/service/v1:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,40 @@
package service
import (
"errors"
"go-common/app/service/live/zeus/expr"
"go-common/app/service/live/zeus/internal/model"
"go-common/library/log"
"sync/atomic"
)
type MatchService struct {
matcher atomic.Value
}
func NewMatchService(config string) (*MatchService, error) {
s := &MatchService{}
if err := s.Reload(config); err != nil {
return nil, err
}
return s, nil
}
func (m *MatchService) Reload(config string) error {
matcher, err := model.NewMatcher(config)
if err != nil {
log.Error("Match Service reload config failed, config:%s", config)
return err
}
m.matcher.Store(matcher)
log.Info("Match Service reload config success, config:%s", config)
return nil
}
func (m *MatchService) Match(group string, env expr.Env) (bool, string, error) {
matcher := m.matcher.Load().(*model.Matcher)
if matcher == nil {
return false, "", errors.New("matcher not initialized")
}
return matcher.Match(group, env)
}

View File

@@ -0,0 +1,34 @@
package service
import (
"context"
"go-common/app/service/live/zeus/internal/conf"
"go-common/app/service/live/zeus/internal/dao"
)
// Service struct
type Service struct {
c *conf.Config
dao *dao.Dao
}
// New init
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
dao: dao.New(c),
}
return s
}
// Ping Service
func (s *Service) Ping(ctx context.Context) (err error) {
//return s.dao.Ping(ctx)
return nil
}
// Close Service
func (s *Service) Close() {
s.dao.Close()
}

View File

@@ -0,0 +1,37 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["zeus.go"],
importpath = "go-common/app/service/live/zeus/internal/service/v1",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/common/live/library/mengde:go_default_library",
"//app/service/live/zeus/api/v1:go_default_library",
"//app/service/live/zeus/expr:go_default_library",
"//app/service/live/zeus/internal/conf:go_default_library",
"//app/service/live/zeus/internal/service: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,70 @@
package v1
import (
"context"
"go-common/app/common/live/library/mengde"
v1pb "go-common/app/service/live/zeus/api/v1"
"go-common/app/service/live/zeus/expr"
"go-common/app/service/live/zeus/internal/conf"
"go-common/app/service/live/zeus/internal/service"
"go-common/library/ecode"
"go-common/library/log"
)
// ZeusService struct
type ZeusService struct {
conf *conf.Config
// optionally add other properties here, such as dao
// dao *dao.Dao
mengde *mengde.MengdeClient
match *service.MatchService
}
//NewZeusService init
func NewZeusService(c *conf.Config) (s *ZeusService) {
mengde, err := mengde.NewMengdeClient(c.Sven.TreeID, c.Sven.Zone, c.Sven.Env, c.Sven.Build, c.Sven.Token)
if err != nil {
panic(err)
}
matcherConfig := mengde.Config().Config[c.Index.Matcher]
match, err := service.NewMatchService(matcherConfig)
if err != nil {
panic(err)
}
s = &ZeusService{
conf: c,
mengde: mengde,
match: match,
}
go s.configWatcher()
return s
}
func (s *ZeusService) configWatcher() {
for config := range s.mengde.ConfigNotify() {
if err := s.match.Reload(config.Config[s.conf.Index.Matcher]); err != nil {
log.Error("zeus reload error:%s", err.Error())
}
}
}
// Match implementation
// `method:"POST"`
func (s *ZeusService) Match(ctx context.Context, req *v1pb.MatchRequest) (*v1pb.MatchResponse, error) {
env := expr.Env{
"$build": req.Build,
"$version": req.Version,
"$buvid": req.Buvid,
"$platform": req.Platform,
"$uid": req.Uid,
}
isMatch, extend, err := s.match.Match(req.Group, env)
if err != nil {
return nil, ecode.Errorf(-1, err.Error())
}
resp := &v1pb.MatchResponse{
IsMatch: isMatch,
Extend: extend,
}
return resp, nil
}