Skip to content

Commit

Permalink
refactor: 监听每整5分钟一次
Browse files Browse the repository at this point in the history
  • Loading branch information
allen committed Apr 29, 2022
1 parent 2420929 commit 20bd04a
Show file tree
Hide file tree
Showing 11 changed files with 113 additions and 67 deletions.
12 changes: 10 additions & 2 deletions internal/app/api/home.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"dingdong/assets"
"dingdong/internal/app/config"
"dingdong/internal/app/pkg/ddmc/session"
"dingdong/internal/app/service"
"dingdong/internal/app/service/notify"
"dingdong/pkg/json"
"dingdong/pkg/yaml"
Expand Down Expand Up @@ -57,10 +58,17 @@ func GetAddress(w http.ResponseWriter, _ *http.Request) {
_, _ = io.WriteString(w, err.Error()+"\n")
return
}
_, err = io.WriteString(w, json.MustEncodeToString(list)+"\n")
_, _ = io.WriteString(w, json.MustEncodeToString(list)+"\n")
}

// AddOrder 提交订单
func AddOrder(w http.ResponseWriter, _ *http.Request) {
err := service.AddOrder()
if err != nil {
log.Println("io.WriteString error =>", err)
_, _ = io.WriteString(w, err.Error()+"\n")
return
}
_, _ = io.WriteString(w, "创建订单成功\n")
}

// SetConfig 通过接口更新配置并重载配置
Expand Down
6 changes: 4 additions & 2 deletions internal/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func Run() {
http.HandleFunc("/config", api.ConfigView)
http.HandleFunc("/notify", api.Notify)
http.HandleFunc("/address", api.GetAddress)
http.HandleFunc("/addOrder", api.AddOrder)
http.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.FS(assets.FS))))

