Skip to content

Commit

Permalink
Merge branch 'master' of github.com:catatsuy/isucon9-qualify into opt…
Browse files Browse the repository at this point in the history
…imized-app
  • Loading branch information
kazeburo committed Aug 28, 2019
2 parents 725b048 + fa3d977 commit 3e66042
Show file tree
Hide file tree
Showing 24 changed files with 951 additions and 63 deletions.
27 changes: 21 additions & 6 deletions bench/asset/asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"log"
"math/rand"
"os"
"path/filepath"
"strings"
"sync"
"sync/atomic"
Expand All @@ -20,6 +21,15 @@ const (
ItemStatusStop = "stop"
ItemStatusCancel = "cancel"

TransactionEvidenceStatusWaitShipping = "wait_shipping"
TransactionEvidenceStatusWaitDone = "wait_done"
TransactionEvidenceStatusDone = "done"

ShippingsStatusInitial = "initial"
ShippingsStatusWaitPickup = "wait_pickup"
ShippingsStatusShipping = "shipping"
ShippingsStatusDone = "done"

ItemsPerPage = 48

ActiveSellerNumSellItems = 100
Expand Down Expand Up @@ -85,7 +95,7 @@ var (
)

// Initialize is a function to load initial data
func Initialize() {
func Initialize(dataDir string) {
users = make(map[int64]AppUser)
activeSellerIDs = make([]int64, 0, 400)
buyerIDs = make([]int64, 0, 1000)
Expand All @@ -96,7 +106,7 @@ func Initialize() {
userItems = make(map[int64][]int64)
transactionEvidences = make(map[int64]AppTransactionEvidence)

f, err := os.Open("initial-data/result/users_json.txt")
f, err := os.Open(filepath.Join(dataDir, "result/users_json.txt"))
if err != nil {
log.Fatal(err)
}
Expand All @@ -119,7 +129,7 @@ func Initialize() {
}
f.Close()

f, err = os.Open("initial-data/result/items_json.txt")
f, err = os.Open(filepath.Join(dataDir, "result/items_json.txt"))
if err != nil {
log.Fatal(err)
}
Expand All @@ -139,7 +149,7 @@ func Initialize() {
}
f.Close()

f, err = os.Open("initial-data/result/category_json.txt")
f, err = os.Open(filepath.Join(dataDir, "result/category_json.txt"))
if err != nil {
log.Fatal(err)
}
Expand All @@ -162,7 +172,7 @@ func Initialize() {
}
f.Close()

f, err = os.Open("initial-data/result/transaction_evidences_json.txt")
f, err = os.Open(filepath.Join(dataDir, "result/transaction_evidences_json.txt"))
if err != nil {
log.Fatal(err)
}
Expand All @@ -179,7 +189,7 @@ func Initialize() {
}
f.Close()

f, err = os.Open("initial-data/keywords.tsv")
f, err = os.Open(filepath.Join(dataDir, "keywords.tsv"))
if err != nil {
log.Fatal(err)
}
Expand Down Expand Up @@ -281,6 +291,11 @@ func GetRandomChildCategory() AppCategory {
return childCategories[rand.Intn(len(childCategories))]
}

func GetCategory(categoryID int) (AppCategory, bool) {
c, ok := categories[categoryID]
return c, ok
}

// TODO: transactionEvidencesをちゃんと管理するようにして存在しないケースをなくす
func GetTransactionEvidence(id int64) (AppTransactionEvidence, bool) {
te, ok := transactionEvidences[id]
Expand Down
18 changes: 15 additions & 3 deletions bench/fails/fails.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@ import (
const (
ErrApplication failure.StringCode = "error application"
ErrSession failure.StringCode = "error session"
ErrCritical failure.StringCode = "error critical"
ErrTimeout failure.StringCode = "error timeout"
)

type Critical struct {
Msgs []string
mu sync.Mutex
Msgs []string
critical int

mu sync.Mutex
}

func NewCritical() *Critical {
Expand All @@ -25,6 +28,13 @@ func NewCritical() *Critical {
}
}

func (c *Critical) GetCriticalCount() int {
c.mu.Lock()
defer c.mu.Unlock()

return c.critical
}

func (c *Critical) GetMsgs() []string {
c.mu.Lock()
defer c.mu.Unlock()
Expand All @@ -43,9 +53,11 @@ func (c *Critical) Add(err error) {
log.Printf("%+v", err)

if msg, ok := failure.MessageOf(err); ok {
switch c, _ := failure.CodeOf(err); c {
switch code, _ := failure.CodeOf(err); code {
case ErrTimeout:
msg += "(タイムアウトしました)"
case ErrCritical:
c.critical++
}

c.Msgs = append(c.Msgs, msg)
Expand Down
219 changes: 217 additions & 2 deletions bench/scenario/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,221 @@ func sell(ctx context.Context, s1 *session.Session, price int) (int64, error) {
return targetItemID, nil
}

func FindItemFromUsesTransactions(ctx context.Context, s *session.Session, targetItemID int64) (session.ItemDetail, error) {
return findItemFromUsesTransactions(ctx, s, targetItemID, 0, 0, 0)
}

func findItemFromUsesTransactions(ctx context.Context, s *session.Session, targetItemID, nextItemID, nextCreatedAt, loop int64) (session.ItemDetail, error) {
var hasNext bool
var items []session.ItemDetail
var err error
if nextItemID > 0 && nextCreatedAt > 0 {
hasNext, items, err = s.UsersTransactionsWithItemIDAndCreatedAt(ctx, nextItemID, nextCreatedAt)
} else {
hasNext, items, err = s.UsersTransactions(ctx)
}
if err != nil {
return session.ItemDetail{}, err
}

for _, item := range items {
if item.ID == targetItemID {
return item, nil
}
nextItemID = item.ID
nextCreatedAt = item.CreatedAt
}
loop = loop + 1
if hasNext || loop < 30 { // TODO: max pager
nextItem, err := findItemFromUsesTransactions(ctx, s, targetItemID, nextItemID, nextCreatedAt, loop)
if err != nil {
return nextItem, nil
}
}
return session.ItemDetail{}, failure.Wrap(err, failure.Messagef("/users/transactions.json から商品を探すことができませんでした (item_id: %d)", targetItemID))
}

func buyCompleteWithVerify(ctx context.Context, s1, s2 *session.Session, targetItemID int64, price int) error {
token := sPayment.ForceSet(CorrectCardNumber, targetItemID, price)

_, err := s2.Buy(ctx, targetItemID, token)
if err != nil {
return err
}

itemFromBuyerTrx, err := FindItemFromUsesTransactions(ctx, s2, targetItemID)
if err != nil {
return err
}
itemFromSellerTrx, err := FindItemFromUsesTransactions(ctx, s1, targetItemID)
if err != nil {
return err
}
itemFromBuyer, err := s2.Item(ctx, targetItemID)
if err != nil {
return err
}
itemFromSeller, err := s1.Item(ctx, targetItemID)
if err != nil {
return err
}

// status 確認
if itemFromBuyer.Status != asset.ItemStatusTrading || itemFromSeller.Status != asset.ItemStatusTrading ||
itemFromBuyerTrx.Status != asset.ItemStatusTrading || itemFromSellerTrx.Status != asset.ItemStatusTrading {
return failure.New(fails.ErrApplication, failure.Messagef("購入後の商品のステータスが正しくありません (item_id: %d)", targetItemID))
}
if itemFromBuyer.TransactionEvidenceStatus != asset.TransactionEvidenceStatusWaitShipping ||
itemFromSeller.TransactionEvidenceStatus != asset.TransactionEvidenceStatusWaitShipping ||
itemFromBuyerTrx.TransactionEvidenceStatus != asset.TransactionEvidenceStatusWaitShipping ||
itemFromSellerTrx.TransactionEvidenceStatus != asset.TransactionEvidenceStatusWaitShipping {
return failure.New(fails.ErrApplication, failure.Messagef("購入後のtransaction_evidenceのステータスが正しくありません (item_id: %d)", targetItemID))
}
if itemFromBuyer.ShippingStatus != asset.ShippingsStatusInitial ||
itemFromSeller.ShippingStatus != asset.ShippingsStatusInitial ||
itemFromBuyerTrx.ShippingStatus != asset.ShippingsStatusInitial ||
itemFromSellerTrx.ShippingStatus != asset.ShippingsStatusInitial {
return failure.New(fails.ErrApplication, failure.Messagef("購入後のshippingのステータスが正しくありません (item_id: %d)", targetItemID))
}

reserveID, apath, err := s1.Ship(ctx, targetItemID)
if err != nil {
return err
}

itemFromBuyer, err = s2.Item(ctx, targetItemID)
if err != nil {
return err
}
itemFromBuyerTrx, err = FindItemFromUsesTransactions(ctx, s2, targetItemID)
if err != nil {
return err
}
itemFromSellerTrx, err = FindItemFromUsesTransactions(ctx, s1, targetItemID)
if err != nil {
return err
}
itemFromSeller, err = s1.Item(ctx, targetItemID)
if err != nil {
return err
}

// status 確認
if itemFromBuyer.Status != asset.ItemStatusTrading || itemFromSeller.Status != asset.ItemStatusTrading ||
itemFromBuyerTrx.Status != asset.ItemStatusTrading || itemFromSellerTrx.Status != asset.ItemStatusTrading {
return failure.New(fails.ErrApplication, failure.Messagef("集荷予約後の商品のステータスが正しくありません (item_id: %d)", targetItemID))
}
if itemFromBuyer.TransactionEvidenceStatus != asset.TransactionEvidenceStatusWaitShipping ||
itemFromSeller.TransactionEvidenceStatus != asset.TransactionEvidenceStatusWaitShipping ||
itemFromBuyerTrx.TransactionEvidenceStatus != asset.TransactionEvidenceStatusWaitShipping ||
itemFromSellerTrx.TransactionEvidenceStatus != asset.TransactionEvidenceStatusWaitShipping {
return failure.New(fails.ErrApplication, failure.Messagef("集荷予約後のtransaction_evidenceのステータスが正しくありません (item_id: %d)", targetItemID))
}
if itemFromBuyer.ShippingStatus != asset.ShippingsStatusWaitPickup ||
itemFromSeller.ShippingStatus != asset.ShippingsStatusWaitPickup ||
itemFromBuyerTrx.ShippingStatus != asset.ShippingsStatusWaitPickup ||
itemFromSellerTrx.ShippingStatus != asset.ShippingsStatusWaitPickup {
return failure.New(fails.ErrApplication, failure.Messagef("集荷予約後のshippingのステータスが正しくありません (item_id: %d)", targetItemID))
}

md5Str, err := s1.DownloadQRURL(ctx, apath)
if err != nil {
return err
}

sShipment.ForceSetStatus(reserveID, server.StatusShipping)
if !sShipment.CheckQRMD5(reserveID, md5Str) {
return failure.New(fails.ErrApplication, failure.Messagef("QRコードの画像に誤りがあります (item_id: %d, reserve_id: %s)", targetItemID, reserveID))
}

err = s1.ShipDone(ctx, targetItemID)
if err != nil {
return err
}

itemFromSellerTrx, err = FindItemFromUsesTransactions(ctx, s1, targetItemID)
if err != nil {
return err
}
itemFromBuyer, err = s2.Item(ctx, targetItemID)
if err != nil {
return err
}
itemFromSeller, err = s1.Item(ctx, targetItemID)
if err != nil {
return err
}
itemFromBuyerTrx, err = FindItemFromUsesTransactions(ctx, s2, targetItemID)
if err != nil {
return err
}

// status 確認
if itemFromBuyer.Status != asset.ItemStatusTrading || itemFromSeller.Status != asset.ItemStatusTrading ||
itemFromBuyerTrx.Status != asset.ItemStatusTrading || itemFromSellerTrx.Status != asset.ItemStatusTrading {
return failure.New(fails.ErrApplication, failure.Messagef("発送完了後の商品のステータスが正しくありません (item_id: %d)", targetItemID))
}
if itemFromBuyer.TransactionEvidenceStatus != asset.TransactionEvidenceStatusWaitDone ||
itemFromSeller.TransactionEvidenceStatus != asset.TransactionEvidenceStatusWaitDone ||
itemFromBuyerTrx.TransactionEvidenceStatus != asset.TransactionEvidenceStatusWaitDone ||
itemFromSellerTrx.TransactionEvidenceStatus != asset.TransactionEvidenceStatusWaitDone {
return failure.New(fails.ErrApplication, failure.Messagef("発送完了後のtransaction_evidenceのステータスが正しくありません (item_id: %d)", targetItemID))
}
if itemFromBuyer.ShippingStatus != asset.ShippingsStatusShipping ||
itemFromSeller.ShippingStatus != asset.ShippingsStatusShipping ||
itemFromBuyerTrx.ShippingStatus != asset.ShippingsStatusShipping ||
itemFromSellerTrx.ShippingStatus != asset.ShippingsStatusShipping {
return failure.New(fails.ErrApplication, failure.Messagef("発送完了後のshippingのステータスが正しくありません (item_id: %d)", targetItemID))
}

ok := sShipment.ForceSetStatus(reserveID, server.StatusDone)
if !ok {
return failure.New(fails.ErrApplication, failure.Messagef("配送予約IDに誤りがあります (item_id: %d, reserve_id: %s)", targetItemID, reserveID))
}

err = s2.Complete(ctx, targetItemID)
if err != nil {
return err
}

itemFromBuyer, err = s2.Item(ctx, targetItemID)
if err != nil {
return err
}
itemFromSellerTrx, err = FindItemFromUsesTransactions(ctx, s1, targetItemID)
if err != nil {
return err
}
itemFromSeller, err = s1.Item(ctx, targetItemID)
if err != nil {
return err
}
itemFromBuyerTrx, err = FindItemFromUsesTransactions(ctx, s2, targetItemID)
if err != nil {
return err
}

// status 確認
if itemFromBuyer.Status != asset.ItemStatusSoldOut || itemFromSeller.Status != asset.ItemStatusSoldOut ||
itemFromBuyerTrx.Status != asset.ItemStatusSoldOut || itemFromSellerTrx.Status != asset.ItemStatusSoldOut {
return failure.New(fails.ErrApplication, failure.Messagef("取引完了後の商品のステータスが正しくありません (item_id: %d)", targetItemID))
}
if itemFromBuyer.TransactionEvidenceStatus != asset.TransactionEvidenceStatusDone ||
itemFromSeller.TransactionEvidenceStatus != asset.TransactionEvidenceStatusDone ||
itemFromBuyerTrx.TransactionEvidenceStatus != asset.TransactionEvidenceStatusDone ||
itemFromSellerTrx.TransactionEvidenceStatus != asset.TransactionEvidenceStatusDone {
return failure.New(fails.ErrApplication, failure.Messagef("取引完了後のtransaction_evidenceのステータスが正しくありません (item_id: %d)", targetItemID))
}
if itemFromBuyer.ShippingStatus != asset.ShippingsStatusDone ||
itemFromSeller.ShippingStatus != asset.ShippingsStatusDone ||
itemFromBuyerTrx.ShippingStatus != asset.ShippingsStatusDone ||
itemFromSellerTrx.ShippingStatus != asset.ShippingsStatusDone {
return failure.New(fails.ErrApplication, failure.Messagef("取引完了後のshippingのステータスが正しくありません (item_id: %d)", targetItemID))
}

return nil
}

func buyComplete(ctx context.Context, s1, s2 *session.Session, targetItemID int64, price int) error {
token := sPayment.ForceSet(CorrectCardNumber, targetItemID, price)

Expand All @@ -91,7 +306,7 @@ func buyComplete(ctx context.Context, s1, s2 *session.Session, targetItemID int6

sShipment.ForceSetStatus(reserveID, server.StatusShipping)
if !sShipment.CheckQRMD5(reserveID, md5Str) {
return failure.New(fails.ErrApplication, failure.Message("QRコードの画像に誤りがあります"))
return failure.New(fails.ErrApplication, failure.Messagef("QRコードの画像に誤りがあります (item_id: %d, reserve_id: %s)", targetItemID, reserveID))
}

err = s1.ShipDone(ctx, targetItemID)
Expand All @@ -101,7 +316,7 @@ func buyComplete(ctx context.Context, s1, s2 *session.Session, targetItemID int6

ok := sShipment.ForceSetStatus(reserveID, server.StatusDone)
if !ok {
return failure.New(fails.ErrApplication, failure.Message("配送予約IDに誤りがあります"))
return failure.New(fails.ErrApplication, failure.Messagef("配送予約IDに誤りがあります (item_id: %d, reserve_id: %s)", targetItemID, reserveID))
}

err = s2.Complete(ctx, targetItemID)
Expand Down
Loading

0 comments on commit 3e66042

Please sign in to comment.