Skip to content

implement user favorite management features#33

Open
antonioualex wants to merge 1 commit into
GlobalWebIndex:mainfrom
antonioualex:user-favorite-management
Open

implement user favorite management features#33
antonioualex wants to merge 1 commit into
GlobalWebIndex:mainfrom
antonioualex:user-favorite-management

Conversation

@antonioualex

Copy link
Copy Markdown

GWI Favorites Asset Service - Implementation

Overview

This PR implements a user favorites management system for the GWI platform, allowing users to manage personalized lists of favorite assets (Charts, Insights, and Audiences) through a RESTful API.

🚀 Features Implemented

Core API Endpoints

  • GET /favorite/ - Retrieve all user favorites
  • POST /favorite/{aid} - Add asset to favorites
  • PATCH /favorite/{id} - Update favorite description
  • DELETE /favorite/{id} - Remove from favorites

Database & Persistence

  • PostgreSQL with Docker containerization
  • Migration System for schema management and data seeding
  • Repository Pattern for data access abstraction

🔧 Technical Implementation

Technology Stack

  • Go 1.24+ with modern best practices
  • PostgreSQL for data persistence
  • Docker & Docker Compose for containerization
  • Testcontainers for integration testing
  • Mockgen for test mocking
  • Bun ORM for PostgreSQL

Testing Strategy

  • Unit Tests: Individual component testing with mocks
  • Integration Tests: Database integration with Testcontainers
  • Test Coverage: Comprehensive coverage across all layers
  • CI/CD: GitHub Actions for automated testing

📁 Project Structure

├── app/                    # Application layer (use cases, business logic)
├── cmd/                    # Application entry points
├── domain/                 # Core domain entities and interfaces
├── infra/                  # Infrastructure setup (Docker, migrations)
├── internal/               # Internal packages (config, server setup)
├── persistence/            # Data access layer (repositories)
└── presentation/           # HTTP handlers and routing

@alesr alesr left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @antonioualex, thanks so much for submitting your solution for the assignment! I’ve left a couple of questions for you to take a look at when you have a moment. No rush, take your time. 😊

Comment thread cmd/main.go
func cleanExit(code int) {
// Allow deferred functions to run before exiting
defer os.Exit(code)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please elaborate on what is happening here?

The server returns an error, logs the error and then?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The server returns an error, logs the error and then calls cleanExit(1). Inside cleanExit(), os.Exit(1) is scheduled as a deferred function. When cleanExit() finishes, the deferred os.Exit(1) executes immediately. The cleanExit function doesn't actually accomplish what its comment and name suggests creating confusion about when exit will occur. Besides that, there's nothing left in that scope to run. I would remove cleanExit() entirely and use os.Exit(1) directly in main() so it can be clearer and doesn't create false expectations.

Comment thread internal/server/server.go
sqldb := sql.OpenDB(pgdriver.NewConnector(
pgdriver.WithNetwork(cfg.Network),
pgdriver.WithAddr(cfg.Address),
pgdriver.WithTLSConfig(nil),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to pass nil to the WithTLSConfig?

Is TLS enabled by default? What does it mean to add this flag and pass a nil configuration?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It means no custom TLS configuration is provided which overrides the default behavior. When I pass nil to WithTLSConfig(), the connector will use disabled ssl mode which is needed for local development. The correct approach would be to use, pgdriver.WithInsecure(cfg bool) and pass the value through configuration.

Comment thread internal/server/server.go
func Run(ctx context.Context, cfg *config.Config) error {
slog.Info("Starting GWI application...")

db, err := setupDatabase(cfg.Database)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would be the benefit of not initializing the database here, but pass it as an argument to the run function?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 It would give better testability by giving the opportunity to inject a mock database.

Comment thread app/favorite.go

favorite.ID = 0 // Ensure ID is zero (default value) for insertion

return s.favoriteRepository.Insert(ctx, favorite)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens to the insert if the user closes the connection with the server?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A context cancellation will occur and if it is before or during the database operation execution, then it will not be performed and an error context.Canceled will be returned. In this case it will also log user info and will return an error InternalServerError in the application layer, which is not correct, should return (and handle) a different type of error. If context cancellation occurs after the database write completes, then the data will be stored in the database and the connection will close before the success response reaches the client.

@antonioualex

Copy link
Copy Markdown
Author

Hi @alesr, thank you very much for your review, appreciate it!! 😊 😄 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants