Skip to content

Conversation

@sunwon12
Copy link
Contributor

@sunwon12 sunwon12 commented Jan 7, 2026

다중 사용자 퀴즈 알림 시스템

Before: 최초의 퀴즈 생성 요청자만 퀴즈 생성 완료를 보낸다. 문제는 1분 동안 퀴즈 생성 시 타유저가 요청을 보내면 멱등성은 보장되지만, 타유저가 알림을 받지 못함
After: 퀴즈 생성 중 타유저가 생성요청 보내더라도 타유저에게 퀴즈 생성 완료 알림을 보낸다

QuizSubscriber

도메인 추가: 특정 책의 퀴즈 생성을 기다리는 사용자 목록을 DB(quiz_subscriber)에 저장합니다.
레디스 zset 사용해서 알림 받을 사용자 저장을 고민하였지만, 레디스가 다운되더라도 퀴즈는 정상적으로 동작해야 하기 때문에 레디스를 사용하지 않았습니다

QuizGenerationService

개선: 퀴즈 생성 요청 시, 요청자를 구독자 목록에 추가합니다.

QuizGenerationHandlerService

개선: 퀴즈 생성이 완료되면 QuizSubscriber 테이블을 조회하여 기다리던 모든 사용자에게 알림 이벤트를 발행합니다. 알림 발송 후 해당 책퀴즈에 대한 구독자 목록을 정리합니다.

TODO

  • Thundering Herd 방지: 현재는 따닥 정도로 사용자들이 동시에 요청 보낼 시 제미나이 퀴즈 생성 요청이 중복 될 수 있음

@sunwon12 sunwon12 requested a review from AlphaBs January 7, 2026 17:30
@sunwon12 sunwon12 self-assigned this Jan 7, 2026
@sunwon12 sunwon12 added the ♻️ refactor Extra attention is needed label Jan 7, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @sunwon12, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

이 풀 리퀘스트는 퀴즈 생성 시스템에서 다중 사용자 알림 기능을 개선하고 'Thundering Herd' 문제를 방지하기 위한 것입니다. 기존에는 퀴즈 생성 요청을 보낸 최초 사용자에게만 완료 알림이 전달되었으나, 이제는 퀴즈 생성 중 동일한 퀴즈에 대한 요청이 들어오면 해당 사용자들도 구독자로 등록되어 퀴즈 생성이 완료되었을 때 모두에게 알림이 발송되도록 변경되었습니다. 이를 통해 사용자 경험을 향상시키고 시스템의 멱등성을 유지하면서 효율적인 알림 처리를 가능하게 합니다.

Highlights

  • 새로운 구독자 시스템 도입: 퀴즈 생성을 기다리는 사용자 목록을 데이터베이스에 저장하는 QuizSubscriber 엔티티와 QuizSubscriberRepository를 새로 추가했습니다.
  • 다중 사용자 알림 기능 개선: 퀴즈 생성 완료 시, 해당 퀴즈 생성을 요청했던 모든 구독자에게 알림 이벤트를 발행하도록 QuizGenerationHandlerService의 로직을 변경했습니다. 알림 발송 후에는 구독자 목록을 정리합니다.
  • 동시 요청 처리 로직 강화: 퀴즈 생성 요청 시, 퀴즈가 이미 생성 중이거나 대기 중인 경우 요청자를 QuizSubscriber 목록에 추가하여 'Thundering Herd' 문제를 방지하고 모든 요청자가 알림을 받을 수 있도록 QuizGenerationService를 개선했습니다.
  • 코드 리팩토링 및 테스트 강화: QuizGenerationAsyncServiceQuizGenerationHandlerService의 메서드 시그니처를 변경하여 구독자 관리를 중앙화하고, 새로운 구독자 로직을 검증하기 위한 통합 테스트를 추가했습니다. 기존 단위 테스트도 업데이트 및 정리했습니다.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new QuizSubscriber entity and repository to manage members who request quiz generation for a specific book. The core change modifies the quiz generation flow: when a quiz is requested, the requesting member is now recorded as a QuizSubscriber. If a quiz is already being generated, subsequent requests from other members will also add them as subscribers without re-initiating generation. Once quiz generation is successfully completed, the system now iterates through all recorded subscribers for that book, publishes a QuizCreatedEvent for each, and then clears all subscribers for that book. The QuizGenerationAsyncService and QuizGenerationService were updated to reflect these changes, including removing the memberId parameter from success handlers and incorporating the QuizSubscriberRepository. The QuizGenerationHandlerService now handles the event publishing and subscriber cleanup within a transactional context. Unit and integration tests were updated and new ones added to cover the new subscriber logic, including concurrent request scenarios. Review comments suggest improving the QuizSubscriber entity by removing redundant createdAt initialization in the constructor in favor of @CreatedDate with JPA Auditing, and optimizing the deleteAllByBookId method in QuizSubscriberRepository for better performance with large datasets by using a direct DELETE query. Another comment suggests considering stream-based processing for findAllByBookId in QuizGenerationHandlerService to handle a potentially large number of subscribers more efficiently.

Comment on lines +42 to 48
private void sendEventToAllRequesters(Book book) {
List<QuizSubscriber> subscribers = quizSubscriberRepository.findAllByBookId(book.getId());
for (QuizSubscriber subscriber : subscribers) {
eventPublisher.publishEvent(new QuizCreatedEvent(book.getId(), subscriber.getMemberId()));
}
quizSubscriberRepository.deleteAllByBookId(book.getId());
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

퀴즈 생성 완료 후 모든 구독자에게 알림을 보내는 로직이 추가되었네요. 한 가지 고려할 점은 findAllByBookId가 매우 많은 수의 구독자를 반환할 경우 메모리 사용량이 급증할 수 있다는 점입니다. 현재는 구독자 수가 많지 않을 것으로 예상되지만, 향후 확장성을 고려하여 Stream을 사용한 처리를 검토해볼 수 있습니다.

예를 들어, Stream<QuizSubscriber> findAllByBookId(Long bookId)와 같이 리포지토리 메서드를 변경하고 서비스에서 스트림을 순회하며 이벤트를 발행하면 대용량 데이터 처리 시 더 안정적일 수 있습니다. @Transactional(readOnly = true)와 함께 사용하면 더 효과적입니다.

@github-actions
Copy link

github-actions bot commented Jan 7, 2026

Test Results

102 files  102 suites   20s ⏱️
516 tests 516 ✅ 0 💤 0 ❌
526 runs  526 ✅ 0 💤 0 ❌

Results for commit 7975706.

♻️ This comment has been updated with latest results.

@github-actions
Copy link

github-actions bot commented Jan 7, 2026

🌻 테스트 커버리지 리포트

Overall Project 52.45% 🍏

There is no coverage information present for the Files changed

@sunwon12 sunwon12 merged commit 8a1ebdd into dev Jan 15, 2026
2 checks passed
@sunwon12 sunwon12 deleted the refactor/quiz-alarm branch January 15, 2026 09:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

♻️ refactor Extra attention is needed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants