In 349 연동된 채널 삭제 api -> develop#220
Hidden character warning
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
Walkthrough채널 연동 해제 API가 추가되어 채널의 user 연관을 해제할 수 있게 되었고, 동기화 시에는 user가 없는 기존 채널을 재사용하도록 upsert 로직이 바뀌었습니다. Changes채널 연동 해제 및 재연결 로직
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant ChannelController
participant ChannelService
participant ChannelRepository
participant Channel
ChannelController->>ChannelService: disconnectChannel(channelId)
ChannelService->>ChannelRepository: findById(channelId)
ChannelRepository-->>ChannelService: Channel or empty
alt 채널 없음 또는 user 없음
ChannelService-->>ChannelController: CHANNEL_NOT_FOUND 예외
else 존재
ChannelService->>ChannelService: validateChannelOwnership
ChannelService->>Channel: updateUser(null)
ChannelService-->>ChannelController: 처리 완료
end
sequenceDiagram
participant YoutubeChannelDataPersistenceService
participant ChannelRepository
participant Channel
YoutubeChannelDataPersistenceService->>ChannelRepository: findByUser_IdAndYoutubeChannelId(userId, item.id)
ChannelRepository-->>YoutubeChannelDataPersistenceService: 없음
YoutubeChannelDataPersistenceService->>ChannelRepository: findByYoutubeChannelIdAndUserIsNull(item.id)
alt user 없는 채널 존재
ChannelRepository-->>YoutubeChannelDataPersistenceService: existing channel
YoutubeChannelDataPersistenceService->>Channel: updateUser(user)
YoutubeChannelDataPersistenceService->>YoutubeChannelDataPersistenceService: updateChannel(channel, item)
else 없음
YoutubeChannelDataPersistenceService->>Channel: Channel.builder() 로 신규 생성
end
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@src/main/java/com/example/inflace/domain/channel/repository/ChannelRepository.java`:
- Line 14: `ChannelRepository.findByYoutubeChannelIdAndUserIsNull` assumes a
single match, but the current data model can produce multiple null-user rows for
the same YouTube channel. Update the contract to reflect that reality by either
enforcing uniqueness in the schema/domain for the null-user case or changing the
repository and reconnect flow to handle multiple results explicitly. Use the
existing `ChannelRepository` method and the reconnect logic that calls it to
either return a collection and clean up duplicates, or guarantee a single row
before keeping `Optional`.
In
`@src/main/java/com/example/inflace/domain/channel/service/ChannelService.java`:
- Around line 380-389: `disconnectChannel` leaves a channel row with `user =
null`, but the shared ownership check still dereferences
`channel.getUser().getId()` and can throw NPE on later lookups. Update the
common validation path in `ChannelService` (especially
`validateChannelOwnership` and any caller like `disconnectChannel`) to handle a
null `getUser()` before accessing the user ID, and return the existing
channel/not-found or forbidden error instead of allowing a 500.
In
`@src/main/java/com/example/inflace/domain/channel/service/sync/YoutubeChannelDataPersistenceService.java`:
- Around line 83-87: `YoutubeChannelDataPersistenceService`의
`findByYoutubeChannelIdAndUserIsNull(item.id())` 기반 재할당은 동시 요청에서 같은 disconnected
`Channel`을 두 번 읽어 소유자 덮어쓰기가 발생할 수 있으므로 보호가 필요합니다. `updateUser(user)`로 들어가기 전에 이
조회를 `PESSIMISTIC_WRITE` 락이 걸린 조회로 바꾸거나, 한 번만 claim 되는 원자적 업데이트/조회 방식으로 변경해
`channelRepository` 경로가 동시에 같은 row를 재할당하지 못하게 하세요.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: e96baa42-6d26-486e-b6e3-ec8fa73c85b7
📒 Files selected for processing (6)
src/main/java/com/example/inflace/domain/channel/controller/ChannelApi.javasrc/main/java/com/example/inflace/domain/channel/controller/ChannelController.javasrc/main/java/com/example/inflace/domain/channel/domain/Channel.javasrc/main/java/com/example/inflace/domain/channel/repository/ChannelRepository.javasrc/main/java/com/example/inflace/domain/channel/service/ChannelService.javasrc/main/java/com/example/inflace/domain/channel/service/sync/YoutubeChannelDataPersistenceService.java
| Optional<Channel> findByUser_Id(UUID userId); | ||
| Optional<Channel> findByUser_IdAndYoutubeChannelId(UUID userId, String youtubeChannelId); | ||
| Optional<Channel> findByYoutubeChannelId(String youtubeChannelId); | ||
| Optional<Channel> findByYoutubeChannelIdAndUserIsNull(String youtubeChannelId); |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
Optional 전제가 현재 데이터 모델과 맞지 않습니다.
지금 스키마는 (user_id, youtube_channel_id)만 유니크라서, 같은 youtube_channel_id에 대해 user_id = NULL인 행이 여러 개 생길 수 있습니다. 게다가 재연동 로직은 "현재 사용자 소유 행 없음 + null-user 행 없음"이면 새 row를 저장하므로, 동일 유튜브 채널을 여러 사용자가 연결했다가 모두 해제하면 이 메서드가 단건이 아니라 다건을 맞게 됩니다. 그 상태에서 재연동은 Optional 조회 단계에서 깨지거나 임의의 행을 재사용하게 됩니다. DB에서 이 상태의 유일성을 강제하거나, 조회 계약을 다건 처리로 바꿔 정리 로직을 두는 쪽으로 맞춰야 합니다.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@src/main/java/com/example/inflace/domain/channel/repository/ChannelRepository.java`
at line 14, `ChannelRepository.findByYoutubeChannelIdAndUserIsNull` assumes a
single match, but the current data model can produce multiple null-user rows for
the same YouTube channel. Update the contract to reflect that reality by either
enforcing uniqueness in the schema/domain for the null-user case or changing the
repository and reconnect flow to handle multiple results explicitly. Use the
existing `ChannelRepository` method and the reconnect logic that calls it to
either return a collection and clean up duplicates, or guarantee a single row
before keeping `Optional`.
| .orElseGet(() -> channelRepository.findByYoutubeChannelIdAndUserIsNull(item.id()) | ||
| .map(channel -> { | ||
| channel.updateUser(user); | ||
| return updateChannel(channel, item); | ||
| }) |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
fd -i 'Channel.java|ChannelRepository.java' src/main/java \
--exec sh -c 'echo "### $1"; rg -n -C3 "`@Version`|`@Lock`|findByYoutubeChannelIdAndUserIsNull|youtubeChannelId|uniqueConstraints|class Channel|interface ChannelRepository" "$1"' sh {}Repository: JECT-Study/inflace-4th-server
Length of output: 2016
🏁 Script executed:
#!/bin/bash
set -euo pipefail
for f in \
src/main/java/com/example/inflace/domain/channel/domain/Channel.java \
src/main/java/com/example/inflace/domain/common/domain/BaseTimeEntity.java \
src/main/java/com/example/inflace/domain/channel/repository/ChannelRepository.java \
src/main/java/com/example/inflace/domain/channel/service/sync/YoutubeChannelDataPersistenceService.java
do
echo "### $f"
sed -n '1,220p' "$f"
echo
done
echo "### version/lock search"
rg -n "`@Version`|`@Lock`|PESSIMISTIC_WRITE|OPTIMISTIC|findByYoutubeChannelIdAndUserIsNull|user_id|youtube_channel_id" src/main/java src/main/resourcesRepository: JECT-Study/inflace-4th-server
Length of output: 2857
user IS NULL 재할당에 락이 필요합니다.
동시 재연동 요청이 같은 disconnected row를 동시에 읽으면 둘 다 updateUser(user)까지 진행해 마지막 커밋이 소유자를 덮어쓸 수 있습니다. Channel에 @Version도 없고 이 조회에도 락이 없어서, PESSIMISTIC_WRITE나 원자적 claim 쿼리로 보호해야 합니다.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@src/main/java/com/example/inflace/domain/channel/service/sync/YoutubeChannelDataPersistenceService.java`
around lines 83 - 87, `YoutubeChannelDataPersistenceService`의
`findByYoutubeChannelIdAndUserIsNull(item.id())` 기반 재할당은 동시 요청에서 같은 disconnected
`Channel`을 두 번 읽어 소유자 덮어쓰기가 발생할 수 있으므로 보호가 필요합니다. `updateUser(user)`로 들어가기 전에 이
조회를 `PESSIMISTIC_WRITE` 락이 걸린 조회로 바꾸거나, 한 번만 claim 되는 원자적 업데이트/조회 방식으로 변경해
`channelRepository` 경로가 동시에 같은 row를 재할당하지 못하게 하세요.
Issue
#201
comment
요청에 맞춰 채널 연동 해제 기능을 구현했습니다.
Summary by CodeRabbit