This repository has been archived by the owner on Jun 25, 2024. It is now read-only.
generated from bgpat/isucon-boilerplate
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
/home/isucon/gasshuku-isucon/Makefile
- Loading branch information
anonymous
committed
Sep 8, 2023
1 parent
94742d2
commit 5034bce
Showing
57 changed files
with
5,224 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
.PHONY: dump-schema | ||
dump-schema: | ||
mysqldump isulibrary -d | grep -v "/\*" | grep -v "\-\-" >webapp/sql/0_schema.sql | ||
|
||
.PHONY: dump-data | ||
dump-data: | ||
mysqldump isulibrary -t | grep -v "/\*" | grep -v "\-\-" | grep -v LOCK | grep -v '^s*$$' >webapp/sql/1_data.sql | ||
|
||
.PHONY: init-db | ||
init-db: | ||
sh webapp/sql/init_db.sh | ||
|
||
.PHONY: go-gen | ||
go-gen: | ||
cd bench && go generate ./... | ||
|
||
.PHONY: run-go | ||
run-go: | ||
cd webapp/go && go run *.go | ||
|
||
.PHONY: run-bench | ||
run-bench: | ||
cd bench && go run main.go >/dev/null | ||
|
||
.PHONY: run-generator | ||
run-generator: | ||
touch bench/repository/init_data.json webapp/sql/1_data.sql | ||
@make init-db | ||
cd bench/repository/generator && go run *.go | ||
@make dump-data | ||
|
||
.PHONY: up | ||
up: | ||
cd dev && docker compose up -d | ||
|
||
.PHONY: build-up | ||
build-up: | ||
cd dev && docker compose up -d --build | ||
|
||
.PHONY: down | ||
down: | ||
cd dev && docker compose down | ||
|
||
.PHONY: compose-log | ||
compose-log: | ||
cd dev && docker compose logs -f backend |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
package action | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"time" | ||
|
||
"github.com/isucon/isucandar/agent" | ||
"github.com/isucon/isucandar/failure" | ||
"github.com/logica0419/gasshuku-isucon/bench/config" | ||
"github.com/logica0419/gasshuku-isucon/bench/model" | ||
"github.com/logica0419/gasshuku-isucon/bench/utils" | ||
) | ||
|
||
const ( | ||
libAgentsNum = 10 // 図書館職員エージェント数 | ||
searchAgentsNum = 10 // 検索端末エージェント数 | ||
) | ||
|
||
// Actionパッケージ内でしか使わないものを管理する構造体 | ||
// | ||
// Agentsは初期化以降ReadOnlyなため、ロックを取る機構は用意していない | ||
type Controller struct { | ||
initializeAgent *agent.Agent | ||
|
||
initializeTimeout time.Duration | ||
requestTimeout time.Duration | ||
|
||
libAgents []utils.Choice[*agent.Agent] | ||
searchAgents []utils.Choice[*agent.Agent] | ||
} | ||
|
||
func NewController(c *config.Config) (*Controller, error) { | ||
initializeAgent, err := agent.NewAgent(agent.WithBaseURL(c.BaseURL), agent.WithDefaultTransport(), | ||
agent.WithTimeout(time.Duration(c.InitializeTimeout)*time.Millisecond)) | ||
if err != nil { | ||
return nil, failure.NewError(model.ErrCritical, err) | ||
} | ||
initializeAgent.Name = "Isulibrary-InitializeAgent" | ||
|
||
libAgents := make([]utils.Choice[*agent.Agent], libAgentsNum) | ||
searchAgents := make([]utils.Choice[*agent.Agent], searchAgentsNum) | ||
|
||
for i := 0; i < libAgentsNum; i++ { | ||
libAgents[i].Weight = 1 | ||
libAgents[i].Val, err = agent.NewAgent(agent.WithBaseURL(c.BaseURL), agent.WithDefaultTransport(), | ||
agent.WithTimeout(time.Duration(c.RequestTimeout)*time.Millisecond)) | ||
if err != nil { | ||
return nil, failure.NewError(model.ErrCritical, err) | ||
} | ||
libAgents[i].Val.Name = fmt.Sprintf("Isulibrary-LibAgent-%d", i+1) | ||
} | ||
for i := 0; i < searchAgentsNum; i++ { | ||
searchAgents[i].Weight = 1 | ||
searchAgents[i].Val, err = agent.NewAgent(agent.WithBaseURL(c.BaseURL), agent.WithDefaultTransport(), | ||
agent.WithTimeout(time.Duration(c.RequestTimeout)*time.Millisecond)) | ||
if err != nil { | ||
return nil, failure.NewError(model.ErrCritical, err) | ||
} | ||
searchAgents[i].Val.Name = fmt.Sprintf("Isulibrary-SearchAgent-%d", i+1) | ||
} | ||
|
||
return &Controller{ | ||
initializeAgent: initializeAgent, | ||
initializeTimeout: time.Duration(c.InitializeTimeout) * time.Millisecond, | ||
requestTimeout: time.Duration(c.RequestTimeout) * time.Millisecond, | ||
libAgents: libAgents, | ||
searchAgents: searchAgents, | ||
}, nil | ||
} | ||
|
||
func (c *Controller) libAgent() *agent.Agent { | ||
a, _ := utils.WeightedSelect(c.libAgents, false) | ||
return a | ||
} | ||
|
||
func (c *Controller) searchAgent() *agent.Agent { | ||
a, _ := utils.WeightedSelect(c.searchAgents, false) | ||
return a | ||
} | ||
|
||
func processErr(ctx context.Context, err error) error { | ||
select { | ||
case <-ctx.Done(): | ||
return failure.NewError(model.ErrDeadline, err) | ||
default: | ||
if model.IsErrTimeout(err) { | ||
return failure.NewError(model.ErrTimeout, err) | ||
} | ||
return failure.NewError(model.ErrRequestFailed, err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
package action | ||
|
||
import ( | ||
"context" | ||
"net/http" | ||
"strconv" | ||
|
||
"github.com/isucon/isucandar/failure" | ||
"github.com/logica0419/gasshuku-isucon/bench/model" | ||
"github.com/logica0419/gasshuku-isucon/bench/utils" | ||
) | ||
|
||
type BookController interface { | ||
PostBooks(ctx context.Context, body []PostBooksRequest) (*http.Response, error) | ||
GetBooks(ctx context.Context, query GetBooksQuery) (*http.Response, error) | ||
GetBook(ctx context.Context, id string, encrypted bool) (*http.Response, error) | ||
GetBookQRCode(ctx context.Context, id string) (*http.Response, error) | ||
} | ||
|
||
var _ BookController = &Controller{} | ||
|
||
type PostBooksRequest struct { | ||
Title string `json:"title"` | ||
Author string `json:"author"` | ||
Genre model.Genre `json:"genre"` | ||
} | ||
|
||
// POST /api/books | ||
func (c *Controller) PostBooks(ctx context.Context, body []PostBooksRequest) (*http.Response, error) { | ||
reader, err := utils.EncodeJson(body) | ||
if err != nil { | ||
return nil, failure.NewError(model.ErrCritical, err) | ||
} | ||
|
||
agent := c.libAgent() | ||
|
||
req, err := agent.POST("/api/books", reader) | ||
if err != nil { | ||
return nil, failure.NewError(model.ErrCritical, err) | ||
} | ||
req.Header.Set("Content-Type", "application/json") | ||
|
||
res, err := agent.Do(ctx, req) | ||
if err != nil { | ||
return nil, processErr(ctx, err) | ||
} | ||
|
||
return res, nil | ||
} | ||
|
||
type GetBooksQuery struct { | ||
Title string | ||
Author string | ||
Genre model.Genre | ||
Page int | ||
LastBookID string | ||
} | ||
|
||
type GetBooksResponse struct { | ||
Books []model.BookWithLending `json:"books"` | ||
Total int `json:"total"` | ||
} | ||
|
||
// GET /api/books | ||
func (c *Controller) GetBooks(ctx context.Context, query GetBooksQuery) (*http.Response, error) { | ||
agent := c.searchAgent() | ||
|
||
url := "/api/books?" | ||
if query.Title != "" { | ||
url += "title=" + query.Title + "&" | ||
} | ||
if query.Author != "" { | ||
url += "author=" + query.Author + "&" | ||
} | ||
if query.Genre >= 0 { | ||
url += "genre=" + query.Genre.String() + "&" | ||
} | ||
if query.Page > 1 { | ||
url += "page=" + strconv.Itoa(query.Page) + "&" | ||
} | ||
if query.LastBookID != "" { | ||
url += "last_book_id=" + query.LastBookID + "&" | ||
} | ||
url = url[:len(url)-1] // 最後の一文字(?か&)を削除する | ||
|
||
req, err := agent.GET(url) | ||
if err != nil { | ||
return nil, failure.NewError(model.ErrCritical, err) | ||
} | ||
|
||
res, err := agent.Do(ctx, req) | ||
if err != nil { | ||
return nil, processErr(ctx, err) | ||
} | ||
|
||
return res, nil | ||
} | ||
|
||
// GET /api/books/:id | ||
func (c *Controller) GetBook(ctx context.Context, id string, encrypted bool) (*http.Response, error) { | ||
agent := c.libAgent() | ||
|
||
url := "/api/books/" + id | ||
if encrypted { | ||
url += "?encrypted=true" | ||
} | ||
|
||
req, err := agent.GET(url) | ||
if err != nil { | ||
return nil, failure.NewError(model.ErrCritical, err) | ||
} | ||
|
||
res, err := agent.Do(ctx, req) | ||
if err != nil { | ||
return nil, processErr(ctx, err) | ||
} | ||
|
||
return res, nil | ||
} | ||
|
||
// GET /api/members/:id/qrcode | ||
func (c *Controller) GetBookQRCode(ctx context.Context, id string) (*http.Response, error) { | ||
agent := c.libAgent() | ||
|
||
req, err := agent.GET("/api/books/" + id + "/qrcode") | ||
if err != nil { | ||
return nil, failure.NewError(model.ErrCritical, err) | ||
} | ||
|
||
res, err := agent.Do(ctx, req) | ||
if err != nil { | ||
return nil, processErr(ctx, err) | ||
} | ||
|
||
return res, nil | ||
} |
Oops, something went wrong.