Skip to content

Commit

Permalink
fillUserResponseBulkのuserIconのN+1解消
Browse files Browse the repository at this point in the history
  • Loading branch information
sor4chi committed Nov 25, 2023
1 parent 92d0081 commit 5cff267
Showing 1 changed file with 37 additions and 13 deletions.
50 changes: 37 additions & 13 deletions go/user_handler.go
Expand Up @@ -11,6 +11,7 @@ import (
"net/http"
"os"
"strings"
"sync"
"time"

"github.com/google/uuid"
Expand Down Expand Up @@ -489,6 +490,8 @@ func fillUserResponseBulk(ctx context.Context, tx *sqlx.Tx, userModels []*UserMo

themeModelMap := make(map[int64]ThemeModel)
userIDs := make([]int64, len(userModels))
userIconGetIDs := make([]int64, len(userModels))
userIconHashMap := make(map[int64][32]byte, len(userModels))

for i := range userModels {
userModel := userModels[i]
Expand Down Expand Up @@ -518,29 +521,50 @@ func fillUserResponseBulk(ctx context.Context, tx *sqlx.Tx, userModels []*UserMo

for i := range userModels {
userModel := userModels[i]
themeModel := themeModelMap[userModel.ID]
var iconHash = [32]byte{}

if v, ok := userImageHashCache.Get(userModel.ID); ok {
cachedbyte, _ := hex.DecodeString(v)
copy(iconHash[:], cachedbyte)
userIconHashMap[userModel.ID] = iconHash
}

var image []byte
if err := tx.GetContext(ctx, &image, "SELECT image FROM icons WHERE user_id = ?", userModel.ID); err != nil {
if !errors.Is(err, sql.ErrNoRows) {
return []User{}, err
}
image, err = os.ReadFile(fallbackImage)
if err != nil {
return []User{}, err
}
if iconHash == [32]byte{} {
userIconGetIDs[i] = userModel.ID
}
}

if iconHash == [32]byte{} {
iconHash = sha256.Sum256(image)
userImageHashCache.Set(userModel.ID, fmt.Sprintf("%x", iconHash))
if len(userIconGetIDs) > 0 {
query, args, err := sqlx.In("SELECT user_id, image FROM icons WHERE user_id IN (?)", userIconGetIDs)
if err != nil {
return []User{}, err
}
query = tx.Rebind(query)
var userIcons []struct {
UserID int64 `db:"user_id"`
Image []byte `db:"image"`
}
if err := tx.SelectContext(ctx, &userIcons, query, args...); err != nil {
return []User{}, err
}
wg := sync.WaitGroup{}
for i := range userIcons {
wg.Add(1)
go func() {
defer wg.Done()
userIcon := userIcons[i]
iconHash := sha256.Sum256(userIcon.Image)
userIconHashMap[userIcon.UserID] = iconHash
userImageHashCache.Set(userIcon.UserID, fmt.Sprintf("%x", iconHash))
}()
}
wg.Wait()
}

for i := range userModels {
userModel := userModels[i]
themeModel := themeModelMap[userModel.ID]
iconHash := userIconHashMap[userModel.ID]

user := User{
ID: userModel.ID,
Expand Down

0 comments on commit 5cff267

Please sign in to comment.