bugfix
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"io"
|
||||
"log/slog"
|
||||
"mime/multipart"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -143,6 +144,7 @@ func (s *UserService) InfoGetBySelf(ctx context.Context, userID int64) (*dto.Use
|
||||
|
||||
if user, err := redisdao.UserInfoGet(ctx, userID); err == nil && user != nil {
|
||||
info := buildUserInfoResponse(user)
|
||||
s.consumeNewUserFlag(userID, &info)
|
||||
return &info, nil
|
||||
} else if err != nil && !isCacheMiss(err) {
|
||||
// 缓存异常不阻断,继续回落 DB。
|
||||
@@ -158,9 +160,22 @@ func (s *UserService) InfoGetBySelf(ctx context.Context, userID int64) (*dto.Use
|
||||
_ = redisdao.UserInfoSet(ctx, user, 0)
|
||||
|
||||
info := buildUserInfoResponse(user)
|
||||
s.consumeNewUserFlag(userID, &info)
|
||||
return &info, nil
|
||||
}
|
||||
|
||||
// consumeNewUserFlag 消费「新用户」标记。
|
||||
// is_new_user 只在注册时写 true,此前没有任何复位路径,会让客户端「新用户引导」反复触发。
|
||||
// 首次读取用户信息即视为引导已消费:本次响应返回 false,并异步复位 DB(best-effort,失败只告警)。
|
||||
// 只在「获取用户信息」路径调用——WxLogin 的 is_new_user 表示「本次是否新注册」,语义保持不变。
|
||||
func (s *UserService) consumeNewUserFlag(userID int64, info *dto.UserInfoGetBySelfResponse) {
|
||||
if !info.IsNewUser {
|
||||
return
|
||||
}
|
||||
info.IsNewUser = false
|
||||
go s.resetNewUserFlag(userID)
|
||||
}
|
||||
|
||||
// ProfileUpdate 修改当前用户资料。
|
||||
func (s *UserService) ProfileUpdate(ctx context.Context, userID int64, request *dto.UserProfileUpdateBySelfRequest) (*dto.UserProfileUpdateBySelfResponse, *errcode.Error) {
|
||||
ctx, span := global.Tracer.Start(ctx, "svc.UserProfileUpdate")
|
||||
@@ -257,9 +272,13 @@ func (s *UserService) AvatarUpload(ctx context.Context, userID int64, fileHeader
|
||||
return nil, errcode.UploadFileSaveFailed
|
||||
}
|
||||
subDir := fmt.Sprintf("%s/%d/avatar", user.UserUUID, userID)
|
||||
if _, serr := upload.FileSaveTmpBytes(ctx, imageData, fileName, subDir); serr != nil {
|
||||
tmpPath, serr := upload.FileSaveTmpBytes(ctx, imageData, fileName, subDir)
|
||||
if serr != nil {
|
||||
return nil, errcode.UploadFileSaveFailed
|
||||
}
|
||||
// 头像不消耗额度、上传接口也无限流,临时文件必须清理,
|
||||
// 否则单个认证用户循环上传即可把磁盘写满(此前返回值被丢弃,文件从不删除)。
|
||||
defer func() { _ = os.Remove(tmpPath) }()
|
||||
cosKey := fmt.Sprintf("%s/%s", subDir, fileName)
|
||||
if cerr := upload.FileUploadCos(ctx, cosKey); cerr != nil {
|
||||
return nil, errcode.UploadFileSaveFailed
|
||||
@@ -415,3 +434,16 @@ func buildUserInfoResponse(user *mysqlmodel.User) dto.UserInfoGetBySelfResponse
|
||||
VIPExpire: user.VIPExpire,
|
||||
}
|
||||
}
|
||||
|
||||
// resetNewUserFlag 异步复位 is_new_user(best-effort,失败仅告警)。
|
||||
// 使用独立 context,避免请求结束后 ctx 被取消导致复位失败。
|
||||
func (s *UserService) resetNewUserFlag(userID int64) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if err := s.userDao.UserUpdateByID(ctx, userID, map[string]any{"is_new_user": false}); err != nil {
|
||||
slog.WarnContext(ctx, "reset is_new_user failed", "user_id", userID, "error", err)
|
||||
return
|
||||
}
|
||||
_ = redisdao.UserInfoDel(ctx, userID)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user