Conversation
- message 이벤트에서 isAppMention 체크 제거: 스레드 내 다른 앱(@linear 등) 멘션 시 AI가 호출되던 문제 수정 - app_mention 이벤트에서만 멘션 처리하도록 변경 (AI) 접두사 방식은 유지) - Claude 응답의 **텍스트** 마크다운을 Slack mrkdwn *텍스트* 볼드로 변환하는 convertMarkdownToSlack 메서드 추가
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughSlack AI 응답의 마크다운 굵은 텍스트를 Slack 형식으로 변환하는 로직을 추가하고, 이벤트 컨트롤러에서 스레드 후속 처리 분기와 일부 로직을 제거·정리하며 이벤트 캐시 회수 로직과 로그 메시지들을 한국어 메시지로 변경했습니다. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
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. Comment |
There was a problem hiding this comment.
Pull request overview
Slack 스레드 내에서 다른 앱(@linear 등) 멘션 시 AI가 잘못 호출되던 버그를 수정하고, Claude 응답의 Markdown 볼드(**text**)를 Slack mrkdwn 볼드(*text*)로 변환하는 기능을 추가한 PR입니다.
Changes:
message이벤트 핸들러에서isAppMention체크 분기를 제거하여 다른 앱 멘션에 반응하지 않도록 수정app_mention이벤트에서만 멘션을 처리하도록 분리 (기존AI)접두사 방식은 유지)convertMarkdownToSlack메서드를 추가하여 Claude 응답의**bold**를 Slack*bold*로 변환
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
SlackEventController.java |
message 이벤트에서 isAppMention 분기 제거, java.util.List import 제거 |
SlackAIService.java |
MARKDOWN_BOLD_PATTERN 추가, convertMarkdownToSlack 메서드 추가, formatSlackResponse에서 변환 적용 |
src/main/java/gg/agit/konect/infrastructure/slack/ai/SlackEventController.java
Show resolved
Hide resolved
src/main/java/gg/agit/konect/infrastructure/slack/ai/SlackAIService.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/main/java/gg/agit/konect/infrastructure/slack/ai/SlackAIService.java`:
- Line 25: The MARKDOWN_BOLD_PATTERN in SlackAIService (private static final
Pattern MARKDOWN_BOLD_PATTERN) doesn't match bold markdown spanning multiple
lines; update its compilation to allow DOTALL (e.g.,
Pattern.compile("\\*\\*(.+?)\\*\\*", Pattern.DOTALL)) or change the inner token
to a multiline-safe class like "[\\s\\S]+?" so that inputs like
"**line1\nline2**" are correctly matched and converted.
- Around line 173-175: convertMarkdownToSlack can NPE when text is null because
MARKDOWN_BOLD_PATTERN.matcher(text) will throw; update convertMarkdownToSlack to
guard against null input (e.g., if text == null return "" or return null-safe
value) before calling MARKDOWN_BOLD_PATTERN.matcher, then proceed with
MARKDOWN_BOLD_PATTERN.matcher(text).replaceAll("*$1*"); ensure the null-guard is
added in the convertMarkdownToSlack method to make failure mode explicit and
easier to debug.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 51f0ad4b-7bbe-4843-b190-2f10fb1a398b
📒 Files selected for processing (2)
src/main/java/gg/agit/konect/infrastructure/slack/ai/SlackAIService.javasrc/main/java/gg/agit/konect/infrastructure/slack/ai/SlackEventController.java
💤 Files with no reviewable changes (1)
- src/main/java/gg/agit/konect/infrastructure/slack/ai/SlackEventController.java
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Cleanup artifacts
🧰 Additional context used
📓 Path-based instructions (2)
src/main/java/**/*.java
⚙️ CodeRabbit configuration file
src/main/java/**/*.java: 아래 원칙으로 리뷰 코멘트를 작성한다.
- 코멘트는 반드시 한국어로 작성한다.
- 반드시 수정이 필요한 항목만 코멘트로 남기고, 단순 취향 차이는 지적하지 않는다.
- 각 코멘트 첫 줄에 심각도를
[LEVEL: high|medium|low]형식으로 반드시 표기한다.- 심각도 기준: high=운영 장애 가능, medium=품질 저하, low=개선 권고.
- 각 코멘트는 "문제 -> 영향 -> 제안" 순서로 3문장 이내로 간결하게 작성한다.
- 가능하면 재현 조건 및 실패 시나리오도 포함한다.
- 제안은 현재 코드베이스(Spring Boot + JPA + Flyway) 패턴과 일치해야 한다.
- 보안, 트랜잭션 경계, 예외 처리, N+1, 성능 회귀 가능성을 우선 점검한다.
- 가독성: 변수/메서드 이름이 의도를 바로 드러내는지, 중첩과 메서드 길이가 과도하지 않은지 점검한다.
- 단순화: 불필요한 추상화, 중복 로직, 과한 방어 코드가 있으면 더 단순한 대안을 제시한다.
- 확장성: 새 요구사항 추가 시 변경 범위가 최소화되는 구조인지(하드코딩 분기/값 여부 포함) 점검한다.
Files:
src/main/java/gg/agit/konect/infrastructure/slack/ai/SlackAIService.java
**/*
⚙️ CodeRabbit configuration file
**/*: 공통 리뷰 톤 가이드:
- 모든 코멘트는 첫 줄에
[LEVEL: ...]태그를 포함한다.- 과장된 표현 없이 사실 기반으로 작성한다.
- 한 코멘트에는 하나의 이슈만 다룬다.
- 코드 예시가 필요하면 최소 수정 예시를 제시한다.
- 가독성/단순화/확장성 이슈를 발견하면 우선순위를 높여 코멘트한다.
Files:
src/main/java/gg/agit/konect/infrastructure/slack/ai/SlackAIService.java
🔇 Additional comments (1)
src/main/java/gg/agit/konect/infrastructure/slack/ai/SlackAIService.java (1)
177-179: LGTM!마크다운 볼드 변환 로직이 기존
formatSlackResponse메서드에 자연스럽게 통합되었습니다. PR 목적에 부합하는 변경입니다.
src/main/java/gg/agit/konect/infrastructure/slack/ai/SlackAIService.java
Outdated
Show resolved
Hide resolved
src/main/java/gg/agit/konect/infrastructure/slack/ai/SlackAIService.java
Show resolved
Hide resolved
- app_mention 핸들러에서 threadTs 존재 시 fetchAIThreadReplies 호출해 대화 히스토리 전달 - convertMarkdownToSlack에 null 방어 코드 추가 - MARKDOWN_BOLD_PATTERN에 Pattern.DOTALL 플래그 추가해 멀티라인 볼드 지원 - formatSlackResponse에서 AI_RESPONSE_PREFIX 상수 활용으로 변경
|
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/main/java/gg/agit/konect/infrastructure/slack/ai/SlackEventController.java (1)
76-78:⚠️ Potential issue | 🟠 Major[LEVEL: medium] ConcurrentHashMap.newKeySet()은 삽입 순서를 보장하지 않아 "가장 오래된" 항목 제거가 불가능합니다.
iterator().next()는 임의의 요소를 반환하므로 최근 이벤트가 제거되고 오래된 이벤트가 남아 중복 처리 방지가 실패할 수 있습니다.Collections.newSetFromMap(new LinkedHashMap<>())을 synchronized로 래핑하거나, 별도의ConcurrentLinkedQueue로 삽입 순서를 추적하세요.♻️ LinkedHashSet 기반 수정 예시
- private final Set<String> processedEventIds = ConcurrentHashMap.newKeySet(); + private final Set<String> processedEventIds = + Collections.synchronizedSet(new LinkedHashSet<>());또는 lock-free 방식이 필요하면:
private final ConcurrentLinkedQueue<String> eventIdQueue = new ConcurrentLinkedQueue<>(); private final Set<String> processedEventIds = ConcurrentHashMap.newKeySet(); // 삽입 시 if (processedEventIds.add(eventId)) { eventIdQueue.add(eventId); } // 제거 시 while (processedEventIds.size() > EVENT_CACHE_MAX_SIZE) { String oldest = eventIdQueue.poll(); if (oldest != null) { processedEventIds.remove(oldest); } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/gg/agit/konect/infrastructure/slack/ai/SlackEventController.java` around lines 76 - 78, The current removal logic in SlackEventController uses processedEventIds.iterator().next() on a ConcurrentHashMap.newKeySet() which does not preserve insertion order, so replace this with an ordered strategy: either wrap a LinkedHashSet via Collections.synchronizedSet(...) (or Collections.newSetFromMap(new LinkedHashMap<>())) for deterministic oldest-element removal, or add a ConcurrentLinkedQueue<String> eventIdQueue alongside the existing processedEventIds and push IDs into the queue when added; then, when processedEventIds.size() > EVENT_CACHE_MAX_SIZE, poll the queue to get the oldest ID and remove that ID from processedEventIds (repeat until under limit). Ensure additions use processedEventIds.add(eventId) and only enqueue when add returns true, and update the removal code that currently calls iterator().next() to use the chosen ordered-removal approach.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/main/java/gg/agit/konect/infrastructure/slack/ai/SlackAIService.java`:
- Around line 29-32: The two long string constants EMPTY_QUERY_MESSAGE and
ERROR_MESSAGE in SlackAIService exceed the 120-char line limit; fix by splitting
each literal into multiple shorter string literals concatenated with + across
lines (e.g., break the Unicode-escaped message into parts and join into
EMPTY_QUERY_MESSAGE and ERROR_MESSAGE) or move the messages into a properties
resource and load them (e.g., messages.properties + ResourceBundle) and replace
the constants with loaded values; ensure the final assembled strings remain
identical and update any references to EMPTY_QUERY_MESSAGE / ERROR_MESSAGE
accordingly.
---
Outside diff comments:
In
`@src/main/java/gg/agit/konect/infrastructure/slack/ai/SlackEventController.java`:
- Around line 76-78: The current removal logic in SlackEventController uses
processedEventIds.iterator().next() on a ConcurrentHashMap.newKeySet() which
does not preserve insertion order, so replace this with an ordered strategy:
either wrap a LinkedHashSet via Collections.synchronizedSet(...) (or
Collections.newSetFromMap(new LinkedHashMap<>())) for deterministic
oldest-element removal, or add a ConcurrentLinkedQueue<String> eventIdQueue
alongside the existing processedEventIds and push IDs into the queue when added;
then, when processedEventIds.size() > EVENT_CACHE_MAX_SIZE, poll the queue to
get the oldest ID and remove that ID from processedEventIds (repeat until under
limit). Ensure additions use processedEventIds.add(eventId) and only enqueue
when add returns true, and update the removal code that currently calls
iterator().next() to use the chosen ordered-removal approach.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: ecc6bf21-29d4-4691-9ad3-bcfb3314cc87
📒 Files selected for processing (2)
src/main/java/gg/agit/konect/infrastructure/slack/ai/SlackAIService.javasrc/main/java/gg/agit/konect/infrastructure/slack/ai/SlackEventController.java
📜 Review details
🧰 Additional context used
📓 Path-based instructions (2)
src/main/java/**/*.java
⚙️ CodeRabbit configuration file
src/main/java/**/*.java: 아래 원칙으로 리뷰 코멘트를 작성한다.
- 코멘트는 반드시 한국어로 작성한다.
- 반드시 수정이 필요한 항목만 코멘트로 남기고, 단순 취향 차이는 지적하지 않는다.
- 각 코멘트 첫 줄에 심각도를
[LEVEL: high|medium|low]형식으로 반드시 표기한다.- 심각도 기준: high=운영 장애 가능, medium=품질 저하, low=개선 권고.
- 각 코멘트는 "문제 -> 영향 -> 제안" 순서로 3문장 이내로 간결하게 작성한다.
- 가능하면 재현 조건 및 실패 시나리오도 포함한다.
- 제안은 현재 코드베이스(Spring Boot + JPA + Flyway) 패턴과 일치해야 한다.
- 보안, 트랜잭션 경계, 예외 처리, N+1, 성능 회귀 가능성을 우선 점검한다.
- 가독성: 변수/메서드 이름이 의도를 바로 드러내는지, 중첩과 메서드 길이가 과도하지 않은지 점검한다.
- 단순화: 불필요한 추상화, 중복 로직, 과한 방어 코드가 있으면 더 단순한 대안을 제시한다.
- 확장성: 새 요구사항 추가 시 변경 범위가 최소화되는 구조인지(하드코딩 분기/값 여부 포함) 점검한다.
Files:
src/main/java/gg/agit/konect/infrastructure/slack/ai/SlackEventController.javasrc/main/java/gg/agit/konect/infrastructure/slack/ai/SlackAIService.java
**/*
⚙️ CodeRabbit configuration file
**/*: 공통 리뷰 톤 가이드:
- 모든 코멘트는 첫 줄에
[LEVEL: ...]태그를 포함한다.- 과장된 표현 없이 사실 기반으로 작성한다.
- 한 코멘트에는 하나의 이슈만 다룬다.
- 코드 예시가 필요하면 최소 수정 예시를 제시한다.
- 가독성/단순화/확장성 이슈를 발견하면 우선순위를 높여 코멘트한다.
Files:
src/main/java/gg/agit/konect/infrastructure/slack/ai/SlackEventController.javasrc/main/java/gg/agit/konect/infrastructure/slack/ai/SlackAIService.java
🪛 GitHub Actions: Checkstyle
src/main/java/gg/agit/konect/infrastructure/slack/ai/SlackAIService.java
[error] 30-30: Checkstyle: LineLength violation. Line is longer than 120 characters (found 207).
[error] 32-32: Checkstyle: LineLength violation. Line is longer than 120 characters (found 160).
🔇 Additional comments (4)
src/main/java/gg/agit/konect/infrastructure/slack/ai/SlackAIService.java (3)
25-27: LGTM!이전 리뷰에서 지적된
Pattern.DOTALL플래그가 적용되어 멀티라인 볼드 텍스트를 올바르게 처리합니다.
174-179: LGTM!이전 리뷰에서 지적된 null 방어 코드가 적절히 추가되었습니다.
181-183: LGTM!
AI_RESPONSE_PREFIX상수를 활용하여 응답 포맷팅이 일관되게 처리됩니다.src/main/java/gg/agit/konect/infrastructure/slack/ai/SlackEventController.java (1)
121-133: LGTM!스레드 컨텍스트 존재 여부에 따라
fetchAIThreadReplies를 호출하고, 결과를processAIQuery에 전달하는 로직이 PR 목적에 맞게 구현되었습니다.
🔍 개요
🚀 주요 변경 내용
isAppMention체크 제거: 스레드 내 다른 앱(@linear 등) 멘션 시 AI가 호출되던 문제 수정convertMarkdownToSlack메서드 추가💬 참고 사항
✅ Checklist (완료 조건)