Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

solution for challenge9 #552

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

Open
kushalShukla-web wants to merge 1 commit into RezaSi:main
base: main
Choose a base branch
Loading
from kushalShukla-web:solution9

Conversation

@kushalShukla-web
Copy link

@kushalShukla-web kushalShukla-web commented Oct 9, 2025

No description provided.

Copy link

coderabbitai bot commented Oct 9, 2025
edited
Loading

Walkthrough

Adds an in-memory book management module in a single Go file, defining domain model, repository, service, HTTP handler, interfaces, constructors, and a main function to start an HTTP server exposing CRUD and search endpoints for books.

Changes

Cohort / File(s) Change Summary
Domain Model
challenge-9/submissions/kushalShukla-web/solution-template.go
Added Book struct with fields: ID, Title, Author, PublishedYear, ISBN, Description.
Repository (In-memory)
challenge-9/submissions/kushalShukla-web/solution-template.go
Added InMemoryBookRepository with CRUD and search (by author/title); methods: GetAll, GetByID, Create, Update, Delete, SearchByAuthor, SearchByTitle; constructor NewInMemoryBookRepository.
Service Layer
challenge-9/submissions/kushalShukla-web/solution-template.go
Added DefaultBookService implementing business logic; methods: GetAllBooks, GetBookByID, CreateBook, UpdateBook, DeleteBook, SearchBooksByAuthor, SearchBooksByTitle; constructor NewBookService.
HTTP Handler & Routing
challenge-9/submissions/kushalShukla-web/solution-template.go
Added BookHandler with HandleBooks for endpoints: list, create, get by ID, update, delete, search via query params; constructor NewBookHandler; JSON responses with status codes.
Interfaces (Public APIs)
challenge-9/submissions/kushalShukla-web/solution-template.go
Added interfaces BookService and BookRepository reflecting service and repository methods.
Application Wiring
challenge-9/submissions/kushalShukla-web/solution-template.go
Added main() to wire repository, service, handler, configure routes, and start HTTP server on port 8080.

Sequence Diagram(s)

sequenceDiagram
 autonumber
 actor Client
 participant HTTP as HTTP Server
 participant Handler as BookHandler
 participant Service as BookService
 participant Repo as InMemoryBookRepository
 rect rgba(200,220,255,0.25)
 note over Client,HTTP: Create Book
 Client->>HTTP: POST /api/books {book}
 HTTP->>Handler: HandleBooks(request)
 Handler->>Service: CreateBook(book)
 Service->>Repo: Create(book)
 Repo-->>Service: result / error
 Service-->>Handler: result / error
 Handler-->>HTTP: 201 Created / 400-500
 HTTP-->>Client: JSON response
 end
 rect rgba(200,255,200,0.25)
 note over Client,HTTP: Get/List/Search
 Client->>HTTP: GET /api/books[?author=...|title=...]
 HTTP->>Handler: HandleBooks(request)
 alt search by author/title
 Handler->>Service: SearchBooksByAuthor/Title(q)
 else list all
 Handler->>Service: GetAllBooks()
 end
 Service->>Repo: Query
 Repo-->>Service: Books
 Service-->>Handler: Books
 Handler-->>HTTP: 200 OK
 HTTP-->>Client: JSON array
 end
 rect rgba(255,230,200,0.25)
 note over Client,HTTP: Get/Update/Delete by ID
 Client->>HTTP: GET/PUT/DELETE /api/books/{id}
 HTTP->>Handler: HandleBooks(request)
 opt GET
 Handler->>Service: GetBookByID(id)
 Service->>Repo: GetByID(id)
 end
 opt PUT
 Handler->>Service: UpdateBook(id, book)
 Service->>Repo: Update(id, book)
 end
 opt DELETE
 Handler->>Service: DeleteBook(id)
 Service->>Repo: Delete(id)
 end
 Repo-->>Service: result / not found
 Service-->>Handler: result / error
 Handler-->>HTTP: 200/204/404/400
 HTTP-->>Client: JSON / message
 end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Pre-merge checks

