diff --git a/src/main/java/cmf/commitField/domain/commit/scheduler/CommitScheduler.java b/src/main/java/cmf/commitField/domain/commit/scheduler/CommitScheduler.java index 95a13f1..84cecdc 100644 --- a/src/main/java/cmf/commitField/domain/commit/scheduler/CommitScheduler.java +++ b/src/main/java/cmf/commitField/domain/commit/scheduler/CommitScheduler.java @@ -10,6 +10,8 @@ import org.springframework.stereotype.Service; import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; @@ -34,56 +36,69 @@ public void updateUserCommits() { Set activeUsers = redisTemplate.keys("commit_active:*"); log.info("๐Ÿ” Active User Count: {}", activeUsers.size()); + // ํ˜„์žฌ ์ ‘์† ๊ธฐ๋ก์ด ์žˆ๋Š” ์œ ์ €, ์ปค๋ฐ‹ ๊ธฐ๋ก์ด ์žˆ๋Š” ์œ ์ €๋Š” ์ฃผ๊ธฐ์ ์œผ๋กœ ๊ฐฑ์‹  for (String key : activeUsers) { String username = key.replace("commit_active:", ""); - User user = userRepository.findByUsername(username).orElse(null); - if (user != null) { - processUserCommit(user); - } - } + String lastcmKey = "commit_lastCommitted:" + username; // active์œ ์ €์˜ key + String lastCommitted = redisTemplate.opsForValue().get(lastcmKey); // ๋งˆ์ง€๋ง‰ ์ปค๋ฐ‹ ์‹œ๊ฐ„ + + System.out.println("username: "+username); + System.out.println("user lastCommitted: "+lastCommitted); + if(username!=null && lastCommitted!=null) processUserCommit(username); + } } // ๐Ÿ”น ์œ ์ € ์ปค๋ฐ‹ ๊ฒ€์‚ฌ ๋ฐ ๋ฐ˜์˜ - private void processUserCommit(User user) { - // Redis์—์„œ lastCommitted ๊ฐ’ ๊ฐ€์ ธ์˜ค๊ธฐ - String redisKey = "commit_last:" + user.getUsername(); - String lastCommittedStr = redisTemplate.opsForValue().get(redisKey); - LocalDateTime lastCommitted; - if(lastCommittedStr != null){ - lastCommitted=LocalDateTime.parse(lastCommittedStr); - }else{ - user.setLastCommitted(LocalDateTime.now()); // ๋ ˆ๋””์Šค์— ์ €์žฅ๋˜์–ด์žˆ์ง€ ์•Š์•˜๋‹ค๋ฉด ๋“ฑ๋ก ์‹œ์ ์— lastCommitted๋ฅผ ๊ฐฑ์‹  - lastCommitted=user.getLastCommitted(); // Redis์— ์—†์œผ๋ฉด DB๊ฐ’ ์‚ฌ์šฉ; + private void processUserCommit(String username) { + // ์œ ์ €๊ฐ€ ์ ‘์†ํ•œ ๋™์•ˆ ์ถ”๊ฐ€ํ•œ commit์ˆ˜๋ฅผ ํ™•์ธ. + String key = "commit_active:" + username; // active์œ ์ €์˜ key + String lastcmKey = "commit_lastCommitted:" + username; // active์œ ์ €์˜ key + String currentCommit = redisTemplate.opsForValue().get(key); // ํ˜„์žฌ๊นŒ์ง€ ํ™•์ธํ•œ ์ปค๋ฐ‹ ๊ฐœ์ˆ˜ + String lastcommitted = redisTemplate.opsForValue().get(lastcmKey); // ๋งˆ์ง€๋ง‰ ์ปค๋ฐ‹ ์‹œ๊ฐ„ + long updateTotalCommit, newCommitCount; + + + LocalDateTime lastCommittedTime; + try { + lastCommittedTime = LocalDateTime.parse(lastcommitted, DateTimeFormatter.ISO_DATE_TIME); + } catch (DateTimeParseException e) { + System.out.println("lastcommitted ๊ฐ’์ด ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š์Œ: " + lastcommitted); + lastCommittedTime = LocalDateTime.now().minusHours(1); } // ํ˜„์žฌ ์ปค๋ฐ‹ ๊ฐœ์ˆ˜ ์กฐํšŒ - long currentCommitCount = totalCommitService.getUpdateCommits( - user.getUsername(), - lastCommitted, // ๐Ÿš€ Redis์— ์ €์žฅ๋œ lastCommitted ๊ธฐ์ค€์œผ๋กœ ์กฐํšŒ - LocalDateTime.now() - ).getTotalCommitContributions(); - - // Redis์—์„œ ์ด์ „ ์ปค๋ฐ‹ ๊ฐœ์ˆ˜ ๊ฐ€์ ธ์˜ค๊ธฐ - Integer previousCommitCount = commitCacheService.getCachedCommitCount(user.getUsername()); - long newCommitCount = previousCommitCount == null ? 0 : (currentCommitCount - previousCommitCount); - - if (newCommitCount > 0) { - updateCommitData(user, currentCommitCount, newCommitCount); - } + updateTotalCommit = totalCommitService.getUpdateCommits( + username, + lastCommittedTime, // ๐Ÿš€ Redis์— ์ €์žฅ๋œ lastCommitted ๊ธฐ์ค€์œผ๋กœ ์กฐํšŒ + LocalDateTime.now() + ).getCommits(); + System.out.println("์ปค๋ฐ‹ ๊ฐœ์ˆ˜ ๋ถˆ๋Ÿฌ๋“ค์ด๊ธฐ ์™„๋ฃŒ, ํ˜„์žฌ๊นŒ์ง€ ์—…๋ฐ์ดํŠธ ๋œ ์ปค๋ฐ‹ ์ˆ˜ : "+updateTotalCommit); - log.info("๐Ÿ” User: {}, New Commits: {}, Total Commits: {}", user.getUsername(), newCommitCount, currentCommitCount); - } + if(currentCommit.equals("0") && updateTotalCommit > 0){ + User user = userRepository.findByUsername(username).get(); + LocalDateTime now = LocalDateTime.now(); + //์ด๋ฒˆ ๊ธฐ๊ฐ„์— ์ฒ˜์Œ์œผ๋กœ ์ปค๋ฐ‹ ์ˆ˜๊ฐ€ ๊ฐฑ์‹ ๋œ ๊ฒฝ์šฐ, ์ด ์‹œ๊ฐ„์„ ๊ธฐ์ ์œผ๋กœ commitCount๋ฅผ ๊ณ„์‚ฐํ•œ๋‹ค. + user.setLastCommitted(now); + userRepository.save(user); + + String redisKey = "commit_update:" + username; // ๋ณ€๊ฒฝ ์•Œ๋ฆผ์„ ์œ„ํ•œ ๋ณ€์ˆ˜ + redisTemplate.opsForValue().set(redisKey, String.valueOf(updateTotalCommit), 3, TimeUnit.HOURS); - // ๐Ÿ”น ์ƒˆ ์ปค๋ฐ‹์ด ์žˆ์œผ๋ฉด ๋ฐ์ดํ„ฐ ์—…๋ฐ์ดํŠธ - private void updateCommitData(User user, long currentCommitCount, long newCommitCount) { - // 1๏ธโƒฃ Redis์— lastCommitted ์—…๋ฐ์ดํŠธ (3์‹œ๊ฐ„ TTL) - String redisKey = "commit_last:" + user.getUsername(); - redisTemplate.opsForValue().set(redisKey, LocalDateTime.now().toString(), 3, TimeUnit.HOURS); + redisTemplate.opsForValue().set(lastcmKey, String.valueOf(now), 3, TimeUnit.HOURS); + } - // 2๏ธโƒฃ Redis์— ์ตœ์‹  ์ปค๋ฐ‹ ๊ฐœ์ˆ˜ ์ €์žฅ (3์‹œ๊ฐ„ ๋™์•ˆ ์œ ์ง€) - commitCacheService.updateCachedCommitCount(user.getUsername(), currentCommitCount); + //๊ธฐ์กด ์ปค๋ฐ‹์ด ์žˆ๊ณ  ์ปค๋ฐ‹ ์ˆ˜์— ๋ณ€ํ™”๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ์ฒ˜๋ฆฌ + newCommitCount = updateTotalCommit - Long.parseLong(currentCommit); // ์ƒˆ๋กœ ์ถ”๊ฐ€๋œ ์ปค๋ฐ‹ ์ˆ˜ + if(newCommitCount>0){ + String redisKey = "commit_update:" + username; // ๋ณ€๊ฒฝ ์•Œ๋ฆผ์„ ์œ„ํ•œ ๋ณ€์ˆ˜ + redisTemplate.opsForValue().set(redisKey, String.valueOf(newCommitCount), 3, TimeUnit.HOURS); + + updateTotalCommit+=newCommitCount; + redisTemplate.opsForValue().set(key, String.valueOf(updateTotalCommit), 3, TimeUnit.HOURS); + } - log.info("โœ… ์ปค๋ฐ‹ ๋ฐ˜์˜ ์™„๋ฃŒ - User: {}, New Commits: {}", user.getUsername(), newCommitCount); + // FIXME: ์ฐจํ›„ ๋ฆฌํŒฉํ† ๋ง ํ•„์š” + log.info("๐Ÿ” User: {}, LastCommitted: {}, New Commits: {}, Total Commits: {}", username, lastcommitted, newCommitCount, currentCommit); } } diff --git a/src/main/java/cmf/commitField/domain/commit/scheduler/CommitUpdateService.java b/src/main/java/cmf/commitField/domain/commit/scheduler/CommitUpdateService.java index 0735c71..b37739a 100644 --- a/src/main/java/cmf/commitField/domain/commit/scheduler/CommitUpdateService.java +++ b/src/main/java/cmf/commitField/domain/commit/scheduler/CommitUpdateService.java @@ -29,7 +29,6 @@ public UserInfoDto updateUserTier(String username){ userRepository.save(user); return UserInfoDto.builder() - .userId(user.getId()) .username(user.getUsername()) .email(user.getEmail()) .avatarUrl(user.getAvatarUrl()) diff --git a/src/main/java/cmf/commitField/domain/commit/totalCommit/dto/CommitUpdateDTO.java b/src/main/java/cmf/commitField/domain/commit/totalCommit/dto/CommitUpdateDTO.java new file mode 100644 index 0000000..2ddb87d --- /dev/null +++ b/src/main/java/cmf/commitField/domain/commit/totalCommit/dto/CommitUpdateDTO.java @@ -0,0 +1,12 @@ +package cmf.commitField.domain.commit.totalCommit.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +@AllArgsConstructor +public class CommitUpdateDTO { + long commits; +} diff --git a/src/main/java/cmf/commitField/domain/commit/totalCommit/service/TotalCommitService.java b/src/main/java/cmf/commitField/domain/commit/totalCommit/service/TotalCommitService.java index e79db30..6d33faa 100644 --- a/src/main/java/cmf/commitField/domain/commit/totalCommit/service/TotalCommitService.java +++ b/src/main/java/cmf/commitField/domain/commit/totalCommit/service/TotalCommitService.java @@ -1,5 +1,6 @@ package cmf.commitField.domain.commit.totalCommit.service; +import cmf.commitField.domain.commit.totalCommit.dto.CommitUpdateDTO; import cmf.commitField.domain.commit.totalCommit.dto.TotalCommitGraphQLResponse; import cmf.commitField.domain.commit.totalCommit.dto.TotalCommitResponseDto; import lombok.RequiredArgsConstructor; @@ -215,7 +216,7 @@ private StreakResult calculateStreaks(List commitDates) { } // ์‹œ๊ฐ„๋ณ„ ์ปค๋ฐ‹ ๋ถ„์„ - public TotalCommitResponseDto getUpdateCommits(String username, LocalDateTime since, LocalDateTime until) { + public CommitUpdateDTO getUpdateCommits(String username, LocalDateTime since, LocalDateTime until) { String query = String.format(""" query { user(login: "%s") { @@ -223,7 +224,7 @@ public TotalCommitResponseDto getUpdateCommits(String username, LocalDateTime si commitContributionsByRepository { contributions(first: 100) { nodes { - occurredAt # โœ… ์‹œ๊ฐ„ ์ •๋ณด ํฌํ•จ + occurredAt # ์‹œ๊ฐ„ ์ •๋ณด ํฌํ•จ } } } @@ -244,12 +245,13 @@ public TotalCommitResponseDto getUpdateCommits(String username, LocalDateTime si throw new RuntimeException("Failed to fetch GitHub data"); } + + System.out.println("๋ฉ”์†Œ๋“œ ์ž‘๋™ ํ™•์ธ : "+response.getData().getUser()); TotalCommitGraphQLResponse.ContributionsCollection contributions = response.getData().getUser().getContributionsCollection(); - return new TotalCommitResponseDto( - contributions.getTotalCommitContributions(), - contributions.getRestrictedContributionsCount() + return new CommitUpdateDTO( + contributions.getTotalCommitContributions() ); } } diff --git a/src/main/java/cmf/commitField/domain/pet/repository/PetRepository.java b/src/main/java/cmf/commitField/domain/pet/repository/PetRepository.java index cd9e248..4ee7d9c 100644 --- a/src/main/java/cmf/commitField/domain/pet/repository/PetRepository.java +++ b/src/main/java/cmf/commitField/domain/pet/repository/PetRepository.java @@ -11,4 +11,5 @@ public interface PetRepository extends JpaRepository { Optional findById(Long id); List findByUserEmail(String email); + List findByUserUsername(String username); } diff --git a/src/main/java/cmf/commitField/domain/user/controller/AuthController.java b/src/main/java/cmf/commitField/domain/user/controller/AuthController.java index e6cc1c3..4fc52ad 100644 --- a/src/main/java/cmf/commitField/domain/user/controller/AuthController.java +++ b/src/main/java/cmf/commitField/domain/user/controller/AuthController.java @@ -15,7 +15,7 @@ public class AuthController { @GetMapping("/login") public ResponseEntity user() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - + System.out.println("/login ํ˜ธ์ถœ"); if (authentication instanceof OAuth2AuthenticationToken) { OAuth2User principal = (OAuth2User) authentication.getPrincipal(); return ResponseEntity.ok(principal.getAttributes()); // ์‚ฌ์šฉ์ž ์ •๋ณด ๋ฐ˜ํ™˜ diff --git a/src/main/java/cmf/commitField/domain/user/controller/UserController.java b/src/main/java/cmf/commitField/domain/user/controller/UserController.java new file mode 100644 index 0000000..5e63629 --- /dev/null +++ b/src/main/java/cmf/commitField/domain/user/controller/UserController.java @@ -0,0 +1,31 @@ +package cmf.commitField.domain.user.controller; + +import cmf.commitField.domain.commit.totalCommit.service.TotalCommitService; +import cmf.commitField.domain.user.dto.UserInfoDto; +import cmf.commitField.domain.user.entity.CustomOAuth2User; +import cmf.commitField.domain.user.service.UserService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/user") +@RequiredArgsConstructor +public class UserController { + private final UserService userService; + private final TotalCommitService totalCommitService; + + @GetMapping("info") + public ResponseEntity getUserInfo(@AuthenticationPrincipal CustomOAuth2User oAuth2User){ + String username = oAuth2User.getName(); + + //์œ ์ € ์ •๋ณด์˜ ์กฐํšŒ + //์ด ์ด๋ฒคํŠธ๊ฐ€ ์ผ์–ด๋‚˜๋ฉด ์œ ์ €์˜ ์ •๋ณด๋ฅผ ํ™•์ธํ•˜๊ณ , ์กฐํšŒํ•œ ์œ ์ €๋ฅผ active ์ƒํƒœ๋กœ ๋งŒ๋“ ๋‹ค. + UserInfoDto userInfoDto = userService.showUserInfo(username); + + return ResponseEntity.ok(userInfoDto); + } +} diff --git a/src/main/java/cmf/commitField/domain/user/dto/UserInfoDto.java b/src/main/java/cmf/commitField/domain/user/dto/UserInfoDto.java index 34d2045..57aeee6 100644 --- a/src/main/java/cmf/commitField/domain/user/dto/UserInfoDto.java +++ b/src/main/java/cmf/commitField/domain/user/dto/UserInfoDto.java @@ -9,13 +9,16 @@ @Getter public class UserInfoDto { - private Long userId; private String username; private String email; private String avatarUrl; private LocalDateTime createdAt; private LocalDateTime lastCommitted; private long commitCount; + + private int petType; + private int petExp; + private String petGrow; private String tier; // ํŽซ ์ƒ๋žต, ์ฐจํ›„ ํ•„์š”์‹œ ์ถ”๊ฐ€ diff --git a/src/main/java/cmf/commitField/domain/user/service/UserService.java b/src/main/java/cmf/commitField/domain/user/service/UserService.java index 97ee82e..e77fa50 100644 --- a/src/main/java/cmf/commitField/domain/user/service/UserService.java +++ b/src/main/java/cmf/commitField/domain/user/service/UserService.java @@ -1,18 +1,68 @@ package cmf.commitField.domain.user.service; +import cmf.commitField.domain.commit.scheduler.CommitUpdateService; +import cmf.commitField.domain.commit.totalCommit.service.TotalCommitService; +import cmf.commitField.domain.pet.entity.Pet; +import cmf.commitField.domain.pet.repository.PetRepository; +import cmf.commitField.domain.pet.service.PetService; +import cmf.commitField.domain.user.dto.UserInfoDto; +import cmf.commitField.domain.user.entity.User; import cmf.commitField.domain.user.repository.UserRepository; import lombok.RequiredArgsConstructor; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDateTime; +import java.util.concurrent.TimeUnit; + @Service @RequiredArgsConstructor public class UserService { + private final StringRedisTemplate redisTemplate; private final UserRepository userRepository; + private final PetRepository petRepository; + // FIXME: ์ˆ˜์ • ํ•„์š” + private final TotalCommitService totalCommitService; + private final CommitUpdateService commitUpdateService; + private final PetService petService; @Transactional public void updateUserStatus(String username, boolean status) { System.out.println("Updating status for " + username + " to " + status); userRepository.updateStatus(username, status); } + + @Transactional + public UserInfoDto showUserInfo(String username) { + User user = userRepository.findByUsername(username).get(); + Pet pet = petRepository.findByUserEmail(user.getEmail()).get(0); // TODO: ํ™•์žฅ์‹œ ์ฝ”๋“œ ์ˆ˜์ • ํ•„์š” + + // ์œ ์ € ์ •๋ณด ์กฐํšŒ ํ›„ ๋ณ€๊ฒฝ์‚ฌํ•ญ์€ ์—…๋ฐ์ดํŠธ + // TODO: ์Šค์ผ€์ฅด๋Ÿฌ ์ˆ˜์ • ํ›„ ํŽซ ๋ถ€๋ถ„ ์ˆ˜์ • ํ•„์š” + commitUpdateService.updateUserTier(user.getUsername()); + petService.getExpPet(user.getUsername(), 0); + + long commit = totalCommitService.getUpdateCommits(username, user.getLastCommitted(), LocalDateTime.now()).getCommits(); + System.out.println("์ปค๋ฐ‹์ˆ˜ ํ…Œ์ŠคํŠธ : "+commit); + + String key = "commit_active:" + user.getUsername(); + if(redisTemplate.opsForValue().get(key)==null){ + redisTemplate.opsForValue().set(key, String.valueOf(0), 3, TimeUnit.HOURS); + redisTemplate.opsForValue().set("commit_lastCommitted:" + username, LocalDateTime.now().toString(),3, TimeUnit.HOURS); + } + + return UserInfoDto.builder() + .username(user.getUsername()) + .email(user.getEmail()) + .avatarUrl(user.getAvatarUrl()) + .tier(user.getTier().toString()) + .commitCount(user.getCommitCount()) + .createdAt(user.getCreatedAt()) + .lastCommitted(user.getLastCommitted()) + .petType(pet.getType()) + .petExp(pet.getExp()) + .petGrow(pet.getGrow().toString()) + .build(); + } } diff --git a/src/main/java/cmf/commitField/global/config/RedisConfig.java b/src/main/java/cmf/commitField/global/config/RedisConfig.java index 03fa0d0..76717ae 100644 --- a/src/main/java/cmf/commitField/global/config/RedisConfig.java +++ b/src/main/java/cmf/commitField/global/config/RedisConfig.java @@ -42,4 +42,5 @@ public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConne template.setConnectionFactory(redisConnectionFactory); return template; } + } diff --git a/src/main/java/cmf/commitField/global/security/SecurityConfig.java b/src/main/java/cmf/commitField/global/security/SecurityConfig.java index d475dc7..864db28 100644 --- a/src/main/java/cmf/commitField/global/security/SecurityConfig.java +++ b/src/main/java/cmf/commitField/global/security/SecurityConfig.java @@ -2,24 +2,31 @@ import cmf.commitField.domain.user.service.CustomOAuth2UserService; import jakarta.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.security.web.SecurityFilterChain; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsConfigurationSource; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import java.time.LocalDateTime; import java.util.List; +import java.util.concurrent.TimeUnit; @Configuration @EnableWebSecurity public class SecurityConfig { + @Autowired + private StringRedisTemplate redisTemplate; private final CustomOAuth2UserService customOAuth2UserService; public SecurityConfig(CustomOAuth2UserService customOAuth2UserService) { @@ -49,6 +56,9 @@ protected SecurityFilterChain config(HttpSecurity http) throws Exception { OAuth2User principal = (OAuth2User) authentication.getPrincipal(); String username = principal.getAttribute("login"); + // Redis์— ์œ ์ € ํ™œ์„ฑํ™” ์ •๋ณด ์ €์žฅ + setUserActive(username); + // ๋””๋ฒ„๊น… ๋กœ๊ทธ System.out.println("OAuth2 ๋กœ๊ทธ์ธ ์„ฑ๊ณต: " + username); response.sendRedirect("http://localhost:5173/home"); // ๋กœ๊ทธ์ธ ์„ฑ๊ณต ํ›„ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ @@ -60,6 +70,12 @@ protected SecurityFilterChain config(HttpSecurity http) throws Exception { .clearAuthentication(true) // ์ธ์ฆ ์ •๋ณด ์ง€์šฐ๊ธฐ .deleteCookies("JSESSIONID") // ์„ธ์…˜ ์ฟ ํ‚ค ์‚ญ์ œ .logoutSuccessHandler((request, response, authentication) -> { + OAuth2AuthenticationToken oauth2Token = (OAuth2AuthenticationToken) authentication; + OAuth2User principal = oauth2Token.getPrincipal(); + String username = principal.getAttribute("login"); + + redisTemplate.delete("commit_active:" + username); // Redis์—์„œ ์‚ญ์ œ + System.out.println("๋กœ๊ทธ์•„์›ƒ ์„ฑ๊ณต"); response.setStatus(HttpServletResponse.SC_OK); response.sendRedirect("http://localhost:5173/"); // ๋กœ๊ทธ์•„์›ƒ ํ›„ ํ™ˆ์œผ๋กœ ์ด๋™ @@ -83,4 +99,13 @@ public CorsConfigurationSource corsConfigurationSource() { source.registerCorsConfiguration("/**", config); return source; } + + public void setUserActive(String username) { + redisTemplate.opsForValue().set("commit_active:" + username, "0"); + redisTemplate.opsForValue().set("commit_lastCommitted:" + username, LocalDateTime.now().toString(),3, TimeUnit.HOURS); + } + + public void removeUserActive(String username) { + redisTemplate.delete("commit_active:" + username); + } }