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,48 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["message_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/reply/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["message.go"],
importpath = "go-common/app/job/main/reply/dao/message",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/reply/conf:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/xstr:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,175 @@
package message
import (
"context"
"fmt"
"net/url"
"strconv"
"strings"
"time"
"go-common/app/job/main/reply/conf"
"go-common/library/ecode"
"go-common/library/log"
xhttp "go-common/library/net/http/blademaster"
"go-common/library/xstr"
)
const (
// 1 main site related
// 1_1 reply related
// 1_2 at related
// 1_3 report related
//_codeReplyGet = "1_1_1"
_codeReplyDelete = "1_1_2"
_codeReplyLike = "1_1_3"
_codeAt = "1_2_1"
_codeReport = "1_3_1"
_dataTypeReply = 1
_dataTypeAt = 2
_dataTypeLike = 3
_dataTypeSystem = 4
_notifyTypeCnt = 2
)
// Dao message dao.
type Dao struct {
httpCli *xhttp.Client
apiURL string
}
// NewMessageDao new a message dao and return.
func NewMessageDao(c *conf.Config) *Dao {
return &Dao{
httpCli: xhttp.NewClient(c.HTTPClient),
apiURL: c.Host.Message + "/api/notify/send.user.notify.do",
}
}
// Like send a like message.
func (dao *Dao) Like(c context.Context, mid, tomid int64, title, msg, extraInfo string, now time.Time) (err error) {
return dao.send(c, _codeReplyLike, "", title, msg, _dataTypeLike, mid, []int64{tomid}, extraInfo, now.Unix())
}
// Reply send a reply message.
func (dao *Dao) Reply(c context.Context, mc, resID string, mid, tomid int64, title, msg, extraInfo string, now time.Time) (err error) {
return dao.send(c, mc, resID, title, msg, _dataTypeReply, mid, []int64{tomid}, extraInfo, now.Unix())
}
// DeleteReply send delete reply message.
func (dao *Dao) DeleteReply(c context.Context, mid int64, title, msg string, now time.Time) (err error) {
return dao.send(c, _codeReplyDelete, "", title, msg, _dataTypeSystem, 0, []int64{mid}, "", now.Unix())
}
// At send a at message.
func (dao *Dao) At(c context.Context, mid int64, mids []int64, title, msg, extraInfo string, now time.Time) (err error) {
if len(mids) == 0 {
return
}
return dao.send(c, _codeAt, "", title, msg, _dataTypeAt, mid, mids, extraInfo, now.Unix())
}
// AcceptReport send accept report message.
func (dao *Dao) AcceptReport(c context.Context, mid int64, title, msg string, now time.Time) (err error) {
return dao.send(c, _codeReport, "", title, msg, _dataTypeSystem, 0, []int64{mid}, "", now.Unix())
}
// System send a system message.
func (dao *Dao) System(c context.Context, mc, resID string, mid int64, title, msg, info string, now time.Time) (err error) {
return dao.send(c, mc, resID, title, msg, _dataTypeSystem, 0, []int64{mid}, info, now.Unix())
}
func (dao *Dao) send(c context.Context, mc, resID, title, msg string, tp int, pub int64, mids []int64, info string, ts int64) (err error) {
params := url.Values{}
params.Set("type", "json")
params.Set("source", "1")
params.Set("mc", mc)
params.Set("title", title)
params.Set("data_type", strconv.Itoa(tp))
params.Set("context", msg)
params.Set("mid_list", xstr.JoinInts(mids))
params.Set("publisher", strconv.FormatInt(pub, 10))
params.Set("ext_info", info)
if resID != "" {
params.Set("notify_type", fmt.Sprint(_notifyTypeCnt))
params.Set("res_id", resID)
}
var res struct {
Code int `json:"code"`
}
if err = dao.httpCli.Post(c, dao.apiURL, "", params, &res); err != nil {
log.Error("message url(%s) error(%v)", dao.apiURL+"?"+params.Encode(), err)
return
}
if res.Code != ecode.OK.Code() {
log.Error("message url(%s) error(%v)", dao.apiURL+"?"+params.Encode(), res.Code)
err = fmt.Errorf("message send failed")
return
}
log.Info("sendmessage success:%v;code:%d", params, res.Code)
if tp != _dataTypeSystem {
params.Set("mobi_app", "android_i")
if tp == _dataTypeAt {
params.Set("title", converAt(title))
} else if tp == _dataTypeLike {
params.Set("context", convertMsg(msg))
} else if tp == _dataTypeReply {
params.Set("title", convertMsg(title))
params.Set("context", convertMsg(msg))
}
var res1 struct {
Code int `json:"code"`
}
if err = dao.httpCli.Post(c, dao.apiURL, "", params, &res1); err != nil {
log.Error("message url(%s) error(%v)", dao.apiURL+"?"+params.Encode(), err)
return
}
if res1.Code != ecode.OK.Code() {
log.Error("message url(%s) error(%v)", dao.apiURL+"?"+params.Encode(), res1.Code)
err = fmt.Errorf("message send failed")
return
}
log.Info("send international message success:%v;code:%d", params, res1.Code)
}
return
}
func converAt(title string) string {
return strings.Replace(title, "评论中@了你", "評論中@了你", -1)
}
func convertMsg(msg string) string {
rmsg := []rune(msg)
for i, c := range rmsg {
switch c {
case '评':
rmsg[i] = '評'
case '论':
rmsg[i] = '論'
case '赞':
rmsg[i] = '讚'
case '条':
rmsg[i] = '條'
case '专':
rmsg[i] = '專'
case '栏':
rmsg[i] = '欄'
case '数':
rmsg[i] = '數'
case '达':
rmsg[i] = '達'
case '应':
rmsg[i] = '應'
case '点':
rmsg[i] = '點'
case '击':
rmsg[i] = '擊'
default:
continue
}
}
return string(rmsg)
}

View File

@@ -0,0 +1,229 @@
package message
import (
"context"
"flag"
"go-common/app/job/main/reply/conf"
"os"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.community.reply-job")
flag.Set("conf_token", "5deea0665f8a7670b22a719337a39c7d")
flag.Set("tree_id", "2123")
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/reply-job-test.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = NewMessageDao(conf.Conf)
os.Exit(m.Run())
}
func TestMessageNewMessageDao(t *testing.T) {
convey.Convey("NewMessageDao", t, func(ctx convey.C) {
var (
c = conf.Conf
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := NewMessageDao(c)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestMessageLike(t *testing.T) {
convey.Convey("Like", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
tomid = int64(0)
title = ""
msg = ""
extraInfo = ""
now = time.Now()
err error
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err = d.Like(c, mid, tomid, title, msg, extraInfo, now)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(msg, convey.ShouldBeBlank)
})
})
})
}
func TestMessageReply(t *testing.T) {
convey.Convey("Reply", t, func(ctx convey.C) {
var (
c = context.Background()
mc = ""
resID = ""
mid = int64(0)
tomid = int64(0)
title = ""
msg = ""
extraInfo = ""
now = time.Now()
err error
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err = d.Reply(c, mc, resID, mid, tomid, title, msg, extraInfo, now)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(msg, convey.ShouldBeBlank)
})
})
})
}
func TestMessageDeleteReply(t *testing.T) {
convey.Convey("DeleteReply", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
title = ""
msg = ""
now = time.Now()
err error
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err = d.DeleteReply(c, mid, title, msg, now)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(msg, convey.ShouldBeBlank)
})
})
})
}
func TestMessageAt(t *testing.T) {
convey.Convey("At", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
mids = []int64{}
title = ""
msg = ""
extraInfo = ""
now = time.Now()
err error
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err = d.At(c, mid, mids, title, msg, extraInfo, now)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(msg, convey.ShouldBeBlank)
})
})
})
}
func TestMessageAcceptReport(t *testing.T) {
convey.Convey("AcceptReport", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
title = ""
msg = ""
now = time.Now()
err error
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err = d.AcceptReport(c, mid, title, msg, now)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(msg, convey.ShouldBeBlank)
})
})
})
}
func TestMessageSystem(t *testing.T) {
convey.Convey("System", t, func(ctx convey.C) {
var (
c = context.Background()
mc = ""
resID = ""
mid = int64(0)
title = ""
msg = ""
info = ""
now = time.Now()
err error
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err = d.System(c, mc, resID, mid, title, msg, info, now)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(msg, convey.ShouldBeBlank)
})
})
})
}
func TestMessagesend(t *testing.T) {
convey.Convey("send", t, func(ctx convey.C) {
var (
c = context.Background()
mc = ""
resID = ""
title = ""
msg = ""
tp = int(0)
pub = int64(0)
mids = []int64{}
info = ""
ts = int64(0)
err error
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err = d.send(c, mc, resID, title, msg, tp, pub, mids, info, ts)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(msg, convey.ShouldBeBlank)
})
})
})
}
func TestMessageconverAt(t *testing.T) {
convey.Convey("converAt", t, func(ctx convey.C) {
var (
title = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := converAt(title)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldBeBlank)
})
})
})
}
func TestMessageconvertMsg(t *testing.T) {
convey.Convey("convertMsg", t, func(ctx convey.C) {
var (
msg = "评"
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := convertMsg(msg)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldEqual, "評")
})
})
})
}

View File

@@ -0,0 +1,66 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"audio_playlist_test.go",
"audio_test.go",
"bangumi_test.go",
"credit_test.go",
"dao_test.go",
"drawyoo_test.go",
"dynamic_test.go",
"live_test.go",
"topic_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/reply/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"audio.go",
"audio_playlist.go",
"bangumi.go",
"credit.go",
"dao.go",
"drawyoo.go",
"dynamic.go",
"live.go",
"topic.go",
],
importpath = "go-common/app/job/main/reply/dao/notice",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/reply/conf:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,42 @@
package notice
import (
"context"
"fmt"
"net/url"
"strconv"
"go-common/library/log"
)
const (
_urlAudio = "https://m.bilibili.com/audio/au%d"
)
type audio struct {
Title string `json:"title"`
}
// Audio is Audio
func (d *Dao) Audio(c context.Context, oid int64) (title, link string, err error) {
params := url.Values{}
uri := d.urlAudio
params.Set("ids", strconv.FormatInt(oid, 10))
var res struct {
Code int `json:"code"`
Data map[int64]*audio `json:"data"`
}
if err = d.httpClient.Get(c, uri, "", params, &res); err != nil {
log.Error("d.httpClient.Get(%s?%s) error(%v)", uri, params.Encode(), err)
return
}
if res.Data == nil {
err = fmt.Errorf("url:%s code:%d", uri, res.Code)
return
}
if r := res.Data[oid]; r != nil {
title = r.Title
}
link = fmt.Sprintf(_urlAudio, oid)
return
}

View File

@@ -0,0 +1,36 @@
package notice
import (
"context"
"fmt"
"net/url"
"go-common/library/log"
)
const (
_urlAudioPlayList = "https://m.bilibili.com/audio/am%d"
)
// AudioPlayList is show AudioPlay list
func (d *Dao) AudioPlayList(c context.Context, oid int64) (title, link string, err error) {
params := url.Values{}
uri := fmt.Sprintf(d.urlAudioPlaylist, oid)
var res struct {
Code int `json:"code"`
Data *struct {
Title string `json:"title"`
} `json:"data"`
}
if err = d.httpClient.Get(c, uri, "", params, &res); err != nil {
log.Error("d.httpClient.Get(%s?%s) error(%v)", uri, params.Encode(), err)
return
}
if res.Data == nil {
err = fmt.Errorf("url:%s code:%d", uri, res.Code)
return
}
title = res.Data.Title
link = fmt.Sprintf(_urlAudioPlayList, oid)
return
}

View File