❌ Failed checks (1 warning, 2 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title Check ❓ Inconclusive The pull request title "solution for challenge9" indicates that it contains the solution for the ninth challenge but does not convey the primary functionality added, namely an in-memory book management module with HTTP API endpoints, making it too generic to clearly summarize the main change. Consider renaming the pull request to a concise title that reflects the main implementation, such as "Add in-memory book management HTTP API for challenge 9," so that readers immediately understand the key change.
Description Check ❓ Inconclusive No pull request description was provided, so there is no contextual information about the changes beyond the title and filenames, leaving reviewers without guidance on the intent or scope of the implementation. Please add a brief description summarizing the purpose of the changes, the main features implemented, and any important details that will help reviewers understand the solution without inspecting every file.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 061108a and 614c456.

📒 Files selected for processing (1)
  • challenge-9/submissions/kushalShukla-web/solution-template.go (1 hunks)

Comment on lines +94 to +101
func (x *InMemoryBookRepository) Create(book *Book) error {
if book == nil {
return fmt.Errorf("Error while creating a book")
}
book.ID = strconv.Itoa(len(x.books) + 1)
x.books[strconv.Itoa((len(x.books) + 1))] = book

return nil
Copy link

@coderabbitai coderabbitai bot Oct 9, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Prevent ID reuse when books are deleted.

Create derives the next ID from len(x.books)+1. Once an item is deleted, that ID is recycled, causing the next create to overwrite an existing book silently. This corrupts stored data. Please generate IDs that skip occupied keys.

Apply this diff:

-	book.ID = strconv.Itoa(len(x.books) + 1)
-	x.books[strconv.Itoa((len(x.books) + 1))] = book
-
-	return nil
+	nextID := len(x.books) + 1
+	for {
+		id := strconv.Itoa(nextID)
+		if _, exists := x.books[id]; !exists {
+			book.ID = id
+			x.books[id] = book
+			return nil
+		}
+		nextID++
+	}
🤖 Prompt for AI Agents
In challenge-9/submissions/kushalShukla-web/solution-template.go around lines 94
to 101, the Create method currently assigns ID using len(x.books)+1 which reuses
IDs after deletions and can overwrite existing books; change it to compute a new
unused numeric ID by scanning existing map keys, parsing them to ints, finding
the maximum numeric ID, and using max+1 (or alternatively loop incrementing a
counter until you find a key that does not exist) before assigning book.ID and
storing the book; also keep the nil check and return an error as before.

Comment on lines +200 to +212
case r.Method == http.MethodGet && r.URL.Path == "/api/books":
books, err := h.Service.GetAllBooks()
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
}
if len(books) == 0 {
w.WriteHeader(http.StatusOK)
} else {
w.WriteHeader(http.StatusCreated)
}
json.NewEncoder(w).Encode(books)
return
Copy link

@coderabbitai coderabbitai bot Oct 9, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix GET /api/books response handling.

After logging an internal error the handler keeps writing a success payload, and on success it responds with 201 instead of 200. Return immediately on errors and stick to HTTP 200 for successful reads.

Apply this diff:

-		if err != nil {
-			w.WriteHeader(http.StatusInternalServerError)
-			w.Write([]byte(err.Error()))
-		}
-		if len(books) == 0 {
-			w.WriteHeader(http.StatusOK)
-		} else {
-			w.WriteHeader(http.StatusCreated)
-		}
-		json.NewEncoder(w).Encode(books)
+		if err != nil {
+			http.Error(w, err.Error(), http.StatusInternalServerError)
+			return
+		}
+		w.WriteHeader(http.StatusOK)
+		json.NewEncoder(w).Encode(books)
📝 Committable suggestion

!!️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
case r.Method == http.MethodGet && r.URL.Path == "/api/books":
books, err := h.Service.GetAllBooks()
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
}
if len(books) == 0 {
w.WriteHeader(http.StatusOK)
} else {
w.WriteHeader(http.StatusCreated)
}
json.NewEncoder(w).Encode(books)
return
case r.Method == http.MethodGet && r.URL.Path == "/api/books":
books, err := h.Service.GetAllBooks()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(books)
return
🤖 Prompt for AI Agents
In challenge-9/submissions/kushalShukla-web/solution-template.go around lines
200 to 212, the GET /api/books branch continues after an internal error and uses
201 for successful reads; change it to return immediately after writing the
error response and set successful responses to HTTP 200. Specifically: after
detecting err != nil write status 500 and the error body then return; for the
non-error path always write status 200 (not 201) and then encode the books;
ensure you don't write multiple headers before the return.

Comment on lines +257 to +265
case r.Method == http.MethodGet && strings.HasPrefix(r.URL.Path, "/api/books/"):
id := strings.TrimPrefix(r.URL.Path, "/api/books/")
book, err := h.Service.GetBookByID(id)
if err != nil {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte(err.Error()))
}
json.NewEncoder(w).Encode(&book)
return
Copy link