conf := config.Get()
Expand All @@ -43,14 +44,15 @@ func isPeak() bool {
func Monitor() {
cartMap := service.MockCartMap()
for {
conf := config.Get()
<-time.After(time.Second)
conf := config.Get()
// duration := conf.MonitorIntervalMin + rand.Intn(conf.MonitorIntervalMax-conf.MonitorIntervalMin)
if !conf.MonitorNeeded && !conf.PickUpNeeded {
continue
}
// 每5分钟第1秒运行一次
now := time.Now()
if now.Second() != 1 {
if now.Minute()%5 != 0 || now.Second() != 1 {
continue
}
if isPeak() {
Expand Down
5 changes: 0 additions & 5 deletions internal/app/pkg/ddmc/session/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,5 @@ func GetAddress() ([]address.Item, error) {
return nil, errs.New(code.NoValidAddress)
}

// res := make(map[string]address.Item)
// for _, v := range result.Data.Valid {
// str := fmt.Sprintf("%s %s %s", v.UserName, v.Location.Address, v.AddrDetail)
// res[str] = v
// }
return result.Data.Valid, nil
}
6 changes: 3 additions & 3 deletions internal/app/pkg/ddmc/session/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func retryInterval(resp *req.Response, attempt int) time.Duration {

func retryHook(resp *req.Response, err error) {
if err != nil {
log.Println("Request error =>", err.Error())
log.Printf("Request error => %+v", err)
}
r := resp.Request.RawRequest
log.Println("Retry request =>", r.Method, r.URL)
Expand Down Expand Up @@ -129,7 +129,7 @@ func chooseAddr() {

options := make([]string, 0, len(addrList))
for _, v := range addrList {
options = append(options, fmt.Sprintf("%s %s %s", v.Location.Address, v.Location.Name, v.AddrDetail))
options = append(options, fmt.Sprintf("%s %s %s %s", v.Location.Address, v.Location.Name, v.AddrDetail, v.StationName))
}

var addr string
Expand All @@ -144,7 +144,7 @@ func chooseAddr() {
index := textual.IndexOf(addr, options)
s.Address = addrList[index]
log.Printf("Address => %#v", s.Address)
log.Printf("已选择收货地址: %s %s %s", s.Address.Location.Address, s.Address.Location.Name, s.Address.AddrDetail)
log.Printf("已选择收货地址: %s %s %s %s", s.Address.Location.Address, s.Address.Location.Name, s.Address.AddrDetail, s.Address.StationName)
return
}

Expand Down
2 changes: 1 addition & 1 deletion internal/app/pkg/errs/code/code.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const (
NoValidProduct // 当前购物车中没有可购商品
NoReserveTime // 当前没有可用的配送时段
NoReserveTimeAndRetry // 当前没有可用的配送时段, 请稍后再试
ReserveTimeIsDisabled // 您选择的送达时间已经失效了,请重新选择
ReserveTimeIsDisabled // 您选择的送达时间已经失效, 请重新选择
)

func (i ErrorCode) Int() int {
Expand Down
4 changes: 2 additions & 2 deletions internal/app/pkg/errs/code/errorcode_string.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 15 additions & 13 deletions internal/app/pkg/errs/errs.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,36 +25,38 @@ type ErrorImpl struct {
}

// Unwrap 获取内部错误
func (e ErrorImpl) Unwrap() error {
func (e *ErrorImpl) Unwrap() error {
return e.error
}

func (e ErrorImpl) Code() code.ErrorCode {
func (e *ErrorImpl) Code() code.ErrorCode {
return e.code
}

func (e ErrorImpl) Error() string {
if e.error == nil {
return e.code.String()
}
return e.code.String() + " " + e.error.Error()
}

func (e ErrorImpl) Message() string {
func (e *ErrorImpl) Message() string {
// 不要注释这里的代码, 运行前请先执行 make generate
return e.code.String()
}

func (e ErrorImpl) CodeEqual(code code.ErrorCode) bool {
func (e *ErrorImpl) Error() string {
return fmt.Sprintf("%v", e)
}

func (e *ErrorImpl) CodeEqual(code code.ErrorCode) bool {
return e.code == code
}

// Format 格式化打印
func (e ErrorImpl) Format(f fmt.State, verb rune) {
func (e *ErrorImpl) Format(f fmt.State, verb rune) {
_, _ = io.WriteString(f, e.Message())
if e.error == nil {
return
}
_, _ = io.WriteString(f, " ")
if v, ok := e.error.(fmt.Formatter); ok {
v.Format(f, verb)
} else {
_, _ = io.WriteString(f, e.Error())
_, _ = io.WriteString(f, e.error.Error())
}
}

Expand Down
4 changes: 1 addition & 3 deletions internal/app/service/reserve.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"net/http"
"time"

"dingdong/internal/app/config"
"dingdong/internal/app/dto/reserve_time"
"dingdong/internal/app/pkg/date"
"dingdong/internal/app/pkg/ddmc/session"
Expand Down Expand Up @@ -36,13 +35,12 @@ func MockMultiReserveTime() *reserve_time.GoTimes {
reserveTime := &reserve_time.GoTimes{}
halfPastTwoPM := date.TodayUnix(14, 30, 0)
now := time.Now().Unix()
conf := config.Get()
if now >= date.TodayUnix(0, 0, 0) && now <= date.TodayUnix(6, 20, 0) {
reserveTime.StartTimestamp = date.TodayUnix(6, 30, 0)
reserveTime.EndTimestamp = halfPastTwoPM
return reserveTime
}
if now >= date.SecondSnapUpUnix()-conf.AdvanceTime && now <= date.TodayUnix(8, 50, 0) {
if now >= date.TodayUnix(8, 20, 0) && now <= date.TodayUnix(8, 50, 0) {
reserveTime.StartTimestamp = halfPastTwoPM
reserveTime.EndTimestamp = date.TodayUnix(22, 30, 0)
return reserveTime
Expand Down
59 changes: 46 additions & 13 deletions internal/app/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
const (
FirstSnapUp = iota + 1
SecondSnapUp
PickUpMode
)

const (
Expand Down Expand Up @@ -199,7 +200,6 @@ func (t *Task) CheckOrder(wg *sync.WaitGroup) {
<-time.After(10 * time.Millisecond)
continue
}
t.MockMultiReserveTime() // 更新配送时段
duration := durationMinMillis + rand.Intn(durationGapMillis)
checkOrderMap, err := CheckOrder(t.CartMap(), t.ReserveTime())
if err != nil {
Expand Down Expand Up @@ -227,11 +227,11 @@ func (t *Task) AddNewOrder(wg *sync.WaitGroup) {
<-time.After(10 * time.Millisecond)
continue
}
t.MockMultiReserveTime() // 更新配送时段
err := AddNewOrder(t.CartMap(), t.ReserveTime(), t.CheckOrderMap())
if err != nil {
_err := errs.New(code.ReserveTimeIsDisabled)
if !errs.As(err, &_err) {
t.Finished()
return
}
log.Println(err)
Expand All @@ -256,30 +256,29 @@ func (t *Task) AddNewOrder(wg *sync.WaitGroup) {
}
}

func timeTrigger() bool {
func timeTrigger() int {
conf := config.Get()
now := time.Now()
firstTime := date.FirstSnapUpUnix()
// log.Println(conf.SnapUp&FirstSnapUp == FirstSnapUp, now, firstTime, now.Unix(), firstTime)
if conf.SnapUp&FirstSnapUp == FirstSnapUp && now.Unix() == firstTime-conf.AdvanceTime {
log.Println("===== 6点抢购开始 =====")
return true
return FirstSnapUp
}
secondTime := date.SecondSnapUpUnix()
// log.Println(conf.SnapUp&SecondSnapUp == SecondSnapUp, now, secondTime, now.Unix(), secondTime)
if conf.SnapUp&SecondSnapUp == SecondSnapUp && now.Unix() == secondTime-conf.AdvanceTime {
log.Println("===== 8点半抢购开始 =====")
return true
return SecondSnapUp
}
return false
return 0
}

func SnapUpOnce() {
func SnapUpOnce(mode int) {
conf := config.Get()
wg := new(sync.WaitGroup)
task := NewTask()
defer task.Finished()
task.MockMultiReserveTime() // 模拟配送时段

for i := 0; i < conf.BaseConcurrency; i++ {
wg.Add(1)
Expand All @@ -291,13 +290,26 @@ func SnapUpOnce() {
go task.GetCart(wg)
}

if mode == PickUpMode {
for i := 0; i < conf.BaseConcurrency; i++ {
wg.Add(1)
go task.GetMultiReserveTime(wg)
}
}

if mode == FirstSnapUp || mode == SecondSnapUp {
task.MockMultiReserveTime() // 更新配送时段
}

for i := 0; i < conf.BaseConcurrency; i++ {
wg.Add(1)
go task.CheckOrder(wg)
}

// 提前1秒开始提交订单, 提前太早有可能被风控
// <-time.After(time.Duration(60-1-time.Now().Second()) * time.Second)
// 只提前2秒开始提交订单, 提前太早有可能被风控
if mode == FirstSnapUp || mode == SecondSnapUp {
<-time.After(time.Duration(60-2-time.Now().Second()) * time.Second)
}
for i := 0; i < conf.SubmitConcurrency; i++ {
wg.Add(1)
go task.AddNewOrder(wg)
Expand All @@ -312,8 +324,9 @@ func SnapUp() {
for {
select {
case <-timer:
if timeTrigger() {
go SnapUpOnce()
mode := timeTrigger()
if mode > 0 {
go SnapUpOnce(mode)
}
}
}
Expand All @@ -323,7 +336,7 @@ func SnapUp() {
func PickUp() {
for {
<-pickUpCh
SnapUpOnce()
SnapUpOnce(PickUpMode)
}
}

Expand Down Expand Up @@ -395,3 +408,23 @@ func Notify() {
wg.Wait()
}
}

func AddOrder() error {
err := AllCheck()
if err != nil {
return err
}
cartMap, err := GetCart()
if err != nil {
return err
}
reserveTimes, err := GetMultiReserveTime(cartMap)
if err != nil {
return err
}
orderMap, err := CheckOrder(cartMap, reserveTimes)
if err != nil {
return err
}
return AddNewOrder(cartMap, reserveTimes, orderMap)
}
18 changes: 18 additions & 0 deletions internal/app/test/common/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package common

import (
"testing"
"time"

"dingdong/internal/app/config"
"dingdong/internal/app/pkg/date"
Expand Down Expand Up @@ -29,6 +30,12 @@ func BenchmarkSnapUpTime(b *testing.B) {
}

func TestError(t *testing.T) {
err1 := errs.Wrap(code.Unexpected, errs.Wrap(code.InvalidResponse, errs.New(code.ReserveTimeIsDisabled)))
t.Log(err1.Error())
t.Log(err1.Message())
err2 := errs.Wrap(code.Unexpected, errs.WithMessage(code.InvalidResponse, "提交订单失败"))
t.Logf("%#v", err2)

err := errs.New(code.ReserveTimeIsDisabled)
second := errs.New(code.ReserveTimeIsDisabled)
if !errs.As(err, &second) {
Expand All @@ -38,6 +45,17 @@ func TestError(t *testing.T) {
t.Log("error is equal")
}

func TestTimer(t *testing.T) {
go func() {
for {
t.Log("timer =>", time.Now().Second())
time.Sleep(time.Second)
}
}()
<-time.After(time.Duration(60-1-time.Now().Second()) * time.Second)
t.Log("timer finished")
}

func TestJsonGet(t *testing.T) {
conf := config.Get()
bs := json.MustEncode(conf)
Expand Down
Loading

0 comments on commit 20bd04a

Please sign in to comment.