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,57 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"dao_test.go",
"shorturl_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/shorturl/conf:go_default_library",
"//app/interface/main/shorturl/model:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"dao.go",
"shorturl.go",
"shorturl_cache.go",
],
importpath = "go-common/app/interface/main/shorturl/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/shorturl/conf:go_default_library",
"//app/interface/main/shorturl/model:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/database/sql: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,82 @@
package dao
import (
"context"
"runtime"
"time"
"go-common/app/interface/main/shorturl/conf"
"go-common/library/cache/memcache"
"go-common/library/database/sql"
"go-common/library/log"
)
// Dao struct conf
type Dao struct {
db *sql.DB
memchDB *memcache.Pool
mcExpire int32
cacheCh chan func()
}
// New new dao
func New(c *conf.Config) (d *Dao) {
d = &Dao{
db: sql.NewMySQL(c.Mysql),
memchDB: memcache.NewPool(c.Memcache.Config),
cacheCh: make(chan func(), 1024),
mcExpire: int32(time.Duration(c.Memcache.Expire) / time.Second),
}
for i := 0; i < runtime.NumCPU(); i++ {
go d.cacheproc()
}
return
}
func (d *Dao) cacheproc() {
for {
f, ok := <-d.cacheCh
if !ok {
return
}
f()
}
}
// AddCache add cache chan
func (d *Dao) AddCache(f func()) {
select {
case d.cacheCh <- f:
default:
log.Error("d.cacheCh is full")
}
}
// Close close db.
func (d *Dao) Close() {
if d.db != nil {
d.db.Close()
}
}
// Ping ping dao
func (d *Dao) Ping(c context.Context) (err error) {
if err = d.db.Ping(c); err != nil {
log.Error("d.PingDB error(%v)", err)
}
if err = d.PingMC(c); err != nil {
log.Error("d.PingMC error(%v)", err)
}
return
}
// PingMC ping mc is ok.
func (d *Dao) PingMC(c context.Context) (err error) {
conn := d.memchDB.Get(c)
item := memcache.Item{Key: "ping", Value: []byte{1}, Expiration: d.mcExpire}
if err = conn.Set(&item); err != nil {
log.Error("conn.Set(%s) error(%v)", item.Key, err)
}
conn.Close()
return
}

View File

@@ -0,0 +1,26 @@
package dao
import (
"flag"
"path/filepath"
"go-common/app/interface/main/shorturl/conf"
. "github.com/smartystreets/goconvey/convey"
)
var d *Dao
func init() {
dir, _ := filepath.Abs("../cmd/shorturl-test.toml")
flag.Set("conf", dir)
conf.Init()
d = New(conf.Conf)
}
func WithDao(f func(d *Dao)) func() {
return func() {
Reset(func() {})
f(d)
}
}

View File

@@ -0,0 +1,152 @@
package dao
import (
"context"
"database/sql"
"fmt"
"go-common/app/interface/main/shorturl/model"
"go-common/library/log"
)
const (
_prefix = "su_"
//short_url
_getSQL = "SELECT id,mid,short_url,long_url,state,ctime,mtime FROM short_url WHERE short_url=?"
_getAllSQL = "SELECT id,mid,short_url,long_url,state,ctime,mtime FROM short_url"
_getLimitSQL = "SELECT id,mid,short_url,long_url,state,ctime,mtime FROM short_url WHERE state=? " // TODO limit page
_shortInSQL = "INSERT IGNORE INTO short_url(mid,short_url,long_url,state,ctime) VALUES(?,?,?,?,?)"
_shortUpSQL = "UPDATE short_url SET mid=?,long_url=? WHERE id=?"
_shortCountSQL = "SELECT COUNT(*) FROM short_url WHERE state=?"
_shortByIDSQL = "SELECT id,mid,short_url,long_url,state,ctime,mtime FROM short_url WHERE id=?"
_updateStateSQL = "UPDATE short_url SET mid=?,state=? WHERE id=?"
)
// Short get short_url
func (d *Dao) Short(ctx context.Context, short string) (res *model.ShortUrl, err error) {
rows := d.db.QueryRow(ctx, _getSQL, short)
res = &model.ShortUrl{}
if err = rows.Scan(&res.ID, &res.Mid, &res.Short, &res.Long, &res.State, &res.CTime, &res.MTime); err != nil {
if err == sql.ErrNoRows {
res = nil
err = nil
} else {
log.Error("rows.Scan error(%v)", err)
}
return
}
return
}
// ShortbyID get short_url by id
func (d *Dao) ShortbyID(ctx context.Context, id int64) (res *model.ShortUrl, err error) {
rows := d.db.QueryRow(ctx, _shortByIDSQL, id)
res = &model.ShortUrl{}
if err = rows.Scan(&res.ID, &res.Mid, &res.Short, &res.Long, &res.State, &res.CTime, &res.MTime); err != nil {
if err == sql.ErrNoRows {
res = nil
err = nil
} else {
log.Error("rows.Scan err (%v)", err)
}
return
}
res.FormatDate()
return
}
// AllShorts get all short_url
func (d *Dao) AllShorts(ctx context.Context) (res []*model.ShortUrl, err error) {
rows, err := d.db.Query(ctx, _getAllSQL)
if err != nil {
log.Error("query error (%v)", err)
return
}
defer rows.Close()
for rows.Next() {
su := &model.ShortUrl{}
if err = rows.Scan(&su.ID, &su.Mid, &su.Short, &su.Long, &su.State, &su.CTime, &su.MTime); err != nil {
log.Error("rows.Scan err (%v)", err)
return
}
su.FormatDate()
res = append(res, su)
}
return
}
// ShortCount get all short_url
func (d *Dao) ShortCount(ctx context.Context, mid int64, long string) (count int, err error) {
countSQL := _shortCountSQL
if mid > 0 {
countSQL = fmt.Sprintf("%s AND mid=%d", countSQL, mid)
}
if long != "" {
countSQL += " AND long_url='" + long + "'"
}
row := d.db.QueryRow(ctx, countSQL, model.StateNormal)
if err = row.Scan(&count); err != nil {
log.Error("row.Scan error(%v)", err)
return
}
return
}
// InShort add short_url
func (d *Dao) InShort(ctx context.Context, su *model.ShortUrl) (id int64, err error) {
res, err := d.db.Exec(ctx, _shortInSQL, su.Mid, su.Short, su.Long, su.State, su.CTime)
if err != nil {
log.Error("tx.Exec() error(%v)", err)
return
}
return res.LastInsertId()
}
// ShortUp add short_url
func (d *Dao) ShortUp(ctx context.Context, id, mid int64, long string) (rows int64, err error) {
res, err := d.db.Exec(ctx, _shortUpSQL, mid, long, id)
if err != nil {
log.Error("tx.Exec error(%v)", err)
return
}
return res.RowsAffected()
}
// UpdateState update state
func (d *Dao) UpdateState(ctx context.Context, id, mid int64, state int) (rows int64, err error) {
_, err = d.db.Exec(ctx, _updateStateSQL, mid, state, id)
if err != nil {
log.Error("d.db.Exec(%s) error(%v)", _updateStateSQL, err)
return
}
return
}
// ShortLimit get short_url list
func (d *Dao) ShortLimit(ctx context.Context, pn, ps int, mid int64, long string) (res []*model.ShortUrl, err error) {
limitSQL := _getLimitSQL
if mid > 0 {
limitSQL = fmt.Sprintf("%s AND mid=%d", limitSQL, mid)
}
if long != "" {
limitSQL += " AND long_url='" + long + "'"
}
limitSQL += " ORDER BY id DESC LIMIT ?,? "
rows, err := d.db.Query(ctx, limitSQL, model.StateNormal, pn, ps)
if err != nil {
log.Error("query error (%v)", err)
return
}
defer rows.Close()
res = []*model.ShortUrl{}
for rows.Next() {
su := &model.ShortUrl{}
if err = rows.Scan(&su.ID, &su.Mid, &su.Short, &su.Long, &su.State, &su.CTime, &su.MTime); err != nil {
log.Error("rows.Scan err (%v)", err)
return
}
su.FormatDate()
res = append(res, su)
}
return
}

View File

@@ -0,0 +1,62 @@
package dao
import (
"context"
"go-common/app/interface/main/shorturl/model"
"go-common/library/cache/memcache"
"go-common/library/log"
)
func cacheKey(short string) string {
return _prefix + short
}
// Cache get short url cache.
func (d *Dao) Cache(c context.Context, short string) (su *model.ShortUrl, err error) {
var (
key = cacheKey(short)
conn = d.memchDB.Get(c)
item *memcache.Item
)
defer conn.Close()
if item, err = conn.Get(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
} else {
log.Error("conn.Get(%s) error(%v)", key, err)
}
return
}
if err = conn.Scan(item, &su); err != nil {
log.Error("conn.Get(%s) error(%v)", key, err)
}
return
}
// SetEmptyCache set empty cache for a few time
func (d *Dao) SetEmptyCache(c context.Context, short string) (err error) {
var (
key = cacheKey(short)
conn = d.memchDB.Get(c)
)
defer conn.Close()
if err = conn.Set(&memcache.Item{Key: key, Object: &model.ShortUrl{}, Flags: memcache.FlagJSON, Expiration: 300}); err != nil {
log.Error("conn.Set error(%v)", err)
}
return
}
// SetCache save model.ShortUrl to memcache
func (d *Dao) SetCache(c context.Context, su *model.ShortUrl) (err error) {
var (
key = cacheKey(su.Short)
conn = d.memchDB.Get(c)
)
defer conn.Close()
if err = conn.Set(&memcache.Item{Key: key, Object: su, Flags: memcache.FlagJSON, Expiration: 0}); err != nil {
log.Error("conn.Set error(%v)", err)
return
}
return
}

View File

@@ -0,0 +1,72 @@
package dao
import (
"context"
. "github.com/smartystreets/goconvey/convey"
model "go-common/app/interface/main/shorturl/model"
xtime "go-common/library/time"
"testing"
"time"
)
func TestDao_Short(t *testing.T) {
Convey("Short", t, WithDao(func(d *Dao) {
_, err := d.Short(context.TODO(), "http://b23.tv/EbUzmu")
So(err, ShouldBeNil)
}))
}
func TestDao_ShortbyID(t *testing.T) {
Convey("ShortbyID", t, WithDao(func(d *Dao) {
_, err := d.ShortbyID(context.TODO(), 1)
So(err, ShouldBeNil)
}))
}
func TestDao_AllShorts(t *testing.T) {
Convey("AllShorts", t, WithDao(func(d *Dao) {
_, err := d.AllShorts(context.TODO())
So(err, ShouldBeNil)
}))
}
func TestDao_ShortCount(t *testing.T) {
Convey("ShortCount", t, WithDao(func(d *Dao) {
_, err := d.ShortCount(context.TODO(), 1, "http://www.baidu.com")
So(err, ShouldBeNil)
}))
}
func TestDao_InShort(t *testing.T) {
Convey("InShort", t, WithDao(func(d *Dao) {
su := &model.ShortUrl{
Long: "http://www.baidu.com",
Mid: 279,
State: model.StateNormal,
CTime: xtime.Time(time.Now().Unix()),
}
_, err := d.InShort(context.TODO(), su)
So(err, ShouldBeNil)
}))
}
func TestDao_ShortUp(t *testing.T) {
Convey("ShortUp", t, WithDao(func(d *Dao) {
_, err := d.ShortUp(context.TODO(), 1, 20, "http://www.baidu.com")
So(err, ShouldBeNil)
}))
}
func TestDao_UpdateState(t *testing.T) {
Convey("UpdateState", t, WithDao(func(d *Dao) {
_, err := d.UpdateState(context.TODO(), 1, 279, 0)
So(err, ShouldBeNil)
}))
}
func TestDao_ShortLimit(t *testing.T) {
Convey("ShortLimit", t, WithDao(func(d *Dao) {
_, err := d.ShortLimit(context.TODO(), 1, 20, 279, "http://www.baidu.com")
So(err, ShouldBeNil)
}))
}