|
1 | 1 | package cmf.commitField.domain.commit.scheduler; |
2 | 2 |
|
3 | 3 | import cmf.commitField.domain.commit.sinceCommit.service.CommitCacheService; |
4 | | -import cmf.commitField.domain.commit.sinceCommit.service.GithubService; |
| 4 | +import cmf.commitField.domain.commit.totalCommit.service.TotalCommitService; |
5 | 5 | import cmf.commitField.domain.redpanda.RedpandaProducer; |
6 | 6 | import cmf.commitField.domain.user.entity.User; |
7 | 7 | import cmf.commitField.domain.user.repository.UserRepository; |
8 | 8 | import lombok.RequiredArgsConstructor; |
9 | 9 | import lombok.extern.slf4j.Slf4j; |
| 10 | +import org.springframework.data.redis.core.StringRedisTemplate; |
10 | 11 | import org.springframework.scheduling.annotation.Scheduled; |
11 | 12 | import org.springframework.stereotype.Service; |
12 | 13 |
|
| 14 | +import java.time.LocalDateTime; |
13 | 15 | import java.util.List; |
| 16 | +import java.util.Set; |
| 17 | +import java.util.concurrent.atomic.AtomicInteger; |
14 | 18 |
|
15 | 19 | @Slf4j |
16 | 20 | @Service |
17 | 21 | @RequiredArgsConstructor |
18 | 22 | public class CommitScheduler { |
19 | | - private final GithubService githubService; |
| 23 | + private final TotalCommitService totalCommitService; |
20 | 24 | private final CommitCacheService commitCacheService; |
21 | 25 | private final RedpandaProducer redpandaProducer; |
22 | 26 | private final UserRepository userRepository; |
23 | | - |
| 27 | + private final StringRedisTemplate redisTemplate; |
| 28 | + private final AtomicInteger counter = new AtomicInteger(0); // 카운터 변수 |
24 | 29 | @Scheduled(fixedRate = 60000) // 1분마다 실행 |
25 | 30 | public void updateUserCommits() { |
| 31 | + // 최근 3시간 이내에 커밋 기록이 없는 유저는 주기적으로 검사하지 않고, 10분에 한 번씩 검사함 -> 전체 검사 |
| 32 | + // 최근 3시간 이내에 커밋 기록이 있는 유저는 1분에 한번씩 검사함. -> 일부 검사 |
| 33 | + // Redis에 커밋 기록이 있는 유저를 기록하고, 이 유저들에 한해서만 API를 검색함 |
| 34 | + // Redis에 저장되지 않은 유저는 1시간에 한 번씩 검사하는 메소드를 실행 |
| 35 | + // 검사를 실행한 후, 커밋 기록이 갱신된 유저는 반영 후 Redis에 3시간동안 지속되게끔 값을 생성해준다. |
26 | 36 | log.info("🔍 updateUserCommits 실행중"); |
27 | | - List<User> activeUsers = userRepository.findAll(); // 💫 변경 필요, 차후 active 상태인 user만 찾게끔 변경해야 함. |
| 37 | + int count = counter.incrementAndGet(); // 실행 횟수 증가 |
| 38 | + |
| 39 | + if (count % 10 == 0) { |
| 40 | + // 🔹 10분마다 전체 유저 검색 |
| 41 | + List<User> allUsers = userRepository.findAll(); |
| 42 | + log.info("🔍 All User Count: {}", allUsers.size()); |
| 43 | + |
| 44 | + for (User user : allUsers) { |
| 45 | + // 🔹 API에서 해당 유저의 최근 커밋 개수 가져오기 |
| 46 | + long newCommitCount = totalCommitService.getSeasonCommits( |
| 47 | + user.getUsername(), |
| 48 | + user.getLastCommitted(), |
| 49 | + LocalDateTime.now() |
| 50 | + ).getTotalCommitContributions(); |
| 51 | + |
| 52 | + if (newCommitCount > 0) { |
| 53 | + // 🔹 커밋 기록이 있으면 DB, Redis, 메시지 큐 반영 |
| 54 | + updateCommitData(user, newCommitCount); |
| 55 | + } |
| 56 | + |
| 57 | + log.info("🔍 User: {}, Commit Count: {}", user.getUsername(), newCommitCount); |
| 58 | + } |
| 59 | + } else { |
| 60 | + // 🔹 1분마다 Redis에 저장된 유저만 검색 |
| 61 | + Set<String> activeUsers = redisTemplate.keys("commit_active:*"); // Redis에서 저장된 유저 키 가져오기 |
| 62 | + log.info("🔍 Active User Count: {}", activeUsers.size()); |
28 | 63 |
|
29 | | - log.info("🔍 Active User Count: {}", activeUsers.size()); |
| 64 | + for (String key : activeUsers) { |
| 65 | + String username = key.replace("commit_active:", ""); // Redis 키에서 유저명 추출 |
| 66 | + User user = userRepository.findByUsername(username).orElse(null); |
| 67 | + if (user == null) continue; |
30 | 68 |
|
31 | | - for (User user : activeUsers) { |
32 | | - Integer cachedCount = commitCacheService.getCachedCommitCount(user.getUsername()); |
33 | | - int newCommitCount = githubService.getUserCommitCount(user.getUsername()); |
| 69 | + // 🔹 API에서 해당 유저의 최근 커밋 개수 가져오기 |
| 70 | + long newCommitCount = totalCommitService.getSeasonCommits( |
| 71 | + user.getUsername(), |
| 72 | + user.getLastCommitted(), |
| 73 | + LocalDateTime.now() |
| 74 | + ).getTotalCommitContributions(); |
34 | 75 |
|
35 | | - log.info("🔍 User: {}, Commit Count: {}", user.getUsername(), newCommitCount); |
| 76 | + if (newCommitCount > 0) { |
| 77 | + // 🔹 커밋 기록이 있으면 DB, Redis, 메시지 큐 반영 |
| 78 | + updateCommitData(user, newCommitCount); |
| 79 | + } |
36 | 80 |
|
37 | | - if (cachedCount == null || cachedCount != newCommitCount) { // 변화가 있을 때만 처리 |
38 | | - commitCacheService.updateCachedCommitCount(user.getUsername(), newCommitCount); |
39 | | - redpandaProducer.sendCommitUpdate(user.getUsername(), newCommitCount); |
| 81 | + log.info("🔍 Active User: {}, Commit Count: {}", user.getUsername(), newCommitCount); |
40 | 82 | } |
41 | 83 | } |
42 | 84 | } |
| 85 | + |
| 86 | + // 🔹 커밋 기록이 있으면 DB + Redis + 메시지 큐 반영하는 메소드 |
| 87 | + private void updateCommitData(User user, long newCommitCount) { |
| 88 | + // 1️⃣ DB의 lastCommitted 갱신 |
| 89 | + user.setLastCommitted(LocalDateTime.now()); |
| 90 | + userRepository.save(user); |
| 91 | + |
| 92 | + // 2️⃣ Redis에 갱신 (3시간 동안 유지) |
| 93 | + commitCacheService.updateCachedCommitCount(user.getUsername(), newCommitCount); |
| 94 | + |
| 95 | + // 3️⃣ 레드판다 메시지 전송 |
| 96 | + redpandaProducer.sendCommitUpdate(user.getUsername(), newCommitCount); |
| 97 | + |
| 98 | + log.info("✅ 커밋 반영 완료 - User: {}, New Commits: {}", user.getUsername(), newCommitCount); |
| 99 | + } |
| 100 | + |
43 | 101 | } |
0 commit comments