@@ -0,0 +1,29 @@
package notice
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestNoticeAudioPlayList(t *testing.T) {
convey.Convey("AudioPlayList", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
title, link, err := d.AudioPlayList(c, oid)
ctx.Convey("Then err should be nil.title,link should not be nil.", func(ctx convey.C) {
if err != nil {
ctx.So(err, convey.ShouldNotBeNil)
} else {
ctx.So(err, convey.ShouldBeNil)
}
ctx.So(link, convey.ShouldNotBeNil)
ctx.So(title, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,29 @@
package notice
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestNoticeAudio(t *testing.T) {
convey.Convey("Audio", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
title, link, err := d.Audio(c, oid)
ctx.Convey("Then err should be nil.title,link should not be nil.", func(ctx convey.C) {
if err != nil {
ctx.So(err, convey.ShouldNotBeNil)
} else {
ctx.So(err, convey.ShouldBeNil)
}
ctx.So(link, convey.ShouldNotBeNil)
ctx.So(title, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,41 @@
package notice
import (
"context"
"fmt"
"net/url"
"strconv"
"go-common/library/log"
)
type bangumi struct {
EpisodeID int64 `json:"episode_id,string"`
SeasonID int64 `json:"season_id"`
Title string `json:"title"`
IndexTitle string `json:"index_title"`
}
// Bangumi return link.
func (d *Dao) Bangumi(c context.Context, oid int64) (title, link string, epid int64, err error) {
params := url.Values{}
params.Set("aids", strconv.FormatInt(oid, 10))
params.Set("platform", "reply")
params.Set("build", "0")
var res struct {
Code int `json:"code"`
Result map[int64]*bangumi `json:"result"`
}
if err = d.httpClient.Get(c, d.urlBangumi, "", params, &res); err != nil {
log.Error("d.httpClient.Get(%s?%s) error(%v)", d.urlBangumi, params.Encode(), err)
return
}
if res.Code != 0 || res.Result == nil {
err = fmt.Errorf("url:%s?%s code:%d", d.urlBangumi, params.Encode(), res.Code)
return
}
if r := res.Result[oid]; r != nil {
epid = r.EpisodeID
}
return
}

View File

@@ -0,0 +1,30 @@
package notice
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestNoticeBangumi(t *testing.T) {
convey.Convey("Bangumi", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
title, link, epid, err := d.Bangumi(c, oid)
ctx.Convey("Then err should be nil.title,link,epid should not be nil.", func(ctx convey.C) {
if err != nil {
ctx.So(err, convey.ShouldNotBeNil)
} else {
ctx.So(err, convey.ShouldBeNil)
}
ctx.So(epid, convey.ShouldNotBeNil)
ctx.So(link, convey.ShouldNotBeNil)
ctx.So(title, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,88 @@
package notice
import (
"context"
"fmt"
"net/url"
"strconv"
"go-common/library/log"
)
const (
_urlBan = "https://www.bilibili.com/blackroom/ban/%d"
_urlNotice = "https://www.bilibili.com/blackroom/notice/%d"
_urlCreditLink = "https://www.bilibili.com/judgement/case/%d"
)
type notice struct {
Title string `json:"title"`
}
type ban struct {
Title string `json:"punishTitle"`
}
type credit struct {
Title string `json:"punishTitle"`
}
// Credit return link.
func (d *Dao) Credit(c context.Context, oid int64) (title, link string, err error) {
params := url.Values{}
params.Set("ids", strconv.FormatInt(oid, 10))
var res struct {
Code int `json:"code"`
Data map[int64]*credit `json:"data"`
}
if err = d.httpClient.Get(c, d.urlCredit, "", params, &res); err != nil {
log.Error("d.httpClient.Get(%s?%s) error(%v)", d.urlCredit, params.Encode(), err)
return
}
if res.Code != 0 || res.Data == nil {
err = fmt.Errorf("url:%s?%s code:%d", d.urlCredit, params.Encode(), res.Code)
return
}
if r := res.Data[oid]; r != nil {
title = r.Title
}
link = fmt.Sprintf(_urlCreditLink, oid)
return
}
// Notice get blackromm notice info.
func (d *Dao) Notice(c context.Context, oid int64) (title, link string, err error) {
params := url.Values{}
params.Set("ids", strconv.FormatInt(oid, 10))
var res struct {
Code int `json:"code"`
Data map[int64]*notice `json:"data"`
}
if err = d.httpClient.Get(c, d.urlNotice, "", params, &res); err != nil {
log.Error("httpNotice(%s) error(%v)", d.urlNotice, err)
return
}
if r := res.Data[oid]; r != nil {
title = r.Title
}
link = fmt.Sprintf(_urlNotice, oid)
return
}
// Ban get blackroom ban info.
func (d *Dao) Ban(c context.Context, oid int64) (title, link string, err error) {
params := url.Values{}
params.Set("ids", strconv.FormatInt(oid, 10))
var res struct {
Code int `json:"code"`
Data map[int64]*ban `json:"data"`
}
if err = d.httpClient.Get(c, d.urlBan, "", params, &res); err != nil {
log.Error("httpNotice(%s) error(%v)", d.urlBan, err)
return
}
if r := res.Data[oid]; r != nil {
title = r.Title
}
link = fmt.Sprintf(_urlBan, oid)
return
}

View File

@@ -0,0 +1,71 @@
package notice
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestCreditBan(t *testing.T) {
convey.Convey("Audio", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
title, link, err := d.Ban(c, oid)
ctx.Convey("Then err should be nil.title,link should not be nil.", func(ctx convey.C) {
if err != nil {
ctx.So(err, convey.ShouldNotBeNil)
} else {
ctx.So(err, convey.ShouldBeNil)
}
ctx.So(link, convey.ShouldNotBeNil)
ctx.So(title, convey.ShouldNotBeNil)
})
})
})
}
func TestNoticeCredit(t *testing.T) {
convey.Convey("Audio", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
title, link, err := d.Credit(c, oid)
ctx.Convey("Then err should be nil.title,link should not be nil.", func(ctx convey.C) {
if err != nil {
ctx.So(err, convey.ShouldNotBeNil)
} else {
ctx.So(err, convey.ShouldBeNil)
}
ctx.So(link, convey.ShouldNotBeNil)
ctx.So(title, convey.ShouldNotBeNil)
})
})
})
}
func TestNoticeCreditNotice(t *testing.T) {
convey.Convey("Audio", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
title, link, err := d.Notice(c, oid)
ctx.Convey("Then err should be nil.title,link should not be nil.", func(ctx convey.C) {
if err != nil {
ctx.So(err, convey.ShouldNotBeNil)
} else {
ctx.So(err, convey.ShouldBeNil)
}
ctx.So(link, convey.ShouldNotBeNil)
ctx.So(title, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,53 @@
package notice
import (
"go-common/app/job/main/reply/conf"
bm "go-common/library/net/http/blademaster"
)
// Dao activity dao.
type Dao struct {
c *conf.Config
urlLiveSmallVideo string
urlLiveActivity string
urlLiveNotice string
urlLivePicture string
urlCredit string
urlTopic string
urlActivity string
urlActivitySub string
urlDrwayoo string
urlDynamic string
urlNotice string
urlBan string
urlBangumi string
urlAudio string
urlAudioPlaylist string
httpClient *bm.Client
drawyooHTTPClient *bm.Client
}
// New new a dao and return.
func New(c *conf.Config) *Dao {
return &Dao{
c: c,
// http
urlLiveSmallVideo: c.Host.LiveVC + "/clip/v1/video/detail",
urlLiveActivity: c.Host.LiveAct + "/comment/v1/relation/get_by_id",
urlLiveNotice: c.Host.LiveVC + "/news/v1/notice/info",
urlLivePicture: c.Host.LiveVC + "/link_draw/v1/doc/detail",
urlCredit: c.Host.API + "/x/internal/credit/blocked/cases",
urlTopic: c.Host.Activity + "/activity/page/one/%d",
urlActivity: c.Host.Activity + "/activity/page/one/%d",
urlActivitySub: c.Host.Activity + "/activity/subject/url",
urlDrwayoo: c.Host.DrawYoo + "/api/pushS",
urlDynamic: c.Host.LiveVC + "/dynamic_repost/v0/dynamic_repost/ftch_rp_cont?dynamic_ids[]=%d",
urlNotice: c.Host.API + "/x/internal/credit/publish/infos",
urlBan: c.Host.API + "/x/internal/credit/blocked/infos",
urlBangumi: c.Host.Bangumi + "/api/inner/aid_episodes_v2",
urlAudio: c.Host.API + "/x/internal/v1/audio/songs/batch",
urlAudioPlaylist: c.Host.API + "/x/internal/v1/audio/menus/%d",
httpClient: bm.NewClient(c.HTTPClient),
drawyooHTTPClient: bm.NewClient(c.DrawyooHTTPClient),
}
}

View File

@@ -0,0 +1,34 @@
package notice
import (
"flag"
"go-common/app/job/main/reply/conf"
"os"
"testing"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.community.reply-job")
flag.Set("conf_token", "5deea0665f8a7670b22a719337a39c7d")
flag.Set("tree_id", "2123")
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/reply-job-test.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
os.Exit(m.Run())
}

View File

@@ -0,0 +1,35 @@
package notice
import (
"context"
"fmt"
"net/url"
"strconv"
"go-common/library/log"
)
// Drawyoo return link.
func (d *Dao) Drawyoo(c context.Context, hid int64) (title, link string, err error) {
params := url.Values{}
params.Set("hid", strconv.FormatInt(hid, 10))
params.Set("act", "getHidInfo")
var res struct {
State int `json:"state"`
Data []*struct {
Title string `json:"title"`
Link string `json:"link"`
} `json:"data"`
}
if err = d.drawyooHTTPClient.Post(c, d.urlDrwayoo, "", params, &res); err != nil {
log.Error("d.httpClient.Get(%s?%s) error(%v)", d.urlDrwayoo, params.Encode(), err)
return
}
if len(res.Data) == 0 {
err = fmt.Errorf("url:%s code:%d", d.urlDrwayoo, res.State)
return
}
title = res.Data[0].Title
link = res.Data[0].Link
return
}

View File

@@ -0,0 +1,29 @@
package notice
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestNoticeDrawyoo(t *testing.T) {
convey.Convey("Drawyoo", t, func(ctx convey.C) {
var (
c = context.Background()
hid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
title, link, err := d.Drawyoo(c, hid)
ctx.Convey("Then err should be nil.title,link should not be nil.", func(ctx convey.C) {
if err != nil {
ctx.So(err, convey.ShouldNotBeNil)
} else {
ctx.So(err, convey.ShouldBeNil)
}
ctx.So(link, convey.ShouldNotBeNil)
ctx.So(title, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,43 @@
package notice
import (
"context"
"fmt"
"net/url"
"go-common/library/log"
)
const (
_dynamicLink = "https://t.bilibili.com/%d"
)
// Dynamic return link and content.
func (d *Dao) Dynamic(c context.Context, oid int64) (content, link string, err error) {
params := url.Values{}
uri := fmt.Sprintf(d.urlDynamic, oid)
var res struct {
Code int `json:"code"`
Data *struct {
Pairs []struct {
DynamicID int64 `json:"dynamic_id"`
Content string `json:"rp_cont"`
Type int32 `json:"type"`
} `json:"pairs"`
TotalCount int64 `json:"total_count"`
} `json:"data,omitempty"`
Message string `json:"message"`
}
if err = d.httpClient.Get(c, uri, "", params, &res); err != nil {
log.Error("d.httpClient.Get(%s?%s) error(%v)", uri, params.Encode(), err)
return
}
if res.Code != 0 || res.Data == nil || len(res.Data.Pairs) == 0 {
err = fmt.Errorf("get dynamic failed!url:%s?%s code:%d message:%s pairs:%v", uri, params.Encode(), res.Code, res.Message, res.Data.Pairs)
return
}
content = res.Data.Pairs[0].Content
link = fmt.Sprintf(_dynamicLink, oid)
return
}

View File

@@ -0,0 +1,29 @@
package notice
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestNoticeDynamic(t *testing.T) {
convey.Convey("Dynamic", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
content, link, err := d.Dynamic(c, oid)
ctx.Convey("Then err should be nil.content,link should not be nil.", func(ctx convey.C) {
if err != nil {
ctx.So(err, convey.ShouldNotBeNil)
} else {
ctx.So(err, convey.ShouldBeNil)
}
ctx.So(link, convey.ShouldNotBeNil)
ctx.So(content, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,117 @@
package notice
import (
"context"
"fmt"
"net/url"
"strconv"
"go-common/library/log"
)
const (
_liveSmallVideoLink = "http://vc.bilibili.com/video/%d"
_liveNoticeLink = "http://link.bilibili.com/p/eden/news#/newsdetail?id=%d"
_livePictureLink = "http://h.bilibili.com/ywh/%d"
)
// LiveSmallVideo return link.
func (d *Dao) LiveSmallVideo(c context.Context, oid int64) (title, link string, err error) {
params := url.Values{}
params.Set("video_id", strconv.FormatInt(oid, 10))
var res struct {
Code int `json:"code"`
Data *struct {
Item *struct {
Description string `json:"description"`
} `json:"item"`
} `json:"data"`
}
if err = d.httpClient.Get(c, d.urlLiveSmallVideo, "", params, &res); err != nil {
log.Error("d.httpClient.Get(%s?%s) error(%v)", d.urlLiveSmallVideo, params.Encode(), err)
return
}
if res.Code != 0 || res.Data == nil || res.Data.Item == nil {
err = fmt.Errorf("url:%s?%s code:%d", d.urlLiveSmallVideo, params.Encode(), res.Code)
return
}
title = res.Data.Item.Description
link = fmt.Sprintf(_liveSmallVideoLink, oid)
return
}
// LiveActivity return link.
func (d *Dao) LiveActivity(c context.Context, oid int64) (title, link string, err error) {
params := url.Values{}
params.Set("id", strconv.FormatInt(oid, 10))
var res struct {
Code int `json:"code"`
Data *struct {
Name string `json:"name"`
URL string `json:"url"`
} `json:"data"`
}
if err = d.httpClient.Get(c, d.urlLiveActivity, "", params, &res); err != nil {
log.Error("d.httpClient.Get(%s?%s) error(%v)", d.urlLiveActivity, params.Encode(), err)
return
}
if res.Code != 0 || res.Data == nil {
err = fmt.Errorf("url:%s?%s code:%d", d.urlLiveActivity, params.Encode(), res.Code)
return
}
title = res.Data.Name
link = res.Data.URL
return
}
// LiveNotice return link.
func (d *Dao) LiveNotice(c context.Context, oid int64) (title, link string, err error) {
params := url.Values{}
params.Set("id", strconv.FormatInt(oid, 10))
var res struct {
Code int `json:"code"`
Data *struct {
Title string `json:"title"`
} `json:"data"`
}
if err = d.httpClient.Get(c, d.urlLiveNotice, "", params, &res); err != nil {
log.Error("d.httpClient.Get(%s?%s) error(%v)", d.urlLiveNotice, params.Encode(), err)
return
}
if res.Code != 0 || res.Data == nil {
err = fmt.Errorf("url:%s?%s code:%d", d.urlLiveNotice, params.Encode(), res.Code)
return
}
title = res.Data.Title
link = fmt.Sprintf(_liveNoticeLink, oid)
return
}
// LivePicture return link.
func (d *Dao) LivePicture(c context.Context, oid int64) (title, link string, err error) {
params := url.Values{}
params.Set("doc_id", strconv.FormatInt(oid, 10))
var res struct {
Code int `json:"code"`
Data *struct {
Item *struct {
Title string `json:"title"`
Desc string `json:"description"`
} `json:"item"`
} `json:"data"`
}
if err = d.httpClient.Get(c, d.urlLivePicture, "", params, &res); err != nil {
log.Error("d.httpClient.Get(%s?%s) error(%v)", d.urlLivePicture, params.Encode(), err)
return
}
if res.Code != 0 || res.Data == nil || res.Data.Item == nil {
err = fmt.Errorf("url:%s?%s code:%d", d.urlLivePicture, params.Encode(), res.Code)
return
}
title = res.Data.Item.Title
if title == "" {
title = res.Data.Item.Desc
}
link = fmt.Sprintf(_livePictureLink, oid)
return
}

View File

@@ -0,0 +1,92 @@
package notice
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestNoticeLiveSmallVideo(t *testing.T) {
convey.Convey("LiveSmallVideo", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
title, link, err := d.LiveSmallVideo(c, oid)
ctx.Convey("Then err should be nil.title,link should not be nil.", func(ctx convey.C) {
if err != nil {
ctx.So(err, convey.ShouldNotBeNil)
} else {
ctx.So(err, convey.ShouldBeNil)
}
ctx.So(link, convey.ShouldNotBeNil)
ctx.So(title, convey.ShouldNotBeNil)
})
})
})
}
func TestNoticeLiveActivity(t *testing.T) {
convey.Convey("LiveActivity", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
title, link, err := d.LiveActivity(c, oid)
ctx.Convey("Then err should be nil.title,link should not be nil.", func(ctx convey.C) {
if err != nil {
ctx.So(err, convey.ShouldNotBeNil)
} else {
ctx.So(err, convey.ShouldBeNil)
}
ctx.So(link, convey.ShouldNotBeNil)
ctx.So(title, convey.ShouldNotBeNil)
})
})
})
}
func TestNoticeLiveNotice(t *testing.T) {
convey.Convey("LiveNotice", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
title, link, err := d.LiveNotice(c, oid)
ctx.Convey("Then err should be nil.title,link should not be nil.", func(ctx convey.C) {
if err != nil {
ctx.So(err, convey.ShouldNotBeNil)
} else {
ctx.So(err, convey.ShouldBeNil)
}
ctx.So(link, convey.ShouldNotBeNil)
ctx.So(title, convey.ShouldNotBeNil)
})
})
})
}
func TestNoticeLivePicture(t *testing.T) {
convey.Convey("LivePicture", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
title, link, err := d.LivePicture(c, oid)
ctx.Convey("Then err should be nil.title,link should not be nil.", func(ctx convey.C) {
if err != nil {
ctx.So(err, convey.ShouldNotBeNil)
} else {
ctx.So(err, convey.ShouldBeNil)
}
ctx.So(link, convey.ShouldNotBeNil)
ctx.So(title, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,90 @@
package notice
import (
"context"
"fmt"
"net/url"
"strconv"
"go-common/library/log"
)
// Topic return topic link.
func (d *Dao) Topic(c context.Context, oid int64) (title, link string, err error) {
params := url.Values{}
uri := fmt.Sprintf(d.urlTopic, oid)
var res struct {
Code int `json:"code"`
Data *struct {
Title string `json:"name"`
PCLink string `json:"pc_url"`
H5Link string `json:"h5_url"`
} `json:"data"`
}
if err = d.httpClient.Get(c, uri, "", params, &res); err != nil {
log.Error("d.httpClient.Get(%s?%s) error(%v)", uri, params.Encode(), err)
return
}
if res.Data == nil {
err = fmt.Errorf("url:%s code:%d", uri, res.Code)
return
}
title = res.Data.Title
link = res.Data.PCLink
if link == "" {
link = res.Data.H5Link
}
return
}
// Activity return topic link.
func (d *Dao) Activity(c context.Context, oid int64) (title, link string, err error) {
params := url.Values{}
uri := fmt.Sprintf(d.urlActivity, oid)
var res struct {
Code int `json:"code"`
Data *struct {
Title string `json:"name"`
PCLink string `json:"pc_url"`
H5Link string `json:"h5_url"`
} `json:"data"`
}
if err = d.httpClient.Get(c, uri, "", params, &res); err != nil {
log.Error("d.httpClient.Get(%s?%s) error(%v)", uri, params.Encode(), err)
return
}
if res.Data == nil {
err = fmt.Errorf("url:%s code:%d", uri, res.Code)
return
}
title = res.Data.Title
link = res.Data.PCLink
if link == "" {
link = res.Data.H5Link
}
return
}
// ActivitySub return topic link.
func (d *Dao) ActivitySub(c context.Context, oid int64) (title, link string, err error) {
params := url.Values{}
params.Set("oid", strconv.FormatInt(oid, 10))
var res struct {
Code int `json:"code"`
Data *struct {
Title string `json:"name"`
Link string `json:"act_url"`
} `json:"data"`
}
if err = d.httpClient.Get(c, d.urlActivitySub, "", params, &res); err != nil {
log.Error("d.httpClient.Get(%s?%s) error(%v)", d.urlActivitySub, params.Encode(), err)
return
}
if res.Data == nil {
err = fmt.Errorf("url:%s code:%d", d.urlActivitySub, res.Code)
return
}
title = res.Data.Title
link = res.Data.Link
return
}

View File

@@ -0,0 +1,71 @@
package notice
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestNoticeTopic(t *testing.T) {
convey.Convey("Topic", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
title, link, err := d.Topic(c, oid)
ctx.Convey("Then err should be nil.title,link should not be nil.", func(ctx convey.C) {
if err != nil {
ctx.So(err, convey.ShouldNotBeNil)
} else {
ctx.So(err, convey.ShouldBeNil)
}
ctx.So(link, convey.ShouldNotBeNil)
ctx.So(title, convey.ShouldNotBeNil)
})
})
})
}
func TestNoticeActivity(t *testing.T) {
convey.Convey("Activity", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
title, link, err := d.Activity(c, oid)
ctx.Convey("Then err should be nil.title,link should not be nil.", func(ctx convey.C) {
if err != nil {
ctx.So(err, convey.ShouldNotBeNil)
} else {
ctx.So(err, convey.ShouldBeNil)
}
ctx.So(link, convey.ShouldNotBeNil)
ctx.So(title, convey.ShouldNotBeNil)
})
})
})
}
func TestNoticeActivitySub(t *testing.T) {
convey.Convey("ActivitySub", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
title, link, err := d.ActivitySub(c, oid)
ctx.Convey("Then err should be nil.title,link should not be nil.", func(ctx convey.C) {
if err != nil {
ctx.So(err, convey.ShouldNotBeNil)
} else {
ctx.So(err, convey.ShouldBeNil)
}
ctx.So(link, convey.ShouldNotBeNil)
ctx.So(title, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,74 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"admin_test.go",
"business_test.go",
"content_test.go",
"dao_test.go",
"databus_test.go",
"memcache_test.go",
"redis_test.go",
"reply_test.go",
"report_test.go",
"subject_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/reply/conf:go_default_library",
"//app/job/main/reply/model/reply:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"admin.go",
"business.go",
"content.go",
"dao.go",
"databus.go",
"fold.go",
"memcache.go",
"redis.go",
"reply.go",
"report.go",
"subject.go",
],
importpath = "go-common/app/job/main/reply/dao/reply",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/reply/conf:go_default_library",
"//app/job/main/reply/model/reply:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/cache/redis:go_default_library",
"//library/database/sql:go_default_library",
"//library/log:go_default_library",
"//library/queue/databus:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,47 @@
package reply
import (
"context"
"time"
"go-common/library/database/sql"
"go-common/library/log"
)
const (
_inAdminSQL = "INSERT INTO reply_admin_log (oid,type,rpID,adminid,result,remark,isnew,isreport,state,ctime,mtime) VALUES(?,?,?,?,?,?,?,?,?,?,?)"
_upAdminSQL = "UPDATE reply_admin_log SET isnew=0,mtime=? WHERE rpID=? AND isnew=1"
)
// AdminDao define admin mysql info
type AdminDao struct {
mysql *sql.DB
}
// NewAdminDao new ReplyReportDao and return.
func NewAdminDao(db *sql.DB) (dao *AdminDao) {
dao = &AdminDao{
mysql: db,
}
return
}
// Insert insert reply report.
func (dao *AdminDao) Insert(c context.Context, adminid, oid, rpID int64, tp int8, result, remark string, isnew, isreport, state int8, now time.Time) (id int64, err error) {
res, err := dao.mysql.Exec(c, _inAdminSQL, oid, tp, rpID, adminid, result, remark, isnew, isreport, state, now, now)
if err != nil {
log.Error("mysqlDB.Exec error(%v)", err)
return
}
return res.LastInsertId()
}
// UpIsNotNew update reply report.
func (dao *AdminDao) UpIsNotNew(c context.Context, rpID int64, now time.Time) (rows int64, err error) {
res, err := dao.mysql.Exec(c, _upAdminSQL, now, rpID)
if err != nil {
log.Error("mysqlDB.Exec error(%v)", err)
return
}
return res.RowsAffected()
}

View File

@@ -0,0 +1,51 @@
package reply
import (
"context"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestReplyInsert(t *testing.T) {
convey.Convey("Insert", t, func(ctx convey.C) {
var (
c = context.Background()
adminid = int64(0)
oid = int64(0)
rpID = int64(0)
tp = int8(0)
result = ""
remark = ""
isnew = int8(0)
isreport = int8(0)
state = int8(0)
now = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
id, err := d.Admin.Insert(c, adminid, oid, rpID, tp, result, remark, isnew, isreport, state, now)
ctx.Convey("Then err should be nil.id should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(id, convey.ShouldNotBeNil)
})
})
})
}
func TestReplyUpIsNotNew(t *testing.T) {
convey.Convey("UpIsNotNew", t, func(ctx convey.C) {
var (
c = context.Background()
rpID = int64(0)
now = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rows, err := d.Admin.UpIsNotNew(c, rpID, now)
ctx.Convey("Then err should be nil.rows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rows, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,44 @@
package reply
import (
"context"
"go-common/app/job/main/reply/model/reply"
"go-common/library/database/sql"
)
const (
_selBussinessSQL = "SELECT type, alias FROM business WHERE state=0"
)
// BusinessDao business dao.
type BusinessDao struct {
db *sql.DB
}
// NewBusinessDao new BusinessDao and return.
func NewBusinessDao(db *sql.DB) (dao *BusinessDao) {
dao = &BusinessDao{
db: db,
}
return
}
// ListBusiness gets all business records
func (dao *BusinessDao) ListBusiness(c context.Context) (business []*reply.Business, err error) {
rows, err := dao.db.Query(c, _selBussinessSQL)
if err != nil {
return
}
defer rows.Close()
business = make([]*reply.Business, 0)
for rows.Next() {
b := new(reply.Business)
if err = rows.Scan(&b.Type, &b.Alias); err != nil {
return
}
business = append(business, b)
}
err = rows.Err()
return
}

View File

@@ -0,0 +1,23 @@
package reply
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestReplyListBusiness(t *testing.T) {
convey.Convey("ListBusiness", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
business, err := d.Business.ListBusiness(c)
ctx.Convey("Then err should be nil.business should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(business, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,66 @@
package reply
import (
"context"
"fmt"
"go-common/app/job/main/reply/model/reply"
"go-common/library/database/sql"
"go-common/library/log"
)
const (
_contSharding int64 = 200
)
const (
_inContSQL = "INSERT IGNORE INTO reply_content_%d (rpid,message,ats,ip,plat,device,version,ctime,mtime,topics) VALUES(?,?,?,?,?,?,?,?,?,?)"
_selContSQL = "SELECT rpid,message,ats,ip,plat,device,topics FROM reply_content_%d WHERE rpid=?"
)
// ContentDao define content mysql stmt
type ContentDao struct {
selContStmts []*sql.Stmt
mysql *sql.DB
}
// NewContentDao new contentDao and return.
func NewContentDao(db *sql.DB) (dao *ContentDao) {
dao = &ContentDao{
mysql: db,
selContStmts: make([]*sql.Stmt, _contSharding),
}
for i := int64(0); i < _contSharding; i++ {
dao.selContStmts[i] = dao.mysql.Prepared(fmt.Sprintf(_selContSQL, i))
}
return
}
func (dao *ContentDao) hit(oid int64) int64 {
return oid % int64(_contSharding)
}
// TxInsert insert reply content by transaction.
func (dao *ContentDao) TxInsert(tx *sql.Tx, oid int64, rc *reply.Content) (rows int64, err error) {
res, err := tx.Exec(fmt.Sprintf(_inContSQL, dao.hit(oid)), rc.RpID, rc.Message, rc.Ats, rc.IP, rc.Plat, rc.Device, rc.Version, rc.CTime, rc.MTime, rc.Topics)
if err != nil {
log.Error("mysqlDB.Exec error(%v)", err)
return
}
return res.RowsAffected()
}
// Get get reply content.
func (dao *ContentDao) Get(c context.Context, oid int64, rpID int64) (rc *reply.Content, err error) {
row := dao.selContStmts[dao.hit(oid)].QueryRow(c, rpID)
rc = &reply.Content{}
if err = row.Scan(&rc.RpID, &rc.Message, &rc.Ats, &rc.IP, &rc.Plat, &rc.Device, &rc.Topics); err != nil {
if err == sql.ErrNoRows {
err = nil
rc = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}

View File

@@ -0,0 +1,43 @@
package reply
import (
"context"
"go-common/app/job/main/reply/model/reply"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestReplyTxInsert1(t *testing.T) {
convey.Convey("TxInsert", t, func(ctx convey.C) {
var (
tx, _ = d.mysql.Begin(context.Background())
oid = int64(0)
rc = &reply.Content{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rows, err := d.Content.TxInsert(tx, oid, rc)
ctx.Convey("Then err should be nil.rows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rows, convey.ShouldNotBeNil)
})
})
tx.Rollback()
})
}
func TestReplyGet1(t *testing.T) {
convey.Convey("Get", t, func(ctx convey.C) {
var (
oid = int64(0)
rpID = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rc, err := d.Content.Get(context.Background(), oid, rpID)
ctx.Convey("Then err should be nil.rc should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rc, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,75 @@
package reply
import (
"context"
"go-common/app/job/main/reply/conf"
"go-common/library/database/sql"
"go-common/library/queue/databus"
)
// Dao define mysql info
type Dao struct {
// memcache
Mc *MemcacheDao
// mysql
mysql *sql.DB
Admin *AdminDao
Content *ContentDao
Report *ReportDao
Reply *RpDao
Subject *SubjectDao
Business *BusinessDao
// redis
Redis *RedisDao
// databus
eventBus *databus.Databus
}
// New new a db and return
func New(c *conf.Config) (d *Dao) {
d = &Dao{
// memchache
Mc: NewMemcacheDao(c.Memcache),
// mysql
mysql: sql.NewMySQL(c.MySQL.Reply),
// redis
Redis: NewRedisDao(c.Redis),
// databus
eventBus: databus.New(c.Databus.Event),
}
d.Admin = NewAdminDao(d.mysql)
d.Content = NewContentDao(d.mysql)
d.Reply = NewReplyDao(d.mysql)
d.Report = NewReportDao(d.mysql)
d.Subject = NewSubjectDao(d.mysql)
d.Business = NewBusinessDao(d.mysql)
return
}
// Ping check db is alive
func (d *Dao) Ping(c context.Context) (err error) {
if err = d.mysql.Ping(c); err != nil {
return
}
if err = d.Redis.Ping(c); err != nil {
return
}
return d.Mc.Ping(c)
}
// Close close all db connection
func (d *Dao) Close() {
if d.Mc.mc != nil {
d.Mc.mc.Close()
}
if d.Redis.redis != nil {
d.Redis.redis.Close()
}
d.mysql.Close()
}
// BeginTran begin mysql transaction
func (d *Dao) BeginTran(c context.Context) (*sql.Tx, error) {
return d.mysql.Begin(c)
}

View File

@@ -0,0 +1,34 @@
package reply
import (
"flag"
"go-common/app/job/main/reply/conf"
"os"
"testing"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.community.reply-job")
flag.Set("conf_token", "5deea0665f8a7670b22a719337a39c7d")
flag.Set("tree_id", "2123")
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/reply-job-test.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
os.Exit(m.Run())
}

View File

@@ -0,0 +1,33 @@
package reply
import (
"context"
"fmt"
model "go-common/app/job/main/reply/model/reply"
"go-common/library/log"
)
type event struct {
Action string `json:"action"`
Mid int64 `json:"mid"`
Subject *model.Subject `json:"subject"`
Reply *model.Reply `json:"reply"`
Report *model.Report `json:"report,omitempty"`
}
// PubEvent pub reply event.
func (d *Dao) PubEvent(c context.Context, action string, mid int64, sub *model.Subject, rp *model.Reply, report *model.Report) error {
e := &event{
Action: action,
Mid: mid,
Subject: sub,
Reply: rp,
Report: report,
}
if sub == nil {
log.Error("PubEvent failed,sub is nil!value: %v %v %v %v", action, mid, rp, report)
return nil
}
return d.eventBus.Send(c, fmt.Sprint(sub.Oid), &e)
}

View File

@@ -0,0 +1,27 @@
package reply
import (
"context"
model "go-common/app/job/main/reply/model/reply"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestReplyPubEvent(t *testing.T) {
convey.Convey("PubEvent", t, func(ctx convey.C) {
var (
action = ""
mid = int64(0)
sub = &model.Subject{}
rp = &model.Reply{}
report = &model.Report{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.PubEvent(context.Background(), action, mid, sub, rp, report)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,44 @@
package reply
import (
"context"
"fmt"
"go-common/app/job/main/reply/model/reply"
"go-common/library/database/sql"
)
const (
_foldedReplies = "SELECT id,oid,type,mid,root,parent,dialog,count,rcount,`like`,floor,state,attr,ctime,mtime FROM reply_%d WHERE oid=? AND type=? AND root=? AND state=12"
_countFoldedReplies = "SELECT COUNT(*) FROM reply_%d WHERE oid=? AND type=? AND root=? AND state=12"
)
// TxCountFoldedReplies ...
func (dao *RpDao) TxCountFoldedReplies(tx *sql.Tx, oid int64, tp int8, root int64) (count int, err error) {
if err = tx.QueryRow(fmt.Sprintf(_countFoldedReplies, dao.hit(oid)), oid, tp, root).Scan(&count); err != nil {
if err == sql.ErrNoRows {
err = nil
}
return
}
return
}
// FoldedReplies ...
func (dao *RpDao) FoldedReplies(ctx context.Context, oid int64, tp int8, root int64) (rps []*reply.Reply, err error) {
rows, err := dao.mysql.Query(ctx, fmt.Sprintf(_foldedReplies, dao.hit(oid)), oid, tp, root)
if err != nil {
return
}
defer rows.Close()
for rows.Next() {
r := new(reply.Reply)
if err = rows.Scan(&r.RpID, &r.Oid, &r.Type, &r.Mid, &r.Root, &r.Parent, &r.Dialog, &r.Count, &r.RCount, &r.Like, &r.Floor, &r.State, &r.Attr, &r.CTime, &r.MTime); err != nil {
return
}
rps = append(rps, r)
}
if err = rows.Err(); err != nil {
return
}
return
}

View File

@@ -0,0 +1,241 @@
package reply
import (
"context"
"fmt"
"strconv"
"time"
"go-common/app/job/main/reply/conf"
model "go-common/app/job/main/reply/model/reply"
"go-common/library/cache/memcache"
"go-common/library/log"
)
const (
_prefixSub = "s_"
_prefixRp = "r_"
_prefixAdminTop = "at_"
_prefixUpperTop = "ut_"
)
// MemcacheDao define memcache info
type MemcacheDao struct {
mc *memcache.Pool
expire int32
topExpire int32
}
// NewMemcacheDao return a new mc dao
func NewMemcacheDao(c *conf.Memcache) *MemcacheDao {
return &MemcacheDao{
mc: memcache.NewPool(c.Config),
expire: int32(time.Duration(c.Expire) / time.Second),
topExpire: int32(time.Duration(c.TopExpire) / time.Second),
}
}
func keyAdminTop(oid int64, tp int8) string {
if oid > _oidOverflow {
return fmt.Sprintf("%s_%d_%d", _prefixAdminTop, oid, tp)
}
return _prefixAdminTop + strconv.FormatInt((oid<<8)|int64(tp), 10)
}
func keyUpperTop(oid int64, tp int8) string {
if oid > _oidOverflow {
return fmt.Sprintf("%s_%d_%d", _prefixUpperTop, oid, tp)
}
return _prefixUpperTop + strconv.FormatInt((oid<<8)|int64(tp), 10)
}
func keySub(oid int64, tp int8) string {
if oid > _oidOverflow {
return fmt.Sprintf("%s_%d_%d", _prefixSub, oid, tp)
}
return _prefixSub + strconv.FormatInt((oid<<8)|int64(tp), 10)
}
func keyRp(rpID int64) string {
return _prefixRp + strconv.FormatInt(rpID, 10)
}
// Ping check connection success.
func (dao *MemcacheDao) Ping(c context.Context) (err error) {
conn := dao.mc.Get(c)
item := memcache.Item{Key: "ping", Value: []byte{1}, Expiration: dao.expire}
err = conn.Set(&item)
conn.Close()
return
}
// AddSubject add subject into memcache.
func (dao *MemcacheDao) AddSubject(c context.Context, subs ...*model.Subject) (err error) {
if len(subs) == 0 {
return
}
conn := dao.mc.Get(c)
for _, sub := range subs {
key := keySub(sub.Oid, sub.Type)
item := &memcache.Item{Key: key, Object: sub, Expiration: dao.expire, Flags: memcache.FlagJSON}
if err = conn.Set(item); err != nil {
log.Error("conn.Set(%s,%v) error(%v)", key, sub, err)
}
}
conn.Close()
return
}
// GetSubject get subject from memcache.
func (dao *MemcacheDao) GetSubject(c context.Context, oid int64, tp int8) (sub *model.Subject, err error) {
key := keySub(oid, tp)
conn := dao.mc.Get(c)
defer conn.Close()
item, err := conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
err = nil
}
return
}
sub = new(model.Subject)
if err = conn.Scan(item, sub); err != nil {
log.Error("conn.Scan(%s) error(%v)", item.Value, err)
sub = nil
}
return
}
// AddReply add reply into memcache.
func (dao *MemcacheDao) AddReply(c context.Context, rs ...*model.Reply) (err error) {
if len(rs) == 0 {
return
}
conn := dao.mc.Get(c)
for _, r := range rs {
key := keyRp(r.RpID)
item := &memcache.Item{Key: key, Object: r, Expiration: dao.expire, Flags: memcache.FlagJSON}
if err = conn.Set(item); err != nil {
log.Error("conn.Set(%s,%v) error(%v)", key, r, err)
}
}
conn.Close()
return
}
// GetTop get subject top reply from memcache
func (dao *MemcacheDao) GetTop(c context.Context, oid int64, tp int8, top uint32) (rp *model.Reply, err error) {
var key string
if top == model.ReplyAttrUpperTop {
key = keyUpperTop(oid, tp)
} else if top == model.ReplyAttrAdminTop {
key = keyAdminTop(oid, tp)
} else {
return
}
conn := dao.mc.Get(c)
defer conn.Close()
item, err := conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
err = nil
}
return
}
rp = new(model.Reply)
if err = conn.Scan(item, &rp); err != nil {
log.Error("conn.Scan(%s) error(%v)", item.Value, err)
rp = nil
}
return
}
// AddTop add top reply into memcache.
func (dao *MemcacheDao) AddTop(c context.Context, rp *model.Reply) (err error) {
if rp == nil {
return
}
var key string
if rp.AttrVal(model.ReplyAttrAdminTop) == 1 {
key = keyAdminTop(rp.Oid, rp.Type)
} else if rp.AttrVal(model.ReplyAttrUpperTop) == 1 {
key = keyUpperTop(rp.Oid, rp.Type)
} else {
return
}
conn := dao.mc.Get(c)
defer conn.Close()
item := &memcache.Item{Key: key, Object: rp, Expiration: dao.topExpire, Flags: memcache.FlagJSON}
if err = conn.Set(item); err != nil {
log.Error("conn.Set(%s,%v) error(%v)", key, rp, err)
}
return
}
// DeleteTop delete topreply from memcache.
func (dao *MemcacheDao) DeleteTop(c context.Context, rp *model.Reply, tp uint32) (err error) {
var key string
if tp == model.SubAttrAdminTop {
key = keyAdminTop(rp.Oid, rp.Type)
} else if tp == model.SubAttrUpperTop {
key = keyUpperTop(rp.Oid, rp.Type)
}
conn := dao.mc.Get(c)
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
} else {
log.Error("conn.Delete(%s) error(%v)", key, err)
}
}
conn.Close()
return
}
// DeleteSub delete sub from memcache.
func (dao *MemcacheDao) DeleteSub(c context.Context, oid int64, tp int8) (err error) {
conn := dao.mc.Get(c)
if err = conn.Delete(keySub(oid, tp)); err != nil {
if err == memcache.ErrNotFound {
err = nil
} else {
log.Error("conn.Delete error(%v)", err)
}
}
conn.Close()
return
}
// DeleteReply delete reply from memcache.
func (dao *MemcacheDao) DeleteReply(c context.Context, rpID int64) (err error) {
conn := dao.mc.Get(c)
if err = conn.Delete(keyRp(rpID)); err != nil {
if err == memcache.ErrNotFound {
err = nil
} else {
log.Error("conn.Delete error(%v)", err)
}
}
conn.Close()
return
}
// GetReply get reply from memcache.
func (dao *MemcacheDao) GetReply(c context.Context, rpID int64) (rp *model.Reply, err error) {
key := keyRp(rpID)
conn := dao.mc.Get(c)
defer conn.Close()
item, err := conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
err = nil
}
return
}
rp = new(model.Reply)
if err = conn.Scan(item, rp); err != nil {
log.Error("conn.Scan(%s) error(%v)", item.Value, err)
rp = nil
}
return
}

View File

@@ -0,0 +1,209 @@
package reply
import (
"context"
model "go-common/app/job/main/reply/model/reply"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestReplykeyAdminTop(t *testing.T) {
convey.Convey("keyAdminTop", t, func(ctx convey.C) {
var (
oid = int64(0)
tp = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyAdminTop(oid, tp)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestReplykeyUpperTop(t *testing.T) {
convey.Convey("keyUpperTop", t, func(ctx convey.C) {
var (
oid = int64(0)
tp = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyUpperTop(oid, tp)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestReplykeySub(t *testing.T) {
convey.Convey("keySub", t, func(ctx convey.C) {
var (
oid = int64(0)
tp = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keySub(oid, tp)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestReplykeyRp(t *testing.T) {
convey.Convey("keyRp", t, func(ctx convey.C) {
var (
rpID = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyRp(rpID)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestReplyPing1(t *testing.T) {
convey.Convey("Ping", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.Ping(c)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestReplyAddSubject(t *testing.T) {
convey.Convey("AddSubject", t, func(ctx convey.C) {
var (
c = context.Background()
subs = &model.Subject{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.Mc.AddSubject(c, subs)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestReplyGetSubject(t *testing.T) {
convey.Convey("GetSubject", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
tp = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
sub, err := d.Mc.GetSubject(c, oid, tp)
ctx.Convey("Then err should be nil.sub should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(sub, convey.ShouldNotBeNil)
})
})
})
}
func TestReplyAddReply(t *testing.T) {
convey.Convey("AddReply", t, func(ctx convey.C) {
var (
c = context.Background()
rs = &model.Reply{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.Mc.AddReply(c, rs)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestReplyGetTop1(t *testing.T) {
convey.Convey("GetTop", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
tp = int8(0)
top = uint32(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rp, err := d.Mc.GetTop(c, oid, tp, top)
ctx.Convey("Then err should be nil.rp should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rp, convey.ShouldBeNil)
})
})
})
}
func TestReplyAddTop(t *testing.T) {
convey.Convey("AddTop", t, func(ctx convey.C) {
var (
c = context.Background()
rp = &model.Reply{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.Mc.AddTop(c, rp)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestReplyDeleteTop(t *testing.T) {
convey.Convey("DeleteTop", t, func(ctx convey.C) {
var (
c = context.Background()
rp = &model.Reply{}
tp = uint32(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.Mc.DeleteTop(c, rp, tp)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestReplyDeleteReply(t *testing.T) {
convey.Convey("DeleteReply", t, func(ctx convey.C) {
var (
c = context.Background()
rpID = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.Mc.DeleteReply(c, rpID)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestReplyGetReply(t *testing.T) {
convey.Convey("GetReply", t, func(ctx convey.C) {
var (
c = context.Background()
rpID = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rp, err := d.Mc.GetReply(c, rpID)
ctx.Convey("Then err should be nil.rp should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rp, convey.ShouldBeNil)
})
})
})
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,862 @@
package reply
import (
"context"
"testing"
"time"
"go-common/app/job/main/reply/model/reply"
"github.com/smartystreets/goconvey/convey"
)
func TestReplykeyDialogIdx(t *testing.T) {
convey.Convey("keyDialogIdx", t, func(ctx convey.C) {
var (
dialogID = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyDialogIdx(dialogID)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestReplykeyIdx(t *testing.T) {
convey.Convey("keyIdx", t, func(ctx convey.C) {
var (
oid = int64(0)
tp = int8(0)
sort = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyIdx(oid, tp, sort)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestReplykeyNewRtIdx(t *testing.T) {
convey.Convey("keyNewRtIdx", t, func(ctx convey.C) {
var (
rpID = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyNewRtIdx(rpID)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestReplykeyAuditIdx(t *testing.T) {
convey.Convey("keyAuditIdx", t, func(ctx convey.C) {
var (
oid = int64(0)
tp = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyAuditIdx(oid, tp)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestReplykeyRpt(t *testing.T) {
convey.Convey("keyRpt", t, func(ctx convey.C) {
var (
mid = int64(0)
now = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyRpt(mid, now)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestReplykeyLike(t *testing.T) {
convey.Convey("keyLike", t, func(ctx convey.C) {
var (
rpID = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyLike(rpID)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestReplykeyUAct(t *testing.T) {
convey.Convey("keyUAct", t, func(ctx convey.C) {
var (
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyUAct(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestReplykeySpamRpRec(t *testing.T) {
convey.Convey("keySpamRpRec", t, func(ctx convey.C) {
var (
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keySpamRpRec(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestReplykeySpamRpDaily(t *testing.T) {
convey.Convey("keySpamRpDaily", t, func(ctx convey.C) {
var (
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keySpamRpDaily(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestReplykeySpamActRec(t *testing.T) {
convey.Convey("keySpamActRec", t, func(ctx convey.C) {
var (
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keySpamActRec(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestReplykeyTopOid(t *testing.T) {
convey.Convey("keyTopOid", t, func(ctx convey.C) {
var (
tp = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyTopOid(tp)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestReplykeyNotifyCnt(t *testing.T) {
convey.Convey("keyNotifyCnt", t, func(ctx convey.C) {
var (
oid = int64(0)
typ = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyNotifyCnt(oid, typ)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestReplykeyMaxLikeCnt(t *testing.T) {
convey.Convey("keyMaxLikeCnt", t, func(ctx convey.C) {
var (
rpid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := keyMaxLikeCnt(rpid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestReplyDelAuditIndexs(t *testing.T) {
convey.Convey("DelAuditIndexs", t, func(ctx convey.C) {
var (
rs = &reply.Reply{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.Redis.DelAuditIndexs(context.Background(), rs)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestReplyAddAuditIndex(t *testing.T) {
convey.Convey("AddAuditIndex", t, func(ctx convey.C) {
var (
rp = &reply.Reply{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.Redis.AddAuditIndex(context.Background(), rp)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestReplyAddFloorIndexEnd(t *testing.T) {
convey.Convey("AddFloorIndexEnd", t, func(ctx convey.C) {
var (
oid = int64(0)
tp = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.Redis.AddFloorIndexEnd(context.Background(), oid, tp)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestReplyAddFloorIndex(t *testing.T) {
convey.Convey("AddFloorIndex", t, func(ctx convey.C) {
var (
oid = int64(0)
tp = int8(0)
rs = &reply.Reply{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.Redis.AddFloorIndex(context.Background(), oid, tp, rs)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestReplyAddCountIndexBatch(t *testing.T) {
convey.Convey("AddCountIndexBatch", t, func(ctx convey.C) {
var (
oid = int64(0)
tp = int8(0)
rs = &reply.Reply{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.Redis.AddCountIndexBatch(context.Background(), oid, tp, rs)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestReplyAddCountIndex(t *testing.T) {
convey.Convey("AddCountIndex", t, func(ctx convey.C) {
var (
oid = int64(0)
tp = int8(0)
rp = &reply.Reply{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.Redis.AddCountIndex(context.Background(), oid, tp, rp)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestReplyAddLikeIndexBatch(t *testing.T) {
convey.Convey("AddLikeIndexBatch", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
tp = int8(0)
rpts map[int64]*reply.Report
rs = &reply.Reply{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.Redis.AddLikeIndexBatch(c, oid, tp, rpts, rs)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestReplyAddLikeIndex(t *testing.T) {
convey.Convey("AddLikeIndex", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
tp = int8(0)
rpts map[int64]*reply.Report
r = &reply.Reply{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.Redis.AddLikeIndex(c, oid, tp, rpts, r)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestReplyAddIndex(t *testing.T) {
convey.Convey("AddIndex", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
tp = int8(0)
rpt = &reply.Report{}
rp = &reply.Reply{}
isRecover bool
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.Redis.AddIndex(c, oid, tp, rpt, rp, isRecover)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestReplyDelIndexBySortType(t *testing.T) {
convey.Convey("DelIndexBySortType", t, func(ctx convey.C) {
var (
c = context.Background()
rp = &reply.Reply{}
sortType = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.Redis.DelIndexBySortType(c, rp, sortType)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestReplyDelIndex(t *testing.T) {
convey.Convey("DelIndex", t, func(ctx convey.C) {
var (
c = context.Background()
rp = &reply.Reply{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.Redis.DelIndex(c, rp)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestReplyAddNewChildIndex(t *testing.T) {
convey.Convey("AddNewChildIndex", t, func(ctx convey.C) {
var (
c = context.Background()
root = int64(0)
rs = &reply.Reply{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.Redis.AddNewChildIndex(c, root, rs)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestReplyAddTopOid(t *testing.T) {
convey.Convey("AddTopOid", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
tp = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.Redis.AddTopOid(c, oid, tp)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestReplyDelTopOid(t *testing.T) {
convey.Convey("DelTopOid", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
tp = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.Redis.DelTopOid(c, oid, tp)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestReplyAddLike(t *testing.T) {
convey.Convey("AddLike", t, func(ctx convey.C) {
var (
c = context.Background()
rpID = int64(0)
ras = &reply.Action{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.Redis.AddLike(c, rpID, ras)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestReplyDelLike(t *testing.T) {
convey.Convey("DelLike", t, func(ctx convey.C) {
var (
c = context.Background()
rpID = int64(0)
ra = &reply.Action{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.Redis.DelLike(c, rpID, ra)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestReplyExpireLike(t *testing.T) {
convey.Convey("ExpireLike", t, func(ctx convey.C) {
var (
c = context.Background()
rpID = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
ok, err := d.Redis.ExpireLike(c, rpID)
ctx.Convey("Then err should be nil.ok should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(ok, convey.ShouldNotBeNil)
})
})
})
}
func TestReplyRange(t *testing.T) {
convey.Convey("Range", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
tp = int8(0)
sort = int8(0)
start = int(0)
end = int(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rpIds, err := d.Redis.Range(c, oid, tp, sort, start, end)
ctx.Convey("Then err should be nil.rpIds should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rpIds, convey.ShouldNotBeNil)
})
})
})
}
func TestReplyFloorEnd(t *testing.T) {
convey.Convey("FloorEnd", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
tp = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
score, found, err := d.Redis.FloorEnd(c, oid, tp)
ctx.Convey("Then err should be nil.score,found should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(found, convey.ShouldNotBeNil)
ctx.So(score, convey.ShouldNotBeNil)
})
})
})
}
func TestReplyMinScore(t *testing.T) {
convey.Convey("MinScore", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
tp = int8(0)
sort = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
score, err := d.Redis.MinScore(c, oid, tp, sort)
ctx.Convey("Then err should be nil.score should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(score, convey.ShouldNotBeNil)
})
})
})
}
func TestReplyCountReplies(t *testing.T) {
convey.Convey("CountReplies", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
tp = int8(0)
sort = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
count, err := d.Redis.CountReplies(c, oid, tp, sort)
ctx.Convey("Then err should be nil.count should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(count, convey.ShouldNotBeNil)
})
})
})
}
func TestReplyExpireDialogIndex(t *testing.T) {
convey.Convey("ExpireDialogIndex", t, func(ctx convey.C) {
var (
c = context.Background()
dialogID = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
ok, err := d.Redis.ExpireDialogIndex(c, dialogID)
ctx.Convey("Then err should be nil.ok should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(ok, convey.ShouldNotBeNil)
})
})
})
}
func TestReplyExpireIndex(t *testing.T) {
convey.Convey("ExpireIndex", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
tp = int8(0)
sort = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
ok, err := d.Redis.ExpireIndex(c, oid, tp, sort)
ctx.Convey("Then err should be nil.ok should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(ok, convey.ShouldNotBeNil)
})
})
})
}
func TestReplyExpireNewChildIndex(t *testing.T) {
convey.Convey("ExpireNewChildIndex", t, func(ctx convey.C) {
var (
c = context.Background()
root = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
ok, err := d.Redis.ExpireNewChildIndex(c, root)
ctx.Convey("Then err should be nil.ok should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(ok, convey.ShouldNotBeNil)
})
})
})
}
func TestReplyAddDialogIndex(t *testing.T) {
convey.Convey("AddDialogIndex", t, func(ctx convey.C) {
var (
c = context.Background()
dialogID = int64(0)
rps = []*reply.Reply{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.Redis.AddDialogIndex(c, dialogID, rps)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestReplySetUserReportCnt(t *testing.T) {
convey.Convey("SetUserReportCnt", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
count = int(0)
now = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.Redis.SetUserReportCnt(c, mid, count, now)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestReplyGetUserReportCnt(t *testing.T) {
convey.Convey("GetUserReportCnt", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
now = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
count, err := d.Redis.GetUserReportCnt(c, mid, now)
ctx.Convey("Then err should be nil.count should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(count, convey.ShouldNotBeNil)
})
})
})
}
func TestReplyGetUserReportTTL(t *testing.T) {
convey.Convey("GetUserReportTTL", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
now = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
ttl, err := d.Redis.GetUserReportTTL(c, mid, now)
ctx.Convey("Then err should be nil.ttl should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(ttl, convey.ShouldNotBeNil)
})
})
})
}
func TestReplyRankIndex(t *testing.T) {
convey.Convey("RankIndex", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
tp = int8(0)
rpID = int64(0)
sort = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rank, err := d.Redis.RankIndex(c, oid, tp, rpID, sort)
ctx.Convey("Then err should be nil.rank should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rank, convey.ShouldNotBeNil)
})
})
})
}
func TestReplyExpireUserAct(t *testing.T) {
convey.Convey("ExpireUserAct", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
ok, err := d.Redis.ExpireUserAct(c, mid)
ctx.Convey("Then err should be nil.ok should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(ok, convey.ShouldNotBeNil)
})
})
})
}
func TestReplyAddUserActs(t *testing.T) {
convey.Convey("AddUserActs", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
actions map[int64]int8
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.Redis.AddUserActs(c, mid, actions)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestReplyDelUserAct(t *testing.T) {
convey.Convey("DelUserAct", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
rpID = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.Redis.DelUserAct(c, mid, rpID)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestReplyUserAct(t *testing.T) {
convey.Convey("UserAct", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
rpID = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
act, err := d.Redis.UserAct(c, mid, rpID)
ctx.Convey("Then err should be nil.act should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(act, convey.ShouldNotBeNil)
})
})
})
}
func TestReplyUserActs(t *testing.T) {
convey.Convey("UserActs", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
rpids = []int64{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
acts, err := d.Redis.UserActs(c, mid, rpids)
ctx.Convey("Then err should be nil.acts should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(acts, convey.ShouldNotBeNil)
})
})
})
}
func TestReplySpamReply(t *testing.T) {
convey.Convey("SpamReply", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rec, daily, err := d.Redis.SpamReply(c, mid)
ctx.Convey("Then err should be nil.rec,daily should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(daily, convey.ShouldNotBeNil)
ctx.So(rec, convey.ShouldNotBeNil)
})
})
})
}
func TestReplySpamAction(t *testing.T) {
convey.Convey("SpamAction", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
code, err := d.Redis.SpamAction(c, mid)
ctx.Convey("Then err should be nil.code should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(code, convey.ShouldNotBeNil)
})
})
})
}
func TestReplyNotifyCnt(t *testing.T) {
convey.Convey("NotifyCnt", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
typ = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
cnt, err := d.Redis.NotifyCnt(c, oid, typ)
ctx.Convey("Then err should be nil.cnt should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(cnt, convey.ShouldNotBeNil)
})
})
})
}
func TestReplySetNotifyCnt(t *testing.T) {
convey.Convey("SetNotifyCnt", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
typ = int8(0)
cnt = int(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.Redis.SetNotifyCnt(c, oid, typ, cnt)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestReplyMaxLikeCnt(t *testing.T) {
convey.Convey("MaxLikeCnt", t, func(ctx convey.C) {
var (
c = context.Background()
rpid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
cnt, err := d.Redis.MaxLikeCnt(c, rpid)
ctx.Convey("Then err should be nil.cnt should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(cnt, convey.ShouldNotBeNil)
})
})
})
}
func TestReplySetMaxLikeCnt(t *testing.T) {
convey.Convey("SetMaxLikeCnt", t, func(ctx convey.C) {
var (
c = context.Background()
rpid = int64(0)
cnt = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.Redis.SetMaxLikeCnt(c, rpid, cnt)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,544 @@
package reply
import (
"context"
"fmt"
"strings"
"time"
"go-common/app/job/main/reply/model/reply"
"go-common/library/database/sql"
"go-common/library/log"
)
const (
_replySharding int64 = 200
)
const (
_inSQL = "INSERT IGNORE INTO reply_%d (id,oid,type,mid,root,parent,dialog,floor,state,attr,ctime,mtime) VALUES(?,?,?,?,?,?,?,?,?,?,?,?)"
_incrCntSQL = "UPDATE reply_%d SET count=count+1,rcount=rcount+1,mtime=? WHERE id=?"
_incrFCntSQL = "UPDATE reply_%d SET count=count+1,mtime=? WHERE id=?"
_incrRCntSQL = "UPDATE reply_%d SET rcount=rcount+1,mtime=? WHERE id=?"
_decrCntSQL = "UPDATE reply_%d SET rcount=rcount-1,mtime=? WHERE id=? AND rcount > 0"
_upStateSQL = "UPDATE reply_%d SET state=?,mtime=? WHERE id=?"
_upAttrSQL = "UPDATE reply_%d SET attr=?,mtime=? WHERE id=?"
_upLikeSQL = "UPDATE reply_%d SET `like`=?,hate=?,mtime=? WHERE id=?"
_selSQLForUpdate = "SELECT id,oid,type,mid,root,parent,dialog,count,rcount,`like`,hate,floor,state,attr,ctime,mtime FROM reply_%d WHERE id=? for update"
_selSQL = "SELECT id,oid,type,mid,root,parent,dialog,count,rcount,`like`,hate,floor,state,attr,ctime,mtime FROM reply_%d WHERE id=?"
_selAllSQL = "SELECT id,rcount,`like`,hate,floor,attr FROM reply_%d WHERE oid=? AND type=? AND root=0 AND state in (0,1,2,5,6)"
_selAllByRtSQL = "SELECT id,oid,type,mid,root,parent,dialog,count,rcount,`like`,hate,floor,state,ctime,mtime FROM reply_%d WHERE oid=? AND type=? AND root=? AND state in (0,1,2,5,6)"
_selIncrByDialogSQL = "SELECT id,oid,type,mid,root,parent,dialog,count,rcount,`like`,hate,floor,state,attr,ctime,mtime FROM reply_%d WHERE oid=? AND type=? AND root=? AND state IN (0,1,2,5,6) AND dialog=? and id>? limit 10000"
_selByRootSQL = "SELECT id,oid,type,mid,root,parent,dialog,count,rcount,`like`,hate,floor,state,ctime,mtime FROM reply_%d WHERE oid=? AND type=? AND root=? AND state=?"
_selTopSQL = "SELECT id,oid,type,mid,root,parent,dialog,count,rcount,`like`,floor,state,attr,ctime,mtime FROM reply_%d WHERE oid=? AND type=? AND root=0 AND attr&(1<<?) limit 1"
_selAllByFloorSQL = "SELECT id,rcount,`like`,hate,floor,attr FROM reply_%d WHERE oid=? AND type=? AND root=0 AND state in (0,1,2,5,6) and floor>=? and floor<?"
_selByFloorLimitSQL = "SELECT id,rcount,`like`,hate,floor,attr FROM reply_%d WHERE oid=? AND type=? AND root=0 AND state in (0,1,2,5,6) and floor<? order by floor desc limit ?"
_selByLikeLimitSQL = "SELECT id,rcount,`like`,hate,floor,attr FROM reply_%d WHERE oid=? AND type=? AND root=0 AND state in (0,1,2,5,6) order by `like` desc limit ?"
_selByCountLimitSQL = "SELECT id,rcount,`like`,hate,floor,attr FROM reply_%d WHERE oid=? AND type=? AND root=0 AND state in (0,1,2,5,6) order by `rcount` desc limit ?"
_fixDialogSelSQL = "select id, parent, floor from reply_%d where oid=? and type=? and root=? and id>? limit ?"
_fixDialogSetSQL = "update reply_%d set dialog=?, mtime=? where id in (%s)"
)
// RpDao define reply db sqlStmt
type RpDao struct {
// stmt
upStateStmt []*sql.Stmt
upLikeStmt []*sql.Stmt
selStmt []*sql.Stmt
selAllStmt []*sql.Stmt
selAllByRtStmt []*sql.Stmt
selByDialogStmt []*sql.Stmt
selByRootStmt []*sql.Stmt
selTopStmt []*sql.Stmt
fixDialogStmt []*sql.Stmt
mysql *sql.DB
}
// NewReplyDao new replyDao and return.
func NewReplyDao(db *sql.DB) (dao *RpDao) {
dao = &RpDao{
mysql: db,
upStateStmt: make([]*sql.Stmt, _replySharding),
upLikeStmt: make([]*sql.Stmt, _replySharding),
selTopStmt: make([]*sql.Stmt, _repSharding),
selStmt: make([]*sql.Stmt, _replySharding),
selAllStmt: make([]*sql.Stmt, _replySharding),
selByDialogStmt: make([]*sql.Stmt, _replySharding),
selAllByRtStmt: make([]*sql.Stmt, _replySharding),
selByRootStmt: make([]*sql.Stmt, _replySharding),
fixDialogStmt: make([]*sql.Stmt, _replySharding),
}
for i := int64(0); i < _replySharding; i++ {
dao.upStateStmt[i] = dao.mysql.Prepared(fmt.Sprintf(_upStateSQL, i))
dao.upLikeStmt[i] = dao.mysql.Prepared(fmt.Sprintf(_upLikeSQL, i))
dao.selStmt[i] = dao.mysql.Prepared(fmt.Sprintf(_selSQL, i))
dao.selAllStmt[i] = dao.mysql.Prepared(fmt.Sprintf(_selAllSQL, i))
dao.selTopStmt[i] = dao.mysql.Prepared(fmt.Sprintf(_selTopSQL, i))
dao.selByDialogStmt[i] = dao.mysql.Prepared(fmt.Sprintf(_selIncrByDialogSQL, i))
dao.selAllByRtStmt[i] = dao.mysql.Prepared(fmt.Sprintf(_selAllByRtSQL, i))
dao.selByRootStmt[i] = dao.mysql.Prepared(fmt.Sprintf(_selByRootSQL, i))
dao.fixDialogStmt[i] = dao.mysql.Prepared(fmt.Sprintf(_fixDialogSelSQL, i))
}
return
}
func (dao *RpDao) hit(oid int64) int64 {
return oid % _replySharding
}
// TxInsert insert reply by transaction.
func (dao *RpDao) TxInsert(tx *sql.Tx, r *reply.Reply) (rows int64, err error) {
res, err := tx.Exec(fmt.Sprintf(_inSQL, dao.hit(r.Oid)), r.RpID, r.Oid, r.Type, r.Mid, r.Root, r.Parent, r.Dialog, r.Floor, r.State, r.Attr, r.CTime, r.MTime)
if err != nil {
log.Error("mysqlDB.Exec error(%v)", err)
return
}
return res.RowsAffected()
}
// TxIncrCount incr count and rcount of reply by transaction.
func (dao *RpDao) TxIncrCount(tx *sql.Tx, oid, rpID int64, now time.Time) (rows int64, err error) {
res, err := tx.Exec(fmt.Sprintf(_incrCntSQL, dao.hit(oid)), now, rpID)
if err != nil {
log.Error("mysqlDB.Exec error(%v)", err)
return
}
return res.RowsAffected()
}
// TxIncrFCount incr rcount of reply by transaction
func (dao *RpDao) TxIncrFCount(tx *sql.Tx, oid, rpID int64, now time.Time) (rows int64, err error) {
res, err := tx.Exec(fmt.Sprintf(_incrFCntSQL, dao.hit(oid)), now, rpID)
if err != nil {
log.Error("mysqlDB.Exec error(%v)", err)
return
}
return res.RowsAffected()
}
// TxIncrRCount incr rcount of reply by transaction
func (dao *RpDao) TxIncrRCount(tx *sql.Tx, oid, rpID int64, now time.Time) (rows int64, err error) {
res, err := tx.Exec(fmt.Sprintf(_incrRCntSQL, dao.hit(oid)), now, rpID)
if err != nil {
log.Error("mysqlDB.Exec error(%v)", err)
return
}
return res.RowsAffected()
}
// TxDecrCount decr rcount of reply by transaction.
func (dao *RpDao) TxDecrCount(tx *sql.Tx, oid, rpID int64, now time.Time) (rows int64, err error) {
res, err := tx.Exec(fmt.Sprintf(_decrCntSQL, dao.hit(oid)), now, rpID)
if err != nil {
log.Error("mysqlDB.Exec error(%v)", err)
return
}
return res.RowsAffected()
}
// GetForUpdate decr rcount of reply by transaction.
func (dao *RpDao) GetForUpdate(tx *sql.Tx, oid, rpID int64) (r *reply.Reply, err error) {
r = new(reply.Reply)
row := tx.QueryRow(fmt.Sprintf(_selSQLForUpdate, dao.hit(oid)), rpID)
if err = row.Scan(&r.RpID, &r.Oid, &r.Type, &r.Mid, &r.Root, &r.Parent, &r.Dialog, &r.Count, &r.RCount, &r.Like, &r.Hate, &r.Floor, &r.State, &r.Attr, &r.CTime, &r.MTime); err != nil {
if err == sql.ErrNoRows {
r = nil
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// TxUpState update reply state by transaction.
func (dao *RpDao) TxUpState(tx *sql.Tx, oid, rpID int64, state int8, now time.Time) (rows int64, err error) {
res, err := tx.Exec(fmt.Sprintf(_upStateSQL, dao.hit(oid)), state, now, rpID)
if err != nil {
log.Error("mysqlDB.Exec error(%v)", err)
return
}
return res.RowsAffected()
}
// UpState update reply state.
func (dao *RpDao) UpState(c context.Context, oid, rpID int64, state int8, now time.Time) (rows int64, err error) {
res, err := dao.upStateStmt[dao.hit(oid)].Exec(c, state, now, rpID)
if err != nil {
log.Error("mysqlDB.Exec error(%v)", err)
return
}
return res.RowsAffected()
}
// TxUpAttr update reply state.
func (dao *RpDao) TxUpAttr(tx *sql.Tx, oid, rpID int64, attr uint32, now time.Time) (rows int64, err error) {
res, err := tx.Exec(fmt.Sprintf(_upAttrSQL, dao.hit(oid)), attr, now, rpID)
if err != nil {
log.Error("mysqlDB.Exec error(%v)", err)
return
}
return res.RowsAffected()
}
// UpLike incr or decr reply like.
func (dao *RpDao) UpLike(c context.Context, oid, rpID int64, like, hate int, now time.Time) (rows int64, err error) {
res, err := dao.upLikeStmt[dao.hit(oid)].Exec(c, like, hate, now, rpID)
if err != nil {
log.Error("mysqlDB.Exec error(%v)", err)
return
}
return res.RowsAffected()
}
// Get get reply.
func (dao *RpDao) Get(c context.Context, oid, rpID int64) (r *reply.Reply, err error) {
r = &reply.Reply{}
row := dao.selStmt[dao.hit(oid)].QueryRow(c, rpID)
if err = row.Scan(&r.RpID, &r.Oid, &r.Type, &r.Mid, &r.Root, &r.Parent, &r.Dialog, &r.Count, &r.RCount, &r.Like, &r.Hate, &r.Floor, &r.State, &r.Attr, &r.CTime, &r.MTime); err != nil {
if err == sql.ErrNoRows {
r = nil
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// GetTop get top reply
func (dao *RpDao) GetTop(c context.Context, oid int64, tp int8, bit uint32) (r *reply.Reply, err error) {
r = &reply.Reply{}
row := dao.selTopStmt[dao.hit(oid)].QueryRow(c, oid, tp, bit)
if err = row.Scan(&r.RpID, &r.Oid, &r.Type, &r.Mid, &r.Root, &r.Parent, &r.Dialog, &r.Count, &r.RCount, &r.Like, &r.Floor, &r.State, &r.Attr, &r.CTime, &r.MTime); err != nil {
if err == sql.ErrNoRows {
r = nil
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// GetByDialog get all reply by dialog
func (dao *RpDao) GetByDialog(c context.Context, oid int64, typ int8, root int64, dialog int64) (rps []*reply.Reply, err error) {
var minID int64
for {
count := 0
rows, err := dao.selByDialogStmt[dao.hit(oid)].Query(c, oid, typ, root, dialog, minID)
if err != nil {
log.Error("mysql.QueryGetByDialog error(%v)", err)
return nil, err
}
defer rows.Close()
for rows.Next() {
r := &reply.Reply{}
if err = rows.Scan(&r.RpID, &r.Oid, &r.Type, &r.Mid, &r.Root, &r.Parent, &r.Dialog, &r.Count, &r.RCount, &r.Like, &r.Hate, &r.Floor, &r.State, &r.Attr, &r.CTime, &r.MTime); err != nil {
log.Error("row.Scan() error(%v)", err)
return nil, err
}
rps = append(rps, r)
count++
if r.RpID > minID {
minID = r.RpID
}
}
if err = rows.Err(); err != nil {
log.Error("mysql rows.Err() error(%v)", err)
return nil, err
}
// 每次查10000个直到某一次查出来count小于10000
if count < 10000 {
break
}
}
return
}
// GetAllInSlice GetAllInSlice
func (dao *RpDao) GetAllInSlice(c context.Context, oid int64, typ int8, maxFloor int, shard int) (rs []*reply.Reply, err error) {
if shard < 1 {
log.Error("shard(%d) is too small", shard)
return nil, fmt.Errorf("shard(%d) is too small", shard)
}
start := 1
startTs := time.Now()
for {
if start > maxFloor {
nowTs := time.Now()
if nowTs.Sub(startTs) > time.Second*3 {
log.Warn("GetAllInSlice (%d,%d,%d,%d) running over 3 secs,total time is:%v", oid, typ, maxFloor, shard, nowTs.Sub(startTs))
}
return
}
end := start + shard
if end > maxFloor {
end = maxFloor + 1
}
var result []*reply.Reply
result, err = dao.GetAllByFloor(c, oid, typ, start, end)
if err != nil {
//try again
result, err = dao.GetAllByFloor(c, oid, typ, start, end)
if err != nil {
return
}
}
rs = append(rs, result...)
start += shard
}
}
// GetByFloorLimit GetByFloorLimit
func (dao *RpDao) GetByFloorLimit(ctx context.Context, oid int64, typ int8, floor int, limit int) (rs []*reply.Reply, err error) {
lastFloor := floor
for lastFloor > 1 && limit > 0 {
count := _maxCount
if limit <= _maxCount {
count = limit
}
limit -= _maxCount
var temp []*reply.Reply
temp, err = dao.getByFloorLimit(ctx, oid, typ, lastFloor, count)
if err != nil {
return
}
if len(temp) > 0 {
lastFloor = temp[len(temp)-1].Floor
rs = append(rs, temp...)
}
if len(temp) < count {
break
}
}
return
}
func (dao *RpDao) getByFloorLimit(ctx context.Context, oid int64, typ int8, floor int, limit int) (rs []*reply.Reply, err error) {
rows, err := dao.mysql.Query(ctx, fmt.Sprintf(_selByFloorLimitSQL, dao.hit(oid)), oid, typ, floor, limit)
if err != nil {
log.Error("mysql.Query %s error(%v)", _selByFloorLimitSQL, err)
return
}
defer rows.Close()
for rows.Next() {
r := &reply.Reply{}
if err = rows.Scan(&r.RpID, &r.RCount, &r.Like, &r.Hate, &r.Floor, &r.Attr); err != nil {
log.Error("row.Scan error(%v)", err)
return
}
rs = append(rs, r)
}
if err = rows.Err(); err != nil {
log.Error("rows.err error(%v)", err)
return
}
return
}
// GetByLikeLimit GetByLikeLimit
func (dao *RpDao) GetByLikeLimit(ctx context.Context, oid int64, typ int8, limit int) (rs []*reply.Reply, err error) {
rows, err := dao.mysql.Query(ctx, fmt.Sprintf(_selByLikeLimitSQL, dao.hit(oid)), oid, typ, limit)
if err != nil {
log.Error("mysql.Query error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
r := &reply.Reply{}
if err = rows.Scan(&r.RpID, &r.RCount, &r.Like, &r.Hate, &r.Floor, &r.Attr); err != nil {
log.Error("row.Scan error(%v)", err)
return
}
rs = append(rs, r)
}
if err = rows.Err(); err != nil {
log.Error("rows.err error(%v)", err)
return
}
return
}
// GetByCountLimit GetByCountLimit
func (dao *RpDao) GetByCountLimit(ctx context.Context, oid int64, typ int8, limit int) (rs []*reply.Reply, err error) {
rows, err := dao.mysql.Query(ctx, fmt.Sprintf(_selByCountLimitSQL, dao.hit(oid)), oid, typ, limit)
if err != nil {
log.Error("mysql.Query error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
r := &reply.Reply{}
if err = rows.Scan(&r.RpID, &r.RCount, &r.Like, &r.Hate, &r.Floor, &r.Attr); err != nil {
log.Error("row.Scan error(%v)", err)
return
}
rs = append(rs, r)
}
if err = rows.Err(); err != nil {
log.Error("rows.err error(%v)", err)
return
}
return
}
// GetAllByFloor GetAllByFloor
func (dao *RpDao) GetAllByFloor(ctx context.Context, oid int64, typ int8, start int, end int) (rs []*reply.Reply, err error) {
rows, err := dao.mysql.Query(ctx, fmt.Sprintf(_selAllByFloorSQL, dao.hit(oid)), oid, typ, start, end)
if err != nil {
log.Error("mysql.Query error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
r := &reply.Reply{}
if err = rows.Scan(&r.RpID, &r.RCount, &r.Like, &r.Hate, &r.Floor, &r.Attr); err != nil {
log.Error("row.Scan error(%v)", err)
return
}
rs = append(rs, r)
}
if err = rows.Err(); err != nil {
log.Error("rows.err error(%v)", err)
return
}
return
}
// GetAll get all replies.
func (dao *RpDao) GetAll(c context.Context, oid int64, tp int8) (rs []*reply.Reply, err error) {
rows, err := dao.selAllStmt[dao.hit(oid)].Query(c, oid, tp)
if err != nil {
log.Error("mysql.Query error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
r := &reply.Reply{}
if err = rows.Scan(&r.RpID, &r.RCount, &r.Like, &r.Hate, &r.Floor, &r.Attr); err != nil {
log.Error("row.Scan error(%v)", err)
return
}
rs = append(rs, r)
}
if err = rows.Err(); err != nil {
log.Error("rows.err error(%v)", err)
return
}
return
}
// GetAllByRoot get all replies by root reply.
func (dao *RpDao) GetAllByRoot(c context.Context, oid, rpID int64, tp int8) (rs []*reply.Reply, err error) {
rows, err := dao.selAllByRtStmt[dao.hit(oid)].Query(c, oid, tp, rpID)
if err != nil {
log.Error("mysql.Query error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
r := &reply.Reply{}
if err = rows.Scan(&r.RpID, &r.Oid, &r.Type, &r.Mid, &r.Root, &r.Parent, &r.Dialog, &r.Count, &r.RCount, &r.Like, &r.Hate, &r.Floor, &r.State, &r.CTime, &r.MTime); err != nil {
log.Error("row.Scan error(%v)", err)
return
}
rs = append(rs, r)
}
if err = rows.Err(); err != nil {
log.Error("rows.err error(%v)", err)
return
}
return
}
// GetsByRoot get all replies by root reply.
func (dao *RpDao) GetsByRoot(c context.Context, oid, rpID int64, tp, state int8) (rs []*reply.Reply, err error) {
rows, err := dao.selByRootStmt[dao.hit(oid)].Query(c, oid, tp, rpID, state)
if err != nil {
log.Error("mysql.Query error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
r := &reply.Reply{}
if err = rows.Scan(&r.RpID, &r.Oid, &r.Type, &r.Mid, &r.Root, &r.Parent, &r.Dialog, &r.Count, &r.RCount, &r.Like, &r.Hate, &r.Floor, &r.State, &r.CTime, &r.MTime); err != nil {
log.Error("row.Scan error(%v)", err)
return
}
rs = append(rs, r)
}
if err = rows.Err(); err != nil {
log.Error("rows.err error(%v)", err)
return
}
return
}
// FixDialogGetRepliesByRoot ...
func (dao *RpDao) FixDialogGetRepliesByRoot(c context.Context, oid int64, tp int8, rootID int64) (rps []*reply.RpItem, err error) {
var (
minID int64
)
for {
count := 0
rows, err := dao.fixDialogStmt[dao.hit(oid)].Query(c, oid, tp, rootID, minID, 10000)
if err == sql.ErrNoRows {
err = nil
break
} else if err != nil {
log.Error("stmt.Query() error(%v)", err)
return nil, err
}
defer rows.Close()
for rows.Next() {
rp := &reply.RpItem{}
if err = rows.Scan(&rp.ID, &rp.Parent, &rp.Floor); err != nil {
log.Error("rows.Scan() error(%v)", err)
return nil, err
}
rps = append(rps, rp)
count++
if rp.ID > minID {
minID = rp.ID
}
}
if err = rows.Err(); err != nil {
log.Error("rows.Err() error(%v)", err)
return nil, err
}
if count < 10000 {
break
}
}
return
}
// FixDialogSetDialogBatch ...
func (dao *RpDao) FixDialogSetDialogBatch(c context.Context, oid, dialog int64, rpIDs []int64) {
length := len(rpIDs)
if length == 0 {
return
}
ids := strings.Trim(strings.Join(strings.Split(fmt.Sprint(rpIDs), " "), ","), "[]")
setQuery := fmt.Sprintf(_fixDialogSetSQL, dao.hit(oid), ids)
res, err := dao.mysql.Exec(c, setQuery, dialog, time.Now())
if err != nil {
log.Error("db.exec(query: %s, dialog: %d, oid: %d, rpids:%v, error(%v))", setQuery, dialog, oid, rpIDs, err)
return
}
rows, err := res.RowsAffected()
if rows != int64(length) || err != nil {
log.Error("s.dao.SetDialogBatch RowsAffected(%d) actual length(%d) error(%v)", rows, length, err)
return
}
}

View File

@@ -0,0 +1,448 @@
package reply
import (
"context"
"go-common/app/job/main/reply/model/reply"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestReplyTxInsert(t *testing.T) {
convey.Convey("TxInsert", t, func(ctx convey.C) {
var (
tx, _ = d.mysql.Begin(context.Background())
r = &reply.Reply{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rows, err := d.Reply.TxInsert(tx, r)
ctx.Convey("Then err should be nil.rows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rows, convey.ShouldNotBeNil)
})
})
tx.Rollback()
})
}
func TestReplyTxIncrCount2(t *testing.T) {
convey.Convey("TxIncrCount", t, func(ctx convey.C) {
var (
tx, _ = d.mysql.Begin(context.Background())
oid = int64(0)
rpID = int64(0)
now = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rows, err := d.Reply.TxIncrCount(tx, oid, rpID, now)
ctx.Convey("Then err should be nil.rows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rows, convey.ShouldNotBeNil)
})
})
tx.Rollback()
})
}
func TestReplyTxIncrFCount2(t *testing.T) {
convey.Convey("TxIncrFCount", t, func(ctx convey.C) {
var (
tx, _ = d.mysql.Begin(context.Background())
oid = int64(0)
rpID = int64(0)
now = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rows, err := d.Reply.TxIncrFCount(tx, oid, rpID, now)
ctx.Convey("Then err should be nil.rows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rows, convey.ShouldNotBeNil)
})
})
tx.Rollback()
})
}
func TestReplyTxIncrRCount2(t *testing.T) {
convey.Convey("TxIncrRCount", t, func(ctx convey.C) {
var (
tx, _ = d.mysql.Begin(context.Background())
oid = int64(0)
rpID = int64(0)
now = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rows, err := d.Reply.TxIncrRCount(tx, oid, rpID, now)
ctx.Convey("Then err should be nil.rows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rows, convey.ShouldNotBeNil)
})
})
tx.Rollback()
})
}
func TestReplyTxDecrCount2(t *testing.T) {
convey.Convey("TxDecrCount", t, func(ctx convey.C) {
var (
tx, _ = d.mysql.Begin(context.Background())
oid = int64(0)
rpID = int64(0)
now = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rows, err := d.Reply.TxDecrCount(tx, oid, rpID, now)
ctx.Convey("Then err should be nil.rows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rows, convey.ShouldNotBeNil)
})
})
tx.Rollback()
})
}
func TestReplyGetForUpdate(t *testing.T) {
convey.Convey("GetForUpdate", t, func(ctx convey.C) {
var (
tx, _ = d.mysql.Begin(context.Background())
oid = int64(0)
rpID = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
r, err := d.Reply.GetForUpdate(tx, oid, rpID)
ctx.Convey("Then err should be nil.r should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(r, convey.ShouldBeNil)
})
})
tx.Rollback()
})
}
func TestReplyTxUpState(t *testing.T) {
convey.Convey("TxUpState", t, func(ctx convey.C) {
var (
tx, _ = d.mysql.Begin(context.Background())
oid = int64(0)
rpID = int64(0)
state = int8(0)
now = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rows, err := d.Reply.TxUpState(tx, oid, rpID, state, now)
ctx.Convey("Then err should be nil.rows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rows, convey.ShouldNotBeNil)
})
})
tx.Rollback()
})
}
func TestReplyUpState(t *testing.T) {
convey.Convey("UpState", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
rpID = int64(0)
state = int8(0)
now = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rows, err := d.Reply.UpState(c, oid, rpID, state, now)
ctx.Convey("Then err should be nil.rows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rows, convey.ShouldNotBeNil)
})
})
})
}
func TestReplyTxUpAttr2(t *testing.T) {
convey.Convey("TxUpAttr", t, func(ctx convey.C) {
var (
tx, _ = d.mysql.Begin(context.Background())
oid = int64(0)
rpID = int64(0)
attr = uint32(0)
now = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rows, err := d.Reply.TxUpAttr(tx, oid, rpID, attr, now)
ctx.Convey("Then err should be nil.rows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rows, convey.ShouldNotBeNil)
})
})
tx.Rollback()
})
}
func TestReplyUpLike(t *testing.T) {
convey.Convey("UpLike", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
rpID = int64(0)
like = int(0)
hate = int(0)
now = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rows, err := d.Reply.UpLike(c, oid, rpID, like, hate, now)
ctx.Convey("Then err should be nil.rows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rows, convey.ShouldNotBeNil)
})
})
})
}
func TestReplyGet3(t *testing.T) {
convey.Convey("Get", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
rpID = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
r, err := d.Reply.Get(c, oid, rpID)
ctx.Convey("Then err should be nil.r should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(r, convey.ShouldBeNil)
})
})
})
}
func TestReplyGetTop2(t *testing.T) {
convey.Convey("GetTop", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
tp = int8(0)
bit = uint32(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
r, err := d.Reply.GetTop(c, oid, tp, bit)
ctx.Convey("Then err should be nil.r should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(r, convey.ShouldBeNil)
})
})
})
}
func TestReplyGetByDialog(t *testing.T) {
convey.Convey("GetByDialog", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
typ = int8(0)
root = int64(0)
dialog = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rps, err := d.Reply.GetByDialog(c, oid, typ, root, dialog)
ctx.Convey("Then err should be nil.rps should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rps, convey.ShouldBeNil)
})
})
})
}
func TestReplyGetAllInSlice(t *testing.T) {
convey.Convey("GetAllInSlice", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
typ = int8(0)
maxFloor = int(0)
shard = int(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rs, err := d.Reply.GetAllInSlice(c, oid, typ, maxFloor, shard)
ctx.Convey("Then err should be nil.rs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(rs, convey.ShouldBeNil)
})
})
})
}
func TestReplyGetByFloorLimit(t *testing.T) {
convey.Convey("GetByFloorLimit", t, func(ctx convey.C) {
var (
oid = int64(0)
typ = int8(0)
floor = int(0)
limit = int(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rs, err := d.Reply.GetByFloorLimit(context.Background(), oid, typ, floor, limit)
ctx.Convey("Then err should be nil.rs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rs, convey.ShouldBeNil)
})
})
})
}
func TestReplygetByFloorLimit(t *testing.T) {
convey.Convey("getByFloorLimit", t, func(ctx convey.C) {
var (
oid = int64(0)
typ = int8(0)
floor = int(0)
limit = int(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rs, err := d.Reply.getByFloorLimit(context.Background(), oid, typ, floor, limit)
ctx.Convey("Then err should be nil.rs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rs, convey.ShouldBeNil)
})
})
})
}
func TestReplyGetByLikeLimit(t *testing.T) {
convey.Convey("GetByLikeLimit", t, func(ctx convey.C) {
var (
oid = int64(0)
typ = int8(0)
limit = int(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rs, err := d.Reply.GetByLikeLimit(context.Background(), oid, typ, limit)
ctx.Convey("Then err should be nil.rs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rs, convey.ShouldBeNil)
})
})
})
}
func TestReplyGetByCountLimit(t *testing.T) {
convey.Convey("GetByCountLimit", t, func(ctx convey.C) {
var (
oid = int64(0)
typ = int8(0)
limit = int(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rs, err := d.Reply.GetByCountLimit(context.Background(), oid, typ, limit)
ctx.Convey("Then err should be nil.rs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rs, convey.ShouldBeNil)
})
})
})
}
func TestReplyGetAllByFloor(t *testing.T) {
convey.Convey("GetAllByFloor", t, func(ctx convey.C) {
var (
oid = int64(0)
typ = int8(0)
start = int(0)
end = int(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rs, err := d.Reply.GetAllByFloor(context.Background(), oid, typ, start, end)
ctx.Convey("Then err should be nil.rs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rs, convey.ShouldBeNil)
})
})
})
}
func TestReplyGetAll(t *testing.T) {
convey.Convey("GetAll", t, func(ctx convey.C) {
var (
oid = int64(0)
tp = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rs, err := d.Reply.GetAll(context.Background(), oid, tp)
ctx.Convey("Then err should be nil.rs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rs, convey.ShouldBeNil)
})
})
})
}
func TestReplyGetAllByRoot(t *testing.T) {
convey.Convey("GetAllByRoot", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
rpID = int64(0)
tp = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rs, err := d.Reply.GetAllByRoot(c, oid, rpID, tp)
ctx.Convey("Then err should be nil.rs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rs, convey.ShouldBeNil)
})
})
})
}
func TestReplyGetsByRoot(t *testing.T) {
convey.Convey("GetsByRoot", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
rpID = int64(0)
tp = int8(0)
state = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rs, err := d.Reply.GetsByRoot(c, oid, rpID, tp, state)
ctx.Convey("Then err should be nil.rs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rs, convey.ShouldBeNil)
})
})
})
}
func TestReplyFixDialogGetRepliesByRoot(t *testing.T) {
convey.Convey("FixDialogGetRepliesByRoot", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
tp = int8(0)
rootID = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rps, err := d.Reply.FixDialogGetRepliesByRoot(c, oid, tp, rootID)
ctx.Convey("Then err should be nil.rps should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rps, convey.ShouldBeNil)
})
})
})
}
func TestReplyFixDialogSetDialogBatch(t *testing.T) {
convey.Convey("FixDialogSetDialogBatch", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
dialog = int64(0)
rpIDs = []int64{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
d.Reply.FixDialogSetDialogBatch(c, oid, dialog, rpIDs)
ctx.Convey("No return values", func(ctx convey.C) {
})
})
})
}

View File

@@ -0,0 +1,139 @@
package reply
import (
"context"
"fmt"
"time"
model "go-common/app/job/main/reply/model/reply"
"go-common/library/database/sql"
"go-common/library/log"
)
const (
_repSharding int64 = 200
)
const ( // report
_upRepSQL = "UPDATE reply_report_%d SET state=?,mtime=?,reason=?,content=?,attr=? WHERE rpid=?"
_selRepSQL = "SELECT oid,type,rpid,mid,reason,content,count,score,state,ctime,mtime,attr FROM reply_report_%d WHERE rpid=?"
_selRepByOidSQL = "SELECT oid,type,rpid,mid,reason,content,count,score,state,ctime,mtime,attr FROM reply_report_%d WHERE oid=? and type=?"
// report user
_getRptUsersSQL = "SELECT oid,type,rpid,mid,reason,content,state,ctime,mtime FROM reply_report_user_%d WHERE rpid=? and state=?"
_setRptUserStateSQL = "UPDATE reply_report_user_%d SET state=?,mtime=? WHERE rpid=?"
)
//ReportDao define report mysql stmt
type ReportDao struct {
upRepStmts []*sql.Stmt
selRepStmts []*sql.Stmt
getUsersStmts []*sql.Stmt
setUserStateStmts []*sql.Stmt
mysql *sql.DB
}
// NewReportDao new ReplyReportDao and return.
func NewReportDao(db *sql.DB) (dao *ReportDao) {
dao = &ReportDao{
mysql: db,
upRepStmts: make([]*sql.Stmt, _repSharding),
selRepStmts: make([]*sql.Stmt, _repSharding),
getUsersStmts: make([]*sql.Stmt, _repSharding),
setUserStateStmts: make([]*sql.Stmt, _repSharding),
}
for i := int64(0); i < _repSharding; i++ {
dao.upRepStmts[i] = dao.mysql.Prepared(fmt.Sprintf(_upRepSQL, i))
dao.selRepStmts[i] = dao.mysql.Prepared(fmt.Sprintf(_selRepSQL, i))
dao.getUsersStmts[i] = dao.mysql.Prepared(fmt.Sprintf(_getRptUsersSQL, i))
dao.setUserStateStmts[i] = dao.mysql.Prepared(fmt.Sprintf(_setRptUserStateSQL, i))
}
return
}
func (dao *ReportDao) hit(oid int64) int64 {
return oid % _repSharding
}
// Update update reply report.
func (dao *ReportDao) Update(c context.Context, rpt *model.Report) (rows int64, err error) {
res, err := dao.upRepStmts[dao.hit(rpt.Oid)].Exec(c, rpt.State, rpt.MTime, rpt.Reason, rpt.Content, rpt.Attr, rpt.RpID)
if err != nil {
log.Error("mysqlDB.Exec error(%v)", err)
return
}
return res.RowsAffected()
}
// Get get a reply report.
func (dao *ReportDao) Get(c context.Context, oid, rpID int64) (rpt *model.Report, err error) {
row := dao.selRepStmts[dao.hit(oid)].QueryRow(c, rpID)
rpt = &model.Report{}
err = row.Scan(&rpt.Oid, &rpt.Type, &rpt.RpID, &rpt.Mid, &rpt.Reason, &rpt.Content, &rpt.Count, &rpt.Score, &rpt.State, &rpt.CTime, &rpt.MTime, &rpt.Attr)
if err != nil {
if err == sql.ErrNoRows {
rpt = nil
err = nil
} else {
log.Error("Mysql error(%v)", err)
}
}
return
}
// GetMapByOid return report map by oid.
func (dao *ReportDao) GetMapByOid(c context.Context, oid int64, typ int8) (res map[int64]*model.Report, err error) {
rows, err := dao.mysql.Query(c, fmt.Sprintf(_selRepByOidSQL, dao.hit(oid)), oid, typ)
if err != nil {
log.Error("db.Query(%s) error(%v)", _selRepByOidSQL, err)
return
}
defer rows.Close()
res = make(map[int64]*model.Report)
for rows.Next() {
rpt := &model.Report{}
if err = rows.Scan(&rpt.Oid, &rpt.Type, &rpt.RpID, &rpt.Mid, &rpt.Reason, &rpt.Content, &rpt.Count, &rpt.Score, &rpt.State, &rpt.CTime, &rpt.MTime, &rpt.Attr); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
res[rpt.RpID] = rpt
}
if err = rows.Err(); err != nil {
log.Error("rows.err error(%v)", err)
return
}
return
}
// GetUsers return a report users from mysql.
func (dao *ReportDao) GetUsers(c context.Context, oid int64, tp int8, rpID int64) (res map[int64]*model.ReportUser, err error) {
rows, err := dao.getUsersStmts[dao.hit(oid)].Query(c, rpID, model.ReportUserStateNew)
if err != nil {
log.Error("db.Query error(%v)", err)
return
}
defer rows.Close()
res = make(map[int64]*model.ReportUser)
for rows.Next() {
rpt := &model.ReportUser{}
if err = rows.Scan(&rpt.Oid, &rpt.Type, &rpt.RpID, &rpt.Mid, &rpt.Reason, &rpt.Content, &rpt.State, &rpt.CTime, &rpt.MTime); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
res[rpt.Mid] = rpt
}
if err = rows.Err(); err != nil {
log.Error("rows.err error(%v)", err)
return
}
return
}
// SetUserReported set a user report state by rpID.
func (dao *ReportDao) SetUserReported(c context.Context, oid int64, tp int8, rpID int64, now time.Time) (rows int64, err error) {
res, err := dao.setUserStateStmts[dao.hit(oid)].Exec(c, model.ReportUserStateReported, now, rpID)
if err != nil {
log.Error("db.Exec error(%v)", err)
return
}
return res.RowsAffected()
}

View File

@@ -0,0 +1,97 @@
package reply
import (
"context"
model "go-common/app/job/main/reply/model/reply"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestReplyUpdate(t *testing.T) {
convey.Convey("Update", t, func(ctx convey.C) {
var (
c = context.Background()
rpt = &model.Report{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rows, err := d.Report.Update(c, rpt)
ctx.Convey("Then err should be nil.rows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rows, convey.ShouldNotBeNil)
})
})
})
}
func TestReplyGet(t *testing.T) {
convey.Convey("Get", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
rpID = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rpt, err := d.Report.Get(c, oid, rpID)
ctx.Convey("Then err should be nil.rpt should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rpt, convey.ShouldNotBeNil)
})
})
})
}
func TestReplyGetMapByOid(t *testing.T) {
convey.Convey("GetMapByOid", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
typ = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.Report.GetMapByOid(c, oid, typ)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestReplyGetUsers(t *testing.T) {
convey.Convey("GetUsers", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
tp = int8(0)
rpID = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.Report.GetUsers(c, oid, tp, rpID)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestReplySetUserReported(t *testing.T) {
convey.Convey("SetUserReported", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
tp = int8(0)
rpID = int64(0)
now = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rows, err := d.Report.SetUserReported(c, oid, tp, rpID, now)
ctx.Convey("Then err should be nil.rows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rows, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,187 @@
package reply
import (
"context"
"fmt"
"time"
"go-common/app/job/main/reply/model/reply"
"go-common/library/database/sql"
"go-common/library/log"
)
const (
_subSharding int64 = 50
)
const (
_incrSubCntSQL = "UPDATE reply_subject_%d SET count=count+1,rcount=rcount+1,acount=acount+1,mtime=? WHERE oid=? AND type=?"
_incrSubFCntSQL = "UPDATE reply_subject_%d SET count=count+1,mtime=? WHERE oid=? AND type=?"
_incrSubRCntSQL = "UPDATE reply_subject_%d SET rcount=rcount+1,mtime=? WHERE oid=? AND type=?"
_incrSubACntSQL = "UPDATE reply_subject_%d SET acount=acount+?,mtime=? WHERE oid=? AND type=?"
_incrSubMCntSQL = "UPDATE reply_subject_%d SET mcount=mcount+1,mtime=? WHERE oid=? AND type=?"
_decrSubMCntSQL = "UPDATE reply_subject_%d SET mcount=mcount-1,mtime=? WHERE oid=? AND type=? AND mcount>0"
_decrSubCntSQL = "UPDATE reply_subject_%d SET rcount=rcount-1,mtime=? WHERE oid=? AND type=?"
_upSubAttrSQL = "UPDATE reply_subject_%d SET attr=?,mtime=? WHERE oid=? AND type=?"
_decrSubACntSQL = "UPDATE reply_subject_%d SET acount=acount-?,mtime=? WHERE oid=? AND type=?"
_upSubMetaSQL = "UPDATE reply_subject_%d SET meta=?,mtime=? WHERE oid=? AND type=?"
_selSubjectSQL = "SELECT oid,type,mid,count,rcount,acount,state,attr,ctime,mtime,meta FROM reply_subject_%d WHERE oid=? AND type=?"
_selSubjectForUpdateSQL = "SELECT oid,type,mid,count,rcount,acount,state,attr,ctime,mtime,meta FROM reply_subject_%d WHERE oid=? AND type=? FOR UPDATE"
)
// SubjectDao define subject mysql stmt
type SubjectDao struct {
selSubjectStmt []*sql.Stmt
mysql *sql.DB
}
// NewSubjectDao new ReplySubjectDao and return.
func NewSubjectDao(db *sql.DB) (dao *SubjectDao) {
dao = &SubjectDao{
mysql: db,
selSubjectStmt: make([]*sql.Stmt, _subSharding),
}
for i := int64(0); i < _subSharding; i++ {
dao.selSubjectStmt[i] = dao.mysql.Prepared(fmt.Sprintf(_selSubjectSQL, i))
}
return
}
func (dao *SubjectDao) hit(oid int64) int64 {
return oid % _subSharding
}
// UpMeta update subject meta.
func (dao *SubjectDao) UpMeta(c context.Context, oid int64, tp int8, meta string, now time.Time) (rows int64, err error) {
res, err := dao.mysql.Exec(c, fmt.Sprintf(_upSubMetaSQL, dao.hit(oid)), meta, now, oid, tp)
if err != nil {
log.Error("mysqlDB.Exec error(%v)", err)
return
}
return res.RowsAffected()
}
// TxUpMeta update subject meta.
func (dao *SubjectDao) TxUpMeta(tx *sql.Tx, oid int64, tp int8, meta string, now time.Time) (rows int64, err error) {
res, err := tx.Exec(fmt.Sprintf(_upSubMetaSQL, dao.hit(oid)), meta, now, oid, tp)
if err != nil {
log.Error("mysqlDB.Exec error(%v)", err)
return
}
return res.RowsAffected()
}
// TxUpAttr update subject attr.
func (dao *SubjectDao) TxUpAttr(tx *sql.Tx, oid int64, tp int8, attr uint32, now time.Time) (rows int64, err error) {
res, err := tx.Exec(fmt.Sprintf(_upSubAttrSQL, dao.hit(oid)), attr, now, oid, tp)
if err != nil {
log.Error("mysqlDB.Exec error(%v)", err)
return
}
return res.RowsAffected()
}
// TxIncrCount incr subject count and rcount by transaction.
func (dao *SubjectDao) TxIncrCount(tx *sql.Tx, oid int64, tp int8, now time.Time) (rows int64, err error) {
res, err := tx.Exec(fmt.Sprintf(_incrSubCntSQL, dao.hit(oid)), now, oid, tp)
if err != nil {
log.Error("mysqlDB.Exec() error(%v)", err)
return
}
return res.RowsAffected()
}
// TxIncrFCount incr subject count and rcount by transaction.
func (dao *SubjectDao) TxIncrFCount(tx *sql.Tx, oid int64, tp int8, now time.Time) (rows int64, err error) {
res, err := tx.Exec(fmt.Sprintf(_incrSubFCntSQL, dao.hit(oid)), now, oid, tp)
if err != nil {
log.Error("mysqlDB.Exec() error(%v)", err)
return
}
return res.RowsAffected()
}
// TxIncrMCount incr subject mcount by transaction.
func (dao *SubjectDao) TxIncrMCount(tx *sql.Tx, oid int64, tp int8, now time.Time) (rows int64, err error) {
res, err := tx.Exec(fmt.Sprintf(_incrSubMCntSQL, dao.hit(oid)), now, oid, tp)
if err != nil {
log.Error("mysqlDB.Exec() error(%v)", err)
return
}
return res.RowsAffected()
}
// TxDecrMCount decr subject mcount by transaction.
func (dao *SubjectDao) TxDecrMCount(tx *sql.Tx, oid int64, tp int8, now time.Time) (rows int64, err error) {
res, err := tx.Exec(fmt.Sprintf(_decrSubMCntSQL, dao.hit(oid)), now, oid, tp)
if err != nil {
log.Error("mysqlDB.Exec() error(%v)", err)
return
}
return res.RowsAffected()
}
// TxIncrRCount incr subject rcount by transaction
func (dao *SubjectDao) TxIncrRCount(tx *sql.Tx, oid int64, tp int8, now time.Time) (rows int64, err error) {
res, err := tx.Exec(fmt.Sprintf(_incrSubRCntSQL, dao.hit(oid)), now, oid, tp)
if err != nil {
log.Error("mysqlDB.Exec error(%v)", err)
return
}
return res.RowsAffected()
}
// TxDecrCount decr subject count by transaction.
func (dao *SubjectDao) TxDecrCount(tx *sql.Tx, oid int64, tp int8, now time.Time) (rows int64, err error) {
res, err := tx.Exec(fmt.Sprintf(_decrSubCntSQL, dao.hit(oid)), now, oid, tp)
if err != nil {
log.Error("mysqlDB.Exec() error(%v)", err)
return
}
return res.RowsAffected()
}
// TxIncrACount incr subject acount by transaction.
func (dao *SubjectDao) TxIncrACount(tx *sql.Tx, oid int64, tp int8, count int, now time.Time) (rows int64, err error) {
res, err := tx.Exec(fmt.Sprintf(_incrSubACntSQL, dao.hit(oid)), count, now, oid, tp)
if err != nil {
log.Error("mysqlDB.Exec() error(%v)", err)
return
}
return res.RowsAffected()
}
// TxDecrACount decr subject rcount by transaction.
func (dao *SubjectDao) TxDecrACount(tx *sql.Tx, oid int64, tp int8, count int, now time.Time) (rows int64, err error) {
res, err := tx.Exec(fmt.Sprintf(_decrSubACntSQL, dao.hit(oid)), count, now, oid, tp)
if err != nil {
log.Error("mysqlDB.Exec() error(%v)", err)
return
}
return res.RowsAffected()
}
// Get get a subject.
func (dao *SubjectDao) Get(c context.Context, oid int64, tp int8) (sub *reply.Subject, err error) {
sub = &reply.Subject{}
row := dao.selSubjectStmt[dao.hit(oid)].QueryRow(c, oid, tp)
if err = row.Scan(&sub.Oid, &sub.Type, &sub.Mid, &sub.Count, &sub.RCount, &sub.ACount, &sub.State, &sub.Attr, &sub.CTime, &sub.MTime, &sub.Meta); err != nil {
if err == sql.ErrNoRows {
sub = nil
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// GetForUpdate get a subject for update.
func (dao *SubjectDao) GetForUpdate(tx *sql.Tx, oid int64, tp int8) (sub *reply.Subject, err error) {
sub = &reply.Subject{}
if err = tx.QueryRow(fmt.Sprintf(_selSubjectForUpdateSQL, dao.hit(oid)), oid, tp).Scan(&sub.Oid, &sub.Type, &sub.Mid, &sub.Count, &sub.RCount, &sub.ACount, &sub.State, &sub.Attr, &sub.CTime, &sub.MTime, &sub.Meta); err != nil {
return
}
return
}

View File

@@ -0,0 +1,239 @@
package reply
import (
"context"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestReplyUpMeta(t *testing.T) {
convey.Convey("UpMeta", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
tp = int8(0)
meta = ""
now = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rows, err := d.Subject.UpMeta(c, oid, tp, meta, now)
ctx.Convey("Then err should be nil.rows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rows, convey.ShouldNotBeNil)
})
})
})
}
func TestReplyTxUpMeta(t *testing.T) {
convey.Convey("TxUpMeta", t, func(ctx convey.C) {
var (
tx, _ = d.mysql.Begin(context.Background())
oid = int64(0)
tp = int8(0)
meta = ""
now = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rows, err := d.Subject.TxUpMeta(tx, oid, tp, meta, now)
ctx.Convey("Then err should be nil.rows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rows, convey.ShouldNotBeNil)
})
})
tx.Rollback()
})
}
func TestReplyTxUpAttr(t *testing.T) {
convey.Convey("TxUpAttr", t, func(ctx convey.C) {
var (
tx, _ = d.mysql.Begin(context.Background())
oid = int64(0)
tp = int8(0)
attr = uint32(0)
now = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rows, err := d.Subject.TxUpAttr(tx, oid, tp, attr, now)
ctx.Convey("Then err should be nil.rows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rows, convey.ShouldNotBeNil)
})
})
tx.Rollback()
})
}
func TestReplyTxIncrCount(t *testing.T) {
convey.Convey("TxIncrCount", t, func(ctx convey.C) {
var (
tx, _ = d.mysql.Begin(context.Background())
oid = int64(0)
tp = int8(0)
now = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rows, err := d.Subject.TxIncrCount(tx, oid, tp, now)
ctx.Convey("Then err should be nil.rows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rows, convey.ShouldNotBeNil)
})
})
tx.Rollback()
})
}
func TestReplyTxIncrFCount(t *testing.T) {
convey.Convey("TxIncrFCount", t, func(ctx convey.C) {
var (
tx, _ = d.mysql.Begin(context.Background())
oid = int64(0)
tp = int8(0)
now = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rows, err := d.Subject.TxIncrFCount(tx, oid, tp, now)
ctx.Convey("Then err should be nil.rows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rows, convey.ShouldNotBeNil)
})
})
tx.Rollback()
})
}
func TestReplyTxIncrMCount(t *testing.T) {
convey.Convey("TxIncrMCount", t, func(ctx convey.C) {
var (
tx, _ = d.mysql.Begin(context.Background())
oid = int64(0)
tp = int8(0)
now = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rows, err := d.Subject.TxIncrMCount(tx, oid, tp, now)
ctx.Convey("Then err should be nil.rows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rows, convey.ShouldNotBeNil)
})
})
tx.Rollback()
})
}
func TestReplyTxDecrMCount(t *testing.T) {
convey.Convey("TxDecrMCount", t, func(ctx convey.C) {
var (
tx, _ = d.mysql.Begin(context.Background())
oid = int64(0)
tp = int8(0)
now = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rows, err := d.Subject.TxDecrMCount(tx, oid, tp, now)
ctx.Convey("Then err should be nil.rows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rows, convey.ShouldNotBeNil)
})
})
tx.Rollback()
})
}
func TestReplyTxIncrRCount(t *testing.T) {
convey.Convey("TxIncrRCount", t, func(ctx convey.C) {
var (
tx, _ = d.mysql.Begin(context.Background())
oid = int64(0)
tp = int8(0)
now = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rows, err := d.Subject.TxIncrRCount(tx, oid, tp, now)
ctx.Convey("Then err should be nil.rows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rows, convey.ShouldNotBeNil)
})
})
tx.Rollback()
})
}
func TestReplyTxDecrCount(t *testing.T) {
convey.Convey("TxDecrCount", t, func(ctx convey.C) {
var (
tx, _ = d.mysql.Begin(context.Background())
oid = int64(0)
tp = int8(0)
now = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rows, err := d.Subject.TxDecrCount(tx, oid, tp, now)
ctx.Convey("Then err should be nil.rows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rows, convey.ShouldNotBeNil)
})
})
tx.Rollback()
})
}
func TestReplyTxIncrACount(t *testing.T) {
convey.Convey("TxIncrACount", t, func(ctx convey.C) {
var (
tx, _ = d.mysql.Begin(context.Background())
oid = int64(0)
tp = int8(0)
count = int(0)
now = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rows, err := d.Subject.TxIncrACount(tx, oid, tp, count, now)
ctx.Convey("Then err should be nil.rows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rows, convey.ShouldNotBeNil)
})
})
tx.Rollback()
})
}
func TestReplyTxDecrACount(t *testing.T) {
convey.Convey("TxDecrACount", t, func(ctx convey.C) {
var (
tx, _ = d.mysql.Begin(context.Background())
oid = int64(0)
tp = int8(0)
count = int(0)
now = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
rows, err := d.Subject.TxDecrACount(tx, oid, tp, count, now)
ctx.Convey("Then err should be nil.rows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rows, convey.ShouldNotBeNil)
})
})
tx.Rollback()
})
}
func TestReplyGet2(t *testing.T) {
convey.Convey("Get", t, func(ctx convey.C) {
var (
c = context.Background()
oid = int64(0)
tp = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
sub, err := d.Subject.Get(c, oid, tp)
ctx.Convey("Then err should be nil.sub should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(sub, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,47 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["search_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/reply/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["search.go"],
importpath = "go-common/app/job/main/reply/dao/search",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/reply/conf:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster: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,72 @@
package search
import (
"context"
"encoding/json"
"fmt"
"net/url"
"go-common/app/job/main/reply/conf"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
)
const (
_appIDRecord = "reply_record"
_updateURL = "/x/internal/search/reply/update"
)
// Dao Dao
type Dao struct {
searchHTTPClient *bm.Client
searchUpdateURI string
}
// New New
func New(c *conf.Config) *Dao {
return &Dao{
searchHTTPClient: bm.NewClient(c.HTTPClient),
searchUpdateURI: c.Host.API + _updateURL,
}
}
// DelReply DelReply
func (dao *Dao) DelReply(c context.Context, rpid, oid, mid int64, state int8) (err error) {
return dao.update(c, rpid, oid, mid, state)
}
func (dao *Dao) update(c context.Context, rpid, oid, mid int64, state int8) (err error) {
type updateRecord struct {
ID int64 `json:"id"`
Oid int64 `json:"oid"`
Mid int64 `json:"mid"`
State int8 `json:"state"`
}
var (
res struct {
Code int `json:"code"`
Msg string `json:"message"`
}
)
records := make([]*updateRecord, 0)
record := &updateRecord{}
record.ID = rpid
record.Oid = oid
record.Mid = mid
record.State = state
records = append(records, record)
recordsStr, _ := json.Marshal(records)
params := url.Values{}
params.Set("appid", _appIDRecord)
params.Set("data", string(recordsStr))
if err = dao.searchHTTPClient.Post(c, dao.searchUpdateURI, "", params, &res); err != nil {
log.Error("bm.Post(%s) failed error(%v)", dao.searchUpdateURI+"?"+params.Encode(), err)
return
}
if res.Code != ecode.OK.Code() {
err = fmt.Errorf("update reply es records failed")
}
log.Info("updateSearch: %s post:%s ret:%v", dao.searchUpdateURI, params.Encode(), res)
return
}

View File

@@ -0,0 +1,77 @@
package search
import (
"context"
"flag"
"go-common/app/job/main/reply/conf"
"os"
"testing"
"github.com/smartystreets/goconvey/convey"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.community.reply-job")
flag.Set("conf_token", "5deea0665f8a7670b22a719337a39c7d")
flag.Set("tree_id", "2123")
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/reply-job-test.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
os.Exit(m.Run())
}
func TestSearchDelReply(t *testing.T) {
convey.Convey("DelReply", t, func(ctx convey.C) {
var (
c = context.Background()
rpid = int64(0)
oid = int64(0)
mid = int64(0)
state = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.DelReply(c, rpid, oid, mid, state)
if err != nil {
ctx.So(err, convey.ShouldNotBeNil)
} else {
ctx.So(err, convey.ShouldBeNil)
}
})
})
}
func TestSearchupdate(t *testing.T) {
convey.Convey("update", t, func(ctx convey.C) {
var (
c = context.Background()
rpid = int64(0)
oid = int64(0)
mid = int64(0)
state = int8(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.update(c, rpid, oid, mid, state)
if err != nil {
ctx.So(err, convey.ShouldNotBeNil)
} else {
ctx.So(err, convey.ShouldBeNil)
}
})
})
}

View File

@@ -0,0 +1,45 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["redis_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/reply/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["redis.go"],
importpath = "go-common/app/job/main/reply/dao/spam",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/cache/redis:go_default_library",
"//library/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,166 @@
package spam
import (
"context"
"strconv"
"go-common/library/cache/redis"
"go-common/library/log"
)
// Cache Cache
type Cache struct {
redisPool *redis.Pool
expireRp int
expireAct int
}
// NewCache NewCache
func NewCache(c *redis.Config) *Cache {
return &Cache{
redisPool: redis.NewPool(c),
expireRp: 60, // 60s
expireAct: 20, // 20s
}
}
func (c *Cache) keyRcntCnt(mid int64) string {
return "rc_" + strconv.FormatInt(mid, 10)
}
func (c *Cache) keyUpRcntCnt(mid int64) string {
return "urc_" + strconv.FormatInt(mid, 10)
}
func (c *Cache) keyDailyCnt(mid int64) string {
return "rd_" + strconv.FormatInt(mid, 10)
}
func (c *Cache) keyActRec(mid int64) string {
return "ra_" + strconv.FormatInt(mid, 10)
}
func (c *Cache) keySpamRpRec(mid int64) string {
return "sr_" + strconv.FormatInt(mid, 10)
}
func (c *Cache) keySpamRpDaily(mid int64) string {
return "sd_" + strconv.FormatInt(mid, 10)
}
func (c *Cache) keySpamActRec(mid int64) string {
return "sa_" + strconv.FormatInt(mid, 10)
}
// IncrReply incr user reply count.
func (c *Cache) IncrReply(ctx context.Context, mid int64, isUp bool) (count int, err error) {
key := c.keyRcntCnt(mid)
if isUp {
key = c.keyUpRcntCnt(mid)
}
conn := c.redisPool.Get(ctx)
defer conn.Close()
conn.Send("INCR", key)
conn.Send("EXPIRE", key, c.expireRp)
if err = conn.Flush(); err != nil {
log.Error("conn.Flush error(%v)", err)
return
}
if count, err = redis.Int(conn.Receive()); err != nil {
log.Error("conn.Receive error(%v)", key, err)
return
}
if _, err = conn.Receive(); err != nil {
log.Error("conn.Receive error(%v)", key, err)
return
}
return
}
// IncrAct incr user action count.
func (c *Cache) IncrAct(ctx context.Context, mid int64) (count int, err error) {
key := c.keyActRec(mid)
conn := c.redisPool.Get(ctx)
defer conn.Close()
conn.Send("INCR", key)
conn.Send("EXPIRE", key, c.expireAct)
if err = conn.Flush(); err != nil {
log.Error("conn.Flush error(%v)", err)
return
}
if count, err = redis.Int(conn.Receive()); err != nil {
log.Error("conn.Receive error(%v)", key, err)
return
}
if _, err = conn.Receive(); err != nil {
log.Error("conn.Receive error(%v)", key, err)
return
}
return
}
// IncrDailyReply IncrDailyReply
func (c *Cache) IncrDailyReply(ctx context.Context, mid int64) (count int, err error) {
key := c.keyDailyCnt(mid)
conn := c.redisPool.Get(ctx)
defer conn.Close()
if count, err = redis.Int(conn.Do("INCR", key)); err != nil {
log.Error("conn.Do(INCRBY, %s), error(%v)", key, err)
}
return
}
// TTLDailyReply TTLDailyReply
func (c *Cache) TTLDailyReply(ctx context.Context, mid int64) (ttl int, err error) {
key := c.keyDailyCnt(mid)
conn := c.redisPool.Get(ctx)
defer conn.Close()
if ttl, err = redis.Int(conn.Do("TTL", key)); err != nil {
log.Error("conn.Do(TTL, %s), error(%v)", key, err)
}
return
}
// ExpireDailyReply ExpireDailyReply
func (c *Cache) ExpireDailyReply(ctx context.Context, mid int64, exp int) (err error) {
key := c.keyDailyCnt(mid)
conn := c.redisPool.Get(ctx)
defer conn.Close()
if _, err = conn.Do("EXPIRE", key, exp); err != nil {
log.Error("conn.Do(EXPIRE, %s), error(%v)", key, err)
}
return
}
// SetReplyRecSpam SetReplyRecSpam
func (c *Cache) SetReplyRecSpam(ctx context.Context, mid int64, code, exp int) (err error) {
key := c.keySpamRpRec(mid)
conn := c.redisPool.Get(ctx)
defer conn.Close()
if _, err = conn.Do("SETEX", key, exp, code); err != nil {
log.Error("conn.Do error(%v)", err)
}
return
}
// SetReplyDailySpam SetReplyDailySpam
func (c *Cache) SetReplyDailySpam(ctx context.Context, mid int64, code, exp int) (err error) {
key := c.keySpamRpDaily(mid)
conn := c.redisPool.Get(ctx)
defer conn.Close()
if _, err = conn.Do("SETEX", key, exp, code); err != nil {
log.Error("conn.Do error(%v)", err)
}
return
}
// SetActionRecSpam SetActionRecSpam
func (c *Cache) SetActionRecSpam(ctx context.Context, mid int64, code, exp int) (err error) {
key := c.keySpamActRec(mid)
conn := c.redisPool.Get(ctx)
defer conn.Close()
if _, err = conn.Do("SETEX", key, exp, code); err != nil {
log.Error("conn.Do error(%v)", err)
}
return
}

View File

@@ -0,0 +1,259 @@
package spam
import (
"context"
"flag"
"go-common/app/job/main/reply/conf"
"os"
"testing"
"github.com/smartystreets/goconvey/convey"
)
var (
d *Cache
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.community.reply-job")
flag.Set("conf_token", "5deea0665f8a7670b22a719337a39c7d")
flag.Set("tree_id", "2123")
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/reply-job-test.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = NewCache(conf.Conf.Redis.Config)
os.Exit(m.Run())
}
func TestSpamkeyRcntCnt(t *testing.T) {
convey.Convey("keyRcntCnt", t, func(ctx convey.C) {
var (
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := d.keyRcntCnt(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestSpamkeyUpRcntCnt(t *testing.T) {
convey.Convey("keyUpRcntCnt", t, func(ctx convey.C) {
var (
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := d.keyUpRcntCnt(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestSpamkeyDailyCnt(t *testing.T) {
convey.Convey("keyDailyCnt", t, func(ctx convey.C) {
var (
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := d.keyDailyCnt(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestSpamkeyActRec(t *testing.T) {
convey.Convey("keyActRec", t, func(ctx convey.C) {
var (
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := d.keyActRec(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestSpamkeySpamRpRec(t *testing.T) {
convey.Convey("keySpamRpRec", t, func(ctx convey.C) {
var (
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := d.keySpamRpRec(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestSpamkeySpamRpDaily(t *testing.T) {
convey.Convey("keySpamRpDaily", t, func(ctx convey.C) {
var (
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := d.keySpamRpDaily(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestSpamkeySpamActRec(t *testing.T) {
convey.Convey("keySpamActRec", t, func(ctx convey.C) {
var (
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := d.keySpamActRec(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestSpamIncrReply(t *testing.T) {
convey.Convey("IncrReply", t, func(ctx convey.C) {
var (
mid = int64(0)
isUp bool
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
count, err := d.IncrReply(context.Background(), mid, isUp)
ctx.Convey("Then err should be nil.count should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(count, convey.ShouldNotBeNil)
})
})
})
}
func TestSpamIncrAct(t *testing.T) {
convey.Convey("IncrAct", t, func(ctx convey.C) {
var (
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
count, err := d.IncrAct(context.Background(), mid)
ctx.Convey("Then err should be nil.count should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(count, convey.ShouldNotBeNil)
})
})
})
}
func TestSpamIncrDailyReply(t *testing.T) {
convey.Convey("IncrDailyReply", t, func(ctx convey.C) {
var (
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
count, err := d.IncrDailyReply(context.Background(), mid)
ctx.Convey("Then err should be nil.count should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(count, convey.ShouldNotBeNil)
})
})
})
}
func TestSpamTTLDailyReply(t *testing.T) {
convey.Convey("TTLDailyReply", t, func(ctx convey.C) {
var (
mid = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
ttl, err := d.TTLDailyReply(context.Background(), mid)
ctx.Convey("Then err should be nil.ttl should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(ttl, convey.ShouldNotBeNil)
})
})
})
}
func TestSpamExpireDailyReply(t *testing.T) {
convey.Convey("ExpireDailyReply", t, func(ctx convey.C) {
var (
mid = int64(0)
exp = int(1)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.ExpireDailyReply(context.Background(), mid, exp)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestSpamSetReplyRecSpam(t *testing.T) {
convey.Convey("SetReplyRecSpam", t, func(ctx convey.C) {
var (
mid = int64(0)
code = int(0)
exp = int(1)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.SetReplyRecSpam(context.Background(), mid, code, exp)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestSpamSetReplyDailySpam(t *testing.T) {
convey.Convey("SetReplyDailySpam", t, func(ctx convey.C) {
var (
mid = int64(0)
code = int(0)
exp = int(1)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.SetReplyDailySpam(context.Background(), mid, code, exp)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestSpamSetActionRecSpam(t *testing.T) {
convey.Convey("SetActionRecSpam", t, func(ctx convey.C) {
var (
mid = int64(0)
code = int(0)
exp = int(1)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.SetActionRecSpam(context.Background(), mid, code, exp)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,46 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["databus_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/reply/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["databus.go"],
importpath = "go-common/app/job/main/reply/dao/stat",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/reply/conf:go_default_library",
"//library/log:go_default_library",
"//library/queue/databus: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,54 @@
package stat
import (
"context"
"strconv"
"time"
"go-common/app/job/main/reply/conf"
"go-common/library/log"
"go-common/library/queue/databus"
)
type statMsg struct {
ID int64 `json:"id"`
Timestamp int64 `json:"timestamp"`
Count int `json:"count"`
Type string `json:"type"`
}
// Dao stat dao.
type Dao struct {
// new databus stats
types map[int8]string
databus *databus.Databus
}
// New new a stat dao and return.
func New(c *conf.Config) *Dao {
d := new(Dao)
// new databus stats
d.types = make(map[int8]string)
for name, typ := range c.StatTypes {
d.types[typ] = name
}
d.databus = databus.New(c.Databus.Stats)
return d
}
// Send update stat.
func (d *Dao) Send(c context.Context, typ int8, oid int64, cnt int) (err error) {
// new databus stats
if name, ok := d.types[typ]; ok {
m := &statMsg{
ID: oid,
Type: name,
Count: cnt,
Timestamp: time.Now().Unix(),
}
if err = d.databus.Send(c, strconv.FormatInt(oid, 10), m); err != nil {
log.Error("d.databus.Send(%d,%d,%d) error(%v)", typ, oid, cnt, err)
}
}
return
}

View File

@@ -0,0 +1,54 @@
package stat
import (
"context"
"flag"
"go-common/app/job/main/reply/conf"
"os"
"testing"
"github.com/smartystreets/goconvey/convey"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.community.reply-job")
flag.Set("conf_token", "5deea0665f8a7670b22a719337a39c7d")
flag.Set("tree_id", "2123")
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/reply-job-test.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
os.Exit(m.Run())
}
func TestStatSend(t *testing.T) {
convey.Convey("Send", t, func(ctx convey.C) {
var (
c = context.Background()
typ = int8(0)
oid = int64(0)
cnt = int(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.Send(c, typ, oid, cnt)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}