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

View File

@@ -0,0 +1,489 @@
### account service
### Version 7.17.0
> 1. 修复 mc sdk
### Version 7.15.0
> 1. profile 增加 is_tourist 字段
> 2. 移除 account-notify-job
### Version 7.14.2
> 1. 修正 gRPC 节操修改逻辑
### Version 7.14.1
> 1. goRpc方法添加过期备注
### Version 7.14.0
> 1. gRPC 重构
### Version 7.13.0
> 1. 增加 VIP 相关 gRPC 接口
### Version 7.12.1
> 1. 使用优先队列延迟删除缓存
> 2. 增加队列长度统计
### Version 7.11.0
> 1. gRPC服务迁移到v1
### Version 7.10.3
> 1. add vip decide method
> 2. 实名认证空数据
> 3. 实名认证空指针检查
### Version 7.10.1
> 1. separate privacy http client
### Version 7.10.0
> 1. 增加 /privacy api
### Version 7.9.0
> 1. rpc.ProfileWithStat3 vip信息增加VipPayType
### Version 7.8.6
> 1. 封禁信息改为调用member
### Version 7.8.5
> 1. 删缓存错误以 cause 为准
### Version 7.8.4
> 1. 整理删缓存日志
### Version 7.8.3
> 1. remove cache save
### Version 7.8.2
> 1. logging delete cache error
### Version 7.8.1
> 1. 删除缓存日志
### Version 7.8.0
> 1. 去除显式 ip 参数传递
### Version 7.7.0
> 1. 修改部分基础库
### Version 7.6.0
> 1. 通过名字搜索用户信息走搜索接口
### Version 7.5.0
> 1. cards和myinfo接口调用go相关服务
### Version 7.4.0
> 1. 经验节操修改调用member
### Version 7.3.10
> 1.使用新版 warden
> 2.去除无用 error wrap
### Version 7.3.0
> 1.使用新版 warden
### Version 7.2.0
> 1.添加 GRPC 接口
#### Version 7.1.0
> 1.集成新的官方认证
> 1.官方认证兼容老接口结构
#### Version 7.0.0
> 1.删除大量无用代码
> 2.规范和统一字段名
> 3.使用最新bm和cache gen
#### Version 6.21.2
> 1.minify wallet cache duration
> 2.remove statsd
#### Version 6.21.1
> 1.reduce wallet cache duration
#### Version 6.21.0
> 1.call account thin APIs for info, infos, myinfo, userinfo, profile.
> 2.parallel call dependencies.
#### Version 6.20.0
> 1.add userinfo rpc
#### Version 6.19.0
> 1.del cache for action cleanAccessKey
#### Version 6.18.0
> 1.添加cardbyname接口
#### Version 6.17.0
> 1.del unused code
#### Version 6.16.0
> 1.add member proxy config
#### Version 6.16.0
> 1.add member proxy mid end with 92
#### Version 6.15.0
> 1.profile 硬币信息直接读取coin-service
#### Version 6.14.0
> 1.更新b+缓存
#### Version 6.14.0
> 1.添加userinfo api接口
#### Version 6.13.0
> 1.删除relation代码
#### Version 6.12.0
> 1.mid获取手机号及用户关系
#### Version 6.11.0
> 1.add thin info rpc
#### Version 6.10.4
> 1.fix wallet cache expiration
#### Version 6.10.3
> 1.add vip info cache2 del
#### Version 6.10.2
> 1.add vip info cache del
#### Version 6.10.1
> 1.升级基础库
#### Version 6.10.0
> 1.update http client conf and usage
#### Version 6.9.0
> 1.支持分组缓存清理
#### Version 6.8.0
> 1.myinfo接口调用account-java的获取用户信息myinfo内网接口
#### Version 6.7.0
> 1.迁移info card 到member-service
#### Version 6.6.0
> 1.add rpc token and group
#### Version 6.5.0
> 1.add login empty cache
#### Version 6.4.0
> 1.add http method get vip info
#### Version 6.3.0
> 1.add rpc service method info3
#### Version 6.2.0
> 1.adjust internal http router group
#### Version 6.1.0
> 1.add new mc identify cluster
#### Version 6.0.0
> 1.merge account-service into kratos
#### Version 5.16.0
> 1.add unit tests for dao and service
#### Version 5.15.0
> 1.add new mc identify cluster
#### Version 5.14.0
> 1.更新mc基础包缓存
#### Version 5.13.0
> 1.删除relation redis代码
#### Version 5.12.5
> 1. 修复syslog panic error
#### Version 5.12.4
> 1.修复go-common memcache stat err
#### Version 5.12.3
> 1.添加memcache错误监控
#### Version 5.12.2
> 1.修复profile -404错误
#### Version 5.12.1
> 1.修复wallet的缓存错误
#### Version 5.12.0
> 1.http接口改为内网接口
#### Version 5.11.7
> 1.修复relation关注升级
#### Version 5.11.6
> 1.平滑发版
> 2.fix RESTFul vipinfo
#### Version 5.11.5
> 1.add mc statsd
#### Version 5.11.4
> 1.fix rpc server stat init
#### Version 5.11.3
> 1.fix rpc stat init
#### Version 5.11.2
> 1.升级RESTFul Get
#### Version 5.11.1
> 1.prom监控bugfix
#### Version 5.11.0
> 1.接入prom监控
#### Version 5.10.0
> 1.添加attention返回所有关注列表包括悄悄关注
#### Version 5.9.0
> 1.增加黑名单rpc
> 2.更新vendor
#### Version 5.8.0
> 1.封装relation-service接口
#### Version 5.7.5
> 1.fixed monitor ping
> 2.修改配置文件加载错误提示
#### Version 5.7.4
> 1.接入新的配置中心
> 2.接入rpc DiscoverOff配置
> 3.优化清除access cache逻辑
#### Version 5.7.3
> 1.account 添加用户auditInfo rpc接口
#### Version 5.7.2
> 1.接入新的配置中心
> 2.rpc 注册配置修改
#### Version 5.7.1
> 1.no change
#### Version 5.7.0
> 1.cache callback优化
> 2.升级dao层使用Get2
> 3.memcahed err 不再回写缓存
> 4.拆分account.go
> 5.去掉service请求dao的异常日志
> 6.删除不再使用的代码
#### Version 5.6.2
> 1.profile兼容逻辑
#### Version 5.6.1
> 1.no commit(docker file missing!!!)
#### Version 5.6.0
> 1.tw-proxy local deploy
#### Version 5.5.0
> 1.cal/del 维护新的mc集群
> 2.删除thrift rpc代码
#### Version 5.4.0
> 1.go-common stat小包合并大包
> 2.go-common修复base64编码bug
#### Version 5.3.0
> 1.更新最新的net/rpc
#### Version 5.2.1
> 1.go-common修复trace race bug
#### Version 5.2.0
> 1.支持优先从本地加载配置
> 2.更新vendor支持最新的rpc库
#### Version 5.1.4
> 1.AccessInfo接口cache缓存失败return改为回源帐号
> 2.Secret接口走内存cache
#### Version 5.1.3
> 1.profile接口支持VerifyOrUserGet
#### Version 5.1.2
> 1.wallet过期时间改为CouponDueTime
> 2.修复access删除bug
#### Version 5.1.1
> 1.修复wallet清缓存bug
> 2.更新vendor
#### Version 5.1.0
> 1.支持平滑切流量和重启
#### Version 5.0.0
> 1.net/rpc改为为golang/rpcx
#### Version 4.5.0
> 1.接入配置中心
#### Version 4.3.3
> 1.wallet字段json格式修正
#### Version 4.3.2
> 1.idfSvc改成service实现,并支持两个新方法Access和Verify
> 2.升级vendor
#### Version 4.3.1
> 1.修复ak获取到用户存缓存0的bug
#### Version 4.3.0
> 1.新增支持accesskey白名单
> 2.支持b币新接口
#### Version 4.2.1
> 1.去掉帐号错误码转换
#### Version 4.2.0
> 1.添加accessInfo接口和获取secret的http接口
#### Version 4.1.1
> 1.升级zk的包版本到最新
#### Version 4.1.0
> 1.增加thrift的auth调用
#### Version 4.0.1
> 1.更新所有匿名rpc client为默认user
#### Version 4.0.0
> 1.引入vendor
> 2.rpc修改syslog和上报
#### Version 3.7.0
> 1.新增verify和secret的rpc接口用于identify
#### Version 3.6.1
> 1.新增获取移动端头图的接口
#### Version 3.6.0
> 1.VIP信息聚合
> 2.新增名片信息和空间信息的聚合接口
> 3.新增查询用户信息和是否关注up主的聚合接口
#### Version 3.5.1
> 1.新增profile http接口
> 2.新增批量获取relation
#### Version 3.5.0
> 1.新增获取up主和粉丝的关系rpc接口
#### Version 3.4.0
> 1.新增批量获取up主和粉丝的关系
> 2.cache更新优化
#### Version 3.3.1
> 1.fix relation bug
#### Version 3.3.0
> 1.增加用户是否关注up主的http接口
> 2.增加批量获取用户信息接口的http接口
##### Version 3.2.2
> 1.trace v2
##### Version 3.2.1
> 1.http client读写超时设置分开
##### Version 3.2.0
> 1.修复elk日志
> 2.支持trace v2
##### Version 3.1.0
> 1.使用go-common/xlog
> 2.修改删除cache接口为get
##### Version 3.0.1
> 1.修复relation接口返回nil
##### Version 3.0.0
> 1.context使用官方接口
> 2.添加coin rpc
##### Version 2.4.0
> 1.添加昵称查询card rpc接口
##### Version 2.3.0
> 1.添加服务发现
##### Version 2.2.2
> 1.修改配置信息,更合理
##### Version 2.2.1
> 1.修复rpc返回指针赋值
##### Version 2.2.0
> 1.优化
> 2.add elk
> 3.add trace id
> 4.modify appkey
> 5.add async update cache
> 6.add friend relation
##### Version 2.1.0
> 1.add tracer
##### Version 1.1.0
> 1.基于go-common重构
##### Version 1.0.0
> 1.初始化完成用户信息基础查询功能

View File

@@ -0,0 +1,17 @@
# Owner
wanghuan01
zhoujiahui
# Author
wanghuan01
zhoujiahui
zhoujixiang
chenshangqiang
# Reviewer
wanghuan01
zhoujiahui
zhoujixiang
chenshangqiang
linmiao
haoguawnei

View File

@@ -0,0 +1,20 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- chenshangqiang
- wanghuan01
- zhoujiahui
- zhoujixiang
labels:
- main
- service
- service/main/account
options:
no_parent_owners: true
reviewers:
- chenshangqiang
- haoguawnei
- linmiao
- wanghuan01
- zhoujiahui
- zhoujixiang

View File

@@ -0,0 +1,14 @@
#### account-service
`account-service`主要是为主站各个业务提供一个大的cache和rpc接口。
* 聚合了账号多个业务(`passport` `account` `big` `pay` `relation-service`)的缓存
* 提供了rpc服务
1. 为没有rpc服务的业务(`passport` `account` `big` `pay`)封装rpc接口
2. 已rpc服务的业务(`relation-service`)提供接口封装透传rpc服务
##### 依赖环境
Go 1.7.5或更高版本
##### API文档
TODO example code api

View File

@@ -0,0 +1,71 @@
load(
"@io_bazel_rules_go//proto:def.bzl",
"go_proto_library",
)
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
proto_library(
name = "api_proto",
srcs = ["api.proto"],
tags = ["automanaged"],
deps = ["@gogo_special_proto//github.com/gogo/protobuf/gogoproto"],
)
go_proto_library(
name = "api_go_proto",
compilers = ["@io_bazel_rules_go//proto:gogofast_grpc"],
importpath = "go-common/app/service/main/account/api",
proto = ":api_proto",
tags = ["automanaged"],
deps = [
"//library/time:go_default_library",
"@com_github_gogo_protobuf//gogoproto:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"client.go",
"copy_autogenerated.go",
"mock.go",
"vip.go",
],
embed = [":api_go_proto"],
importpath = "go-common/app/service/main/account/api",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/member/model:go_default_library",
"//library/net/rpc/warden:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/golang/mock/gomock: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",
"//app/service/main/account/api/gorpc:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,240 @@
// +bili:type=service
syntax = "proto3";
package account.service;
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
option go_package = "api";
message Card {
int64 mid = 1 [(gogoproto.jsontag) = "mid"];
string name = 2 [(gogoproto.jsontag) = "name"];
string sex = 3 [(gogoproto.jsontag) = "sex"];
string face = 4 [(gogoproto.jsontag) = "face"];
string sign = 5 [(gogoproto.jsontag) = "sign"];
int32 rank = 6 [(gogoproto.jsontag) = "rank"];
int32 level = 7 [(gogoproto.jsontag) = "level"];
int32 silence = 8 [(gogoproto.jsontag) = "silence"];
VipInfo vip = 9 [(gogoproto.jsontag) = "vip", (gogoproto.nullable) = false];
PendantInfo pendant = 10
[(gogoproto.jsontag) = "pendant", (gogoproto.nullable) = false];
NameplateInfo nameplate = 11
[(gogoproto.jsontag) = "nameplate", (gogoproto.nullable) = false];
OfficialInfo official = 12
[(gogoproto.jsontag) = "official", (gogoproto.nullable) = false];
}
message Info {
int64 mid = 1 [(gogoproto.jsontag) = "mid"];
string name = 2 [(gogoproto.jsontag) = "name"];
string sex = 3 [(gogoproto.jsontag) = "sex"];
string face = 4 [(gogoproto.jsontag) = "face"];
string sign = 5 [(gogoproto.jsontag) = "sign"];
int32 rank = 6 [(gogoproto.jsontag) = "rank"];
}
message Profile {
int64 mid = 1 [(gogoproto.jsontag) = "mid"];
string name = 2 [(gogoproto.jsontag) = "name"];
string sex = 3 [(gogoproto.jsontag) = "sex"];
string face = 4 [(gogoproto.jsontag) = "face"];
string sign = 5 [(gogoproto.jsontag) = "sign"];
int32 rank = 6 [(gogoproto.jsontag) = "rank"];
int32 level = 7 [(gogoproto.jsontag) = "level"];
int32 join_time = 8 [(gogoproto.jsontag) = "jointime"];
int32 moral = 9 [(gogoproto.jsontag) = "moral"];
int32 silence = 10 [(gogoproto.jsontag) = "silence"];
int32 email_status = 11 [(gogoproto.jsontag) = "email_status"];
int32 tel_status = 12 [(gogoproto.jsontag) = "tel_status"];
int32 identification = 13 [(gogoproto.jsontag) = "identification"];
VipInfo vip = 14 [(gogoproto.jsontag) = "vip", (gogoproto.nullable) = false];
PendantInfo pendant = 15
[(gogoproto.jsontag) = "pendant", (gogoproto.nullable) = false];
NameplateInfo nameplate = 16
[(gogoproto.jsontag) = "nameplate", (gogoproto.nullable) = false];
OfficialInfo official = 17
[(gogoproto.jsontag) = "official", (gogoproto.nullable) = false];
int64 birthday = 18 [
(gogoproto.jsontag) = "birthday",
(gogoproto.casttype) = "go-common/library/time.Time"
];
int32 is_tourist = 19 [(gogoproto.jsontag) = "is_tourist"];
}
// +bili:deepcopy-gen=true
// +bili:deepcopy-gen:structs=go-common/app/service/main/member/model.LevelInfo
message LevelInfo {
int32 cur = 1 [(gogoproto.jsontag) = "current_level"];
int32 min = 2 [(gogoproto.jsontag) = "current_min"];
int32 now_exp = 3 [(gogoproto.jsontag) = "current_exp"];
int32 next_exp = 4 [(gogoproto.jsontag) = "next_exp"];
}
message VipInfo {
int32 type = 1 [(gogoproto.jsontag) = "type"];
int32 status = 2 [(gogoproto.jsontag) = "status"];
int64 due_date = 3 [(gogoproto.jsontag) = "due_date"];
int32 vip_pay_type = 4 [(gogoproto.jsontag) = "vip_pay_type"];
}
message PendantInfo {
int32 pid = 1 [(gogoproto.jsontag) = "pid", (gogoproto.casttype) = "int"];
string name = 2 [(gogoproto.jsontag) = "name"];
string image = 3 [(gogoproto.jsontag) = "image"];
int64 expire = 4
[(gogoproto.jsontag) = "expire", (gogoproto.casttype) = "int"];
}
message NameplateInfo {
int32 nid = 1 [(gogoproto.jsontag) = "nid", (gogoproto.casttype) = "int"];
string name = 2 [(gogoproto.jsontag) = "name"];
string image = 3 [(gogoproto.jsontag) = "image"];
string image_small = 4 [(gogoproto.jsontag) = "image_small"];
string level = 5 [(gogoproto.jsontag) = "level"];
string condition = 6 [(gogoproto.jsontag) = "condition"];
}
// +bili:deepcopy-gen=true
// +bili:deepcopy-gen:structs=go-common/app/service/main/member/model.OfficialInfo
message OfficialInfo {
int32 role = 1 [(gogoproto.jsontag) = "role", (gogoproto.casttype) = "int8"];
string title = 2 [(gogoproto.jsontag) = "title"];
string desc = 3 [(gogoproto.jsontag) = "desc"];
}
message MidReq {
int64 mid = 1 [(gogoproto.moretags) = "validate:\"gt=0,required\""];
string real_ip = 2;
}
message MidsReq {
repeated int64 mids = 1
[(gogoproto.moretags) = "validate:\"gt=0,dive,gt=0\""];
string real_ip = 2;
}
message NamesReq {
repeated string names = 1
[(gogoproto.moretags) = "validate:\"gt=0,dive,gt=0\""];
string real_ip = 2;
}
message ExpReq {
int64 mid = 1 [(gogoproto.moretags) = "validate:\"gt=0,required\""];
double exp = 2;
string operater = 3;
string operate = 4;
string reason = 5;
string real_ip = 6;
}
message MoralReq {
int64 mid = 1 [(gogoproto.moretags) = "validate:\"gt=0,required\""];
double moral = 2;
string oper = 3;
string reason = 4;
string remark = 5;
string real_ip = 6;
}
message RelationReq {
int64 mid = 1 [(gogoproto.moretags) = "validate:\"gt=0,required\""];
int64 owner = 2;
string real_ip = 3;
}
message RelationsReq {
int64 mid = 1 [(gogoproto.moretags) = "validate:\"gt=0,required\""];
repeated int64 owners = 2;
string real_ip = 3;
}
message RichRelationReq {
int64 owner = 1;
repeated int64 mids = 2
[(gogoproto.moretags) = "validate:\"gt=0,dive,gt=0\""];
string real_ip = 3;
}
message InfoReply {
Info info = 1;
}
message InfosReply {
map<int64, Info> infos = 1;
}
message CardReply {
Card card = 1;
}
message CardsReply {
map<int64, Card> cards = 1;
}
message ProfileReply {
Profile profile = 1;
}
message ProfileStatReply {
Profile profile = 1;
LevelInfo level_info = 2 [(gogoproto.nullable) = false];
double coins = 3;
int64 following = 4;
int64 follower = 5;
}
message RelationReply {
bool following = 1;
}
message AttentionsReply {
repeated int64 attentions = 1;
}
message BlacksReply {
map<int64, bool> black_list = 1;
}
message RelationsReply {
map<int64, RelationReply> relations = 1;
}
message RichRelationsReply {
map<int64, int32> rich_relations = 1;
}
// +bili:deepcopy-gen=true
// +bili:deepcopy-gen:structs=go-common/app/service/main/account/api.VipInfo
message VipReply {
int32 type = 1;
int32 status = 2;
int64 due_date = 3;
int32 vip_pay_type = 4;
}
message VipsReply {
map<int64, VipReply> vips = 1;
}
message ExpReply {}
message MoralReply {}
service Account {
rpc Info3(MidReq) returns (InfoReply);
rpc Infos3(MidsReq) returns (InfosReply);
rpc InfosByName3(NamesReq) returns (InfosReply);
rpc Card3(MidReq) returns (CardReply);
rpc Cards3(MidsReq) returns (CardsReply);
rpc Profile3(MidReq) returns (ProfileReply);
rpc ProfileWithStat3(MidReq) returns (ProfileStatReply);
rpc AddExp3(ExpReq) returns (ExpReply);
rpc AddMoral3(MoralReq) returns (MoralReply);
rpc Relation3(RelationReq) returns (RelationReply);
rpc Attentions3(MidReq) returns (AttentionsReply);
rpc Blacks3(MidReq) returns (BlacksReply);
rpc Relations3(RelationsReq) returns (RelationsReply);
rpc RichRelations3(RichRelationReq) returns (RichRelationsReply);
rpc Vip3(MidReq) returns (VipReply);
rpc Vips3(MidsReq) returns (VipsReply);
}

View File

@@ -0,0 +1,22 @@
package api
import (
"context"
"go-common/library/net/rpc/warden"
"google.golang.org/grpc"
)
// AppID unique app id for service discovery
const AppID = "account.service"
// NewClient new member grpc client
func NewClient(cfg *warden.ClientConfig, opts ...grpc.DialOption) (AccountClient, error) {
client := warden.NewClient(cfg, opts...)
conn, err := client.Dial(context.Background(), "discovery://default/"+AppID)
if err != nil {
return nil, err
}
return NewAccountClient(conn), nil
}

View File

@@ -0,0 +1,137 @@
// Code generated by deepcopy-gen. DO NOT EDIT.
package api
import (
model "go-common/app/service/main/member/model"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LevelInfo) DeepCopyInto(out *LevelInfo) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LevelInfo.
func (in *LevelInfo) DeepCopy() *LevelInfo {
if in == nil {
return nil
}
out := new(LevelInfo)
in.DeepCopyInto(out)
return out
}
// DeepCopyAsIntoLevelInfo is an autogenerated deepcopy function, copying the receiver, writing into model.LevelInfo.
func (in *LevelInfo) DeepCopyAsIntoLevelInfo(out *model.LevelInfo) {
out.Cur = in.Cur
out.Min = in.Min
out.NowExp = in.NowExp
out.NextExp = in.NextExp
return
}
// DeepCopyFromLevelInfo is an autogenerated deepcopy function, copying the receiver, writing into model.LevelInfo.
func (out *LevelInfo) DeepCopyFromLevelInfo(in *model.LevelInfo) {
out.Cur = in.Cur
out.Min = in.Min
out.NowExp = in.NowExp
out.NextExp = in.NextExp
return
}
// DeepCopyAsLevelInfo is an autogenerated deepcopy function, copying the receiver, creating a new model.LevelInfo.
func (in *LevelInfo) DeepCopyAsLevelInfo() *model.LevelInfo {
if in == nil {
return nil
}
out := new(model.LevelInfo)
in.DeepCopyAsIntoLevelInfo(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *OfficialInfo) DeepCopyInto(out *OfficialInfo) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OfficialInfo.
func (in *OfficialInfo) DeepCopy() *OfficialInfo {
if in == nil {
return nil
}
out := new(OfficialInfo)
in.DeepCopyInto(out)
return out
}
// DeepCopyAsIntoOfficialInfo is an autogenerated deepcopy function, copying the receiver, writing into model.OfficialInfo.
func (in *OfficialInfo) DeepCopyAsIntoOfficialInfo(out *model.OfficialInfo) {
out.Role = in.Role
out.Title = in.Title
out.Desc = in.Desc
return
}
// DeepCopyFromOfficialInfo is an autogenerated deepcopy function, copying the receiver, writing into model.OfficialInfo.
func (out *OfficialInfo) DeepCopyFromOfficialInfo(in *model.OfficialInfo) {
out.Role = in.Role
out.Title = in.Title
out.Desc = in.Desc
return
}
// DeepCopyAsOfficialInfo is an autogenerated deepcopy function, copying the receiver, creating a new model.OfficialInfo.
func (in *OfficialInfo) DeepCopyAsOfficialInfo() *model.OfficialInfo {
if in == nil {
return nil
}
out := new(model.OfficialInfo)
in.DeepCopyAsIntoOfficialInfo(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *VipReply) DeepCopyInto(out *VipReply) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VipReply.
func (in *VipReply) DeepCopy() *VipReply {
if in == nil {
return nil
}
out := new(VipReply)
in.DeepCopyInto(out)
return out
}
// DeepCopyAsIntoVipInfo is an autogenerated deepcopy function, copying the receiver, writing into VipInfo.
func (in *VipReply) DeepCopyAsIntoVipInfo(out *VipInfo) {
out.Type = in.Type
out.Status = in.Status
out.DueDate = in.DueDate
out.VipPayType = in.VipPayType
return
}
// DeepCopyFromVipInfo is an autogenerated deepcopy function, copying the receiver, writing into VipInfo.
func (out *VipReply) DeepCopyFromVipInfo(in *VipInfo) {
out.Type = in.Type
out.Status = in.Status
out.DueDate = in.DueDate
out.VipPayType = in.VipPayType
return
}
// DeepCopyAsVipInfo is an autogenerated deepcopy function, copying the receiver, creating a new VipInfo.
func (in *VipReply) DeepCopyAsVipInfo() *VipInfo {
if in == nil {
return nil
}
out := new(VipInfo)
in.DeepCopyAsIntoVipInfo(out)
return out
}

View File

@@ -0,0 +1,33 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["account3.go"],
importpath = "go-common/app/service/main/account/api/gorpc",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/account/api:go_default_library",
"//app/service/main/account/model:go_default_library",
"//library/net/rpc: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,152 @@
package client
import (
"context"
v1 "go-common/app/service/main/account/api"
"go-common/app/service/main/account/model"
"go-common/library/net/rpc"
)
const (
_info3 = "RPC.Info3"
_card3 = "RPC.Card3"
_infos3 = "RPC.Infos3"
_infosByName3 = "RPC.InfosByName3"
_cards3 = "RPC.Cards3"
_profile3 = "RPC.Profile3"
_profileStat3 = "RPC.ProfileWithStat3"
_addExp3 = "RPC.AddExp3"
_addMoral3 = "RPC.AddMoral3"
_relation3 = "RPC.Relation3"
_relations3 = "RPC.Relations3"
_attentions3 = "RPC.Attentions3"
_blacks3 = "RPC.Blacks3"
_richRelations3 = "RPC.RichRelations3"
)
const (
_appid = "account.service"
)
var (
_noArg = &struct{}{}
)
// Service3 for server client3
type Service3 struct {
client *rpc.Client2
}
// New3 for new struct Service2 obj
// DEPRECATED: Please use gRPC service instead.
func New3(c *rpc.ClientConfig) (s *Service3) {
s = &Service3{}
s.client = rpc.NewDiscoveryCli(_appid, c)
return
}
// Info3 receive ArgMid contains mid and real ip, then init user info.
// DEPRECATED: Please use gRPC service instead.
func (s *Service3) Info3(c context.Context, arg *model.ArgMid) (res *v1.Info, err error) {
res = new(v1.Info)
err = s.client.Call(c, _info3, arg, res)
return
}
// Card3 receive ArgMid contains mid and real ip, then init user card.
// DEPRECATED: Please use gRPC service instead.
func (s *Service3) Card3(c context.Context, arg *model.ArgMid) (res *v1.Card, err error) {
res = new(v1.Card)
err = s.client.Call(c, _card3, arg, res)
return
}
// Infos3 receive ArgMids contains mid and real ip, then init user info.
// DEPRECATED: Please use gRPC service instead.
func (s *Service3) Infos3(c context.Context, arg *model.ArgMids) (res map[int64]*v1.Info, err error) {
err = s.client.Call(c, _infos3, arg, &res)
return
}
// InfosByName3 receive ArgMids contains mid and real ip, then init user info.
// DEPRECATED: Please use gRPC service instead.
func (s *Service3) InfosByName3(c context.Context, arg *model.ArgNames) (res map[int64]*v1.Info, err error) {
err = s.client.Call(c, _infosByName3, arg, &res)
return
}
// Cards3 receive ArgMids contains mid and real ip, then init user card.
// DEPRECATED: Please use gRPC service instead.
func (s *Service3) Cards3(c context.Context, arg *model.ArgMids) (res map[int64]*v1.Card, err error) {
err = s.client.Call(c, _cards3, arg, &res)
return
}
// Profile3 get user profile.
// DEPRECATED: Please use gRPC service instead.
func (s *Service3) Profile3(c context.Context, arg *model.ArgMid) (res *v1.Profile, err error) {
res = new(v1.Profile)
err = s.client.Call(c, _profile3, arg, res)
return
}
// ProfileWithStat3 get user profile.
// DEPRECATED: Please use gRPC service instead.
func (s *Service3) ProfileWithStat3(c context.Context, arg *model.ArgMid) (res *model.ProfileStat, err error) {
res = new(model.ProfileStat)
err = s.client.Call(c, _profileStat3, arg, res)
return
}
// AddExp3 receive ArgExp contains mid, money and reason, then add exp for user.
// DEPRECATED: Please use gRPC service instead.
func (s *Service3) AddExp3(c context.Context, arg *model.ArgExp) (err error) {
err = s.client.Call(c, _addExp3, arg, _noArg)
return
}
// AddMoral3 receive ArgMoral contains mid, moral, oper, reason and remark, then add moral for user.
// DEPRECATED: Please use gRPC service instead.
func (s *Service3) AddMoral3(c context.Context, arg *model.ArgMoral) (err error) {
err = s.client.Call(c, _addMoral3, arg, _noArg)
return
}
// Relation3 get user friend relation.
// DEPRECATED: Please use gRPC service instead.
func (s *Service3) Relation3(c context.Context, arg *model.ArgRelation) (res *model.Relation, err error) {
res = new(model.Relation)
err = s.client.Call(c, _relation3, arg, res)
return
}
// Relations3 batch get user friend relation.
// DEPRECATED: Please use gRPC service instead.
func (s *Service3) Relations3(c context.Context, arg *model.ArgRelations) (res map[int64]*model.Relation, err error) {
err = s.client.Call(c, _relations3, arg, &res)
return
}
// Attentions3 get user attentions ,include followings and whispers.
// DEPRECATED: Please use gRPC service instead.
func (s *Service3) Attentions3(c context.Context, arg *model.ArgMid) (res []int64, err error) {
err = s.client.Call(c, _attentions3, arg, &res)
return
}
// Blacks3 get user black list.
// DEPRECATED: Please use gRPC service instead.
func (s *Service3) Blacks3(c context.Context, arg *model.ArgMid) (res map[int64]struct{}, err error) {
err = s.client.Call(c, _blacks3, arg, &res)
return
}
// RichRelations3 get relation between owner and mids.
// DEPRECATED: Please use gRPC service instead.
func (s *Service3) RichRelations3(c context.Context, arg *model.ArgRichRelation) (res map[int64]int, err error) {
err = s.client.Call(c, _richRelations3, arg, &res)
return
}

View File

@@ -0,0 +1,554 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: api.pb.go
// Package api is a generated GoMock package.
package api
import (
gomock "github.com/golang/mock/gomock"
context "golang.org/x/net/context"
grpc "google.golang.org/grpc"
reflect "reflect"
)
// MockAccountClient is a mock of AccountClient interface
type MockAccountClient struct {
ctrl *gomock.Controller
recorder *MockAccountClientMockRecorder
}
// MockAccountClientMockRecorder is the mock recorder for MockAccountClient
type MockAccountClientMockRecorder struct {
mock *MockAccountClient
}
// NewMockAccountClient creates a new mock instance
func NewMockAccountClient(ctrl *gomock.Controller) *MockAccountClient {
mock := &MockAccountClient{ctrl: ctrl}
mock.recorder = &MockAccountClientMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use
func (m *MockAccountClient) EXPECT() *MockAccountClientMockRecorder {
return m.recorder
}
// Info3 mocks base method
func (m *MockAccountClient) Info3(ctx context.Context, in *MidReq, opts ...grpc.CallOption) (*InfoReply, error) {
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "Info3", varargs...)
ret0, _ := ret[0].(*InfoReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Info3 indicates an expected call of Info3
func (mr *MockAccountClientMockRecorder) Info3(ctx, in interface{}, opts ...interface{}) *gomock.Call {
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Info3", reflect.TypeOf((*MockAccountClient)(nil).Info3), varargs...)
}
// Infos3 mocks base method
func (m *MockAccountClient) Infos3(ctx context.Context, in *MidsReq, opts ...grpc.CallOption) (*InfosReply, error) {
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "Infos3", varargs...)
ret0, _ := ret[0].(*InfosReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Infos3 indicates an expected call of Infos3
func (mr *MockAccountClientMockRecorder) Infos3(ctx, in interface{}, opts ...interface{}) *gomock.Call {
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Infos3", reflect.TypeOf((*MockAccountClient)(nil).Infos3), varargs...)
}
// InfosByName3 mocks base method
func (m *MockAccountClient) InfosByName3(ctx context.Context, in *NamesReq, opts ...grpc.CallOption) (*InfosReply, error) {
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "InfosByName3", varargs...)
ret0, _ := ret[0].(*InfosReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// InfosByName3 indicates an expected call of InfosByName3
func (mr *MockAccountClientMockRecorder) InfosByName3(ctx, in interface{}, opts ...interface{}) *gomock.Call {
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InfosByName3", reflect.TypeOf((*MockAccountClient)(nil).InfosByName3), varargs...)
}
// Card3 mocks base method
func (m *MockAccountClient) Card3(ctx context.Context, in *MidReq, opts ...grpc.CallOption) (*CardReply, error) {
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "Card3", varargs...)
ret0, _ := ret[0].(*CardReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Card3 indicates an expected call of Card3
func (mr *MockAccountClientMockRecorder) Card3(ctx, in interface{}, opts ...interface{}) *gomock.Call {
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Card3", reflect.TypeOf((*MockAccountClient)(nil).Card3), varargs...)
}
// Cards3 mocks base method
func (m *MockAccountClient) Cards3(ctx context.Context, in *MidsReq, opts ...grpc.CallOption) (*CardsReply, error) {
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "Cards3", varargs...)
ret0, _ := ret[0].(*CardsReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Cards3 indicates an expected call of Cards3
func (mr *MockAccountClientMockRecorder) Cards3(ctx, in interface{}, opts ...interface{}) *gomock.Call {
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Cards3", reflect.TypeOf((*MockAccountClient)(nil).Cards3), varargs...)
}
// Profile3 mocks base method
func (m *MockAccountClient) Profile3(ctx context.Context, in *MidReq, opts ...grpc.CallOption) (*ProfileReply, error) {
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "Profile3", varargs...)
ret0, _ := ret[0].(*ProfileReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Profile3 indicates an expected call of Profile3
func (mr *MockAccountClientMockRecorder) Profile3(ctx, in interface{}, opts ...interface{}) *gomock.Call {
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Profile3", reflect.TypeOf((*MockAccountClient)(nil).Profile3), varargs...)
}
// ProfileWithStat3 mocks base method
func (m *MockAccountClient) ProfileWithStat3(ctx context.Context, in *MidReq, opts ...grpc.CallOption) (*ProfileStatReply, error) {
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "ProfileWithStat3", varargs...)
ret0, _ := ret[0].(*ProfileStatReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ProfileWithStat3 indicates an expected call of ProfileWithStat3
func (mr *MockAccountClientMockRecorder) ProfileWithStat3(ctx, in interface{}, opts ...interface{}) *gomock.Call {
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProfileWithStat3", reflect.TypeOf((*MockAccountClient)(nil).ProfileWithStat3), varargs...)
}
// AddExp3 mocks base method
func (m *MockAccountClient) AddExp3(ctx context.Context, in *ExpReq, opts ...grpc.CallOption) (*ExpReply, error) {
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "AddExp3", varargs...)
ret0, _ := ret[0].(*ExpReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// AddExp3 indicates an expected call of AddExp3
func (mr *MockAccountClientMockRecorder) AddExp3(ctx, in interface{}, opts ...interface{}) *gomock.Call {
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddExp3", reflect.TypeOf((*MockAccountClient)(nil).AddExp3), varargs...)
}
// AddMoral3 mocks base method
func (m *MockAccountClient) AddMoral3(ctx context.Context, in *MoralReq, opts ...grpc.CallOption) (*MoralReply, error) {
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "AddMoral3", varargs...)
ret0, _ := ret[0].(*MoralReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// AddMoral3 indicates an expected call of AddMoral3
func (mr *MockAccountClientMockRecorder) AddMoral3(ctx, in interface{}, opts ...interface{}) *gomock.Call {
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddMoral3", reflect.TypeOf((*MockAccountClient)(nil).AddMoral3), varargs...)
}
// Relation3 mocks base method
func (m *MockAccountClient) Relation3(ctx context.Context, in *RelationReq, opts ...grpc.CallOption) (*RelationReply, error) {
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "Relation3", varargs...)
ret0, _ := ret[0].(*RelationReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Relation3 indicates an expected call of Relation3
func (mr *MockAccountClientMockRecorder) Relation3(ctx, in interface{}, opts ...interface{}) *gomock.Call {
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Relation3", reflect.TypeOf((*MockAccountClient)(nil).Relation3), varargs...)
}
// Attentions3 mocks base method
func (m *MockAccountClient) Attentions3(ctx context.Context, in *MidReq, opts ...grpc.CallOption) (*AttentionsReply, error) {
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "Attentions3", varargs...)
ret0, _ := ret[0].(*AttentionsReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Attentions3 indicates an expected call of Attentions3
func (mr *MockAccountClientMockRecorder) Attentions3(ctx, in interface{}, opts ...interface{}) *gomock.Call {
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Attentions3", reflect.TypeOf((*MockAccountClient)(nil).Attentions3), varargs...)
}
// Blacks3 mocks base method
func (m *MockAccountClient) Blacks3(ctx context.Context, in *MidReq, opts ...grpc.CallOption) (*BlacksReply, error) {
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "Blacks3", varargs...)
ret0, _ := ret[0].(*BlacksReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Blacks3 indicates an expected call of Blacks3
func (mr *MockAccountClientMockRecorder) Blacks3(ctx, in interface{}, opts ...interface{}) *gomock.Call {
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Blacks3", reflect.TypeOf((*MockAccountClient)(nil).Blacks3), varargs...)
}
// Relations3 mocks base method
func (m *MockAccountClient) Relations3(ctx context.Context, in *RelationsReq, opts ...grpc.CallOption) (*RelationsReply, error) {
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "Relations3", varargs...)
ret0, _ := ret[0].(*RelationsReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Relations3 indicates an expected call of Relations3
func (mr *MockAccountClientMockRecorder) Relations3(ctx, in interface{}, opts ...interface{}) *gomock.Call {
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Relations3", reflect.TypeOf((*MockAccountClient)(nil).Relations3), varargs...)
}
// RichRelations3 mocks base method
func (m *MockAccountClient) RichRelations3(ctx context.Context, in *RichRelationReq, opts ...grpc.CallOption) (*RichRelationsReply, error) {
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "RichRelations3", varargs...)
ret0, _ := ret[0].(*RichRelationsReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// RichRelations3 indicates an expected call of RichRelations3
func (mr *MockAccountClientMockRecorder) RichRelations3(ctx, in interface{}, opts ...interface{}) *gomock.Call {
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RichRelations3", reflect.TypeOf((*MockAccountClient)(nil).RichRelations3), varargs...)
}
// Vip3 mocks base method
func (m *MockAccountClient) Vip3(ctx context.Context, in *MidReq, opts ...grpc.CallOption) (*VipReply, error) {
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "Vip3", varargs...)
ret0, _ := ret[0].(*VipReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Vip3 indicates an expected call of Vip3
func (mr *MockAccountClientMockRecorder) Vip3(ctx, in interface{}, opts ...interface{}) *gomock.Call {
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Vip3", reflect.TypeOf((*MockAccountClient)(nil).Vip3), varargs...)
}
// Vips3 mocks base method
func (m *MockAccountClient) Vips3(ctx context.Context, in *MidsReq, opts ...grpc.CallOption) (*VipsReply, error) {
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "Vips3", varargs...)
ret0, _ := ret[0].(*VipsReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Vips3 indicates an expected call of Vips3
func (mr *MockAccountClientMockRecorder) Vips3(ctx, in interface{}, opts ...interface{}) *gomock.Call {
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Vips3", reflect.TypeOf((*MockAccountClient)(nil).Vips3), varargs...)
}
// MockAccountServer is a mock of AccountServer interface
type MockAccountServer struct {
ctrl *gomock.Controller
recorder *MockAccountServerMockRecorder
}
// MockAccountServerMockRecorder is the mock recorder for MockAccountServer
type MockAccountServerMockRecorder struct {
mock *MockAccountServer
}
// NewMockAccountServer creates a new mock instance
func NewMockAccountServer(ctrl *gomock.Controller) *MockAccountServer {
mock := &MockAccountServer{ctrl: ctrl}
mock.recorder = &MockAccountServerMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use
func (m *MockAccountServer) EXPECT() *MockAccountServerMockRecorder {
return m.recorder
}
// Info3 mocks base method
func (m *MockAccountServer) Info3(arg0 context.Context, arg1 *MidReq) (*InfoReply, error) {
ret := m.ctrl.Call(m, "Info3", arg0, arg1)
ret0, _ := ret[0].(*InfoReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Info3 indicates an expected call of Info3
func (mr *MockAccountServerMockRecorder) Info3(arg0, arg1 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Info3", reflect.TypeOf((*MockAccountServer)(nil).Info3), arg0, arg1)
}
// Infos3 mocks base method
func (m *MockAccountServer) Infos3(arg0 context.Context, arg1 *MidsReq) (*InfosReply, error) {
ret := m.ctrl.Call(m, "Infos3", arg0, arg1)
ret0, _ := ret[0].(*InfosReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Infos3 indicates an expected call of Infos3
func (mr *MockAccountServerMockRecorder) Infos3(arg0, arg1 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Infos3", reflect.TypeOf((*MockAccountServer)(nil).Infos3), arg0, arg1)
}
// InfosByName3 mocks base method
func (m *MockAccountServer) InfosByName3(arg0 context.Context, arg1 *NamesReq) (*InfosReply, error) {
ret := m.ctrl.Call(m, "InfosByName3", arg0, arg1)
ret0, _ := ret[0].(*InfosReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// InfosByName3 indicates an expected call of InfosByName3
func (mr *MockAccountServerMockRecorder) InfosByName3(arg0, arg1 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InfosByName3", reflect.TypeOf((*MockAccountServer)(nil).InfosByName3), arg0, arg1)
}
// Card3 mocks base method
func (m *MockAccountServer) Card3(arg0 context.Context, arg1 *MidReq) (*CardReply, error) {
ret := m.ctrl.Call(m, "Card3", arg0, arg1)
ret0, _ := ret[0].(*CardReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Card3 indicates an expected call of Card3
func (mr *MockAccountServerMockRecorder) Card3(arg0, arg1 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Card3", reflect.TypeOf((*MockAccountServer)(nil).Card3), arg0, arg1)
}
// Cards3 mocks base method
func (m *MockAccountServer) Cards3(arg0 context.Context, arg1 *MidsReq) (*CardsReply, error) {
ret := m.ctrl.Call(m, "Cards3", arg0, arg1)
ret0, _ := ret[0].(*CardsReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Cards3 indicates an expected call of Cards3
func (mr *MockAccountServerMockRecorder) Cards3(arg0, arg1 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Cards3", reflect.TypeOf((*MockAccountServer)(nil).Cards3), arg0, arg1)
}
// Profile3 mocks base method
func (m *MockAccountServer) Profile3(arg0 context.Context, arg1 *MidReq) (*ProfileReply, error) {
ret := m.ctrl.Call(m, "Profile3", arg0, arg1)
ret0, _ := ret[0].(*ProfileReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Profile3 indicates an expected call of Profile3
func (mr *MockAccountServerMockRecorder) Profile3(arg0, arg1 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Profile3", reflect.TypeOf((*MockAccountServer)(nil).Profile3), arg0, arg1)
}
// ProfileWithStat3 mocks base method
func (m *MockAccountServer) ProfileWithStat3(arg0 context.Context, arg1 *MidReq) (*ProfileStatReply, error) {
ret := m.ctrl.Call(m, "ProfileWithStat3", arg0, arg1)
ret0, _ := ret[0].(*ProfileStatReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ProfileWithStat3 indicates an expected call of ProfileWithStat3
func (mr *MockAccountServerMockRecorder) ProfileWithStat3(arg0, arg1 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProfileWithStat3", reflect.TypeOf((*MockAccountServer)(nil).ProfileWithStat3), arg0, arg1)
}
// AddExp3 mocks base method
func (m *MockAccountServer) AddExp3(arg0 context.Context, arg1 *ExpReq) (*ExpReply, error) {
ret := m.ctrl.Call(m, "AddExp3", arg0, arg1)
ret0, _ := ret[0].(*ExpReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// AddExp3 indicates an expected call of AddExp3
func (mr *MockAccountServerMockRecorder) AddExp3(arg0, arg1 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddExp3", reflect.TypeOf((*MockAccountServer)(nil).AddExp3), arg0, arg1)
}
// AddMoral3 mocks base method
func (m *MockAccountServer) AddMoral3(arg0 context.Context, arg1 *MoralReq) (*MoralReply, error) {
ret := m.ctrl.Call(m, "AddMoral3", arg0, arg1)
ret0, _ := ret[0].(*MoralReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// AddMoral3 indicates an expected call of AddMoral3
func (mr *MockAccountServerMockRecorder) AddMoral3(arg0, arg1 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddMoral3", reflect.TypeOf((*MockAccountServer)(nil).AddMoral3), arg0, arg1)
}
// Relation3 mocks base method
func (m *MockAccountServer) Relation3(arg0 context.Context, arg1 *RelationReq) (*RelationReply, error) {
ret := m.ctrl.Call(m, "Relation3", arg0, arg1)
ret0, _ := ret[0].(*RelationReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Relation3 indicates an expected call of Relation3
func (mr *MockAccountServerMockRecorder) Relation3(arg0, arg1 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Relation3", reflect.TypeOf((*MockAccountServer)(nil).Relation3), arg0, arg1)
}
// Attentions3 mocks base method
func (m *MockAccountServer) Attentions3(arg0 context.Context, arg1 *MidReq) (*AttentionsReply, error) {
ret := m.ctrl.Call(m, "Attentions3", arg0, arg1)
ret0, _ := ret[0].(*AttentionsReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Attentions3 indicates an expected call of Attentions3
func (mr *MockAccountServerMockRecorder) Attentions3(arg0, arg1 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Attentions3", reflect.TypeOf((*MockAccountServer)(nil).Attentions3), arg0, arg1)
}
// Blacks3 mocks base method
func (m *MockAccountServer) Blacks3(arg0 context.Context, arg1 *MidReq) (*BlacksReply, error) {
ret := m.ctrl.Call(m, "Blacks3", arg0, arg1)
ret0, _ := ret[0].(*BlacksReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Blacks3 indicates an expected call of Blacks3
func (mr *MockAccountServerMockRecorder) Blacks3(arg0, arg1 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Blacks3", reflect.TypeOf((*MockAccountServer)(nil).Blacks3), arg0, arg1)
}
// Relations3 mocks base method
func (m *MockAccountServer) Relations3(arg0 context.Context, arg1 *RelationsReq) (*RelationsReply, error) {
ret := m.ctrl.Call(m, "Relations3", arg0, arg1)
ret0, _ := ret[0].(*RelationsReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Relations3 indicates an expected call of Relations3
func (mr *MockAccountServerMockRecorder) Relations3(arg0, arg1 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Relations3", reflect.TypeOf((*MockAccountServer)(nil).Relations3), arg0, arg1)
}
// RichRelations3 mocks base method
func (m *MockAccountServer) RichRelations3(arg0 context.Context, arg1 *RichRelationReq) (*RichRelationsReply, error) {
ret := m.ctrl.Call(m, "RichRelations3", arg0, arg1)
ret0, _ := ret[0].(*RichRelationsReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// RichRelations3 indicates an expected call of RichRelations3
func (mr *MockAccountServerMockRecorder) RichRelations3(arg0, arg1 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RichRelations3", reflect.TypeOf((*MockAccountServer)(nil).RichRelations3), arg0, arg1)
}
// Vip3 mocks base method
func (m *MockAccountServer) Vip3(arg0 context.Context, arg1 *MidReq) (*VipReply, error) {
ret := m.ctrl.Call(m, "Vip3", arg0, arg1)
ret0, _ := ret[0].(*VipReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Vip3 indicates an expected call of Vip3
func (mr *MockAccountServerMockRecorder) Vip3(arg0, arg1 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Vip3", reflect.TypeOf((*MockAccountServer)(nil).Vip3), arg0, arg1)
}
// Vips3 mocks base method
func (m *MockAccountServer) Vips3(arg0 context.Context, arg1 *MidsReq) (*VipsReply, error) {
ret := m.ctrl.Call(m, "Vips3", arg0, arg1)
ret0, _ := ret[0].(*VipsReply)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Vips3 indicates an expected call of Vips3
func (mr *MockAccountServerMockRecorder) Vips3(arg0, arg1 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Vips3", reflect.TypeOf((*MockAccountServer)(nil).Vips3), arg0, arg1)
}

View File

@@ -0,0 +1,19 @@
package api
const (
_normalVip = 1 //月度大会员
_annualVip = 2 //年度会员
_statusAvailable = 1 //未过期
_statusFrozen = 2 //冻结
)
// IsValid decide the user is valid vip or not.
func (v *VipInfo) IsValid() bool {
return v.Status == _statusAvailable && (v.Type == _normalVip || v.Type == _annualVip)
}
// IsFrozen decide the user is frozen vip or not.
func (v *VipInfo) IsFrozen() bool {
return v.Status == _statusFrozen
}

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 = ["account-service-example.toml"],
importpath = "go-common/app/service/main/account/cmd",
tags = ["automanaged"],
deps = [
"//app/service/main/account/conf:go_default_library",
"//app/service/main/account/rpc/server:go_default_library",
"//app/service/main/account/server/grpc:go_default_library",
"//app/service/main/account/server/http:go_default_library",
"//app/service/main/account/service:go_default_library",
"//library/log:go_default_library",
"//library/net/rpc/warden:go_default_library",
"//library/net/rpc/warden/resolver/livezk: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,145 @@
# This is a TOML document. Boom.
version = "3.0.0"
user = "nobody"
pid = "/tmp/account-service.pid"
dir = "./"
perf = "127.0.0.1:6070"
[host]
passportURI = "http://uat-passport.bilibili.co"
vipURI = "http://uat-vip.bilibili.co"
[wardenServer]
addr = "0.0.0.0:6077"
timeout = "1s"
[liveZK]
addrs = ["172.18.33.131:2181", "172.18.33.168:2181", "172.18.33.169:2181"]
timeout = "1s"
[log]
dir = "/data/log/account-service/"
[log.agent]
taskID = "000069"
proto = "unixgram"
addr = "/var/run/lancer/collector.sock"
chan = 10240
[tracer]
family = "account-service"
proto = "unixgram"
addr = "/var/run/dapper-collect/dapper-collect.sock"
[bm]
[bm.inner]
addr = "0.0.0.0:6071"
timeout = "1s"
[bm.local]
addr = "0.0.0.0:6072"
timeout = "1s"
[rpcServer2]
discoverOff = false
token = "123456"
[[rpcServer2.servers]]
proto = "tcp"
addr = "0.0.0.0:6079"
weight = 10
group = "test"
[rpcServer2.zookeeper]
root = "/microservice/account-service-2/"
addrs = ["172.18.33.172:2181"]
timeout = "1s"
[httpClient]
[httpClient.read]
key = "7c7ac0db1aa05587"
secret = "9a6d62d93290c5f771ad381e9ca23f26"
dial = "1s"
timeout = "1s"
keepAlive = "60s"
timer = 1000
[httpClient.read.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[httpClient.read.url]
"http://api.bilibili.co/x/internal/v3/account/privacy" = {key = "7c7ac0db1aa05587", secret = "9a6d62d93290c5f771ad381e9ca23f26"}
[httpClient.write]
key = "7c7ac0db1aa05587"
secret = "9a6d62d93290c5f771ad381e9ca23f26"
dial = "1s"
timeout = "3s"
keepAlive = "60s"
timer = 1000
[httpClient.write.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[httpClient.privacy]
key = "7c7ac0db1aa05587"
secret = "9a6d62d93290c5f771ad381e9ca23f26"
dial = "1s"
timeout = "3s"
keepAlive = "60s"
timer = 1000
[httpClient.privacy.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[identify]
[identify.host]
auth = "http://passport.bilibili.com"
secret = "http://open.bilibili.com"
[identify.httpClient]
key = "7c7ac0db1aa05587"
secret = "9a6d62d93290c5f771ad381e9ca23f26"
dial = "30ms"
timeout = "100ms"
keepAlive = "60s"
[identify.httpClient.breaker]
window = "10s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[identify.httpClient.url]
"http://passport.bilibili.co/intranet/auth/tokenInfo" = {timeout = "100ms"}
"http://passport.bilibili.co/intranet/auth/cookieInfo" = {timeout = "100ms"}
"http://open.bilibili.co/api/getsecret" = {timeout = "500ms"}
[memcache]
accountExpire = "3s"
[memcache.account]
name = "account-service/account"
proto = "tcp"
addr = "172.16.33.54:11211"
active = 10
idle = 5
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "80s"
[relationRPC]
timeout = "1s"
[memberRPC]
timeout = "1s"
[coinRPC]
timeout = "1s"
[suitRPC]
timeout = "1s"
[appkeyFilter]
whiteKeys = ["all"]

View File

@@ -0,0 +1,78 @@
package main
import (
"context"
"flag"
"fmt"
"os"
"os/signal"
"syscall"
"time"
"go-common/app/service/main/account/conf"
rpc "go-common/app/service/main/account/rpc/server"
"go-common/app/service/main/account/server/grpc"
"go-common/app/service/main/account/server/http"
"go-common/app/service/main/account/service"
"go-common/library/log"
"go-common/library/net/rpc/warden"
"go-common/library/net/rpc/warden/resolver/livezk"
"go-common/library/net/trace"
)
const (
discoveryID = "account.service"
)
func main() {
flag.Parse()
if err := conf.Init(); err != nil {
log.Error("conf.Init() error(%v)", err)
panic(err)
}
log.Init(conf.Conf.Log)
defer log.Close()
trace.Init(conf.Conf.Tracer)
defer trace.Close()
log.Info("account-service start")
// service init
svr := service.New(conf.Conf)
rpcSvr := rpc.New(conf.Conf, svr)
// warden init
var wardensvr *warden.Server
if conf.Conf.WardenServer != nil {
var err error
if wardensvr, err = grpc.Start(conf.Conf, svr); err != nil {
panic(fmt.Sprintf("start warden server fail! %s", err))
}
cancel, err := livezk.Register(conf.Conf.LiveZK, conf.Conf.WardenServer.Addr, discoveryID)
if err != nil {
panic(fmt.Sprintf("register grpc service into live zookeeper error: %s", err))
}
defer cancel()
}
http.Init(conf.Conf, svr)
// signal handler
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
s := <-c
log.Info("account-service get a signal %s", s.String())
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
log.Info("account-service exit")
rpcSvr.Close()
if wardensvr != nil {
wardensvr.Shutdown(context.Background())
}
time.Sleep(time.Second)
return
case syscall.SIGHUP:
// TODO reload
default:
return
}
}
}

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 = ["conf.go"],
importpath = "go-common/app/service/main/account/conf",
tags = ["automanaged"],
deps = [
"//library/cache/memcache:go_default_library",
"//library/conf:go_default_library",
"//library/database/elastic:go_default_library",
"//library/log:go_default_library",
"//library/naming/livezk: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/time: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,131 @@
package conf
import (
"errors"
"flag"
"go-common/library/cache/memcache"
"go-common/library/conf"
"go-common/library/database/elastic"
"go-common/library/log"
"go-common/library/naming/livezk"
bm "go-common/library/net/http/blademaster"
v "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/time"
"github.com/BurntSushi/toml"
)
var (
confPath string
// Conf common conf
Conf = &Config{}
client *conf.Client
)
//Config config struct
type Config struct {
Host *Host
// log
Log *log.Config
// http
BM *bm.ServerConfig
RPCServer *rpc.ServerConfig
// http client
HTTPClient HTTPClient
// identify
// Identify *identify.Config
// mc
Memcache *Memcache
// tracer
Tracer *trace.Config
// rpc
MemberRPC *rpc.ClientConfig
MemberGRPC *warden.ClientConfig
RelationRPC *rpc.ClientConfig
CoinRPC *rpc.ClientConfig
SuitRPC *rpc.ClientConfig
BlockRPC *rpc.ClientConfig
// warden
WardenServer *warden.ServerConfig
LiveZK *livezk.Zookeeper
// Elastic config
Elastic *elastic.Config
Verify *v.Config
AppkeyFilter *AppkeyFilter
}
// AppkeyFilter is.
type AppkeyFilter struct {
Privacy []string
}
// Host host.
type Host struct {
AccountURI string
VipURI string
PassportURI string
}
// HTTPClient config
type HTTPClient struct {
Read *bm.ClientConfig
Write *bm.ClientConfig
Privacy *bm.ClientConfig
}
// Memcache config
type Memcache struct {
Account *memcache.Config
AccountExpire time.Duration
}
func configCenter() (err error) {
if client, err = conf.New(); err != nil {
panic(err)
}
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("<account-service.toml> is not exists")
}
if _, err = toml.Decode(s, &tmpConf); err != nil {
return errors.New("could not decode config, maybe <account-service.toml> file err")
}
*Conf = *tmpConf
return
}
func init() {
flag.StringVar(&confPath, "conf", "", "default config path")
}
// Init init config
func Init() (err error) {
if confPath == "" {
return configCenter()
}
_, err = toml.DecodeFile(confPath, &Conf)
return
}

View File

@@ -0,0 +1,83 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"dao.cache.go",
"dao.go",
"mc.go",
"passport.go",
"raw.go",
"realname.go",
"search.go",
"vip.go",
],
importpath = "go-common/app/service/main/account/dao",
tags = ["automanaged"],
deps = [
"//app/service/main/account/api:go_default_library",
"//app/service/main/account/conf:go_default_library",
"//app/service/main/account/model:go_default_library",
"//app/service/main/member/api/gorpc:go_default_library",
"//app/service/main/member/model:go_default_library",
"//app/service/main/member/model/block:go_default_library",
"//app/service/main/usersuit/model:go_default_library",
"//app/service/main/usersuit/rpc/client:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/database/elastic:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/metadata:go_default_library",
"//library/stat/prom:go_default_library",
"//library/sync/errgroup:go_default_library",
"//library/sync/pipeline/fanout:go_default_library",
"//library/xstr: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"],
)
go_test(
name = "go_default_test",
srcs = [
"dao.cache_test.go",
"dao_test.go",
"mc_test.go",
"passport_test.go",
"raw_test.go",
"search_test.go",
"vip_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/service/main/account/conf:go_default_library",
"//app/service/main/account/model:go_default_library",
"//app/service/main/member/model:go_default_library",
"//app/service/main/member/model/block:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/ecode:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)

View File

@@ -0,0 +1,376 @@
// Code generated by $GOPATH/src/go-common/app/tool/cache/gen. DO NOT EDIT.
/*
Package dao is a generated cache proxy package.
It is generated from:
type _cache interface {
Info(c context.Context, key int64) (*v1.Info, error)
//cache: -batch=50 -max_group=10 -batch_err=continue
Infos(c context.Context, keys []int64) (map[int64]*v1.Info, error)
Card(c context.Context, key int64) (*v1.Card, error)
//cache: -batch=50 -max_group=10 -batch_err=continue
Cards(c context.Context, keys []int64) (map[int64]*v1.Card, error)
Vip(c context.Context, key int64) (*v1.VipInfo, error)
//cache: -batch=50 -max_group=10 -batch_err=continue
Vips(c context.Context, keys []int64) (map[int64]*v1.VipInfo, error)
Profile(c context.Context, key int64) (*v1.Profile, error)
}
*/
package dao
import (
"context"
"sync"
v1 "go-common/app/service/main/account/api"
"go-common/library/stat/prom"
"go-common/library/sync/errgroup"
)
var _ _cache
// Info get data from cache if miss will call source method, then add to cache.
func (d *Dao) Info(c context.Context, id int64) (res *v1.Info, err error) {
addCache := true
res, err = d.CacheInfo(c, id)
if err != nil {
addCache = false
err = nil
}
if res != nil {
prom.CacheHit.Incr("Info")
return
}
prom.CacheMiss.Incr("Info")
res, err = d.RawInfo(c, id)
if err != nil {
return
}
miss := res
if !addCache {
return
}
d.cache.Do(c, func(ctx context.Context) {
d.AddCacheInfo(ctx, id, miss)
})
return
}
// Infos get data from cache if miss will call source method, then add to cache.
func (d *Dao) Infos(c context.Context, keys []int64) (res map[int64]*v1.Info, err error) {
if len(keys) == 0 {
return
}
addCache := true
res, err = d.CacheInfos(c, keys)
if err != nil {
addCache = false
res = nil
err = nil
}
var miss []int64
for _, key := range keys {
if (res == nil) || (res[key] == nil) {
miss = append(miss, key)
}
}
prom.CacheHit.Add("Infos", int64(len(keys)-len(miss)))
if len(miss) == 0 {
return
}
var missData map[int64]*v1.Info
missLen := len(miss)
prom.CacheMiss.Add("Infos", int64(missLen))
mutex := sync.Mutex{}
for i := 0; i < missLen; i += 50 * 10 {
var subKeys []int64
group := &errgroup.Group{}
ctx := c
if (i + 50*10) > missLen {
subKeys = miss[i:]
} else {
subKeys = miss[i : i+50*10]
}
missSubLen := len(subKeys)
for j := 0; j < missSubLen; j += 50 {
var ks []int64
if (j + 50) > missSubLen {
ks = subKeys[j:]
} else {
ks = subKeys[j : j+50]
}
group.Go(func() (err error) {
data, err := d.RawInfos(ctx, ks)
mutex.Lock()
for k, v := range data {
if missData == nil {
missData = make(map[int64]*v1.Info, len(keys))
}
missData[k] = v
}
mutex.Unlock()
return
})
}
err1 := group.Wait()
if err1 != nil {
err = err1
}
}
if res == nil {
res = make(map[int64]*v1.Info)
}
for k, v := range missData {
res[k] = v
}
if err != nil {
return
}
if !addCache {
return
}
d.cache.Do(c, func(ctx context.Context) {
d.AddCacheInfos(ctx, missData)
})
return
}
// Card cache: -batch=50 -max_group=10 -batch_err=continue
func (d *Dao) Card(c context.Context, id int64) (res *v1.Card, err error) {
addCache := true
res, err = d.CacheCard(c, id)
if err != nil {
addCache = false
err = nil
}
if res != nil {
prom.CacheHit.Incr("Card")
return
}
prom.CacheMiss.Incr("Card")
res, err = d.RawCard(c, id)
if err != nil {
return
}
miss := res
if !addCache {
return
}
d.cache.Do(c, func(ctx context.Context) {
d.AddCacheCard(ctx, id, miss)
})
return
}
// Cards get data from cache if miss will call source method, then add to cache.
func (d *Dao) Cards(c context.Context, keys []int64) (res map[int64]*v1.Card, err error) {
if len(keys) == 0 {
return
}
addCache := true
res, err = d.CacheCards(c, keys)
if err != nil {
addCache = false
res = nil
err = nil
}
var miss []int64
for _, key := range keys {
if (res == nil) || (res[key] == nil) {
miss = append(miss, key)
}
}
prom.CacheHit.Add("Cards", int64(len(keys)-len(miss)))
if len(miss) == 0 {
return
}
var missData map[int64]*v1.Card
missLen := len(miss)
prom.CacheMiss.Add("Cards", int64(missLen))
mutex := sync.Mutex{}
for i := 0; i < missLen; i += 50 * 10 {
var subKeys []int64
group := &errgroup.Group{}
ctx := c
if (i + 50*10) > missLen {
subKeys = miss[i:]
} else {
subKeys = miss[i : i+50*10]
}
missSubLen := len(subKeys)
for j := 0; j < missSubLen; j += 50 {
var ks []int64
if (j + 50) > missSubLen {
ks = subKeys[j:]
} else {
ks = subKeys[j : j+50]
}
group.Go(func() (err error) {
data, err := d.RawCards(ctx, ks)
mutex.Lock()
for k, v := range data {
if missData == nil {
missData = make(map[int64]*v1.Card, len(keys))
}
missData[k] = v
}
mutex.Unlock()
return
})
}
err1 := group.Wait()
if err1 != nil {
err = err1
}
}
if res == nil {
res = make(map[int64]*v1.Card)
}
for k, v := range missData {
res[k] = v
}
if err != nil {
return
}
if !addCache {
return
}
d.cache.Do(c, func(ctx context.Context) {
d.AddCacheCards(ctx, missData)
})
return
}
// Vip cache: -batch=50 -max_group=10 -batch_err=continue
func (d *Dao) Vip(c context.Context, id int64) (res *v1.VipInfo, err error) {
addCache := true
res, err = d.CacheVip(c, id)
if err != nil {
addCache = false
err = nil
}
if res != nil {
prom.CacheHit.Incr("Vip")
return
}
prom.CacheMiss.Incr("Vip")
res, err = d.RawVip(c, id)
if err != nil {
return
}
miss := res
if !addCache {
return
}
d.cache.Do(c, func(ctx context.Context) {
d.AddCacheVip(ctx, id, miss)
})
return
}
// Vips get data from cache if miss will call source method, then add to cache.
func (d *Dao) Vips(c context.Context, keys []int64) (res map[int64]*v1.VipInfo, err error) {
if len(keys) == 0 {
return
}
addCache := true
res, err = d.CacheVips(c, keys)
if err != nil {
addCache = false
res = nil
err = nil
}
var miss []int64
for _, key := range keys {
if (res == nil) || (res[key] == nil) {
miss = append(miss, key)
}
}
prom.CacheHit.Add("Vips", int64(len(keys)-len(miss)))
if len(miss) == 0 {
return
}
var missData map[int64]*v1.VipInfo
missLen := len(miss)
prom.CacheMiss.Add("Vips", int64(missLen))
mutex := sync.Mutex{}
for i := 0; i < missLen; i += 50 * 10 {
var subKeys []int64
group := &errgroup.Group{}
ctx := c
if (i + 50*10) > missLen {
subKeys = miss[i:]
} else {
subKeys = miss[i : i+50*10]
}
missSubLen := len(subKeys)
for j := 0; j < missSubLen; j += 50 {
var ks []int64
if (j + 50) > missSubLen {
ks = subKeys[j:]
} else {
ks = subKeys[j : j+50]
}
group.Go(func() (err error) {
data, err := d.RawVips(ctx, ks)
mutex.Lock()
for k, v := range data {
if missData == nil {
missData = make(map[int64]*v1.VipInfo, len(keys))
}
missData[k] = v
}
mutex.Unlock()
return
})
}
err1 := group.Wait()
if err1 != nil {
err = err1
}
}
if res == nil {
res = make(map[int64]*v1.VipInfo)
}
for k, v := range missData {
res[k] = v
}
if err != nil {
return
}
if !addCache {
return
}
d.cache.Do(c, func(ctx context.Context) {
d.AddCacheVips(ctx, missData)
})
return
}
// Profile cache: -batch=50 -max_group=10 -batch_err=continue
func (d *Dao) Profile(c context.Context, id int64) (res *v1.Profile, err error) {
addCache := true
res, err = d.CacheProfile(c, id)
if err != nil {
addCache = false
err = nil
}
if res != nil {
prom.CacheHit.Incr("Profile")
return
}
prom.CacheMiss.Incr("Profile")
res, err = d.RawProfile(c, id)
if err != nil {
return
}
miss := res
if !addCache {
return
}
d.cache.Do(c, func(ctx context.Context) {
d.AddCacheProfile(ctx, id, miss)
})
return
}

View File

@@ -0,0 +1,126 @@
package dao
import (
"context"
"testing"
"go-common/library/ecode"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoInfo(t *testing.T) {
var (
c = context.TODO()
id = int64(1405)
)
convey.Convey("Get base-info from cache if miss will call source method", t, func(ctx convey.C) {
res, err := d.Info(c, id)
ctx.Convey("Then err should be nil and res should be not nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoInfos(t *testing.T) {
var (
c = context.TODO()
keys = []int64{110020171, 110019841}
)
convey.Convey("Batch get base-infos from cache if miss will call source method", t, func(ctx convey.C) {
res, err := d.Infos(c, keys)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoCard(t *testing.T) {
var (
c = context.TODO()
id = int64(110020171)
)
convey.Convey("Get card-info from cache if miss will call source method", t, func(ctx convey.C) {
res, err := d.Card(c, id)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoCards(t *testing.T) {
var (
c = context.TODO()
keys = []int64{110020171, 110019841}
)
convey.Convey("Batch get card-info from cache if miss will call source method", t, func(ctx convey.C) {
res, err := d.Cards(c, keys)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoVip(t *testing.T) {
var (
c = context.TODO()
id = int64(110018881)
)
convey.Convey("Get vip-info from cache if miss will call source method", t, func(ctx convey.C) {
res, err := d.Vip(c, id)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoAutoRenewVip(t *testing.T) {
var (
c = context.TODO()
autoRenewMid = int64(27515232)
)
convey.Convey("Get vip-info from cache if miss will call source method", t, func(ctx convey.C) {
res, err := d.Vip(c, autoRenewMid)
t.Logf("data(%+v)", res)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoVips(t *testing.T) {
var (
c = context.TODO()
keys = []int64{1405, 2205}
)
convey.Convey("Batch get vip-info from cache if miss will call source method", t, func(ctx convey.C) {
res, err := d.Vips(c, keys)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoProfile(t *testing.T) {
var (
c = context.TODO()
id = int64(111003471)
)
convey.Convey("Get profile-info from cache if miss will call source method", t, func(ctx convey.C) {
res, err := d.Profile(c, id)
if err == ecode.Degrade {
err = nil
}
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,138 @@
package dao
import (
"context"
"fmt"
"strings"
"time"
v1 "go-common/app/service/main/account/api"
"go-common/app/service/main/account/conf"
member "go-common/app/service/main/member/api/gorpc"
mmodel "go-common/app/service/main/member/model"
usersuit "go-common/app/service/main/usersuit/rpc/client"
"go-common/library/cache/memcache"
"go-common/library/database/elastic"
bm "go-common/library/net/http/blademaster"
"go-common/library/sync/pipeline/fanout"
)
//go:generate $GOPATH/src/go-common/app/tool/cache/gen
type _cache interface {
Info(c context.Context, key int64) (*v1.Info, error)
//cache: -batch=50 -max_group=10 -batch_err=continue
Infos(c context.Context, keys []int64) (map[int64]*v1.Info, error)
Card(c context.Context, key int64) (*v1.Card, error)
//cache: -batch=50 -max_group=10 -batch_err=continue
Cards(c context.Context, keys []int64) (map[int64]*v1.Card, error)
Vip(c context.Context, key int64) (*v1.VipInfo, error)
//cache: -batch=50 -max_group=10 -batch_err=continue
Vips(c context.Context, keys []int64) (map[int64]*v1.VipInfo, error)
Profile(c context.Context, key int64) (*v1.Profile, error)
}
const (
_nameURL = "/api/member/getInfoByName"
_vipInfoURL = "/internal/v1/user/%d"
_vipMultiInfoURL = "/internal/v1/user/list"
_passportDetailURL = "/intranet/acc/detail"
_passportProfile = "/intranet/acc/queryByMid"
)
// Dao dao.
type Dao struct {
// memcache
mc *memcache.Pool
mcExpire int32
// cache async save
cache *fanout.Fanout
// rpc
mRPC *member.Service
suitRPC *usersuit.Service2
// http
httpR *bm.Client
httpW *bm.Client
httpP *bm.Client
// api
detailURI string
profileURI string
nameURI string
// vip api
vipInfoURI string
vipMultiInfoURI string
//es
es *elastic.Elastic
}
// New new a dao.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
// account memcache
mc: memcache.NewPool(c.Memcache.Account),
mcExpire: int32(time.Duration(c.Memcache.AccountExpire) / time.Second),
// cache chan
cache: fanout.New("accountServiceCache", fanout.Worker(1), fanout.Buffer(1024)),
// rpc
// mRPC: member.New(c.MemberRPC),
mRPC: member.New(c.MemberRPC),
suitRPC: usersuit.New(c.SuitRPC),
// http read&write client
httpR: bm.NewClient(c.HTTPClient.Read),
httpW: bm.NewClient(c.HTTPClient.Write),
httpP: bm.NewClient(c.HTTPClient.Privacy),
es: elastic.NewElastic(c.Elastic),
// api
nameURI: c.Host.AccountURI + _nameURL,
// vip api
vipInfoURI: c.Host.VipURI + _vipInfoURL,
vipMultiInfoURI: c.Host.VipURI + _vipMultiInfoURL,
//passport
detailURI: c.Host.PassportURI + _passportDetailURL,
profileURI: c.Host.PassportURI + _passportProfile,
}
return
}
// LevelExp get member level exp.
func (d *Dao) LevelExp(c context.Context, mid int64) (lexp *mmodel.LevelInfo, err error) {
lexp, err = d.mRPC.Exp(c, &mmodel.ArgMid2{Mid: mid})
return
}
// AddMoral add moral.
func (d *Dao) AddMoral(c context.Context, arg *mmodel.ArgUpdateMoral) (err error) {
return d.mRPC.AddMoral(c, arg)
}
// UpdateExp update exp.
func (d *Dao) UpdateExp(c context.Context, arg *mmodel.ArgAddExp) error {
return d.mRPC.UpdateExp(c, arg)
}
// Ping check connection success.
func (d *Dao) Ping(c context.Context) (err error) {
conn := d.mc.Get(c)
err = conn.Set(&memcache.Item{
Key: "ping",
Value: []byte("pong"),
})
conn.Close()
return
}
// Close close memcache resource.
func (d *Dao) Close() {
if d.mc != nil {
d.mc.Close()
}
}
func fullImage(mid int64, image string) string {
if len(image) == 0 {
return ""
}
if strings.HasPrefix(image, "http://") {
return image
}
return fmt.Sprintf("http://i%d.hdslb.com%s", mid%3, image)
}

View File

@@ -0,0 +1,35 @@
package dao
import (
"flag"
"go-common/app/service/main/account/conf"
"os"
"testing"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.account.account-service")
flag.Set("conf_token", "187c672d88909792e47cd2fbc9ccc070")
flag.Set("tree_id", "2318")
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/account-service-example.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
m.Run()
os.Exit(0)
}

View File

@@ -0,0 +1,364 @@
package dao
import (
"context"
"strconv"
"github.com/pkg/errors"
v1 "go-common/app/service/main/account/api"
mc "go-common/library/cache/memcache"
)
const (
_prefixInfo = "i3_"
_prefixCard = "c3_"
_prefixVip = "v3_"
_prefixProfile = "p3_"
)
func keyInfo(mid int64) string {
return _prefixInfo + strconv.FormatInt(mid, 10)
}
func keyCard(mid int64) string {
return _prefixCard + strconv.FormatInt(mid, 10)
}
func keyVip(mid int64) string {
return _prefixVip + strconv.FormatInt(mid, 10)
}
func keyProfile(mid int64) string {
return _prefixProfile + strconv.FormatInt(mid, 10)
}
// CacheInfo get account info from cache.
func (d *Dao) CacheInfo(c context.Context, mid int64) (v *v1.Info, err error) {
key := keyInfo(mid)
conn := d.mc.Get(c)
defer conn.Close()
r, err := conn.Get(key)
if err != nil {
if err == mc.ErrNotFound {
err = nil
return
}
err = errors.Wrap(err, "dao cache info")
return
}
v = &v1.Info{}
if err = conn.Scan(r, v); err != nil {
err = errors.Wrap(err, "dao cache scan info")
}
return
}
// AddCacheInfo set account info into cache.
func (d *Dao) AddCacheInfo(c context.Context, mid int64, v *v1.Info) (err error) {
item := &mc.Item{
Key: keyInfo(mid),
Object: v,
Flags: mc.FlagProtobuf,
Expiration: d.mcExpire,
}
conn := d.mc.Get(c)
err = conn.Set(item)
conn.Close()
if err != nil {
err = errors.Wrap(err, "dao add info cache")
}
return
}
// CacheInfos multi get account info from cache.
func (d *Dao) CacheInfos(c context.Context, mids []int64) (res map[int64]*v1.Info, err error) {
keys := make([]string, 0, len(mids))
keyMidMap := make(map[string]int64, len(mids))
for _, mid := range mids {
key := keyInfo(mid)
if _, ok := keyMidMap[key]; !ok {
// duplicate mid
keyMidMap[key] = mid
keys = append(keys, key)
}
}
conn := d.mc.Get(c)
defer conn.Close()
rs, err := conn.GetMulti(keys)
if err != nil {
if err == mc.ErrNotFound {
err = nil
return
}
err = errors.Wrap(err, "dao infos cache")
return
}
res = make(map[int64]*v1.Info, len(mids))
for _, r := range rs {
ai := &v1.Info{}
conn.Scan(r, ai)
res[ai.Mid] = ai
}
return
}
// AddCacheInfos set account infos cache.
func (d *Dao) AddCacheInfos(c context.Context, im map[int64]*v1.Info) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
for _, i := range im {
item := &mc.Item{
Key: keyInfo(i.Mid),
Object: i,
Flags: mc.FlagProtobuf,
Expiration: d.mcExpire,
}
err = conn.Set(item)
if err != nil {
err = errors.Wrap(err, "dao add infos cache")
}
}
return
}
// CacheCard get account card from cache.
func (d *Dao) CacheCard(c context.Context, mid int64) (v *v1.Card, err error) {
key := keyCard(mid)
conn := d.mc.Get(c)
defer conn.Close()
r, err := conn.Get(key)
if err != nil {
if err == mc.ErrNotFound {
err = nil
return
}
err = errors.Wrap(err, "dao cache card")
return
}
v = &v1.Card{}
if err = conn.Scan(r, v); err != nil {
err = errors.Wrap(err, "dao cache scan card")
}
return
}
// AddCacheCard set account card into cache.
func (d *Dao) AddCacheCard(c context.Context, mid int64, v *v1.Card) (err error) {
item := &mc.Item{
Key: keyCard(mid),
Object: v,
Flags: mc.FlagProtobuf,
Expiration: d.mcExpire,
}
conn := d.mc.Get(c)
err = conn.Set(item)
conn.Close()
if err != nil {
err = errors.Wrap(err, "dao add card cache")
}
return
}
// CacheCards multi get account cards from cache.
func (d *Dao) CacheCards(c context.Context, mids []int64) (res map[int64]*v1.Card, err error) {
keys := make([]string, 0, len(mids))
keyMidMap := make(map[string]int64, len(mids))
for _, mid := range mids {
key := keyCard(mid)
if _, ok := keyMidMap[key]; !ok {
// duplicate mid
keyMidMap[key] = mid
keys = append(keys, key)
}
}
conn := d.mc.Get(c)
defer conn.Close()
rs, err := conn.GetMulti(keys)
if err != nil {
if err == mc.ErrNotFound {
err = nil
return
}
err = errors.Wrap(err, "dao cards cache")
return
}
res = make(map[int64]*v1.Card, len(mids))
for _, r := range rs {
ai := &v1.Card{}
conn.Scan(r, ai)
res[ai.Mid] = ai
}
return
}
// AddCacheCards set account cards cache.
func (d *Dao) AddCacheCards(c context.Context, cm map[int64]*v1.Card) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
for _, card := range cm {
item := &mc.Item{
Key: keyCard(card.Mid),
Object: card,
Flags: mc.FlagProtobuf,
Expiration: d.mcExpire,
}
err = conn.Set(item)
if err != nil {
err = errors.Wrap(err, "dao add cards cache")
}
}
return
}
// CacheVip get vip cache.
func (d *Dao) CacheVip(c context.Context, mid int64) (v *v1.VipInfo, err error) {
key := keyVip(mid)
conn := d.mc.Get(c)
defer conn.Close()
r, err := conn.Get(key)
if err != nil {
if err == mc.ErrNotFound {
err = nil
return
}
err = errors.Wrap(err, "dao vip cache")
return
}
v = new(v1.VipInfo)
if err = conn.Scan(r, v); err != nil {
err = errors.Wrap(err, "dao vip cache scan")
}
return
}
// AddCacheVip set vip cache.
func (d *Dao) AddCacheVip(c context.Context, mid int64, v *v1.VipInfo) (err error) {
conn := d.mc.Get(c)
conn.Set(&mc.Item{
Key: keyVip(mid),
Object: v,
Flags: mc.FlagProtobuf,
Expiration: d.mcExpire,
})
conn.Close()
if err != nil {
err = errors.Wrap(err, "dao vip add cache")
}
return
}
// CacheVips multi get account cards from cache.
func (d *Dao) CacheVips(c context.Context, mids []int64) (res map[int64]*v1.VipInfo, err error) {
keys := make([]string, 0, len(mids))
keyMidMap := make(map[string]int64, len(mids))
for _, mid := range mids {
key := keyVip(mid)
if _, ok := keyMidMap[key]; !ok {
// duplicate mid
keyMidMap[key] = mid
keys = append(keys, key)
}
}
conn := d.mc.Get(c)
defer conn.Close()
rs, err := conn.GetMulti(keys)
if err != nil {
if err == mc.ErrNotFound {
err = nil
return
}
err = errors.Wrap(err, "dao vips cache")
return
}
res = make(map[int64]*v1.VipInfo, len(mids))
for _, r := range rs {
ai := &v1.VipInfo{}
conn.Scan(r, ai)
res[keyMidMap[r.Key]] = ai
}
return
}
// AddCacheVips set account vips cache.
func (d *Dao) AddCacheVips(c context.Context, vm map[int64]*v1.VipInfo) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
for mid, v := range vm {
item := &mc.Item{
Key: keyVip(mid),
Object: v,
Flags: mc.FlagProtobuf,
Expiration: d.mcExpire,
}
err = conn.Set(item)
if err != nil {
err = errors.Wrap(err, "dao add vips cache")
}
}
return
}
// CacheProfile get profile cache.
func (d *Dao) CacheProfile(c context.Context, mid int64) (v *v1.Profile, err error) {
key := keyProfile(mid)
conn := d.mc.Get(c)
defer conn.Close()
r, err := conn.Get(key)
if err != nil {
if err == mc.ErrNotFound {
err = nil
return
}
err = errors.Wrap(err, "dao profile cache")
return
}
v = new(v1.Profile)
if err = conn.Scan(r, v); err != nil {
err = errors.Wrap(err, "dao profile cache scan")
}
return
}
// AddCacheProfile set profile cache.
func (d *Dao) AddCacheProfile(c context.Context, mid int64, v *v1.Profile) (err error) {
conn := d.mc.Get(c)
conn.Set(&mc.Item{
Key: keyProfile(mid),
Object: v,
Flags: mc.FlagProtobuf,
Expiration: d.mcExpire,
})
conn.Close()
if err != nil {
err = errors.Wrap(err, "dao profile add cache")
}
return
}
// DelCache delete cache.
func (d *Dao) DelCache(c context.Context, mid int64) []error {
conn := d.mc.Get(c)
errs := make([]error, 0, 5)
if err := conn.Delete(keyInfo(mid)); err != nil {
errs = append(errs, errors.Wrap(err, keyInfo(mid)))
}
if err := conn.Delete(keyCard(mid)); err != nil {
errs = append(errs, errors.Wrap(err, keyCard(mid)))
}
if err := conn.Delete(keyVip(mid)); err != nil {
errs = append(errs, errors.Wrap(err, keyVip(mid)))
}
if err := conn.Delete(keyProfile(mid)); err != nil {
errs = append(errs, errors.Wrap(err, keyProfile(mid)))
}
if err := conn.Close(); err != nil {
errs = append(errs, errors.Wrap(err, "conn close"))
}
d.cache.Do(c, func(ctx context.Context) {
d.Info(ctx, mid)
d.Card(ctx, mid)
d.Vip(ctx, mid)
d.Profile(ctx, mid)
})
return errs
}

View File

@@ -0,0 +1,397 @@
package dao
import (
"context"
"testing"
"go-common/app/service/main/account/model"
mc "go-common/library/cache/memcache"
"github.com/smartystreets/goconvey/convey"
)
func TestDaokeyInfo(t *testing.T) {
var (
mid = int64(2205)
)
convey.Convey("Generate info-key", t, func(ctx convey.C) {
p1 := keyInfo(mid)
ctx.Convey("Then info-key should contains info prefix.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldContainSubstring, _prefixInfo)
})
})
}
func TestDaokeyCard(t *testing.T) {
var (
mid = int64(2205)
)
convey.Convey("Generate card-info-key", t, func(ctx convey.C) {
p1 := keyCard(mid)
ctx.Convey("Then card-info-key should contains card prefix.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldContainSubstring, _prefixCard)
})
})
}
func TestDaokeyVip(t *testing.T) {
var (
mid = int64(2205)
)
convey.Convey("Generate vip-info-key", t, func(ctx convey.C) {
p1 := keyVip(mid)
ctx.Convey("Then vip-info-key should contains vip prefix.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldContainSubstring, _prefixVip)
})
})
}
func TestDaokeyProfile(t *testing.T) {
var (
mid = int64(2205)
)
convey.Convey("Generate profile-key", t, func(ctx convey.C) {
p1 := keyProfile(mid)
ctx.Convey("Then profile-key should contains profile prefix.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldContainSubstring, _prefixProfile)
})
})
}
func TestDaoCacheInfo(t *testing.T) {
var (
c = context.TODO()
mid = int64(2205)
)
convey.Convey("Get member base-info from cache", t, func(ctx convey.C) {
_, err := d.CacheInfo(c, mid)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoAddCacheInfo(t *testing.T) {
var (
c = context.TODO()
mid = int64(2205)
v = &model.Info{
Mid: 2205,
Name: "Haha",
Sex: "男",
Face: "http://i1.hdslb.com/bfs/face/4b12a3e65d344e31a11e6425767863019738c7bc.jpg",
Sign: "来电只是",
Rank: 500,
}
)
convey.Convey("Add member base-info to cache", t, func(ctx convey.C) {
err := d.AddCacheInfo(c, mid, v)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoCacheInfos(t *testing.T) {
var (
c = context.TODO()
mids = []int64{2205, 2805}
)
convey.Convey("Batch get members' base-info", t, func(ctx convey.C) {
res, err := d.CacheInfos(c, mids)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoAddCacheInfos(t *testing.T) {
var (
c = context.TODO()
im = map[int64]*model.Info{
2205: {
Mid: 2205,
Name: "板桥真菜",
Sex: "2",
Face: "/bfs/face/e93098c3aa8c18b24001740e707ebe2df180f5f7.jpg",
Sign: "没有",
Rank: 10000,
},
3305: {
Mid: 3305,
Name: "FGNB",
Sex: "1",
Face: "/bfs/face/e93098c3aa8c18b24001740e707ebe2df180f5f7.jpg",
Sign: "啦啦",
Rank: 5000,
},
}
)
convey.Convey("Batch set members' base-info to cache", t, func(ctx convey.C) {
err := d.AddCacheInfos(c, im)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoCacheCard(t *testing.T) {
var (
c = context.TODO()
mid = int64(2805)
)
convey.Convey("Get card-info from cache", t, func(ctx convey.C) {
_, err := d.CacheCard(c, mid)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoAddCacheCard(t *testing.T) {
var (
c = context.TODO()
mid = int64(2805)
v = &model.Card{
Mid: 10920044,
Name: "冠冠爱看书",
Sex: "男",
Face: "http://i1.hdslb.com/bfs/face/4b12a3e65d344e31a11e6425767863019738c7bc.jpg",
Sign: "来点字",
Rank: 10000,
Level: 5, //等级
Silence: 0,
Vip: model.VipInfo{
Type: 2,
Status: 1,
DueDate: 162930240,
},
Pendant: model.PendantInfo{
Pid: 159,
Name: "2018拜年祭",
Image: "http://i2.hdslb.com/bfs/face/aace621fa64a698f2ca94d13645a26e9a7a99ed2.png",
Expire: 1566367231,
},
Nameplate: model.NameplateInfo{
Nid: 7,
Name: "见习搬运工",
Image: "http://i1.hdslb.com/bfs/face/8478fb7c54026cd47f09daa493a1b1683113a90d.png",
ImageSmall: "http://i0.hdslb.com/bfs/face/50eef47c3a30a75659d3cc298cfb09031d1a2ce5.png",
Level: "普通勋章",
Condition: "转载视频",
},
}
)
convey.Convey("Add card-info to cache", t, func(ctx convey.C) {
err := d.AddCacheCard(c, mid, v)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoCacheCards(t *testing.T) {
var (
c = context.TODO()
mids = []int64{110017381, 110019061, 110020081}
)
convey.Convey("Batch get card-info from cache", t, func(ctx convey.C) {
res, err := d.CacheCards(c, mids)
ctx.Convey("Then err should be nil and res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoAddCacheCards(t *testing.T) {
var (
c = context.TODO()
card1 = &model.Card{
Mid: 10920044,
Name: "冠冠爱看书",
Sex: "男",
Face: "http://i1.hdslb.com/bfs/face/4b12a3e65d344e31a11e6425767863019738c7bc.jpg",
Sign: "来点字",
Rank: 10000,
Level: 5, //等级
Silence: 0,
Vip: model.VipInfo{
Type: 2,
Status: 1,
DueDate: 162930240,
},
Pendant: model.PendantInfo{
Pid: 159,
Name: "2018拜年祭",
Image: "http://i2.hdslb.com/bfs/face/aace621fa64a698f2ca94d13645a26e9a7a99ed2.png",
Expire: 1566367231,
},
Nameplate: model.NameplateInfo{
Nid: 7,
Name: "见习搬运工",
Image: "http://i1.hdslb.com/bfs/face/8478fb7c54026cd47f09daa493a1b1683113a90d.png",
ImageSmall: "http://i0.hdslb.com/bfs/face/50eef47c3a30a75659d3cc298cfb09031d1a2ce5.png",
Level: "普通勋章",
Condition: "转载视频",
},
}
cm = map[int64]*model.Card{
card1.Mid: card1,
}
)
convey.Convey("Batch set card-info to cache", t, func(ctx convey.C) {
err := d.AddCacheCards(c, cm)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoCacheVip(t *testing.T) {
var (
c = context.TODO()
mid = int64(110003731)
)
convey.Convey("Get vip-info from cache", t, func(ctx convey.C) {
_, err := d.CacheVip(c, mid)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoAddCacheVip(t *testing.T) {
var (
c = context.TODO()
mid = int64(110003731)
v = &model.VipInfo{
Type: 2,
Status: 1,
DueDate: 162930240,
}
)
convey.Convey("Set vip-cache to cache", t, func(ctx convey.C) {
err := d.AddCacheVip(c, mid, v)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoCacheVips(t *testing.T) {
var (
c = context.TODO()
mids = []int64{110002741, 110004601, 110006251}
)
convey.Convey("Batch get vip-infos from cache", t, func(ctx convey.C) {
res, err := d.CacheVips(c, mids)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoAddCacheVips(t *testing.T) {
var (
c = context.TODO()
vm = map[int64]*model.VipInfo{
110007391: {
Type: 2,
Status: 1,
DueDate: 162930240,
},
110010271: {
Type: 2,
Status: 1,
DueDate: 162930240,
},
}
)
convey.Convey("Batch set vip-infos to cache", t, func(ctx convey.C) {
err := d.AddCacheVips(c, vm)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoCacheProfile(t *testing.T) {
var (
c = context.TODO()
mid = int64(110011831)
)
convey.Convey("Get profile-info from cache", t, func(ctx convey.C) {
_, err := d.CacheProfile(c, mid)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoAddCacheProfile(t *testing.T) {
var (
c = context.TODO()
mid = int64(110011951)
v = &model.Profile{
Mid: 10920044,
Name: "冠冠爱看书",
Sex: "男",
Face: "http://i1.hdslb.com/bfs/face/4b12a3e65d344e31a11e6425767863019738c7bc.jpg",
Sign: "来点字",
Rank: 10000,
Level: 5,
JoinTime: 1503296503,
Moral: 71,
Silence: 0,
EmailStatus: 1,
TelStatus: 1,
Identification: 0,
Vip: model.VipInfo{
Type: 2,
Status: 1,
DueDate: 1629302400000,
},
Pendant: model.PendantInfo{
Pid: 159,
Name: "2018拜年祭",
Image: "http://i2.hdslb.com/bfs/face/aace621fa64a698f2ca94d13645a26e9a7a99ed2.png",
Expire: 1551413548,
},
Nameplate: model.NameplateInfo{
Nid: 7,
Name: "见习搬运工",
Image: "http://i1.hdslb.com/bfs/face/8478fb7c54026cd47f09daa493a1b1683113a90d.png",
ImageSmall: "http://i0.hdslb.com/bfs/face/50eef47c3a30a75659d3cc298cfb09031d1a2ce5.png",
Level: "普通勋章",
Condition: "转载视频投稿通过总数>=10",
},
}
)
convey.Convey("Set profile-info to cache", t, func(ctx convey.C) {
err := d.AddCacheProfile(c, mid, v)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoDelCache(t *testing.T) {
var (
c = context.TODO()
mid = int64(110014081)
)
convey.Convey("Delete member's cache", t, func(ctx convey.C) {
errs := d.DelCache(c, mid)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
for _, e := range errs {
if e != mc.ErrNotFound {
ctx.So(e, convey.ShouldBeNil)
}
}
})
})
}

View File

@@ -0,0 +1,64 @@
package dao
import (
"context"
"net/url"
"strconv"
"go-common/app/service/main/account/model"
"go-common/library/ecode"
"go-common/library/net/metadata"
"github.com/pkg/errors"
)
// PassportDetail get detail.
func (d *Dao) PassportDetail(c context.Context, mid int64) (res *model.PassportDetail, err error) {
ip := metadata.String(c, metadata.RemoteIP)
params := url.Values{}
// params.Set("access_key", accessKey)
params.Set("mid", strconv.FormatInt(mid, 10))
var resp struct {
Code int `json:"code"`
Info *model.PassportDetail `json:"data"`
}
req, err := d.httpR.NewRequest("GET", d.detailURI, ip, params)
if err != nil {
err = errors.Wrap(err, "dao passport detail")
return
}
// req.Header.Set("Cookie", cookie)
req.Header.Set("X-BACKEND-BILI-REAL-IP", ip)
if err = d.httpR.Do(c, req, &resp); err != nil {
err = errors.Wrap(err, "dao passport detail")
return
}
if resp.Code != 0 {
err = ecode.Int(resp.Code)
err = errors.Wrap(err, "dao passport detail")
return
}
res = resp.Info
return
}
// PassportProfile is.
func (d *Dao) PassportProfile(c context.Context, mid int64, ip string) (res *model.PassportProfile, err error) {
params := url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
var resp struct {
Code int `json:"code"`
Data *model.PassportProfile `json:"data"`
}
if err = d.httpP.Get(c, d.profileURI, ip, params, &resp); err != nil {
err = errors.Wrap(err, "dao passport profile")
return nil, err
}
if resp.Code != 0 {
err = ecode.Int(resp.Code)
err = errors.WithStack(err)
return
}
res = resp.Data
return
}

View File

@@ -0,0 +1,22 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoPassportDetail(t *testing.T) {
var (
c = context.TODO()
mid = int64(110016931)
)
convey.Convey("Get passport detail", t, func(ctx convey.C) {
res, err := d.PassportDetail(c, mid)
ctx.Convey("Then err should be nil and res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,389 @@
package dao
import (
"context"
v1 "go-common/app/service/main/account/api"
"go-common/app/service/main/account/model"
mml "go-common/app/service/main/member/model"
bml "go-common/app/service/main/member/model/block"
sml "go-common/app/service/main/usersuit/model"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/sync/errgroup"
"github.com/pkg/errors"
)
// RawInfo raw info.
func (d *Dao) RawInfo(c context.Context, mid int64) (res *v1.Info, err error) {
var base *mml.BaseInfo
if base, err = d.mRPC.Base(c, &mml.ArgMemberMid{Mid: mid}); err != nil {
// err = errors.Wrap(err, "dao raw info")
// err = errors.WithStack(err)
return
}
res = &v1.Info{
Mid: base.Mid,
Name: base.Name,
Sex: base.SexStr(),
Face: base.Face,
Sign: base.Sign,
Rank: int32(base.Rank),
}
return
}
// RawInfos raw infos.
func (d *Dao) RawInfos(c context.Context, mids []int64) (res map[int64]*v1.Info, err error) {
var bm map[int64]*mml.BaseInfo
if bm, err = d.mRPC.Bases(c, &mml.ArgMemberMids{Mids: mids}); err != nil {
// err = errors.Wrap(err, "dao raw info")
err = errors.WithStack(err)
return
}
res = map[int64]*v1.Info{}
for _, base := range bm {
i := &v1.Info{
Mid: base.Mid,
Name: base.Name,
Sex: base.SexStr(),
Face: base.Face,
Sign: base.Sign,
Rank: int32(base.Rank),
}
res[i.Mid] = i
}
return
}
// RawCard get card by mid.
func (d *Dao) RawCard(c context.Context, mid int64) (res *v1.Card, err error) {
eg, _ := errgroup.WithContext(c)
var mb *mml.Member
eg.Go(func() (e error) {
if mb, e = d.mRPC.Member(c, &mml.ArgMemberMid{Mid: mid}); e != nil {
log.Error("d.mRPC.Member(%d) err(%v)", mid, e)
// e = ecode.Degrade
}
return
})
var medal *sml.MedalInfo
eg.Go(func() (e error) {
if medal, e = d.suitRPC.MedalActivated(c, &sml.ArgMid{Mid: mid}); e != nil {
log.Error("s.suitRPC.MedalActivated(%d) err %v", mid, e)
e = ecode.Degrade
}
return
})
var block *bml.RPCResInfo
eg.Go(func() (e error) {
if block, e = d.mRPC.BlockInfo(c, &bml.RPCArgInfo{MID: mid}); e != nil {
log.Error("d.block.BlockInfo(%d) err %v", mid, e)
e = ecode.Degrade
}
return
})
var vip *v1.VipInfo
eg.Go(func() (e error) {
if vip, e = d.Vip(c, mid); e != nil {
log.Error("d.Vip(%d) err(%v)", mid, e)
e = ecode.Degrade
}
return
})
var pendant *sml.PendantEquip
eg.Go(func() (e error) {
if pendant, e = d.suitRPC.Equipment(c, &sml.ArgEquipment{Mid: mid}); e != nil {
log.Error("d.suitRPC.Equipment(%d) err(%v)", mid, e)
e = ecode.Degrade
}
return
})
if err = eg.Wait(); err != nil && err != ecode.Degrade {
return
}
card := &v1.Card{Mid: mid}
if medal != nil {
card.Nameplate.Nid = int(medal.ID)
card.Nameplate.Name = medal.Name
card.Nameplate.Image = medal.Image
card.Nameplate.ImageSmall = medal.ImageSmall
card.Nameplate.Level = medal.LevelDesc
card.Nameplate.Condition = medal.Condition
}
if block != nil {
card.Silence = blockStatusToSilence(block.BlockStatus)
}
if mb != nil {
card.Name = mb.Name
card.Sign = mb.Sign
card.Sex = mb.SexStr()
card.Rank = int32(mb.Rank)
card.Face = mb.Face
if mb.OfficialInfo != nil {
// card.Official = *mb.OfficialInfo
card.Official.DeepCopyFromOfficialInfo(mb.OfficialInfo)
}
card.Level = mb.Cur
}
if vip != nil {
card.Vip = *vip
}
if pendant != nil {
card.Pendant.Pid = int(pendant.Pid)
card.Pendant.Expire = int(pendant.Expires)
if pendant.Pendant != nil {
card.Pendant.Name = pendant.Pendant.Name
card.Pendant.Image = fullImage(mid, pendant.Pendant.Image)
}
}
res = card
return
}
// RawCards get card by mid.
func (d *Dao) RawCards(c context.Context, mids []int64) (res map[int64]*v1.Card, err error) {
eg, _ := errgroup.WithContext(c)
var medals map[int64]*sml.MedalInfo
eg.Go(func() (e error) {
if medals, e = d.suitRPC.MedalActivatedMulti(c, &sml.ArgMids{Mids: mids}); e != nil {
log.Error("s.suitRPC.MedalActivatedMulti(%v) err %v", mids, e)
e = ecode.Degrade
}
return
})
var blocks map[int64]*bml.RPCResInfo
eg.Go(func() (e error) {
var bs []*bml.RPCResInfo
if bs, e = d.mRPC.BlockBatchInfo(c, &bml.RPCArgBatchInfo{MIDs: mids}); e != nil {
log.Error("d.block.BlockBatchInfo(%v) err %v", mids, e)
e = ecode.Degrade
}
blocks = make(map[int64]*bml.RPCResInfo, len(bs))
for _, block := range bs {
blocks[block.MID] = block
}
return
})
var mbs map[int64]*mml.Member
eg.Go(func() (e error) {
if mbs, e = d.mRPC.Members(c, &mml.ArgMemberMids{Mids: mids}); e != nil {
log.Error("d.mRPC.Members(%v) err(%v)", mids, e)
// e = ecode.Degrade
}
return
})
var vipm map[int64]*v1.VipInfo
eg.Go(func() (e error) {
if vipm, e = d.Vips(c, mids); e != nil {
log.Error("d.CpVips(%v) err(%v)", mids, e)
e = ecode.Degrade
}
return
})
var pendantm map[int64]*sml.PendantEquip
eg.Go(func() (e error) {
if pendantm, e = d.suitRPC.Equipments(c, &sml.ArgEquipments{Mids: mids}); e != nil {
log.Error("d.suitRPC.Equipments(%v) err(%v)", mids, e)
e = ecode.Degrade
}
return
})
if err = eg.Wait(); err != nil && err != ecode.Degrade {
return
}
res = map[int64]*v1.Card{}
for _, mid := range mids {
card := &v1.Card{Mid: mid}
if mb, ok := mbs[mid]; ok && mb != nil {
card.Name = mb.Name
card.Sign = mb.Sign
card.Sex = mb.SexStr()
card.Rank = int32(mb.Rank)
card.Face = mb.Face
if mb.OfficialInfo != nil {
// card.Official = *mb.OfficialInfo
card.Official.DeepCopyFromOfficialInfo(mb.OfficialInfo)
}
card.Level = mb.Cur
} else {
continue
}
if block, ok := blocks[mid]; ok && block != nil {
card.Silence = blockStatusToSilence(block.BlockStatus)
}
if medal, ok := medals[mid]; ok && medal != nil {
card.Nameplate.Nid = int(medal.ID)
card.Nameplate.Name = medal.Name
card.Nameplate.Image = medal.Image
card.Nameplate.ImageSmall = medal.ImageSmall
card.Nameplate.Level = medal.LevelDesc
card.Nameplate.Condition = medal.Condition
}
if vip, ok := vipm[mid]; ok && vip != nil {
card.Vip = *vip
}
if pendant, ok := pendantm[mid]; ok && pendant != nil {
card.Pendant.Pid = int(pendant.Pid)
card.Pendant.Expire = int(pendant.Expires)
if pendant.Pendant != nil {
card.Pendant.Name = pendant.Pendant.Name
card.Pendant.Image = fullImage(mid, pendant.Pendant.Image)
}
}
res[mid] = card
}
return
}
// RawProfile get profile by mid.
func (d *Dao) RawProfile(c context.Context, mid int64) (res *v1.Profile, err error) {
eg, _ := errgroup.WithContext(c)
var detail *model.PassportDetail
eg.Go(func() (e error) {
if detail, e = d.PassportDetail(c, mid); e != nil {
log.Error("d.PassPortDetail(%d) err %v", mid, e)
// e = ecode.Degrade
}
return
})
var mb *mml.Member
eg.Go(func() (e error) {
if mb, e = d.mRPC.Member(c, &mml.ArgMemberMid{Mid: mid}); e != nil {
log.Error("d.mRPC.Member(%d) err(%v)", mid, e)
// e = ecode.Degrade
}
return
})
var moral *mml.Moral
eg.Go(func() (e error) {
if moral, e = d.mRPC.Moral(c, &mml.ArgMemberMid{Mid: mid}); e != nil {
log.Error("d.mRPC.Member(%d) err(%v)", mid, e)
e = ecode.Degrade
}
return
})
var realNameStatus *mml.RealnameStatus
eg.Go(func() (e error) {
if realNameStatus, e = d.mRPC.RealnameStatus(c, &mml.ArgMemberMid{Mid: mid}); e != nil {
log.Error("d.mRPC.RealnameStatus(%d) err(%v)", mid, e)
e = ecode.Degrade
}
return
})
var medal *sml.MedalInfo
eg.Go(func() (e error) {
if medal, e = d.suitRPC.MedalActivated(c, &sml.ArgMid{Mid: mid}); e != nil {
log.Error("s.suitRPC.MedalActivated(%d) err %v", mid, e)
e = ecode.Degrade
}
return
})
var block *bml.RPCResInfo
eg.Go(func() (e error) {
if block, e = d.mRPC.BlockInfo(c, &bml.RPCArgInfo{MID: mid}); e != nil {
log.Error("s.dao.BlockInfo(%d) err %v", mid, e)
e = ecode.Degrade
}
return
})
var vip *v1.VipInfo
eg.Go(func() (e error) {
if vip, e = d.Vip(c, mid); e != nil {
log.Error("d.Vip(%d) err(%v)", mid, e)
e = ecode.Degrade
}
return
})
var pendant *sml.PendantEquip
eg.Go(func() (e error) {
if pendant, e = d.suitRPC.Equipment(c, &sml.ArgEquipment{Mid: mid}); e != nil {
log.Error("d.suitRPC.Equipment(%d) err(%v)", mid, e)
e = ecode.Degrade
}
return
})
if err = eg.Wait(); err != nil && err != ecode.Degrade {
return
}
pfl := &v1.Profile{Mid: mid}
if mb != nil {
pfl.Name = mb.Name
pfl.Sign = mb.Sign
pfl.Sex = mb.SexStr()
pfl.Rank = int32(mb.Rank)
pfl.Face = mb.Face
if mb.OfficialInfo != nil {
// pfl.Official = *mb.OfficialInfo
pfl.Official.DeepCopyFromOfficialInfo(mb.OfficialInfo)
}
pfl.Level = mb.Cur
pfl.Birthday = mb.Birthday
}
if block != nil {
pfl.Silence = blockStatusToSilence(block.BlockStatus)
}
if detail != nil {
pfl.JoinTime = int32(detail.JoinTime)
pfl.EmailStatus = bindEmailStatus(detail.Email, detail.Spacesta)
pfl.TelStatus = bindPhoneStatus(detail.Phone)
pfl.IsTourist = boolToInt32(detail.IsTourist)
}
if realNameStatus != nil {
pfl.Identification = identificationStatus(*realNameStatus)
}
pfl.Moral = parseMoral(moral)
if medal != nil {
pfl.Nameplate.Nid = int(medal.ID)
pfl.Nameplate.Name = medal.Name
pfl.Nameplate.Image = medal.Image
pfl.Nameplate.ImageSmall = medal.ImageSmall
pfl.Nameplate.Level = medal.LevelDesc
pfl.Nameplate.Condition = medal.Condition
}
if vip != nil {
pfl.Vip = *vip
}
if pendant != nil {
pfl.Pendant.Pid = int(pendant.Pid)
pfl.Pendant.Expire = int(pendant.Expires)
if pendant.Pendant != nil {
pfl.Pendant.Name = pendant.Pendant.Name
pfl.Pendant.Image = fullImage(mid, pendant.Pendant.Image)
}
}
res = pfl
return
}
func blockStatusToSilence(status bml.BlockStatus) int32 {
return boolToInt32(status == bml.BlockStatusForever || status == bml.BlockStatusLimit)
}
func bindEmailStatus(email string, spacesta int8) int32 {
return boolToInt32(spacesta > -10 && len(email) > 0)
}
func bindPhoneStatus(phone string) int32 {
return boolToInt32(len(phone) > 0)
}
func parseMoral(moral *mml.Moral) int32 {
m := int32(mml.DefaultMoral)
if moral != nil {
m = int32(moral.Moral)
}
return m / 100
}
func identificationStatus(realNameStatus mml.RealnameStatus) int32 {
return boolToInt32(realNameStatus == mml.RealnameStatusTrue)
}
func boolToInt32(b bool) int32 {
if b {
return 1
}
return 0
}

View File

@@ -0,0 +1,163 @@
package dao
import (
"context"
"testing"
mml "go-common/app/service/main/member/model"
bml "go-common/app/service/main/member/model/block"
"go-common/library/ecode"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoRawInfo(t *testing.T) {
var (
c = context.TODO()
mid = int64(110016481)
)
convey.Convey("Get base-info from member-rpc", t, func(ctx convey.C) {
res, err := d.RawInfo(c, mid)
ctx.Convey("Then err should be nil and res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoRawInfos(t *testing.T) {
var (
c = context.TODO()
mids = []int64{110016811, 110017441}
)
convey.Convey("Batch get base-info from member-rpc", t, func(ctx convey.C) {
res, err := d.RawInfos(c, mids)
ctx.Convey("Then err should be nil and res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoRawCard(t *testing.T) {
var (
c = context.TODO()
mid = int64(110018101)
)
convey.Convey("Get card-info from member-rpc", t, func(ctx convey.C) {
res, err := d.RawCard(c, mid)
ctx.Convey("Then err should be nil and res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoRawCards(t *testing.T) {
var (
c = context.TODO()
mids = []int64{110019691, 110019241}
)
convey.Convey("Batch get card-info from member-rpc", t, func(ctx convey.C) {
res, err := d.RawCards(c, mids)
ctx.Convey("Then err should be nil and res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoRawProfile(t *testing.T) {
var (
c = context.TODO()
mid = int64(110019691)
)
convey.Convey("Get profile-info from member-rpc", t, func(ctx convey.C) {
res, err := d.RawProfile(c, mid)
if err == ecode.Degrade {
err = nil
}
ctx.Convey("Then err should be nil and res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoblockStatusToSilence(t *testing.T) {
var (
status bml.BlockStatus
)
convey.Convey("Check whether member in block status ", t, func(ctx convey.C) {
p1 := blockStatusToSilence(status)
ctx.Convey("Then p1 should be 0 or 1.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldBeIn, []int32{0, 1})
})
})
}
func TestDaobindEmailStatus(t *testing.T) {
var (
email = "zxfd43622@qq.com"
spacesta = int8(0)
)
convey.Convey("Get member bind-email status", t, func(ctx convey.C) {
p1 := bindEmailStatus(email, spacesta)
ctx.Convey("Then p1 should be 0 or 1.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldBeIn, []int32{0, 1})
})
})
}
func TestDaobindPhoneStatus(t *testing.T) {
var (
phone = "13849920122"
)
convey.Convey("Get member bind-phone status", t, func(ctx convey.C) {
p1 := bindPhoneStatus(phone)
ctx.Convey("Then p1 should be 0 or 1.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldBeIn, []int32{0, 1})
})
})
}
func TestDaoparseMoral(t *testing.T) {
var (
moral = &mml.Moral{
Mid: 3441,
Moral: 7100,
Added: 100,
Deducted: 0,
}
)
convey.Convey("Parse moral value", t, func(ctx convey.C) {
p1 := parseMoral(moral)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaoidentificationStatus(t *testing.T) {
var (
realNameStatus = mml.RealnameStatusTrue
)
convey.Convey("Get identification status", t, func(ctx convey.C) {
p1 := identificationStatus(realNameStatus)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldEqual, 1)
})
})
}
func TestDaoboolToInt32(t *testing.T) {
var (
b = true
)
convey.Convey("Convert true to int", t, func(ctx convey.C) {
p1 := boolToInt32(b)
ctx.Convey("Then p1 should be 1.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldEqual, 1)
})
})
}

View File

@@ -0,0 +1,16 @@
package dao
import (
"context"
member "go-common/app/service/main/member/model"
)
// RealnameDetail is.
func (d *Dao) RealnameDetail(c context.Context, mid int64) (detail *member.RealnameDetail, err error) {
req := &member.ArgMemberMid{Mid: mid}
if detail, err = d.mRPC.RealnameDetail(c, req); err != nil {
return
}
return
}

View File

@@ -0,0 +1,24 @@
package dao
import (
"context"
"go-common/app/service/main/account/model"
"github.com/pkg/errors"
)
// MidsByName is.
func (d *Dao) MidsByName(ctx context.Context, names []string) ([]int64, error) {
r := d.es.NewRequest("member_user").
Fields("mid").
Index("user_base").
WhereIn("kwname", names).
Ps(len(names)).
Pn(1)
result := &model.SearchMemberResult{}
if err := r.Scan(ctx, &result); err != nil {
return nil, errors.WithStack(err)
}
return result.Mids(), nil
}

View File

@@ -0,0 +1,22 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoMidsByName(t *testing.T) {
var (
c = context.TODO()
names = []string{"", "一"}
)
convey.Convey("Search mids by name", t, func(ctx convey.C) {
p1, err := d.MidsByName(c, names)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,89 @@
package dao
import (
"context"
"net/url"
v1 "go-common/app/service/main/account/api"
"go-common/library/ecode"
"go-common/library/net/metadata"
"go-common/library/xstr"
"github.com/pkg/errors"
)
var (
_emptyVipInfos3 = map[int64]*v1.VipInfo{}
)
// RawVip get mid's vip info from account center by vip API.
func (d *Dao) RawVip(c context.Context, mid int64) (vip *v1.VipInfo, err error) {
params := url.Values{}
var res struct {
Code int `json:"code"`
Data struct {
Type int32 `json:"vipType"`
Status int32 `json:"vipStatus"`
DueDate int64 `json:"vipDueDate"`
VipPayType int32 `json:"isAutoRenew"`
} `json:"data"`
}
err = d.httpR.RESTfulGet(c, d.vipInfoURI, metadata.String(c, metadata.RemoteIP), params, &res, mid)
if err != nil {
err = errors.Wrap(err, "dao vip")
return
}
if res.Code != 0 {
err = ecode.Int(res.Code)
err = errors.Wrap(err, "dao vip")
return
}
vip = &v1.VipInfo{
Type: res.Data.Type,
Status: res.Data.Status,
DueDate: res.Data.DueDate,
VipPayType: res.Data.VipPayType,
}
return
}
// RawVips get multi mid's vip info from account center by vip API.
func (d *Dao) RawVips(c context.Context, mids []int64) (res map[int64]*v1.VipInfo, err error) {
params := url.Values{}
params.Set("idList", xstr.JoinInts(mids))
var info struct {
Code int `json:"code"`
Data map[int64]*struct {
Type int32 `json:"vipType"`
Status int32 `json:"vipStatus"`
DueDate int64 `json:"vipDueDate"`
} `json:"data"`
}
err = d.httpR.Get(c, d.vipMultiInfoURI, "", params, &info)
if err != nil {
err = errors.Wrap(err, "dao vip")
return
}
if info.Code != 0 {
err = ecode.Int(info.Code)
err = errors.Wrap(err, "dao vip")
return
}
if len(info.Data) == 0 {
res = _emptyVipInfos3
return
}
res = make(map[int64]*v1.VipInfo, len(info.Data))
for mid, v := range info.Data {
if v == nil {
continue
}
vip := &v1.VipInfo{
Type: v.Type,
Status: v.Status,
DueDate: v.DueDate,
}
res[mid] = vip
}
return
}

View File

@@ -0,0 +1,36 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoRawVip(t *testing.T) {
var (
c = context.TODO()
mid = int64(110018671)
)
convey.Convey("Get vip-info from vip-rpc", t, func(ctx convey.C) {
vip, err := d.RawVip(c, mid)
ctx.Convey("Then err should be nil and vip should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(vip, convey.ShouldNotBeNil)
})
})
}
func TestDaoRawVips(t *testing.T) {
var (
c = context.TODO()
mids = []int64{110016841, 110018671}
)
convey.Convey("Batch get vip-infos from vip-rpc", t, func(ctx convey.C) {
res, err := d.RawVips(c, mids)
ctx.Convey("Then err should be nil and res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}

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 = [
"acc.go",
"model.go",
"param.go",
"passport.go",
"rpc.go",
],
importpath = "go-common/app/service/main/account/model",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/account/api:go_default_library",
"//app/service/main/member/model:go_default_library",
"//library/time:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/service/main/account/model/queue:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,130 @@
package model
import (
"strconv"
v1 "go-common/app/service/main/account/api"
mmodel "go-common/app/service/main/member/model"
)
// AccJavaInfo thin infomartion
type AccJavaInfo struct {
Mid int64 `json:"mid"`
Scores int32 `json:"scores"`
JoinTime int32 `json:"jointime"`
Silence int32 `json:"silence"`
EmailStatus int32 `json:"email_status"`
TelStatus int32 `json:"tel_status"`
Identification int32 `json:"identification"`
Moral int32 `json:"moral"`
Nameplate struct {
Nid int `json:"nid"`
Name string `json:"name"`
Image string `json:"image"`
ImageSmall string `json:"image_small"`
Level string `json:"level"`
Condition string `json:"condition"`
} `json:"nameplate"`
}
// OldInfo old info.
type OldInfo struct {
Mid string `json:"mid"`
Name string `json:"uname"`
Sex string `json:"sex"`
Sign string `json:"sign"`
Avatar string `json:"avatar"`
Rank string `json:"rank"`
DisplayRank string `json:"DisplayRank"`
LevelInfo mmodel.LevelInfo `json:"level_info"`
Official OldOfficial `json:"official_verify"`
Vip v1.VipInfo `json:"vip"`
}
// OldOfficial old official.
type OldOfficial struct {
Type int8 `json:"type"`
Desc string `json:"desc"`
}
// CvtOfficial is used to convert to old official.
func CvtOfficial(o v1.OfficialInfo) OldOfficial {
old := OldOfficial{}
if o.Role == 0 {
old.Type = -1
} else {
if o.Role <= 2 {
old.Type = 0
} else {
old.Type = 1
}
old.Desc = o.Title
}
return old
}
// Info old info -> info.
func (oi *OldInfo) Info() *v1.Info {
mid, _ := strconv.ParseInt(oi.Mid, 10, 64)
rank, _ := strconv.ParseInt(oi.Rank, 10, 64)
i := &v1.Info{
Mid: mid,
Name: oi.Name,
Sex: oi.Sex,
Face: oi.Avatar,
Sign: oi.Sign,
Rank: int32(rank),
}
return i
}
// Relation relation.
type Relation struct {
Following bool `json:"following"`
}
// ProfileStat profile with stat.
type ProfileStat struct {
*v1.Profile
LevelExp mmodel.LevelInfo `json:"level_exp"`
Coins float64 `json:"coins"`
Following int64 `json:"following"`
Follower int64 `json:"follower"`
}
// SearchMemberResult is.
type SearchMemberResult struct {
Order string `json:"order"`
Sort string `json:"sort"`
Result []struct {
Mid int64 `json:"mid"`
} `json:"result"`
Page Page `json:"page"`
}
// Privacy .
type Privacy struct {
Realname string `json:"realname"`
IdentityCard string `json:"identity_card"`
IdentitySex string `json:"identity_sex"`
Tel string `json:"tel"`
RegIP string `json:"reg_ip"`
RegTS int64 `json:"reg_ts"`
HandIMG string `json:"hand_img"`
}
// Page page.
type Page struct {
Num int `json:"num"`
Size int `json:"size"`
Total int `json:"total"`
}
// Mids is.
func (r *SearchMemberResult) Mids() []int64 {
mids := make([]int64, 0, len(r.Result))
for _, r := range r.Result {
mids = append(mids, r.Mid)
}
return mids
}

View File

@@ -0,0 +1,33 @@
package model
import (
v1 "go-common/app/service/main/account/api"
)
// VipInfo is the type alias v1.VipInfo
// DEPRECATED: using v1.VipInfo
type VipInfo = v1.VipInfo
// Info is the type alias v1.Info
// DEPRECATED: using v1.Info
type Info = v1.Info
// Profile is the type alias v1.Profile
// DEPRECATED: using v1.Profile
type Profile = v1.Profile
// Card is the type alias v1.Card
// DEPRECATED: using v1.Card
type Card = v1.Card
// PendantInfo is the type alias v1.PendantInfo
// DEPRECATED: using v1.PendantInfo
type PendantInfo = v1.PendantInfo
// NameplateInfo is the type alias v1.NameplateInfo
// DEPRECATED: using v1.NameplateInfo
type NameplateInfo = v1.NameplateInfo
// OfficialInfo is the type alias v1.OfficialInfo
// DEPRECATED: using v1.OfficialInfo
type OfficialInfo = v1.OfficialInfo

View File

@@ -0,0 +1,28 @@
package model
// ParamMid is.
type ParamMid struct {
Mid int64 `form:"mid" validate:"gt=0,required"`
}
// ParamMids is.
type ParamMids struct {
Mids []int64 `form:"mids,split" validate:"gt=0,dive,gt=0"`
}
// ParamNames is.
type ParamNames struct {
Names []string `form:"names,split" validate:"gt=0,dive,gt=0"`
}
// ParamModify is.
type ParamModify struct {
Mid int64 `form:"mid" validate:"gt=0,required"`
ModifiedAttr string `form:"modifiedAttr" validate:"gt=0,required"`
}
// ParamMsg is.
type ParamMsg struct {
// by notify
Msg string `form:"msg"`
}

View File

@@ -0,0 +1,33 @@
package model
import (
xtime "go-common/library/time"
)
//PassportDetail detail.
type PassportDetail struct {
Mid int64 `json:"mid"`
Email string `json:"email"`
Phone string `json:"telphone"`
Spacesta int8 `json:"spacesta"`
JoinTime int64 `json:"join_time"`
IsTourist bool `json:"is_tourist"`
}
//PassportProfile .
type PassportProfile struct {
Mid int64 `json:"mid"`
UName string `json:"uname"`
UserID string `json:"user_id"`
Telphone string `json:"telphone"`
NickLock int `json:"nick_lock"`
BindQQ bool `json:"bind_qq"`
BindSina bool `json:"bind_sina"`
SpaceSta int `json:"spacesta"`
LoginTime xtime.Time `json:"login_time"`
LoginIP string `json:"login_ip"`
JoinIP string `json:"join_ip"`
JoinTime xtime.Time `json:"join_time"`
SafeQuestion int `json:"safe_question"`
CountryCode int64 `json:"country_code"`
}

View File

@@ -0,0 +1,5 @@
#! /bin/sh
# proto.sh https://github.com/google/protobuf/releases 下载release包解压后将include中的文件夹拖到/usr/local/include即可
gopath=$GOPATH/src
gogopath=$GOPATH/src/go-common/vendor/github.com/gogo/protobuf
protoc --gofast_out=. --proto_path=/usr/local/include:$gopath:$gogopath:. vip.proto info.proto card.proto profile.proto usersuit.proto

View File

@@ -0,0 +1,33 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"error.go",
"priority_queue.go",
"queue.go",
"ring.go",
],
importpath = "go-common/app/service/main/account/model/queue",
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,32 @@
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package queue
import "errors"
var (
// ErrDisposed is returned when an operation is performed on a disposed
// queue.
ErrDisposed = errors.New(`queue: disposed`)
// ErrTimeout is returned when an applicable queue operation times out.
ErrTimeout = errors.New(`queue: poll timed out`)
// ErrEmptyQueue is returned when an non-applicable queue operation was called
// due to the queue's empty item state
ErrEmptyQueue = errors.New(`queue: empty queue`)
)

View File

@@ -0,0 +1,267 @@
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
The priority queue is almost a spitting image of the logic
used for a regular queue. In order to keep the logic fast,
this code is repeated instead of using casts to cast to interface{}
back and forth. If Go had inheritance and generics, this problem
would be easier to solve.
*/
package queue
import "sync"
// Item is an item that can be added to the priority queue.
type Item interface {
// Compare returns a bool that can be used to determine
// ordering in the priority queue. Assuming the queue
// is in ascending order, this should return > logic.
// Return 1 to indicate this object is greater than the
// the other logic, 0 to indicate equality, and -1 to indicate
// less than other.
Compare(other Item) int
HashCode() int64
}
type priorityItems []Item
func (items *priorityItems) swap(i, j int) {
(*items)[i], (*items)[j] = (*items)[j], (*items)[i]
}
func (items *priorityItems) pop() Item {
size := len(*items)
// Move last leaf to root, and 'pop' the last item.
items.swap(size-1, 0)
item := (*items)[size-1] // Item to return.
(*items)[size-1], *items = nil, (*items)[:size-1]
// 'Bubble down' to restore heap property.
index := 0
childL, childR := 2*index+1, 2*index+2
for len(*items) > childL {
child := childL
if len(*items) > childR && (*items)[childR].Compare((*items)[childL]) < 0 {
child = childR
}
if (*items)[child].Compare((*items)[index]) < 0 {
items.swap(index, child)
index = child
childL, childR = 2*index+1, 2*index+2
} else {
break
}
}
return item
}
func (items *priorityItems) get(number int) []Item {
returnItems := make([]Item, 0, number)
for i := 0; i < number; i++ {
if len(*items) == 0 {
break
}
returnItems = append(returnItems, items.pop())
}
return returnItems
}
func (items *priorityItems) push(item Item) {
// Stick the item as the end of the last level.
*items = append(*items, item)
// 'Bubble up' to restore heap property.
index := len(*items) - 1
parent := int((index - 1) / 2)
for parent >= 0 && (*items)[parent].Compare(item) > 0 {
items.swap(index, parent)
index = parent
parent = int((index - 1) / 2)
}
}
// PriorityQueue is similar to queue except that it takes
// items that implement the Item interface and adds them
// to the queue in priority order.
type PriorityQueue struct {
waiters waiters
items priorityItems
itemMap map[int64]struct{}
lock sync.Mutex
disposeLock sync.Mutex
disposed bool
allowDuplicates bool
}
// Put adds items to the queue.
func (pq *PriorityQueue) Put(items ...Item) error {
if len(items) == 0 {
return nil
}
pq.lock.Lock()
defer pq.lock.Unlock()
if pq.disposed {
return ErrDisposed
}
for _, item := range items {
if pq.allowDuplicates {
pq.items.push(item)
} else if _, ok := pq.itemMap[item.HashCode()]; !ok {
pq.itemMap[item.HashCode()] = struct{}{}
pq.items.push(item)
}
}
for {
sema := pq.waiters.get()
if sema == nil {
break
}
sema.response.Add(1)
sema.ready <- true
sema.response.Wait()
if len(pq.items) == 0 {
break
}
}
return nil
}
// Get retrieves items from the queue. If the queue is empty,
// this call blocks until the next item is added to the queue. This
// will attempt to retrieve number of items.
func (pq *PriorityQueue) Get(number int) ([]Item, error) {
if number < 1 {
return nil, nil
}
pq.lock.Lock()
if pq.disposed {
pq.lock.Unlock()
return nil, ErrDisposed
}
var items []Item
// Remove references to popped items.
deleteItems := func(items []Item) {
for _, item := range items {
delete(pq.itemMap, item.HashCode())
}
}
if len(pq.items) == 0 {
sema := newSema()
pq.waiters.put(sema)
pq.lock.Unlock()
<-sema.ready
if pq.Disposed() {
return nil, ErrDisposed
}
items = pq.items.get(number)
if !pq.allowDuplicates {
deleteItems(items)
}
sema.response.Done()
return items, nil
}
items = pq.items.get(number)
deleteItems(items)
pq.lock.Unlock()
return items, nil
}
// Peek will look at the next item without removing it from the queue.
func (pq *PriorityQueue) Peek() Item {
pq.lock.Lock()
defer pq.lock.Unlock()
if len(pq.items) > 0 {
return pq.items[0]
}
return nil
}
// Empty returns a bool indicating if there are any items left
// in the queue.
func (pq *PriorityQueue) Empty() bool {
pq.lock.Lock()
defer pq.lock.Unlock()
return len(pq.items) == 0
}
// Len returns a number indicating how many items are in the queue.
func (pq *PriorityQueue) Len() int {
pq.lock.Lock()
defer pq.lock.Unlock()
return len(pq.items)
}
// Disposed returns a bool indicating if this queue has been disposed.
func (pq *PriorityQueue) Disposed() bool {
pq.disposeLock.Lock()
defer pq.disposeLock.Unlock()
return pq.disposed
}
// Dispose will prevent any further reads/writes to this queue
// and frees available resources.
func (pq *PriorityQueue) Dispose() {
pq.lock.Lock()
defer pq.lock.Unlock()
pq.disposeLock.Lock()
defer pq.disposeLock.Unlock()
pq.disposed = true
for _, waiter := range pq.waiters {
waiter.response.Add(1)
waiter.ready <- true
}
pq.items = nil
pq.waiters = nil
}
// NewPriorityQueue is the constructor for a priority queue.
func NewPriorityQueue(hint int, allowDuplicates bool) *PriorityQueue {
return &PriorityQueue{
items: make(priorityItems, 0, hint),
itemMap: make(map[int64]struct{}, hint),
allowDuplicates: allowDuplicates,
}
}

View File

@@ -0,0 +1,411 @@
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Package queue includes a regular queue and a priority queue.
These queues rely on waitgroups to pause listening threads
on empty queues until a message is received. If any thread
calls Dispose on the queue, any listeners are immediately returned
with an error. Any subsequent put to the queue will return an error
as opposed to panicking as with channels. Queues will grow with unbounded
behavior as opposed to channels which can be buffered but will pause
while a thread attempts to put to a full channel.
Recently added is a lockless ring buffer using the same basic C design as
found here:
http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue
Modified for use with Go with the addition of some dispose semantics providing
the capability to release blocked threads. This works for both puts
and gets, either will return an error if they are blocked and the buffer
is disposed. This could serve as a signal to kill a goroutine. All threadsafety
is acheived using CAS operations, making this buffer pretty quick.
Benchmarks:
BenchmarkPriorityQueue-8 2000000 782 ns/op
BenchmarkQueue-8 2000000 671 ns/op
BenchmarkChannel-8 1000000 2083 ns/op
BenchmarkQueuePut-8 20000 84299 ns/op
BenchmarkQueueGet-8 20000 80753 ns/op
BenchmarkExecuteInParallel-8 20000 68891 ns/op
BenchmarkRBLifeCycle-8 10000000 177 ns/op
BenchmarkRBPut-8 30000000 58.1 ns/op
BenchmarkRBGet-8 50000000 26.8 ns/op
TODO: We really need a Fibonacci heap for the priority queue.
TODO: Unify the types of queue to the same interface.
*/
package queue
import (
"runtime"
"sync"
"sync/atomic"
"time"
)
type waiters []*sema
func (w *waiters) get() *sema {
if len(*w) == 0 {
return nil
}
sema := (*w)[0]
copy((*w)[0:], (*w)[1:])
(*w)[len(*w)-1] = nil // or the zero value of T
*w = (*w)[:len(*w)-1]
return sema
}
func (w *waiters) put(sema *sema) {
*w = append(*w, sema)
}
func (w *waiters) remove(sema *sema) {
if len(*w) == 0 {
return
}
// build new slice, copy all except sema
ws := *w
newWs := make(waiters, 0, len(*w))
for i := range ws {
if ws[i] != sema {
newWs = append(newWs, ws[i])
}
}
*w = newWs
}
type items []interface{}
func (items *items) get(number int64) []interface{} {
returnItems := make([]interface{}, 0, number)
index := int64(0)
for i := int64(0); i < number; i++ {
if i >= int64(len(*items)) {
break
}
returnItems = append(returnItems, (*items)[i])
(*items)[i] = nil
index++
}
*items = (*items)[index:]
return returnItems
}
func (items *items) peek() (interface{}, bool) {
length := len(*items)
if length == 0 {
return nil, false
}
return (*items)[0], true
}
func (items *items) getUntil(checker func(item interface{}) bool) []interface{} {
length := len(*items)
if len(*items) == 0 {
// returning nil here actually wraps that nil in a list
// of interfaces... thanks go
return []interface{}{}
}
returnItems := make([]interface{}, 0, length)
index := -1
for i, item := range *items {
if !checker(item) {
break
}
returnItems = append(returnItems, item)
index = i
(*items)[i] = nil // prevent memory leak
}
*items = (*items)[index+1:]
return returnItems
}
type sema struct {
ready chan bool
response *sync.WaitGroup
}
func newSema() *sema {
return &sema{
ready: make(chan bool, 1),
response: &sync.WaitGroup{},
}
}
// Queue is the struct responsible for tracking the state
// of the queue.
type Queue struct {
waiters waiters
items items
lock sync.Mutex
disposed bool
}
// Put will add the specified items to the queue.
func (q *Queue) Put(items ...interface{}) error {
if len(items) == 0 {
return nil
}
q.lock.Lock()
if q.disposed {
q.lock.Unlock()
return ErrDisposed
}
q.items = append(q.items, items...)
for {
sema := q.waiters.get()
if sema == nil {
break
}
sema.response.Add(1)
select {
case sema.ready <- true:
sema.response.Wait()
default:
// This semaphore timed out.
}
if len(q.items) == 0 {
break
}
}
q.lock.Unlock()
return nil
}
// Get retrieves items from the queue. If there are some items in the
// queue, get will return a number UP TO the number passed in as a
// parameter. If no items are in the queue, this method will pause
// until items are added to the queue.
func (q *Queue) Get(number int64) ([]interface{}, error) {
return q.Poll(number, 0)
}
// Poll retrieves items from the queue. If there are some items in the queue,
// Poll will return a number UP TO the number passed in as a parameter. If no
// items are in the queue, this method will pause until items are added to the
// queue or the provided timeout is reached. A non-positive timeout will block
// until items are added. If a timeout occurs, ErrTimeout is returned.
func (q *Queue) Poll(number int64, timeout time.Duration) ([]interface{}, error) {
if number < 1 {
// thanks again go
return []interface{}{}, nil
}
q.lock.Lock()
if q.disposed {
q.lock.Unlock()
return nil, ErrDisposed
}
var items []interface{}
if len(q.items) == 0 {
sema := newSema()
q.waiters.put(sema)
q.lock.Unlock()
var timeoutC <-chan time.Time
if timeout > 0 {
timeoutC = time.After(timeout)
}
select {
case <-sema.ready:
// we are now inside the put's lock
if q.disposed {
return nil, ErrDisposed
}
items = q.items.get(number)
sema.response.Done()
return items, nil
case <-timeoutC:
// cleanup the sema that was added to waiters
select {
case sema.ready <- true:
// we called this before Put() could
// Remove sema from waiters.
q.lock.Lock()
q.waiters.remove(sema)
q.lock.Unlock()
default:
// Put() got it already, we need to call Done() so Put() can move on
sema.response.Done()
}
return nil, ErrTimeout
}
}
items = q.items.get(number)
q.lock.Unlock()
return items, nil
}
// Peek returns a the first item in the queue by value
// without modifying the queue.
func (q *Queue) Peek() (interface{}, error) {
q.lock.Lock()
defer q.lock.Unlock()
if q.disposed {
return nil, ErrDisposed
}
peekItem, ok := q.items.peek()
if !ok {
return nil, ErrEmptyQueue
}
return peekItem, nil
}
// TakeUntil takes a function and returns a list of items that
// match the checker until the checker returns false. This does not
// wait if there are no items in the queue.
func (q *Queue) TakeUntil(checker func(item interface{}) bool) ([]interface{}, error) {
if checker == nil {
return nil, nil
}
q.lock.Lock()
if q.disposed {
q.lock.Unlock()
return nil, ErrDisposed
}
result := q.items.getUntil(checker)
q.lock.Unlock()
return result, nil
}
// Empty returns a bool indicating if this bool is empty.
func (q *Queue) Empty() bool {
q.lock.Lock()
defer q.lock.Unlock()
return len(q.items) == 0
}
// Len returns the number of items in this queue.
func (q *Queue) Len() int64 {
q.lock.Lock()
defer q.lock.Unlock()
return int64(len(q.items))
}
// Disposed returns a bool indicating if this queue
// has had disposed called on it.
func (q *Queue) Disposed() bool {
q.lock.Lock()
defer q.lock.Unlock()
return q.disposed
}
// Dispose will dispose of this queue and returns
// the items disposed. Any subsequent calls to Get
// or Put will return an error.
func (q *Queue) Dispose() []interface{} {
q.lock.Lock()
defer q.lock.Unlock()
q.disposed = true
for _, waiter := range q.waiters {
waiter.response.Add(1)
select {
case waiter.ready <- true:
// release Poll immediately
default:
// ignore if it's a timeout or in the get
}
}
disposedItems := q.items
q.items = nil
q.waiters = nil
return disposedItems
}
// New is a constructor for a new threadsafe queue.
func New(hint int64) *Queue {
return &Queue{
items: make([]interface{}, 0, hint),
}
}
// ExecuteInParallel will (in parallel) call the provided function
// with each item in the queue until the queue is exhausted. When the queue
// is exhausted execution is complete and all goroutines will be killed.
// This means that the queue will be disposed so cannot be used again.
func ExecuteInParallel(q *Queue, fn func(interface{})) {
if q == nil {
return
}
q.lock.Lock() // so no one touches anything in the middle
// of this process
todo, done := uint64(len(q.items)), int64(-1)
// this is important or we might face an infinite loop
if todo == 0 {
return
}
numCPU := 1
if runtime.NumCPU() > 1 {
numCPU = runtime.NumCPU() - 1
}
var wg sync.WaitGroup
wg.Add(numCPU)
items := q.items
for i := 0; i < numCPU; i++ {
go func() {
for {
index := atomic.AddInt64(&done, 1)
if index >= int64(todo) {
wg.Done()
break
}
fn(items[index])
items[index] = 0
}
}()
}
wg.Wait()
q.lock.Unlock()
q.Dispose()
}

View File

@@ -0,0 +1,203 @@
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package queue
import (
"runtime"
"sync/atomic"
"time"
)
// roundUp takes a uint64 greater than 0 and rounds it up to the next
// power of 2.
func roundUp(v uint64) uint64 {
v--
v |= v >> 1
v |= v >> 2
v |= v >> 4
v |= v >> 8
v |= v >> 16
v |= v >> 32
v++
return v
}
type node struct {
position uint64
data interface{}
}
type nodes []*node
// RingBuffer is a MPMC buffer that achieves threadsafety with CAS operations
// only. A put on full or get on empty call will block until an item
// is put or retrieved. Calling Dispose on the RingBuffer will unblock
// any blocked threads with an error. This buffer is similar to the buffer
// described here: http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue
// with some minor additions.
type RingBuffer struct {
_padding0 [8]uint64
queue uint64
_padding1 [8]uint64
dequeue uint64
_padding2 [8]uint64
mask, disposed uint64
_padding3 [8]uint64
nodes nodes
}
func (rb *RingBuffer) init(size uint64) {
size = roundUp(size)
rb.nodes = make(nodes, size)
for i := uint64(0); i < size; i++ {
rb.nodes[i] = &node{position: i}
}
rb.mask = size - 1 // so we don't have to do this with every put/get operation
}
// Put adds the provided item to the queue. If the queue is full, this
// call will block until an item is added to the queue or Dispose is called
// on the queue. An error will be returned if the queue is disposed.
func (rb *RingBuffer) Put(item interface{}) error {
_, err := rb.put(item, false)
return err
}
// Offer adds the provided item to the queue if there is space. If the queue
// is full, this call will return false. An error will be returned if the
// queue is disposed.
func (rb *RingBuffer) Offer(item interface{}) (bool, error) {
return rb.put(item, true)
}
func (rb *RingBuffer) put(item interface{}, offer bool) (bool, error) {
var n *node
pos := atomic.LoadUint64(&rb.queue)
L:
for {
if atomic.LoadUint64(&rb.disposed) == 1 {
return false, ErrDisposed
}
n = rb.nodes[pos&rb.mask]
seq := atomic.LoadUint64(&n.position)
switch dif := seq - pos; {
case dif == 0:
if atomic.CompareAndSwapUint64(&rb.queue, pos, pos+1) {
break L
}
// case dif < 0:
// panic(`Ring buffer in a compromised state during a put operation.`)
default:
pos = atomic.LoadUint64(&rb.queue)
}
if offer {
return false, nil
}
runtime.Gosched() // free up the cpu before the next iteration
}
n.data = item
atomic.StoreUint64(&n.position, pos+1)
return true, nil
}
// Get will return the next item in the queue. This call will block
// if the queue is empty. This call will unblock when an item is added
// to the queue or Dispose is called on the queue. An error will be returned
// if the queue is disposed.
func (rb *RingBuffer) Get() (interface{}, error) {
return rb.Poll(0)
}
// Poll will return the next item in the queue. This call will block
// if the queue is empty. This call will unblock when an item is added
// to the queue, Dispose is called on the queue, or the timeout is reached. An
// error will be returned if the queue is disposed or a timeout occurs. A
// non-positive timeout will block indefinitely.
func (rb *RingBuffer) Poll(timeout time.Duration) (interface{}, error) {
var (
n *node
pos = atomic.LoadUint64(&rb.dequeue)
start time.Time
)
if timeout > 0 {
start = time.Now()
}
L:
for {
if atomic.LoadUint64(&rb.disposed) == 1 {
return nil, ErrDisposed
}
n = rb.nodes[pos&rb.mask]
seq := atomic.LoadUint64(&n.position)
switch dif := seq - (pos + 1); {
case dif == 0:
if atomic.CompareAndSwapUint64(&rb.dequeue, pos, pos+1) {
break L
}
// case dif < 0:
// panic(`Ring buffer in compromised state during a get operation.`)
default:
pos = atomic.LoadUint64(&rb.dequeue)
}
if timeout > 0 && time.Since(start) >= timeout {
return nil, ErrTimeout
}
runtime.Gosched() // free up the cpu before the next iteration
}
data := n.data
n.data = nil
atomic.StoreUint64(&n.position, pos+rb.mask+1)
return data, nil
}
// Len returns the number of items in the queue.
func (rb *RingBuffer) Len() uint64 {
return atomic.LoadUint64(&rb.queue) - atomic.LoadUint64(&rb.dequeue)
}
// Cap returns the capacity of this ring buffer.
func (rb *RingBuffer) Cap() uint64 {
return uint64(len(rb.nodes))
}
// Dispose will dispose of this queue and free any blocked threads
// in the Put and/or Get methods. Calling those methods on a disposed
// queue will return an error.
func (rb *RingBuffer) Dispose() {
atomic.CompareAndSwapUint64(&rb.disposed, 0, 1)
}
// IsDisposed will return a bool indicating if this queue has been
// disposed.
func (rb *RingBuffer) IsDisposed() bool {
return atomic.LoadUint64(&rb.disposed) == 1
}
// NewRingBuffer will allocate, initialize, and return a ring buffer
// with the specified size.
func NewRingBuffer(size uint64) *RingBuffer {
rb := &RingBuffer{}
rb.init(size)
return rb
}

View File

@@ -0,0 +1,56 @@
package model
// ArgMid is.
type ArgMid struct {
Mid int64
}
// ArgMids is.
type ArgMids struct {
Mids []int64
}
// ArgNames is.
type ArgNames struct {
Names []string
}
// ArgExp is.
type ArgExp struct {
Mid int64
Exp float64
Operater string
Operate string
Reason string
RealIP string
}
// ArgMoral is.
type ArgMoral struct {
Mid int64
Moral float64
Oper string
Reason string
Remark string
RealIP string
}
// ArgRelation is.
type ArgRelation struct {
Mid, Owner int64
RealIP string
}
// ArgRelations is.
type ArgRelations struct {
Mid int64
Owners []int64
RealIP string
}
// ArgRichRelation is.
type ArgRichRelation struct {
Owner int64
Mids []int64
RealIP string
}

View File

@@ -0,0 +1,17 @@
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/service/main/account/rpc/client:all-srcs",
"//app/service/main/account/rpc/server:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,32 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["account3.go"],
importpath = "go-common/app/service/main/account/rpc/client",
tags = ["automanaged"],
deps = [
"//app/service/main/account/api:go_default_library",
"//app/service/main/account/model:go_default_library",
"//library/net/rpc: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,137 @@
package client
import (
"context"
v1 "go-common/app/service/main/account/api"
"go-common/app/service/main/account/model"
"go-common/library/net/rpc"
)
const (
_info3 = "RPC.Info3"
_card3 = "RPC.Card3"
_infos3 = "RPC.Infos3"
_infosByName3 = "RPC.InfosByName3"
_cards3 = "RPC.Cards3"
_profile3 = "RPC.Profile3"
_profileStat3 = "RPC.ProfileWithStat3"
_addExp3 = "RPC.AddExp3"
_addMoral3 = "RPC.AddMoral3"
_relation3 = "RPC.Relation3"
_relations3 = "RPC.Relations3"
_attentions3 = "RPC.Attentions3"
_blacks3 = "RPC.Blacks3"
_richRelations3 = "RPC.RichRelations3"
)
const (
_appid = "account.service"
)
var (
_noArg = &struct{}{}
)
// Service3 for server client3
type Service3 struct {
client *rpc.Client2
}
// New3 for new struct Service2 obj
func New3(c *rpc.ClientConfig) (s *Service3) {
s = &Service3{}
s.client = rpc.NewDiscoveryCli(_appid, c)
return
}
// Info3 receive ArgMid contains mid and real ip, then init user info.
func (s *Service3) Info3(c context.Context, arg *model.ArgMid) (res *v1.Info, err error) {
res = new(v1.Info)
err = s.client.Call(c, _info3, arg, res)
return
}
// Card3 receive ArgMid contains mid and real ip, then init user card.
func (s *Service3) Card3(c context.Context, arg *model.ArgMid) (res *v1.Card, err error) {
res = new(v1.Card)
err = s.client.Call(c, _card3, arg, res)
return
}
// Infos3 receive ArgMids contains mid and real ip, then init user info.
func (s *Service3) Infos3(c context.Context, arg *model.ArgMids) (res map[int64]*v1.Info, err error) {
err = s.client.Call(c, _infos3, arg, &res)
return
}
// InfosByName3 receive ArgMids contains mid and real ip, then init user info.
func (s *Service3) InfosByName3(c context.Context, arg *model.ArgNames) (res map[int64]*v1.Info, err error) {
err = s.client.Call(c, _infosByName3, arg, &res)
return
}
// Cards3 receive ArgMids contains mid and real ip, then init user card.
func (s *Service3) Cards3(c context.Context, arg *model.ArgMids) (res map[int64]*v1.Card, err error) {
err = s.client.Call(c, _cards3, arg, &res)
return
}
// Profile3 get user profile.
func (s *Service3) Profile3(c context.Context, arg *model.ArgMid) (res *v1.Profile, err error) {
res = new(v1.Profile)
err = s.client.Call(c, _profile3, arg, res)
return
}
// ProfileWithStat3 get user profile.
func (s *Service3) ProfileWithStat3(c context.Context, arg *model.ArgMid) (res *model.ProfileStat, err error) {
res = new(model.ProfileStat)
err = s.client.Call(c, _profileStat3, arg, res)
return
}
// AddExp3 receive ArgExp contains mid, money and reason, then add exp for user.
func (s *Service3) AddExp3(c context.Context, arg *model.ArgExp) (err error) {
err = s.client.Call(c, _addExp3, arg, _noArg)
return
}
// AddMoral3 receive ArgMoral contains mid, moral, oper, reason and remark, then add moral for user.
func (s *Service3) AddMoral3(c context.Context, arg *model.ArgMoral) (err error) {
err = s.client.Call(c, _addMoral3, arg, _noArg)
return
}
// Relation3 get user friend relation.
func (s *Service3) Relation3(c context.Context, arg *model.ArgRelation) (res *model.Relation, err error) {
res = new(model.Relation)
err = s.client.Call(c, _relation3, arg, res)
return
}
// Relations3 batch get user friend relation.
func (s *Service3) Relations3(c context.Context, arg *model.ArgRelations) (res map[int64]*model.Relation, err error) {
err = s.client.Call(c, _relations3, arg, &res)
return
}
// Attentions3 get user attentions ,include followings and whispers.
func (s *Service3) Attentions3(c context.Context, arg *model.ArgMid) (res []int64, err error) {
err = s.client.Call(c, _attentions3, arg, &res)
return
}
// Blacks3 get user black list.
func (s *Service3) Blacks3(c context.Context, arg *model.ArgMid) (res map[int64]struct{}, err error) {
err = s.client.Call(c, _blacks3, arg, &res)
return
}
// RichRelations3 get relation between owner and mids.
func (s *Service3) RichRelations3(c context.Context, arg *model.ArgRichRelation) (res map[int64]int, err error) {
err = s.client.Call(c, _richRelations3, arg, &res)
return
}

View File

@@ -0,0 +1,38 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"rpc.go",
"rpc3.go",
],
importpath = "go-common/app/service/main/account/rpc/server",
tags = ["automanaged"],
deps = [
"//app/service/main/account/api:go_default_library",
"//app/service/main/account/conf:go_default_library",
"//app/service/main/account/model:go_default_library",
"//app/service/main/account/service:go_default_library",
"//library/net/rpc:go_default_library",
"//library/net/rpc/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,28 @@
package server
import (
"go-common/app/service/main/account/conf"
"go-common/app/service/main/account/service"
"go-common/library/net/rpc"
"go-common/library/net/rpc/context"
)
// RPC server
type RPC struct {
s *service.Service
}
// New new rpc server.
func New(c *conf.Config, s *service.Service) (svr *rpc.Server) {
r := &RPC{s: s}
svr = rpc.NewServer(c.RPCServer)
if err := svr.Register(r); err != nil {
panic(err)
}
return
}
// Ping check connection success.
func (r *RPC) Ping(c context.Context, arg *struct{}, res *struct{}) (err error) {
return
}

View File

@@ -0,0 +1,106 @@
package server
import (
v1 "go-common/app/service/main/account/api"
"go-common/app/service/main/account/model"
"go-common/library/net/rpc/context"
)
// Info3 receive ArgMid contains mid and real ip, then init user info.
func (r *RPC) Info3(c context.Context, arg *model.ArgMid, res *v1.Info) (err error) {
var info *v1.Info
if info, err = r.s.Info(c, arg.Mid); err == nil && info != nil {
*res = *info
}
return
}
// Infos3 receive ArgMids contains mids and real ip, then multi init user info.
func (r *RPC) Infos3(c context.Context, a *model.ArgMids, res *map[int64]*v1.Info) (err error) {
*res, err = r.s.Infos(c, a.Mids)
return
}
// InfosByName3 receive ArgMids contains mids and real ip, then multi init user info.
func (r *RPC) InfosByName3(c context.Context, a *model.ArgNames, res *map[int64]*v1.Info) (err error) {
*res, err = r.s.InfosByName(c, a.Names)
return
}
// Card3 receive ArgMid contains mid and real ip, then init user card.
func (r *RPC) Card3(c context.Context, arg *model.ArgMid, res *v1.Card) (err error) {
var card *v1.Card
if card, err = r.s.Card(c, arg.Mid); err == nil && res != nil {
*res = *card
}
return
}
// Cards3 receive ArgMids contains mids and real ip, then multi init user card.
func (r *RPC) Cards3(c context.Context, a *model.ArgMids, res *map[int64]*v1.Card) (err error) {
*res, err = r.s.Cards(c, a.Mids)
return
}
// Profile3 get user audit info.
func (r *RPC) Profile3(c context.Context, arg *model.ArgMid, res *v1.Profile) (err error) {
var p *v1.Profile
if p, err = r.s.Profile(c, arg.Mid); err == nil && p != nil {
*res = *p
}
return
}
// ProfileWithStat3 get user audit info.
func (r *RPC) ProfileWithStat3(c context.Context, arg *model.ArgMid, res *model.ProfileStat) (err error) {
var p *model.ProfileStat
if p, err = r.s.ProfileWithStat(c, arg.Mid); err == nil && p != nil {
*res = *p
}
return
}
// AddExp3 add exp for user.
func (r *RPC) AddExp3(c context.Context, a *model.ArgExp, res *struct{}) (err error) {
err = r.s.AddExp(c, a.Mid, a.Exp, a.Operater, a.Operate, a.Reason)
return
}
// AddMoral3 receive ArgMoral contains mid, moral, oper, reason and remark, then add moral for user.
func (r *RPC) AddMoral3(c context.Context, a *model.ArgMoral, res *struct{}) (err error) {
err = r.s.AddMoral(c, a.Mid, a.Moral, a.Oper, a.Reason, a.Remark)
return
}
// Relation3 get friend relation.
func (r *RPC) Relation3(c context.Context, a *model.ArgRelation, res *model.Relation) (err error) {
var rl *model.Relation
if rl, err = r.s.Relation(c, a.Mid, a.Owner); err == nil && rl != nil {
*res = *rl
}
return
}
// Attentions3 get attentions list ,including following and whisper.
func (r *RPC) Attentions3(c context.Context, a *model.ArgMid, res *[]int64) (err error) {
*res, err = r.s.Attentions(c, a.Mid)
return
}
// Blacks3 get user black list.
func (r *RPC) Blacks3(c context.Context, a *model.ArgMid, res *map[int64]struct{}) (err error) {
*res, err = r.s.Blacks(c, a.Mid)
return
}
// Relations3 get friend relations.
func (r *RPC) Relations3(c context.Context, a *model.ArgRelations, res *map[int64]*model.Relation) (err error) {
*res, err = r.s.Relations(c, a.Mid, a.Owners)
return
}
// RichRelations3 get friend relations.
func (r *RPC) RichRelations3(c context.Context, a *model.ArgRichRelation, res *map[int64]int) (err error) {
*res, err = r.s.RichRelations2(c, a.Owner, a.Mids)
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 = ["server.go"],
importpath = "go-common/app/service/main/account/server/grpc",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/account/api:go_default_library",
"//app/service/main/account/conf:go_default_library",
"//app/service/main/account/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,181 @@
package grpc
import (
"context"
pb "go-common/app/service/main/account/api"
"go-common/app/service/main/account/conf"
"go-common/app/service/main/account/service"
"go-common/library/net/rpc/warden"
)
// New warden rpc server
func New(c *conf.Config, s *service.Service) (svr *warden.Server) {
svr = warden.NewServer(c.WardenServer)
pb.RegisterAccountServer(svr.Server(), &server{as: s})
return svr
}
// Start create and start warden rpc server
func Start(c *conf.Config, s *service.Service) (svr *warden.Server, err error) {
svr = warden.NewServer(c.WardenServer)
pb.RegisterAccountServer(svr.Server(), &server{as: s})
if svr, err = svr.Start(); err != nil {
return
}
return
}
type server struct {
as *service.Service
}
var _ pb.AccountServer = &server{}
func (s *server) Info3(ctx context.Context, req *pb.MidReq) (*pb.InfoReply, error) {
info, err := s.as.Info(ctx, req.Mid)
if err != nil {
return nil, err
}
return &pb.InfoReply{Info: info}, nil
}
func (s *server) Infos3(ctx context.Context, req *pb.MidsReq) (*pb.InfosReply, error) {
infos, err := s.as.Infos(ctx, req.Mids)
if err != nil {
return nil, err
}
return &pb.InfosReply{Infos: infos}, nil
}
func (s *server) InfosByName3(ctx context.Context, req *pb.NamesReq) (*pb.InfosReply, error) {
infos, err := s.as.InfosByName(ctx, req.Names)
if err != nil {
return nil, err
}
return &pb.InfosReply{Infos: infos}, nil
}
func (s *server) Card3(ctx context.Context, req *pb.MidReq) (*pb.CardReply, error) {
card, err := s.as.Card(ctx, req.Mid)
if err != nil {
return nil, err
}
return &pb.CardReply{Card: card}, nil
}
func (s *server) Cards3(ctx context.Context, req *pb.MidsReq) (*pb.CardsReply, error) {
cards, err := s.as.Cards(ctx, req.Mids)
if err != nil {
return nil, err
}
return &pb.CardsReply{Cards: cards}, nil
}
func (s *server) Profile3(ctx context.Context, req *pb.MidReq) (*pb.ProfileReply, error) {
profile, err := s.as.Profile(ctx, req.Mid)
if err != nil {
return nil, err
}
return &pb.ProfileReply{Profile: profile}, nil
}
func (s *server) ProfileWithStat3(ctx context.Context, req *pb.MidReq) (*pb.ProfileStatReply, error) {
profileStat, err := s.as.ProfileWithStat(ctx, req.Mid)
if err != nil {
return nil, err
}
level := pb.LevelInfo{}
level.DeepCopyFromLevelInfo(&profileStat.LevelExp)
return &pb.ProfileStatReply{
Profile: profileStat.Profile,
LevelInfo: level,
Coins: profileStat.Coins,
Follower: profileStat.Follower,
Following: profileStat.Following,
}, nil
}
func (s *server) AddExp3(ctx context.Context, req *pb.ExpReq) (*pb.ExpReply, error) {
return &pb.ExpReply{}, s.as.AddExp(ctx, req.Mid, req.Exp, req.Operater, req.Operate, req.Reason)
}
func (s *server) AddMoral3(ctx context.Context, req *pb.MoralReq) (*pb.MoralReply, error) {
return &pb.MoralReply{}, s.as.AddMoral(ctx, req.Mid, req.Moral, req.Oper, req.Reason, req.Remark)
}
func (s *server) Relation3(ctx context.Context, req *pb.RelationReq) (*pb.RelationReply, error) {
relation, err := s.as.Relation(ctx, req.Mid, req.Owner)
if err != nil {
return nil, err
}
return &pb.RelationReply{Following: relation.Following}, nil
}
func (s *server) Attentions3(ctx context.Context, req *pb.MidReq) (*pb.AttentionsReply, error) {
attentions, err := s.as.Attentions(ctx, req.Mid)
if err != nil {
return nil, err
}
return &pb.AttentionsReply{Attentions: attentions}, nil
}
func (s *server) Blacks3(ctx context.Context, req *pb.MidReq) (*pb.BlacksReply, error) {
blackList, err := s.as.Blacks(ctx, req.Mid)
if err != nil {
return nil, err
}
blackListBool := make(map[int64]bool, len(blackList))
for k := range blackList {
blackListBool[k] = true
}
return &pb.BlacksReply{BlackList: blackListBool}, nil
}
func (s *server) Relations3(ctx context.Context, req *pb.RelationsReq) (*pb.RelationsReply, error) {
relations, err := s.as.Relations(ctx, req.Mid, req.Owners)
if err != nil {
return nil, err
}
newRelations := make(map[int64]*pb.RelationReply, len(relations))
for k, v := range relations {
newRelations[k] = &pb.RelationReply{Following: v.Following}
}
return &pb.RelationsReply{Relations: newRelations}, nil
}
func (s *server) RichRelations3(ctx context.Context, req *pb.RichRelationReq) (*pb.RichRelationsReply, error) {
richRelations, err := s.as.RichRelations2(ctx, req.Owner, req.Mids)
if err != nil {
return nil, err
}
newRichRelations := make(map[int64]int32, len(richRelations))
for k, v := range richRelations {
newRichRelations[k] = int32(v)
}
return &pb.RichRelationsReply{RichRelations: newRichRelations}, nil
}
func (s *server) Vip3(ctx context.Context, req *pb.MidReq) (*pb.VipReply, error) {
vip, err := s.as.Vip(ctx, req.Mid)
if err != nil {
return nil, err
}
reply := new(pb.VipReply)
reply.DeepCopyFromVipInfo(vip)
return reply, nil
}
func (s *server) Vips3(ctx context.Context, req *pb.MidsReq) (*pb.VipsReply, error) {
vips, err := s.as.Vips(ctx, req.Mids)
if err != nil {
return nil, err
}
pvips := make(map[int64]*pb.VipReply, len(vips))
for mid, vip := range vips {
pvip := new(pb.VipReply)
pvip.DeepCopyFromVipInfo(vip)
pvips[mid] = pvip
}
return &pb.VipsReply{Vips: pvips}, nil
}

View File

@@ -0,0 +1,43 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"acc.go",
"http.go",
"v1.go",
"v2.go",
],
importpath = "go-common/app/service/main/account/server/http",
tags = ["automanaged"],
deps = [
"//app/service/main/account/api:go_default_library",
"//app/service/main/account/conf:go_default_library",
"//app/service/main/account/model:go_default_library",
"//app/service/main/account/service:go_default_library",
"//app/service/main/member/model: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",
],
)
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,135 @@
package http
import (
"go-common/app/service/main/account/model"
bm "go-common/library/net/http/blademaster"
)
// info
func info(c *bm.Context) {
p := new(model.ParamMid)
if err := c.Bind(p); err != nil {
return
}
info, err := accSvc.Info(c, p.Mid)
if err != nil {
c.JSON(nil, err)
return
}
c.JSON(info, nil)
}
// infoByName
func infoByName(c *bm.Context) {
p := new(model.ParamNames)
if err := c.Bind(p); err != nil {
return
}
infos, err := accSvc.InfosByName(c, p.Names)
if err != nil {
c.JSON(nil, err)
return
}
c.JSON(infos, nil)
}
// infos
func infos(c *bm.Context) {
p := new(model.ParamMids)
if err := c.Bind(p); err != nil {
return
}
infos, err := accSvc.Infos(c, p.Mids)
if err != nil {
c.JSON(nil, err)
return
}
c.JSON(infos, nil)
}
// card
func card(c *bm.Context) {
p := new(model.ParamMid)
if err := c.Bind(p); err != nil {
return
}
card, err := accSvc.Card(c, p.Mid)
if err != nil {
c.JSON(nil, err)
return
}
c.JSON(card, nil)
}
// cards
func cards(c *bm.Context) {
p := new(model.ParamMids)
if err := c.Bind(p); err != nil {
return
}
cards, err := accSvc.Cards(c, p.Mids)
if err != nil {
c.JSON(nil, err)
return
}
c.JSON(cards, nil)
}
// vip
func vip(c *bm.Context) {
p := new(model.ParamMid)
if err := c.Bind(p); err != nil {
return
}
v, err := accSvc.Vip(c, p.Mid)
if err != nil {
c.JSON(nil, err)
return
}
c.JSON(v, nil)
}
func vips(c *bm.Context) {
p := new(model.ParamMids)
if err := c.Bind(p); err != nil {
return
}
c.JSON(accSvc.Vips(c, p.Mids))
}
// profile
func profile(c *bm.Context) {
p := new(model.ParamMid)
if err := c.Bind(p); err != nil {
return
}
pfl, err := accSvc.Profile(c, p.Mid)
if err != nil {
c.JSON(nil, err)
return
}
c.JSON(pfl, nil)
}
// profileWithStat
func profileWithStat(c *bm.Context) {
p := new(model.ParamMid)
if err := c.Bind(p); err != nil {
return
}
pfl, err := accSvc.ProfileWithStat(c, p.Mid)
if err != nil {
c.JSON(nil, err)
return
}
c.JSON(pfl, nil)
}
// privacy
func privacy(c *bm.Context) {
p := new(model.ParamMid)
if err := c.Bind(p); err != nil {
return
}
c.JSON(accSvc.Privacy(c, p.Mid))
}

View File

@@ -0,0 +1,135 @@
package http
import (
"encoding/json"
"net/http"
"go-common/app/service/main/account/conf"
"go-common/app/service/main/account/model"
"go-common/app/service/main/account/service"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
v "go-common/library/net/http/blademaster/middleware/verify"
)
var (
accSvc *service.Service
verify *v.Verify
)
// Init init account service.
func Init(c *conf.Config, s *service.Service) {
accSvc = s
verify = v.New(c.Verify)
// engine
engine := bm.DefaultServer(c.BM)
innerRouter(engine)
// init inner server
if err := engine.Start(); err != nil {
log.Error("engine.Start() error(%v)", err)
panic(err)
}
}
func filterByAppkey(keys []string) func(*bm.Context) {
allowed := make(map[string]struct{}, len(keys))
for _, k := range keys {
allowed[k] = struct{}{}
}
return func(ctx *bm.Context) {
req := ctx.Request
params := req.Form
appkey := params.Get("appkey")
if _, ok := allowed[appkey]; !ok {
log.Error("appkey: %s try to access %s failed", appkey, req.URL)
ctx.JSON(nil, ecode.AccessDenied)
ctx.Abort()
return
}
}
}
// innerRouter init inner router.
func innerRouter(e *bm.Engine) {
e.Ping(ping)
e.Register(register)
group := e.Group("/x/internal/v3/account", verify.Verify)
{
group.GET("/info", info)
group.GET("/info/by/name", infoByName)
group.GET("/infos", infos)
group.GET("/card", card)
group.GET("/cards", cards)
group.GET("/vip", vip)
group.GET("/vips", vips)
group.GET("/profile", profile)
group.GET("/profile/stat", profileWithStat)
group.GET("/privacy", filterByAppkey(conf.Conf.AppkeyFilter.Privacy), privacy)
group.GET("/cache/del", cacheDel)
group.POST("/cache/clear", cacheClear)
}
v2Group := e.Group("/x/internal/account/v2", verify.Verify)
{
v2Group.GET("/myinfo", v2MyInfo)
v2Group.GET("/userinfo", v2MyInfo)
}
v1Group := e.Group("/x/internal/account", verify.Verify)
{
v1Group.GET("/info", v1Info)
v1Group.GET("/infos", v1Infos)
v1Group.GET("/card", v1Card)
v1Group.GET("/vip", v1Vip)
}
}
// ping check server ok.
func ping(c *bm.Context) {
if err := accSvc.Ping(c); err != nil {
log.Error("ping error(%v)", err)
c.AbortWithStatus(http.StatusServiceUnavailable)
}
}
// register support discovery.
func register(c *bm.Context) {
c.JSON(map[string]struct{}{}, nil)
}
// cache del
func cacheDel(c *bm.Context) {
p := new(model.ParamModify)
if err := c.Bind(p); err != nil {
return
}
c.JSON(nil, accSvc.DelCache(c, p.Mid, p.ModifiedAttr))
}
// cache clear
func cacheClear(c *bm.Context) {
p := new(model.ParamMsg)
if err := c.Bind(p); err != nil {
return
}
var m struct {
New struct {
Mid int64 `json:"mid"`
} `json:"new,omitempty"`
Mid int64 `json:"mid"`
Action string `json:"action"`
}
if err := json.Unmarshal([]byte(p.Msg), &m); err != nil {
c.JSON(nil, err)
return
}
mid := m.Mid
if mid == 0 {
mid = m.New.Mid
}
if mid == 0 {
log.Warn("cache clear no mid msg(%s)", p.Msg)
return
}
log.Info("Try to delete cache with mid: %d and param: %+v", mid, p)
c.JSON(nil, accSvc.DelCache(c, mid, m.Action))
}

View File

@@ -0,0 +1,213 @@
package http
import (
"strconv"
v1 "go-common/app/service/main/account/api"
"go-common/app/service/main/account/model"
bm "go-common/library/net/http/blademaster"
)
// v1Info
func v1Info(c *bm.Context) {
p := new(model.ParamMid)
if err := c.Bind(p); err != nil {
return
}
card, err := accSvc.Card(c, p.Mid)
if err != nil {
c.JSON(nil, err)
return
}
i := &V1Info{}
i.FromCard(card)
c.JSON(i, nil)
}
// v1Infos
func v1Infos(c *bm.Context) {
p := new(model.ParamMids)
if err := c.Bind(p); err != nil {
return
}
cards, err := accSvc.Cards(c, p.Mids)
if err != nil {
c.JSON(nil, err)
return
}
im := make(map[int64]*V1Info, len(cards))
for _, card := range cards {
i := &V1Info{}
i.FromCard(card)
im[card.Mid] = i
}
c.JSON(im, nil)
}
// card
func v1Card(c *bm.Context) {
p := new(model.ParamMid)
if err := c.Bind(p); err != nil {
return
}
ps, err := accSvc.ProfileWithStat(c, p.Mid)
if err != nil {
c.JSON(nil, err)
return
}
card := &V1Card{}
card.FromProfile(ps)
c.JSON(card, nil)
}
// vip
func v1Vip(c *bm.Context) {
p := new(model.ParamMid)
if err := c.Bind(p); err != nil {
return
}
vi, err := accSvc.Vip(c, p.Mid)
if err != nil {
c.JSON(nil, err)
return
}
v := &V1Vip{}
v.FromVip(vi)
c.JSON(v, nil)
}
// V1Info info.
type V1Info struct {
Mid string `json:"mid"`
Name string `json:"uname"`
Sex string `json:"sex"`
Sign string `json:"sign"`
Avatar string `json:"avatar"`
Rank string `json:"rank"`
DisplayRank string `json:"DisplayRank"`
LevelInfo struct {
Cur int `json:"current_level"`
Min int `json:"current_min"`
NowExp int `json:"current_exp"`
NextExp interface{} `json:"next_exp"`
} `json:"level_info"`
Pendant v1.PendantInfo `json:"pendant"`
Nameplate v1.NameplateInfo `json:"nameplate"`
OfficialVerify model.OldOfficial `json:"official_verify"`
Vip struct {
Type int `json:"vipType"`
DueDate int64 `json:"vipDueDate"`
DueRemark string `json:"dueRemark"`
AccessStatus int `json:"accessStatus"`
VipStatus int `json:"vipStatus"`
VipStatusWarn string `json:"vipStatusWarn"`
} `json:"vip"`
}
// FromCard from card.
func (i *V1Info) FromCard(c *v1.Card) {
i.Mid = strconv.FormatInt(c.Mid, 10)
i.Name = c.Name
i.Sex = c.Sex
i.Sign = c.Sign
i.Avatar = c.Face
i.Rank = strconv.FormatInt(int64(c.Rank), 10)
i.DisplayRank = "0"
i.LevelInfo.Cur = int(c.Level)
i.LevelInfo.Min = 0
i.LevelInfo.NowExp = 0
i.LevelInfo.NextExp = 0
i.Pendant = c.Pendant
i.Nameplate = c.Nameplate
i.OfficialVerify = model.CvtOfficial(c.Official)
i.Vip.Type = int(c.Vip.Type)
i.Vip.VipStatus = int(c.Vip.Status)
i.Vip.DueDate = c.Vip.DueDate
}
// V1Card card
type V1Card struct {
Mid string `json:"mid"`
Name string `json:"name"`
Approve bool `json:"approve"`
Sex string `json:"sex"`
Rank string `json:"rank"`
Face string `json:"face"`
DisplayRank string `json:"DisplayRank"`
Regtime int64 `json:"regtime"`
Spacesta int `json:"spacesta"`
Birthday string `json:"birthday"`
Place string `json:"place"`
Description string `json:"description"`
Article int `json:"article"`
Attentions []int64 `json:"attentions"`
Fans int `json:"fans"`
Friend int `json:"friend"`
Attention int `json:"attention"`
Sign string `json:"sign"`
LevelInfo struct {
Cur int `json:"current_level"`
Min int `json:"current_min"`
NowExp int `json:"current_exp"`
NextExp interface{} `json:"next_exp"`
} `json:"level_info"`
Pendant v1.PendantInfo `json:"pendant"`
Nameplate v1.NameplateInfo `json:"nameplate"`
OfficialVerify model.OldOfficial `json:"official_verify"`
Vip struct {
Type int `json:"vipType"`
DueDate int64 `json:"vipDueDate"`
DueRemark string `json:"dueRemark"`
AccessStatus int `json:"accessStatus"`
VipStatus int `json:"vipStatus"`
VipStatusWarn string `json:"vipStatusWarn"`
} `json:"vip"`
}
// FromProfile from profile.
func (i *V1Card) FromProfile(c *model.ProfileStat) {
i.Mid = strconv.FormatInt(c.Mid, 10)
i.Name = c.Name
i.Sex = c.Sex
i.Sign = c.Sign
i.Face = c.Face
i.Rank = strconv.FormatInt(int64(c.Rank), 10)
i.DisplayRank = "0"
i.Regtime = int64(c.JoinTime)
if c.Silence == 1 {
i.Spacesta = -2
}
i.Attentions = []int64{}
i.Fans = int(c.Follower)
i.Attention = int(c.Following)
i.LevelInfo.Cur = int(c.Level)
i.LevelInfo.Min = int(c.LevelExp.Min)
i.LevelInfo.NowExp = int(c.LevelExp.NowExp)
i.LevelInfo.NextExp = c.LevelExp.NextExp
if c.LevelExp.NowExp == -1 {
i.LevelInfo.NextExp = "--"
}
i.Pendant = c.Pendant
i.Nameplate = c.Nameplate
i.OfficialVerify = model.CvtOfficial(c.Official)
i.Vip.Type = int(c.Vip.Type)
i.Vip.VipStatus = int(c.Vip.Status)
i.Vip.DueDate = c.Vip.DueDate
}
// V1Vip vip
type V1Vip struct {
Type int `json:"vipType"`
DueDate int64 `json:"vipDueDate"`
DueRemark string `json:"dueRemark"`
AccessStatus int `json:"accessStatus"`
VipStatus int `json:"vipStatus"`
VipStatusWarn string `json:"vipStatusWarn"`
}
// FromVip from vip.
func (v *V1Vip) FromVip(vi *v1.VipInfo) {
v.Type = int(vi.Type)
v.VipStatus = int(vi.Status)
v.DueDate = vi.DueDate
}

View File

@@ -0,0 +1,98 @@
package http
import (
v1 "go-common/app/service/main/account/api"
"go-common/app/service/main/account/model"
member "go-common/app/service/main/member/model"
bm "go-common/library/net/http/blademaster"
)
// v2MyInfo
func v2MyInfo(c *bm.Context) {
p := new(model.ParamMid)
if err := c.Bind(p); err != nil {
return
}
ps, err := accSvc.ProfileWithStat(c, p.Mid)
if err != nil {
c.JSON(nil, err)
return
}
info := &V2MyInfo{}
info.FromProfile(ps)
c.JSON(info, nil)
}
// V2MyInfo myinfo.
type V2MyInfo struct {
Mid int64 `json:"mid"`
Name string `json:"uname"`
Face string `json:"face"`
Rank int32 `json:"rank"`
Scores int32 `json:"scores"`
Coins float64 `json:"coins"`
Sex int32 `json:"sex"`
Sign string `json:"sign"`
JoinTime int32 `json:"jointime"`
Spacesta int32 `json:"spacesta"`
Active int32 `json:"active"`
Silence int32 `protobuf:"varint,12,opt,name=Silence,proto3" json:"silence"`
EmailStatus int32 `protobuf:"varint,13,opt,name=EmailStatus,proto3" json:"email_status"`
TelStatus int32 `protobuf:"varint,14,opt,name=TelStatus,proto3" json:"tel_status"`
Identification int32 `protobuf:"varint,15,opt,name=Identification,proto3" json:"identification"`
Moral int32 `protobuf:"varint,16,opt,name=Moral,proto3" json:"moral"`
Birthday string `protobuf:"bytes,17,opt,name=Birthday,proto3" json:"birthday"`
Telephone string `protobuf:"bytes,18,opt,name=Telephone,proto3" json:"telephone"`
Level member.LevelInfo `protobuf:"bytes,19,opt,name=Level" json:"level_info"`
Pendant v1.PendantInfo `protobuf:"bytes,20,opt,name=Pendant" json:"pendant"`
Nameplate v1.NameplateInfo `protobuf:"bytes,21,opt,name=Nameplate" json:"nameplate"`
Official model.OldOfficial `json:"official_verify"`
Vip struct {
Type int32 `protobuf:"varint,1,opt,name=Type,proto3" json:"vipType"`
DueDate int64 `protobuf:"varint,2,opt,name=DueDate,proto3" json:"vipDueDate"`
DueRemark string `protobuf:"bytes,3,opt,name=DueRemark,proto3" json:"dueRemark"`
AccessStatus int32 `protobuf:"varint,4,opt,name=AccessStatus,proto3" json:"accessStatus"`
VipStatus int32 `protobuf:"varint,5,opt,name=VipStatus,proto3" json:"vipStatus"`
VipStatusWarn string `protobuf:"bytes,6,opt,name=VipStatusWarn,proto3" json:"vipStatusWarn"`
} `json:"vip"`
}
// FromProfile from profile.
func (i *V2MyInfo) FromProfile(c *model.ProfileStat) {
i.Mid = c.Mid
i.Name = c.Name
switch c.Sex {
case "男":
i.Sex = 1
case "女":
i.Sex = 2
default:
i.Sex = 0
}
i.Sign = c.Sign
i.Face = c.Face
i.Rank = c.Rank
i.JoinTime = c.JoinTime
i.Silence = c.Silence
if c.Silence == 1 {
i.Spacesta = -2
}
i.EmailStatus = c.EmailStatus
i.TelStatus = c.TelStatus
if c.EmailStatus == 1 || c.TelStatus == 1 {
i.Active = 1
}
i.Identification = c.Identification
i.Coins = c.Coins
i.Moral = c.Moral
i.Level.Cur = c.Level
i.Level.Min = c.LevelExp.Min
i.Level.NowExp = c.LevelExp.NowExp
i.Level.NextExp = c.LevelExp.NextExp
i.Pendant = c.Pendant
i.Nameplate = c.Nameplate
i.Official = model.CvtOfficial(c.Official)
i.Vip.Type = c.Vip.Type
i.Vip.VipStatus = c.Vip.Status
i.Vip.DueDate = c.Vip.DueDate
}

View File

@@ -0,0 +1,72 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"acc.go",
"cache_delay.go",
"exp.go",
"relation.go",
"service.go",
"vip.go",
],
importpath = "go-common/app/service/main/account/service",
tags = ["automanaged"],
deps = [
"//app/service/main/account/api:go_default_library",
"//app/service/main/account/conf:go_default_library",
"//app/service/main/account/dao:go_default_library",
"//app/service/main/account/model:go_default_library",
"//app/service/main/account/model/queue:go_default_library",
"//app/service/main/coin/api/gorpc:go_default_library",
"//app/service/main/coin/model:go_default_library",
"//app/service/main/member/model:go_default_library",
"//app/service/main/relation/model:go_default_library",
"//app/service/main/relation/rpc/client:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/metadata:go_default_library",
"//library/stat/prom:go_default_library",
"//library/sync/errgroup: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"],
)
go_test(
name = "go_default_test",
srcs = [
"acc_test.go",
"exp_test.go",
"relation_test.go",
"service_test.go",
"vip_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/service/main/account/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)

View File

@@ -0,0 +1,159 @@
package service
import (
"context"
v1 "go-common/app/service/main/account/api"
"go-common/app/service/main/account/model"
coin "go-common/app/service/main/coin/model"
member "go-common/app/service/main/member/model"
relation "go-common/app/service/main/relation/model"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/net/metadata"
"go-common/library/sync/errgroup"
)
// Info get info by mid.
func (s *Service) Info(c context.Context, mid int64) (res *v1.Info, err error) {
if res, err = s.dao.Info(c, mid); err == ecode.Degrade {
err = nil
}
return
}
// Card get card by mid.
func (s *Service) Card(c context.Context, mid int64) (res *v1.Card, err error) {
if res, err = s.dao.Card(c, mid); err == ecode.Degrade {
err = nil
}
return
}
// Infos get info by mid.
func (s *Service) Infos(c context.Context, mids []int64) (res map[int64]*v1.Info, err error) {
if res, err = s.dao.Infos(c, mids); err == ecode.Degrade {
err = nil
}
return
}
// Cards get card by mid.
func (s *Service) Cards(c context.Context, mids []int64) (res map[int64]*v1.Card, err error) {
if res, err = s.dao.Cards(c, mids); err == ecode.Degrade {
err = nil
}
return
}
// Profile get profile by mid.
func (s *Service) Profile(c context.Context, mid int64) (res *v1.Profile, err error) {
if res, err = s.dao.Profile(c, mid); err == ecode.Degrade {
err = nil
}
return
}
// InfosByName multi get account info by names from cache otherwise account api.
// NOTE not cache used rarely
func (s *Service) InfosByName(c context.Context, names []string) (map[int64]*v1.Info, error) {
if len(names) > 100 {
names = names[:100]
}
mids, err := s.dao.MidsByName(c, names)
if err != nil {
return nil, err
}
return s.dao.Infos(c, mids)
}
// ProfileWithStat get profile by mid.
func (s *Service) ProfileWithStat(c context.Context, mid int64) (res *model.ProfileStat, err error) {
p, err := s.dao.Profile(c, mid)
if err != nil && err != ecode.Degrade {
// err = errors.Wrap(err, "service profile with stat")
// err = errors.WithStack(err)
return
}
err = nil // NOTE: maybe err == ecode.Degrade
res = &model.ProfileStat{
Profile: p,
}
eg, errCtx := errgroup.WithContext(c)
var le *member.LevelInfo
eg.Go(func() (e error) {
if le, e = s.dao.LevelExp(c, mid); e != nil {
log.Error("s.dao.LevelExp(%d) error(%v)", mid, e)
e = nil
}
return
})
var count float64
eg.Go(func() (e error) {
if count, e = s.coinRPC.UserCoins(errCtx, &coin.ArgCoinInfo{Mid: mid}); e != nil {
log.Error("d.coinRP.UserCoins(%d) err(%v)", mid, e)
e = nil
}
return
})
var rs *relation.Stat
eg.Go(func() (e error) {
if rs, e = s.relRPC.Stat(c, &relation.ArgMid{Mid: mid}); e != nil {
log.Error("d.relRPC.Stat(%d) err(%v)", mid, e)
e = nil
}
return
})
eg.Wait()
if le != nil {
res.LevelExp = *le
}
res.Coins = count
if rs != nil {
res.Following = rs.Following
res.Follower = rs.Follower
}
return
}
// Privacy get privacy by mid.
func (s *Service) Privacy(c context.Context, mid int64) (res *model.Privacy, err error) {
var (
pProfile *model.PassportProfile
rDetail *member.RealnameDetail
eg errgroup.Group
ip = metadata.String(c, metadata.RemoteIP)
)
eg.Go(func() (e error) {
if pProfile, e = s.dao.PassportProfile(c, mid, ip); e != nil {
log.Error("s.dao.PassportProfile(%d) err(%+v)", mid, e)
// e = nil
}
return
})
eg.Go(func() (e error) {
if rDetail, e = s.dao.RealnameDetail(c, mid); e != nil {
log.Error("s.dao.RealnameDetail(%d) err(%+v)", mid, e)
e = nil
}
return
})
if err = eg.Wait(); err != nil {
return
}
res = &model.Privacy{}
if rDetail != nil && rDetail.RealnameBrief != nil {
res.Realname = rDetail.Realname
if rDetail.CardType == 0 {
res.IdentityCard = rDetail.Card
res.IdentitySex = rDetail.Gender
res.HandIMG = rDetail.HandIMG
}
}
if pProfile != nil {
res.Tel = pProfile.Telphone
res.RegTS = pProfile.JoinTime.Time().Unix()
res.RegIP = pProfile.JoinIP
}
return
}

View File

@@ -0,0 +1,64 @@
package service
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestInfo(t *testing.T) {
convey.Convey("Info", t, func() {
res, err := s.Info(context.TODO(), 1)
convey.So(res, convey.ShouldNotBeNil)
convey.So(err, convey.ShouldBeNil)
})
}
func TestCard(t *testing.T) {
convey.Convey("Card", t, func() {
res, err := s.Card(context.TODO(), 1)
convey.So(res, convey.ShouldNotBeNil)
convey.So(err, convey.ShouldBeNil)
})
}
func TestInfos(t *testing.T) {
convey.Convey("Infos", t, func() {
res, err := s.Infos(context.TODO(), []int64{1, 2, 3})
convey.So(res, convey.ShouldNotBeNil)
convey.So(err, convey.ShouldBeNil)
})
}
func TestCards(t *testing.T) {
convey.Convey("Cards", t, func() {
res, err := s.Cards(context.TODO(), []int64{1, 2, 3})
convey.So(res, convey.ShouldNotBeNil)
convey.So(err, convey.ShouldBeNil)
})
}
func TestProfile(t *testing.T) {
convey.Convey("Profile", t, func() {
res, err := s.Profile(context.TODO(), 111003471)
convey.So(res, convey.ShouldNotBeNil)
convey.So(err, convey.ShouldBeNil)
})
}
func TestInfosByName(t *testing.T) {
convey.Convey("InfosByName", t, func() {
res, err := s.InfosByName(context.TODO(), []string{"1", "2"})
convey.So(res, convey.ShouldNotBeNil)
convey.So(err, convey.ShouldBeNil)
})
}
func TestProfileWithStat(t *testing.T) {
convey.Convey("ProfileWithStat", t, func() {
res, err := s.ProfileWithStat(context.TODO(), 111003471)
convey.So(res, convey.ShouldNotBeNil)
convey.So(err, convey.ShouldBeNil)
})
}

View File

@@ -0,0 +1,98 @@
package service
import (
"context"
"time"
"go-common/app/service/main/account/model/queue"
"go-common/library/log"
"go-common/library/stat/prom"
)
// Item is
type Item struct {
Mid int64
Time time.Time
Action string
}
// Compare is
func (i *Item) Compare(other queue.Item) int {
o := asItem(other)
if o == nil {
return -1
}
if i.Time.Equal(o.Time) {
return 0
}
if i.Time.After(o.Time) {
return 1
}
return -1
}
// HashCode is
func (i *Item) HashCode() int64 {
return i.Mid
}
func asItem(in queue.Item) *Item {
o, ok := in.(*Item)
if !ok {
return nil
}
return o
}
func asItems(in []queue.Item) []*Item {
out := make([]*Item, 0, len(in))
for _, i := range in {
item := asItem(i)
if item == nil {
continue
}
out = append(out, item)
}
return out
}
func (s *Service) cachedelayproc(ctx context.Context) {
fiveSeconds := time.Second * 5
t := time.NewTicker(fiveSeconds)
delayed := func(t time.Time) bool {
top := asItem(s.cachepq.Peek())
if top == nil {
log.Info("Empty cache queue top at: %v", t)
return false
}
if t.Sub(top.Time) < fiveSeconds {
log.Info("Top item is in five seconds, skip and waiting for next tick")
return false
}
return true
}
for ti := range t.C {
prom.BusinessInfoCount.State("cachepq-enqueued", int64(s.cachepq.Len()))
if !delayed(ti) {
continue
}
for {
qitems, err := s.cachepq.Get(1)
if err != nil {
log.Error("Failed to get queue items from cache queue: %+v", err)
return
}
items := asItems(qitems)
for _, it := range items {
log.Info("Delete cache in delay queue with item: %+v", it)
s.dao.DelCache(ctx, it.Mid)
}
if s.cachepq.Empty() || !delayed(time.Now()) {
break
}
}
}
}

View File

@@ -0,0 +1,34 @@
package service
import (
"context"
mmodel "go-common/app/service/main/member/model"
"go-common/library/net/metadata"
)
// AddExp add user exp.
func (s *Service) AddExp(c context.Context, mid int64, money float64, operater, operate, reason string) error {
ip := metadata.String(c, metadata.RemoteIP)
arg := &mmodel.ArgAddExp{Mid: mid, Count: money, Operate: operate, Reason: reason, IP: ip}
return s.dao.UpdateExp(c, arg)
}
// AddMoral add user moral.
func (s *Service) AddMoral(c context.Context, mid int64, moral float64, oper, reason, remark string) error {
ip := metadata.String(c, metadata.RemoteIP)
arg := &mmodel.ArgUpdateMoral{Mid: mid, Reason: reason, Remark: remark, IP: ip, IsNotify: true}
delta := int64(moral * 100)
arg.Delta = delta
arg.Origin = mmodel.ReportRewardType
if delta < 0 {
arg.Origin = mmodel.PunishmentType
}
arg.Operator = oper
if len(oper) == 0 {
arg.Operator = "系统"
}
// 目前只支持评论reason_type 后续由业务方传递
arg.ReasonType = mmodel.ReplyReasonType
return s.dao.AddMoral(c, arg)
}

View File

@@ -0,0 +1,22 @@
package service
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestAddExp(t *testing.T) {
convey.Convey("AddExp", t, func() {
err := s.AddExp(context.TODO(), 1, 10, "other", "other", "test")
convey.So(err, convey.ShouldBeNil)
})
}
func TestAddMoral(t *testing.T) {
convey.Convey("AddMoral", t, func() {
err := s.AddMoral(context.TODO(), 1, -10, "other", "other", "test")
convey.So(err, convey.ShouldBeNil)
})
}

View File

@@ -0,0 +1,100 @@
package service
import (
"context"
"go-common/app/service/main/account/model"
relation "go-common/app/service/main/relation/model"
"go-common/library/net/metadata"
"github.com/pkg/errors"
)
// Relation get user relation.
func (s *Service) Relation(c context.Context, mid, fid int64) (r *model.Relation, err error) {
ip := metadata.String(c, metadata.RemoteIP)
arg := &relation.ArgRelation{Mid: mid, Fid: fid, RealIP: ip}
res, err := s.relRPC.Relation(c, arg)
if err != nil {
err = errors.Wrap(err, "service relation")
return
}
r = &model.Relation{}
r.Following = res.Following()
return
}
// Relations get user relations.
func (s *Service) Relations(c context.Context, mid int64, fids []int64) (rs map[int64]*model.Relation, err error) {
ip := metadata.String(c, metadata.RemoteIP)
arg := &relation.ArgRelations{Mid: mid, Fids: fids, RealIP: ip}
res, err := s.relRPC.Relations(c, arg)
if err != nil {
err = errors.Wrap(err, "service relations")
return
}
rs = make(map[int64]*model.Relation, len(res))
for _, fid := range fids {
if f, ok := res[fid]; ok {
rs[fid] = &model.Relation{Following: f.Following()}
} else {
rs[fid] = &model.Relation{Following: false}
}
}
return
}
// RichRelations2 get mid relations of fids.
func (s *Service) RichRelations2(c context.Context, mid int64, fids []int64) (rs map[int64]int, err error) {
ip := metadata.String(c, metadata.RemoteIP)
arg := &relation.ArgRelations{Mid: mid, Fids: fids, RealIP: ip}
res, err := s.relRPC.Relations(c, arg)
if err != nil {
err = errors.Wrap(err, "service rich relation")
return
}
rs = make(map[int64]int, len(res))
for mid, f := range res {
rs[mid] = int(f.Attribute)
}
return
}
// Blacks get user balcks.
func (s *Service) Blacks(c context.Context, mid int64) (rs map[int64]struct{}, err error) {
ip := metadata.String(c, metadata.RemoteIP)
arg := &relation.ArgMid{Mid: mid, RealIP: ip}
res, err := s.relRPC.Blacks(c, arg)
if err != nil {
err = errors.Wrap(err, "service blacks")
return
}
rs = make(map[int64]struct{}, len(res))
for _, r := range res {
rs[r.Mid] = struct{}{}
}
return
}
// Attentions get all attentions list ,include followings and whispers.
func (s *Service) Attentions(c context.Context, mid int64) (mids []int64, err error) {
ip := metadata.String(c, metadata.RemoteIP)
arg := &relation.ArgMid{Mid: mid, RealIP: ip}
rls, err := s.relRPC.Followings(c, arg)
if err != nil {
err = errors.Wrap(err, "service attentions")
return
}
for _, rl := range rls {
mids = append(mids, rl.Mid)
}
whs, err := s.relRPC.Whispers(c, arg)
if err != nil {
err = errors.Wrap(err, "service whispers")
return
}
for _, wh := range whs {
mids = append(mids, wh.Mid)
}
return
}

View File

@@ -0,0 +1,48 @@
package service
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestRelation(t *testing.T) {
convey.Convey("Relation", t, func() {
res, err := s.Relation(context.TODO(), 1, 2)
convey.So(res, convey.ShouldNotBeNil)
convey.So(err, convey.ShouldBeNil)
})
}
func TestRelations(t *testing.T) {
convey.Convey("Relations", t, func() {
res, err := s.Relations(context.TODO(), 1, []int64{2, 3})
convey.So(res, convey.ShouldNotBeNil)
convey.So(err, convey.ShouldBeNil)
})
}
func TestRichRelations2(t *testing.T) {
convey.Convey("RichRelations2", t, func() {
res, err := s.RichRelations2(context.TODO(), 1, []int64{2, 3})
convey.So(res, convey.ShouldNotBeNil)
convey.So(err, convey.ShouldBeNil)
})
}
func TestBlacks(t *testing.T) {
convey.Convey("Blacks", t, func() {
res, err := s.Blacks(context.TODO(), 1)
convey.So(res, convey.ShouldNotBeNil)
convey.So(err, convey.ShouldBeNil)
})
}
func TestAttentions(t *testing.T) {
convey.Convey("Attentions", t, func() {
res, err := s.Attentions(context.TODO(), 1)
convey.So(res, convey.ShouldNotBeNil)
convey.So(err, convey.ShouldBeNil)
})
}

View File

@@ -0,0 +1,74 @@
package service
import (
"context"
"time"
"go-common/app/service/main/account/conf"
"go-common/app/service/main/account/dao"
"go-common/app/service/main/account/model/queue"
"go-common/app/service/main/coin/api/gorpc"
"go-common/app/service/main/relation/rpc/client"
mc "go-common/library/cache/memcache"
"go-common/library/log"
"github.com/pkg/errors"
)
// Service http service
type Service struct {
c *conf.Config
dao *dao.Dao
relRPC *relation.Service
coinRPC *coin.Service
cachepq *queue.PriorityQueue
}
// New for new service obj
func New(c *conf.Config) *Service {
s := &Service{
c: c,
dao: dao.New(c),
relRPC: relation.New(c.RelationRPC),
coinRPC: coin.New(c.CoinRPC),
cachepq: queue.NewPriorityQueue(2048, false),
}
go s.cachedelayproc(context.Background())
return s
}
// Ping check server ok
func (s *Service) Ping(c context.Context) (err error) {
return s.dao.Ping(c)
}
// Close dao
func (s *Service) Close() {
s.dao.Close()
}
// DelCache for del user and access cahe
func (s *Service) DelCache(c context.Context, mid int64, action string) error {
defer func() {
item := &Item{
Mid: mid,
Time: time.Now(),
Action: action,
}
switch action {
case "updateVip":
if err := s.cachepq.Put(item); err != nil {
log.Warn("Failed to enqueue cache delay item: %+v: %+v", item, err)
}
}
}()
errs := s.dao.DelCache(context.TODO(), mid)
for _, e := range errs {
if errors.Cause(e) == mc.ErrNotFound {
continue
}
return e
}
return nil
}

View File

@@ -0,0 +1,19 @@
package service
import (
"flag"
"go-common/app/service/main/account/conf"
)
var s *Service
func init() {
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
s = New(conf.Conf)
}

View File

@@ -0,0 +1,18 @@
package service
import (
"context"
v1 "go-common/app/service/main/account/api"
)
// Vip get big member info
func (s *Service) Vip(c context.Context, mid int64) (vip *v1.VipInfo, err error) {
vip, err = s.dao.Vip(c, mid)
return
}
// Vips is
func (s *Service) Vips(ctx context.Context, mids []int64) (map[int64]*v1.VipInfo, error) {
return s.dao.Vips(ctx, mids)
}

View File

@@ -0,0 +1,24 @@
package service
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestVip(t *testing.T) {
convey.Convey("Vip", t, func() {
res, err := s.Vip(context.TODO(), 1)
convey.So(res, convey.ShouldNotBeNil)
convey.So(err, convey.ShouldBeNil)
})
}
func TestVips(t *testing.T) {
convey.Convey("Vips", t, func() {
res, err := s.Vips(context.TODO(), []int64{1, 2, 3})
convey.So(res, convey.ShouldNotBeNil)
convey.So(err, convey.ShouldBeNil)
})
}