@coderabbitai coderabbitai bot Oct 9, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Stop writing a second response body on 404s.

When GetBookByID returns an error, the handler writes the 404 and error message but still encodes &book, appending null to the response and muddying clients. Return immediately after the error and encode the book directly on success.

Apply this diff:

-		book, err := h.Service.GetBookByID(id)
-		if err != nil {
-			w.WriteHeader(http.StatusNotFound)
-			w.Write([]byte(err.Error()))
-		}
-		json.NewEncoder(w).Encode(&book)
+		book, err := h.Service.GetBookByID(id)
+		if err != nil {
+			http.Error(w, err.Error(), http.StatusNotFound)
+			return
+		}
+		json.NewEncoder(w).Encode(book)
📝 Committable suggestion

!!️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
case r.Method == http.MethodGet && strings.HasPrefix(r.URL.Path, "/api/books/"):
id := strings.TrimPrefix(r.URL.Path, "/api/books/")
book, err := h.Service.GetBookByID(id)
if err != nil {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte(err.Error()))
}
json.NewEncoder(w).Encode(&book)
return
case r.Method == http.MethodGet && strings.HasPrefix(r.URL.Path, "/api/books/"):
id := strings.TrimPrefix(r.URL.Path, "/api/books/")
book, err := h.Service.GetBookByID(id)
if err != nil {
http.Error(w, err.Error(), http.StatusNotFound)
return
}
json.NewEncoder(w).Encode(book)
return
🤖 Prompt for AI Agents
In challenge-9/submissions/kushalShukla-web/solution-template.go around lines
257 to 265, the handler writes a 404 and error body when GetBookByID returns an
error but then continues to JSON-encode &book (producing an extra "null" or
duplicate body). Fix by returning immediately after writing the 404 and error
(do not fall through), and only call json.NewEncoder(w).Encode(book) on the
successful path; ensure you set the success status (e.g., http.StatusOK) if
desired before encoding.

Comment on lines +290 to +298
id := strings.TrimPrefix(r.URL.Path, "/api/books/")
err := h.Service.DeleteBook(id)
if err != nil {
w.WriteHeader(http.StatusNotFound)
}
json.NewEncoder(w).Encode(map[string]string{
"message": "Book deleted successfully",
})
return
Copy link

@coderabbitai coderabbitai bot Oct 9, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Return the actual error for failed deletes.

If DeleteBook fails, the handler still emits "Book deleted successfully," misleading clients. Propagate the error response instead of returning a success payload.

Apply this diff:

-		err := h.Service.DeleteBook(id)
-		if err != nil {
-			w.WriteHeader(http.StatusNotFound)
-		}
-		json.NewEncoder(w).Encode(map[string]string{
-			"message": "Book deleted successfully",
-		})
-		return
+		if err := h.Service.DeleteBook(id); err != nil {
+			http.Error(w, err.Error(), http.StatusNotFound)
+			return
+		}
+		json.NewEncoder(w).Encode(map[string]string{
+			"message": "Book deleted successfully",
+		})
+		return
📝 Committable suggestion

!!️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
id := strings.TrimPrefix(r.URL.Path, "/api/books/")
err := h.Service.DeleteBook(id)
if err!=nil {
w.WriteHeader(http.StatusNotFound)
}
json.NewEncoder(w).Encode(map[string]string{
"message": "Book deleted successfully",
})
return
id := strings.TrimPrefix(r.URL.Path, "/api/books/")
iferr := h.Service.DeleteBook(id); err!=nil {
http.Error(w, err.Error(), http.StatusNotFound)
return
}
json.NewEncoder(w).Encode(map[string]string{
"message": "Book deleted successfully",
})
return
🤖 Prompt for AI Agents
In challenge-9/submissions/kushalShukla-web/solution-template.go around lines
290 to 298, the handler currently returns a "Book deleted successfully" payload
even when h.Service.DeleteBook(id) fails; change the logic so that if err != nil
you write an appropriate status (e.g. http.StatusNotFound or
http.StatusInternalServerError depending on error), encode and return a JSON
error payload with the actual err.Error(), and return immediately; only when
DeleteBook succeeds should you encode and return the success JSON (or use
http.StatusNoContent) so clients never receive a success message on failure.

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

Reviewers

@coderabbitai coderabbitai[bot] coderabbitai[bot] requested changes

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

1 participant

AltStyle によって変換されたページ (->オリジナル) /