feat(discover): 발굴 일별 스케줄 연결 + 추천 채널 REST(목록/등록/제외/수동)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
02fa5be25b
commit
35944a8fd6
@ -0,0 +1,57 @@
|
|||||||
|
package com.hlab.yanalyst.domain.channel;
|
||||||
|
|
||||||
|
import com.hlab.yanalyst.global.common.ApiResponse;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/recommended-channels")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Tag(name = "Recommended Channel API", description = "자동 발굴된 추천 채널(떡상 Shorts)")
|
||||||
|
public class RecommendedChannelController {
|
||||||
|
|
||||||
|
private final RecommendedChannelRepository repository;
|
||||||
|
private final ChannelDiscoveryService discoveryService;
|
||||||
|
private final ChannelService channelService;
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
@Operation(summary = "추천 채널 목록", description = "status=NEW 를 배율 내림차순으로 반환")
|
||||||
|
public ApiResponse<List<RecommendedChannel>> list() {
|
||||||
|
return ApiResponse.ok(repository.findByStatusOrderByRatioDesc("NEW"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/{id}/register")
|
||||||
|
@Operation(summary = "내 채널 등록", description = "추천 채널을 내 채널로 등록하고 REGISTERED 처리")
|
||||||
|
@Transactional
|
||||||
|
public ApiResponse<Void> register(@PathVariable Long id) {
|
||||||
|
RecommendedChannel rc = repository.findById(id)
|
||||||
|
.orElseThrow(() -> new IllegalArgumentException("추천 채널을 찾을 수 없습니다: " + id));
|
||||||
|
channelService.saveChannelFromUrl("https://www.youtube.com/channel/" + rc.getChannelId());
|
||||||
|
rc.setStatus("REGISTERED");
|
||||||
|
repository.save(rc);
|
||||||
|
return ApiResponse.ok(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/{id}/exclude")
|
||||||
|
@Operation(summary = "추천 제외", description = "다음 발굴에서 다시 뜨지 않게 EXCLUDED 처리")
|
||||||
|
@Transactional
|
||||||
|
public ApiResponse<Void> exclude(@PathVariable Long id) {
|
||||||
|
RecommendedChannel rc = repository.findById(id)
|
||||||
|
.orElseThrow(() -> new IllegalArgumentException("추천 채널을 찾을 수 없습니다: " + id));
|
||||||
|
rc.setStatus("EXCLUDED");
|
||||||
|
repository.save(rc);
|
||||||
|
return ApiResponse.ok(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/run")
|
||||||
|
@Operation(summary = "수동 발굴 실행", description = "스케줄과 동일한 발굴을 즉시 1회 실행")
|
||||||
|
public ApiResponse<Map<String, Object>> run() {
|
||||||
|
return ApiResponse.ok(discoveryService.runDiscovery());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -25,6 +25,7 @@ public class ScheduledCollectionService {
|
|||||||
private final ChannelRepository channelRepository;
|
private final ChannelRepository channelRepository;
|
||||||
private final ChannelService channelService;
|
private final ChannelService channelService;
|
||||||
private final YoutubeQuotaGuard quotaGuard;
|
private final YoutubeQuotaGuard quotaGuard;
|
||||||
|
private final com.hlab.yanalyst.domain.channel.ChannelDiscoveryService channelDiscoveryService;
|
||||||
|
|
||||||
@Value("${hlab.scheduler.channel-collection.enabled:true}")
|
@Value("${hlab.scheduler.channel-collection.enabled:true}")
|
||||||
private boolean enabled;
|
private boolean enabled;
|
||||||
@ -32,6 +33,20 @@ public class ScheduledCollectionService {
|
|||||||
@Value("${hlab.scheduler.channel-snapshot.enabled:true}")
|
@Value("${hlab.scheduler.channel-snapshot.enabled:true}")
|
||||||
private boolean snapshotEnabled;
|
private boolean snapshotEnabled;
|
||||||
|
|
||||||
|
@Value("${hlab.scheduler.channel-discovery.enabled:true}")
|
||||||
|
private boolean discoveryEnabled;
|
||||||
|
|
||||||
|
/** 추천 채널 발굴(지역 인기 Shorts → 떡상 채널). */
|
||||||
|
@Scheduled(cron = "${hlab.scheduler.channel-discovery.cron:0 30 4 * * *}")
|
||||||
|
public void scheduledDiscovery() {
|
||||||
|
if (!discoveryEnabled) {
|
||||||
|
log.info("[Scheduler] 추천 채널 발굴 비활성화됨 (hlab.scheduler.channel-discovery.enabled=false)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Map<String, Object> result = channelDiscoveryService.runDiscovery();
|
||||||
|
log.info("[Scheduler] 추천 채널 발굴 완료: {}", result);
|
||||||
|
}
|
||||||
|
|
||||||
/** 채널 1개 수집의 추정 쿼터 소비량(playlistItems + videos.list, 대략치). */
|
/** 채널 1개 수집의 추정 쿼터 소비량(playlistItems + videos.list, 대략치). */
|
||||||
private static final long EST_UNITS_PER_CHANNEL = 12;
|
private static final long EST_UNITS_PER_CHANNEL = 12;
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user