GWI – Favorite Assets Service (Engineering Challenge Submission)#55
GWI – Favorite Assets Service (Engineering Challenge Submission)#55alexkazan87 wants to merge 11 commits into
Conversation
alexandros-georgantas
left a comment
There was a problem hiding this comment.
Hello @alexkazan87 👋 ,
Thank you for taking the time working on this assignment!
I have left some comments on this PR and it would be great if you find the time to address them!
Thanks,
Alex
| RUN CGO_ENABLED=0 GOOS=linux go build -o favorites ./cmd/main.go | ||
|
|
||
| FROM alpine:3 | ||
| WORKDIR /root/ |
There was a problem hiding this comment.
Could you suggest any enhancements for the application image? e.g. security
| @echo "Please use 'make <target>' where <target> is one of the following:" | ||
| @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' | ||
|
|
||
| run: ## Run the application |
There was a problem hiding this comment.
Could you please argue about your decision of including the vendor folder in general? What are you trying to achieve and what is the need in the context of this assignment?
|
|
||
| func main() { | ||
| infraProviders := infra.NewInfraProviders() | ||
| tp := time.NewTimeProvider() |
There was a problem hiding this comment.
Could you please elaborate about the need of having these two providers (time and uuid)? What are the benefits of that? Are you using them consistently?
| @@ -0,0 +1,20 @@ | |||
| module github.com/akazantzidis/gwi-ass | |||
There was a problem hiding this comment.
Could you please explain the purpose for this notification service in the scope of this assignment? What is the value added by this service?
| import ( | ||
| "github.com/akazantzidis/gwi-ass/internal/app/auth/command" | ||
| "github.com/akazantzidis/gwi-ass/internal/app/favourite/commands" | ||
| queries2 "github.com/akazantzidis/gwi-ass/internal/app/user/queries" |
There was a problem hiding this comment.
What is the purpose of this queries2 module?
| ID uuid.UUID `json:"id,omitempty"` | ||
| Type AssetType `json:"type"` | ||
| Description string `json:"description"` | ||
| Data json.RawMessage `json:"data"` |
There was a problem hiding this comment.
Could you suggest an alternative approach for modeling the entities required in this assignment? If you had more time how would you refactor this to make it more type safe?
| ) | ||
|
|
||
| var ( | ||
| jwtKey = []byte("secret") |
There was a problem hiding this comment.
In a production environment how would you have handled that?
| appServices := app.NewServices(infraProviders.FavoriteRepository, infraProviders.NotificationService, infraProviders.UserRepository, infraProviders.RefreshTokenRepository, up, tp) | ||
|
|
||
| infraHTTPServer := infra.NewHTTPServer(appServices) | ||
| infraHTTPServer.ListenAndServe(":8080") |
There was a problem hiding this comment.
In a production env how would you have handled that? Please suggest an alternative solution to this implementation.
|
|
||
| appServices := app.NewServices(infraProviders.FavoriteRepository, infraProviders.NotificationService, infraProviders.UserRepository, infraProviders.RefreshTokenRepository, up, tp) | ||
|
|
||
| infraHTTPServer := infra.NewHTTPServer(appServices) |
There was a problem hiding this comment.
Please explain what will happen if something goes wrong during the initialization of the server? Is there any alternative more graceful handling that could be implemented?
pamanta
left a comment
There was a problem hiding this comment.
Hi @alexkazan87,
Thank you very much for taking the time to complete the assignment.
I've also left some comments for you to have a look when you have time :)
| favorite, err := h.repo.GetByID(command.UserID, command.ID) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to fetch favorite: %w", err) | ||
| } | ||
| if favorite == nil { | ||
| return fmt.Errorf("favorite with ID %s does not exist for user %s", command.ID, command.UserID) | ||
| } | ||
|
|
||
| // Update fields | ||
| favorite.Type = command.Type | ||
| favorite.Description = command.Description | ||
| favorite.Data = command.Data | ||
|
|
||
| // Persist the update | ||
| if err := h.repo.Update(command.UserID, *favorite); err != nil { | ||
| return fmt.Errorf("failed to update favorite: %w", err) | ||
| } | ||
|
|
||
| return nil |
There was a problem hiding this comment.
can you identify any concerns with this method? Particularly about race conditions and concurrency? If yes, how would you correct them in a production environment?
| } | ||
| } | ||
|
|
||
| type Favorite struct { |
There was a problem hiding this comment.
How is the relation between user -> favorite established in the designed model? Can you elaborate a bit on how would you model this differently into a DB?
| var req CreateFavoriteRequestModel | ||
| if err := json.NewDecoder(r.Body).Decode(&req); err != nil { | ||
| helper.WriteJSONError(w, http.StatusBadRequest, fmt.Errorf("invalid request body"), nil) | ||
| return | ||
| } |
There was a problem hiding this comment.
In the current implementation, a chart favorite could have the same data structure as an insight or audience without any differentiation or validation. What concerns does this raise in production and how would you address them if you had more time?
| fav, err := c.favoriteServices.Queries.GetFavoriteHandler.Handle( | ||
| queries.GetFavoriteRequest{ | ||
| UserID: userID, | ||
| FavoriteID: favoriteID, | ||
| }, | ||
| ) | ||
|
|
||
| if err != nil { | ||
| helper.WriteJSONError(w, http.StatusInternalServerError, err, nil) | ||
| return | ||
| } | ||
| if fav == nil { | ||
| helper.WriteJSONError(w, http.StatusNotFound, fmt.Errorf("favorite not found"), nil) | ||
| return | ||
| } |
There was a problem hiding this comment.
Could you trace what happens here when a favorite does not exist for a user? Are there any issues? If yes, how would you fix it and how would you ensure this doesn't occur again in the future?
This Pull Request delivers the implementation for the GlobalWebIndex (GWI) engineering challenge. It provides a fully functional HTTP service that allows authenticated users to manage their personal list of favorite assets (charts, insights, audiences). The solution includes: