-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DEAD-39: image-feat: add s3 repository #8
base: DEAD-15
Are you sure you want to change the base?
Conversation
@@ -0,0 +1,20 @@ | |||
services: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
а зачем отдельный docker-compose файл под минио?
SetAvatarImage(ctx context.Context, data *domain.ImageData, userID domain.UserID) (domain.ImageURL, error) | ||
DeleteAvatarImage(ctx context.Context, userID domain.UserID) error |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
тут можно бы назвать исключив слово Avatar: SetImage, DeleteImage. Они находятся в интерфейсе юзкейса Аватарок, соответственно и так понятно, что метод относится к ним
|
||
imageData := new(domain.ImageData) | ||
|
||
file, fileHeader, multipartErr := utils.DecodeImage(r, h.cfg) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
да можно было бы и просто err, она тут ни с чем не пересекается. Обычно ошибкам дают какие то названия кроме err, если только назвав err перетрется ранее присвоенное в err значение, которое пригодится в дальнейшем. А тут нет такой проблемы
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
там в другом проблема, это ошибка типа restErr а ниже err определяется типа internalError, там типы перекрываются, поэтому нейминг другой
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
можно было конечно сделать
var err error
и тогда под этот интерфейс оба типа бы подходили
if errors.Is(err, interr.ErrNotFound) { | ||
if errors.Is(err, interr.ErrNotFound) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
чтобы наверняка?)))
SetFieldImage(ctx context.Context, data *domain.ImageData, fieldID domain.FieldID) (domain.ImageURL, error) | ||
DeleteFieldImage(ctx context.Context, fieldID domain.FieldID) error |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ну и здесь тоже аналогично тому что выше по неймингу
err = h.UC.FieldImage.DeleteFieldImage(r.Context(), fieldID) | ||
|
||
if err != nil { | ||
utils.ProcessInternalServerError(h.log, w, err) | ||
return | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
а тут у нас не может быть not found?
return nil, interr.NewInternalError(err, "unable to upload photo") | ||
} | ||
|
||
url, err := r.MinioAdapter.PresignedGetObject(ctx, r.BucketName, imageID, time.Second*60*60*24, nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
давай константыой хотя бы, а еще лучше конфигом время хранения объекта будем задавать
} else { | ||
return "", interr.NewInternalError(err, "error while viewing image by imageID") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
else можем опустить
type Repository struct { | ||
mu sync.RWMutex | ||
Fields map[domain.FieldID]*domain.ImageID | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
уже бы хорошо такое хранить в каких либо inmemory хранилищах, например в redis. Рестартнется сервис и потеряются все записи в мапе
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
а вообще, почему мы это в бд не храним просто в виде поля к блоку?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
а, ну этим еще параллельно Ваня занимается. Хорошо бы это потом поправить когда его логика будет готова
func (r *Repository) GetUserInfo(ctx context.Context, userID domain.UserID) (*domain.UserInfo, error) { | ||
q := `SELECT (registration_date, extra_info, num_subscribers, num_subscriptions, | ||
avatar_url, first_name, last_name) | ||
func (r *Repository) GetUserInfo(ctx context.Context, userID domain.UserID) (*domain.UserInfo, *domain.ImageID, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
хорошо бы завести вообще специальные объекты, с которыми мы будем оперировать на уровне базы- dto, чтобы туда из SQL запросов инфа о бюзере складывалась, а то странновато что мы imageID прям каким то отдельным полем возвращаем, это же тоже к юзеру относится
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ну это ладно, посмотрим насколько успевать будем
_, err := r.PG.Exec(ctx, q, avatarID, userID) | ||
if err != nil { | ||
return interr.NewInternalError(err, "user Repository.UpdateUserAvatarID pg.Exec") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
то что не найден такой аккаунт хорошо б обработать
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
как и в других таких местах, по примеру как ты сделал GetUserAvatarID
err = uc.repo.ImageRepo.DeleteImage(ctx, *imageID) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return uc.repo.UserRepo.ClearUserAvatarID(ctx, userID) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
не очень нравится, что если не получилось очистить Avatar id, то мы будем на ошибки нарываться потом при получении его. Хорошо бы обработать этот момент конечно. Но ладно, посмотрим по времени
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
так он просто ошибку выше прокинет и на уровне хэндлеров мы ее обработаем, разве отличается от конструкции
if err := uc.repo.UserRepo.ClearUserAvatarID(ctx, userID); err != nil {
return err
}
return nil
err = uc.repo.ImageRepo.DeleteImage(ctx, *imageID) | ||
if err != nil { | ||
return err | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
err = uc.repo.ImageRepo.DeleteImage(ctx, *imageID) | |
if err != nil { | |
return err | |
} | |
if err = uc.repo.ImageRepo.DeleteImage(ctx, *imageID); err != nil { | |
return err | |
} |
) | ||
|
||
func DecodeImage(r *http.Request, cfg *bootstrap.Config) (multipart.File, *multipart.FileHeader, resterr.RestErr) { | ||
err := r.ParseMultipartForm(10 << 20) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
это тоже хорошо бы в константу, а лучше в конфиг.
return resterr.NewBadRequestError("formfile is not valid") | ||
} | ||
|
||
_, _ = f.Seek(0, 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
странновато выглядит. Надо бы ошибку обработать как будто бы если возвращает
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ну я не обработал потому что сдвиг курсора в начало на 0 символов по идее никогда не должен ошибки возвращать, там проблемы обычно бывают если от текущей позиции курсор сдвигаем и он перескакивает через конец содержимого
for _, validType := range cfg.Image.ValidTypes { | ||
if mimeType == validType { | ||
return nil | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
в конфигах можно мапы делать и в них парсить, так было бы чуть оптимальнее, за o(1) времени всегда бы здесь разбирались
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
жесткий хайлоад)))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ну здесь больше 7-10 типов точно не будет, так что я не стал, по факту и так константа
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ну это по факту такой цикл будет на каждый запрос связанный с картинкой. Это да, понятно, что мы не ляжем конечно же от такого. Но по сложности реализации это равноценные решения, никаких проблем в том, чтобы сделать немного оптимальнее я не вижу
if curAvatarID != nil { | ||
err := uc.repo.ImageRepo.DeleteImage(ctx, *curAvatarID) | ||
if err != nil { | ||
return "", err | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
а там не получится просто обновить, без удаления?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
я просто метод обновить картинку убрал из слоя репозиториев, хз сильно ли он нужен
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
с одной стороны чуть побыстрее будет, вместо двух операций одна, с другой стороны чуть побольше логики придется дописать
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ну могу просто свой удаленный код вернуть и update делать
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
давай одним методом обновлять. Раз есть возможность, надо его использовать. Когда я говорил про то, что можно обновление и добавление картинки совместить, я имел в виду апи конец. Внутри на уровне репозитория конечно же CRUD должен быть
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ну да, ты прав тем более здесь по идее может сильно больше времени тратиться
No description provided.