From 914d68dfee5402036adca913e8da27e8f6f45f44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=8E=E1=85=AC=E1=84=8C=E1=85=AE=E1=86=AB=E1=84=92?= =?UTF-8?q?=E1=85=A9?= Date: Sun, 24 Nov 2024 16:49:48 +0900 Subject: [PATCH 1/2] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=98=EA=B2=8C=20=EB=A9=94=EC=86=8C=EB=93=9C=ED=99=94=20?= =?UTF-8?q?=EB=90=98=EC=96=B4=EC=9E=88=EB=8A=94=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=ED=92=80=EC=96=B4=ED=97=A4=EC=B9=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/abtest/controller/AbtestApi.java | 2 +- .../admin/abtest/service/AbtestService.java | 103 +++++++++++------- 2 files changed, 62 insertions(+), 43 deletions(-) diff --git a/src/main/java/in/koreatech/koin/admin/abtest/controller/AbtestApi.java b/src/main/java/in/koreatech/koin/admin/abtest/controller/AbtestApi.java index c5ae6ee8b..de272aa55 100644 --- a/src/main/java/in/koreatech/koin/admin/abtest/controller/AbtestApi.java +++ b/src/main/java/in/koreatech/koin/admin/abtest/controller/AbtestApi.java @@ -189,7 +189,7 @@ ResponseEntity assignAbtestVariableByAdmin( @Operation(summary = "(NORMAL) 실험군 편입 정보 확인") @PostMapping("/assign") ResponseEntity assignOrGetAbtestVariable( - @RequestHeader("accessHistoryId") Integer accessHistoryId, + @RequestHeader("access_history_id") Integer accessHistoryId, @UserAgent UserAgentInfo userAgentInfo, @UserId Integer userId, @RequestBody @Valid AbtestAssignRequest abtestAssignRequest diff --git a/src/main/java/in/koreatech/koin/admin/abtest/service/AbtestService.java b/src/main/java/in/koreatech/koin/admin/abtest/service/AbtestService.java index 3b729c0f9..3212f5e6b 100644 --- a/src/main/java/in/koreatech/koin/admin/abtest/service/AbtestService.java +++ b/src/main/java/in/koreatech/koin/admin/abtest/service/AbtestService.java @@ -140,27 +140,54 @@ public void closeAbtest(Integer abtestId, AbtestCloseRequest request) { } @Transactional - public AbtestAssignResponse assignOrGetVariable(Integer accessHistoryId, UserAgentInfo userAgentInfo, + public AbtestAssignResponse assignOrGetVariable( + Integer accessHistoryId, + UserAgentInfo userAgentInfo, Integer userId, - AbtestAssignRequest request) { + AbtestAssignRequest request + ) { + AccessHistory accessHistory; + if (accessHistoryId == null) { + accessHistory = accessHistoryRepository.save(AccessHistory.builder().build()); + } else { + accessHistory = accessHistoryRepository.getById(accessHistoryId); + } Abtest abtest = abtestRepository.getByTitle(request.title()); - AccessHistory accessHistory = findOrCreateAccessHistory(accessHistoryId); - Optional winnerResponse = returnWinnerIfClosed(abtest); + + Optional winnerResponse; + if (abtest.getStatus() == AbtestStatus.CLOSED) { + if (abtest.getWinner() != null) { + winnerResponse = Optional.of(abtest.getWinner()); + } + throw AbtestWinnerNotDecidedException.withDetail("abtestId: " + abtest.getId()); + } else { + winnerResponse = Optional.empty(); + } + if (winnerResponse.isPresent()) { return AbtestAssignResponse.of(winnerResponse.get(), accessHistory); } + if (isAssignedUser(abtest, accessHistory.getId(), userId)) { return AbtestAssignResponse.of( - getMyVariable(accessHistory.getId(), userAgentInfo, userId, request.title()), accessHistory); + getMyVariable(accessHistory.getId(), userAgentInfo, userId, request.title()), + accessHistory + ); } List cacheCount = loadCacheCount(abtest); AbtestVariable variable = abtest.findAssignVariable(cacheCount); + if (userId != null) { createDeviceIfNotExists(userId, userAgentInfo, accessHistory, abtest); } + accessHistory.addAbtestVariable(variable); - countCacheUpdate(variable); - variableAssignCacheSave(variable, accessHistory.getId()); + + AbtestVariableCount countCache = abtestVariableCountRepository.findOrCreateIfNotExists(variable.getId()); + countCache.addCount(); + abtestVariableCountRepository.save(countCache); + + abtestVariableAssignRepository.save(AbtestVariableAssign.of(variable.getId(), accessHistoryId)); accessHistory.updateLastAccessedAt(clock); return AbtestAssignResponse.of(variable, accessHistory); } @@ -183,22 +210,25 @@ private List loadCacheCount(Abtest abtest) { .toList(); } - private void countCacheUpdate(AbtestVariable variable) { - AbtestVariableCount countCache = abtestVariableCountRepository.findOrCreateIfNotExists(variable.getId()); - countCache.addCount(); - abtestVariableCountRepository.save(countCache); - } - - private void variableAssignCacheSave(AbtestVariable variable, Integer accessHistoryId) { - abtestVariableAssignRepository.save(AbtestVariableAssign.of(variable.getId(), accessHistoryId)); - } - - private AbtestVariable getMyVariable(Integer accessHistoryId, UserAgentInfo userAgentInfo, Integer userId, - String title) { + private AbtestVariable getMyVariable( + Integer accessHistoryId, + UserAgentInfo userAgentInfo, + Integer userId, + String title + ) { Abtest abtest = abtestRepository.getByTitle(title); AccessHistory accessHistory = accessHistoryRepository.getById(accessHistoryId); syncCacheCountToDB(abtest); - Optional winner = returnWinnerIfClosed(abtest); + Optional winner; + if (abtest.getStatus() == AbtestStatus.CLOSED) { + if (abtest.getWinner() != null) { + winner = Optional.of(abtest.getWinner()); + } + throw AbtestWinnerNotDecidedException.withDetail("abtestId: " + abtest.getId()); + } else { + winner = Optional.empty(); + } + if (winner.isPresent()) { return winner.get(); } @@ -284,11 +314,13 @@ public void assignVariableByAdmin(Integer abtestId, AbtestAdminAssignRequest req abtestVariable -> abtestVariableAssignRepository.deleteByVariableIdAndAccessHistoryId( abtestVariable.getId(), accessHistory.getId())); - variableAssignCacheSave(afterVariable, accessHistory.getId()); + abtestVariableAssignRepository.save(AbtestVariableAssign.of(afterVariable.getId(), accessHistory.getId())); } - private static void validateDuplicatedVariables(Optional beforeVariable, - AbtestVariable afterVariable) { + private static void validateDuplicatedVariables( + Optional beforeVariable, + AbtestVariable afterVariable + ) { if (beforeVariable.isEmpty()) { return; } @@ -304,25 +336,12 @@ private static void validateAbtestInProgress(Abtest abtest) { } } - private static Optional returnWinnerIfClosed(Abtest abtest) { - if (abtest.getStatus() == AbtestStatus.CLOSED) { - if (abtest.getWinner() != null) { - return Optional.of(abtest.getWinner()); - } - throw AbtestWinnerNotDecidedException.withDetail("abtestId: " + abtest.getId()); - } - return Optional.empty(); - } - - public AccessHistory findOrCreateAccessHistory(Integer id) { - if (id == null) { - return accessHistoryRepository.save(AccessHistory.builder().build()); - } - return accessHistoryRepository.getById(id); - } - - private void createDeviceIfNotExists(Integer userId, UserAgentInfo userAgentInfo, - AccessHistory accessHistory, Abtest abtest) { + private void createDeviceIfNotExists( + Integer userId, + UserAgentInfo userAgentInfo, + AccessHistory accessHistory, + Abtest abtest + ) { userRepository.getById(userId); if (accessHistory.getDevice() == null) { Device device = deviceRepository.save( From 902ad6c64da085bf62354bd7ac1e2c6068916dfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=8E=E1=85=AC=E1=84=8C=E1=85=AE=E1=86=AB=E1=84=92?= =?UTF-8?q?=E1=85=A9?= Date: Sun, 24 Nov 2024 17:59:11 +0900 Subject: [PATCH 2/2] =?UTF-8?q?refactor:=20=EB=B9=84=EC=A6=88=EB=8B=88?= =?UTF-8?q?=EC=8A=A4=EB=A1=9C=EC=A7=81=20=EC=A0=95=EB=A0=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ... AbtestVariableAssignRedisRepository.java} | 8 +- ...> AbtestVariableCountRedisRepository.java} | 2 +- .../repository/AbtestVariableRepository.java | 3 + .../admin/abtest/service/AbtestService.java | 213 ++++++++++-------- .../in/koreatech/koin/global/auth/UserId.java | 3 + 5 files changed, 136 insertions(+), 93 deletions(-) rename src/main/java/in/koreatech/koin/admin/abtest/repository/{AbtestVariableAssignRepository.java => AbtestVariableAssignRedisRepository.java} (80%) rename src/main/java/in/koreatech/koin/admin/abtest/repository/{AbtestVariableCountRepository.java => AbtestVariableCountRedisRepository.java} (86%) diff --git a/src/main/java/in/koreatech/koin/admin/abtest/repository/AbtestVariableAssignRepository.java b/src/main/java/in/koreatech/koin/admin/abtest/repository/AbtestVariableAssignRedisRepository.java similarity index 80% rename from src/main/java/in/koreatech/koin/admin/abtest/repository/AbtestVariableAssignRepository.java rename to src/main/java/in/koreatech/koin/admin/abtest/repository/AbtestVariableAssignRedisRepository.java index e36b4035b..48ab4caa9 100644 --- a/src/main/java/in/koreatech/koin/admin/abtest/repository/AbtestVariableAssignRepository.java +++ b/src/main/java/in/koreatech/koin/admin/abtest/repository/AbtestVariableAssignRedisRepository.java @@ -8,7 +8,7 @@ import in.koreatech.koin.admin.abtest.model.redis.AbtestVariableAssign; -public interface AbtestVariableAssignRepository extends Repository { +public interface AbtestVariableAssignRedisRepository extends Repository { AbtestVariableAssign save(AbtestVariableAssign abtestVariableAssign); @@ -16,8 +16,10 @@ public interface AbtestVariableAssignRepository extends Repository findByVariableIdAndAccessHistoryId(Integer variableId, - Integer accessHistoryId) { + default Optional findByVariableIdAndAccessHistoryId( + Integer variableId, + Integer accessHistoryId + ) { return findById(variableId + DELIMITER + accessHistoryId); } diff --git a/src/main/java/in/koreatech/koin/admin/abtest/repository/AbtestVariableCountRepository.java b/src/main/java/in/koreatech/koin/admin/abtest/repository/AbtestVariableCountRedisRepository.java similarity index 86% rename from src/main/java/in/koreatech/koin/admin/abtest/repository/AbtestVariableCountRepository.java rename to src/main/java/in/koreatech/koin/admin/abtest/repository/AbtestVariableCountRedisRepository.java index de36d3554..462763ccb 100644 --- a/src/main/java/in/koreatech/koin/admin/abtest/repository/AbtestVariableCountRepository.java +++ b/src/main/java/in/koreatech/koin/admin/abtest/repository/AbtestVariableCountRedisRepository.java @@ -7,7 +7,7 @@ import in.koreatech.koin.admin.abtest.model.redis.AbtestVariableCount; -public interface AbtestVariableCountRepository extends CrudRepository { +public interface AbtestVariableCountRedisRepository extends CrudRepository { List findAll(); diff --git a/src/main/java/in/koreatech/koin/admin/abtest/repository/AbtestVariableRepository.java b/src/main/java/in/koreatech/koin/admin/abtest/repository/AbtestVariableRepository.java index 2d386f506..e81875a1f 100644 --- a/src/main/java/in/koreatech/koin/admin/abtest/repository/AbtestVariableRepository.java +++ b/src/main/java/in/koreatech/koin/admin/abtest/repository/AbtestVariableRepository.java @@ -1,5 +1,6 @@ package in.koreatech.koin.admin.abtest.repository; +import java.util.List; import java.util.Optional; import org.springframework.data.repository.Repository; @@ -11,6 +12,8 @@ public interface AbtestVariableRepository extends Repository findById(Integer variableId); + List findAllByIdIn(List ids); + default AbtestVariable getById(Integer variableId) { return findById(variableId).orElseThrow(() -> AbtestVariableNotFoundException.withDetail("AbtestVariable id: " + variableId)); diff --git a/src/main/java/in/koreatech/koin/admin/abtest/service/AbtestService.java b/src/main/java/in/koreatech/koin/admin/abtest/service/AbtestService.java index 3212f5e6b..5523e0c05 100644 --- a/src/main/java/in/koreatech/koin/admin/abtest/service/AbtestService.java +++ b/src/main/java/in/koreatech/koin/admin/abtest/service/AbtestService.java @@ -33,9 +33,9 @@ import in.koreatech.koin.admin.abtest.model.redis.AbtestVariableAssign; import in.koreatech.koin.admin.abtest.model.redis.AbtestVariableCount; import in.koreatech.koin.admin.abtest.repository.AbtestRepository; -import in.koreatech.koin.admin.abtest.repository.AbtestVariableAssignRepository; +import in.koreatech.koin.admin.abtest.repository.AbtestVariableAssignRedisRepository; import in.koreatech.koin.admin.abtest.repository.AbtestVariableAssignTemplateRepository; -import in.koreatech.koin.admin.abtest.repository.AbtestVariableCountRepository; +import in.koreatech.koin.admin.abtest.repository.AbtestVariableCountRedisRepository; import in.koreatech.koin.admin.abtest.repository.AbtestVariableRepository; import in.koreatech.koin.admin.abtest.repository.AccessHistoryRepository; import in.koreatech.koin.admin.abtest.repository.DeviceRepository; @@ -53,13 +53,13 @@ public class AbtestService { private final Clock clock; private final EntityManager entityManager; - private final AbtestVariableCountRepository abtestVariableCountRepository; + private final AbtestVariableCountRedisRepository abtestVariableCountRedisRepository; private final AbtestRepository abtestRepository; private final AbtestVariableRepository abtestVariableRepository; private final AccessHistoryRepository accessHistoryRepository; private final DeviceRepository deviceRepository; private final UserRepository userRepository; - private final AbtestVariableAssignRepository abtestVariableAssignRepository; + private final AbtestVariableAssignRedisRepository abtestVariableAssignRedisRepository; private final AbtestVariableAssignTemplateRepository abtestVariableAssignTemplateRepository; @Transactional @@ -113,7 +113,7 @@ public void deleteAbtest(Integer abtestId) { private void deleteCountCache(Abtest abtest) { abtest.getAbtestVariables() - .forEach(abtestVariable -> abtestVariableCountRepository.deleteById(abtestVariable.getId())); + .forEach(abtestVariable -> abtestVariableCountRedisRepository.deleteById(abtestVariable.getId())); } public AbtestsResponse getAbtests(Integer page, Integer limit) { @@ -142,6 +142,7 @@ public void closeAbtest(Integer abtestId, AbtestCloseRequest request) { @Transactional public AbtestAssignResponse assignOrGetVariable( Integer accessHistoryId, + // 이 값은 어디에쓰이는지? UserAgentInfo userAgentInfo, Integer userId, AbtestAssignRequest request @@ -153,41 +154,126 @@ public AbtestAssignResponse assignOrGetVariable( accessHistory = accessHistoryRepository.getById(accessHistoryId); } Abtest abtest = abtestRepository.getByTitle(request.title()); + AbtestVariable winnerResponse = abtest.getWinner(); - Optional winnerResponse; + // 종료된 경우 우승자 반환을 위한 분기처리 if (abtest.getStatus() == AbtestStatus.CLOSED) { - if (abtest.getWinner() != null) { - winnerResponse = Optional.of(abtest.getWinner()); + // 종료되었는데 우승자가 결정되지 않은 AB테스트인 경우 예외 발생 + if (winnerResponse == null) { + throw AbtestWinnerNotDecidedException.withDetail("abtestId: " + abtest.getId()); } - throw AbtestWinnerNotDecidedException.withDetail("abtestId: " + abtest.getId()); - } else { - winnerResponse = Optional.empty(); - } - - if (winnerResponse.isPresent()) { - return AbtestAssignResponse.of(winnerResponse.get(), accessHistory); + return AbtestAssignResponse.of(winnerResponse, accessHistory); } - if (isAssignedUser(abtest, accessHistory.getId(), userId)) { - return AbtestAssignResponse.of( - getMyVariable(accessHistory.getId(), userAgentInfo, userId, request.title()), - accessHistory - ); + Device device = accessHistory.getDevice(); + if (device != null && userId != null // nullable한 객체에 대해 not null 보장 + && Objects.equals(device.getUser().getId(), userId) // accessHistory의 유저와 API 요청한 유저가 같아야함 + ) { + // accessHistory가 abtest의 변수에 포함되어있다면 True + boolean isContainedVariable = abtest.getAbtestVariables().stream() + .anyMatch(abtestVariable -> accessHistory.hasVariable(abtestVariable.getId())); + + if (isContainedVariable) { + // -- getMyVariable 시작 + + // -- syncCacheCount 시작 + // abTest 변수들 중 Redis에 올라와있는 변수를 가져온다. + List cachedCount = abtest.getAbtestVariables().stream() + .map(AbtestVariable::getId) + .filter(Objects::nonNull) + .map(abtestVariableCountRedisRepository::findById) + .filter(Optional::isPresent) + .map(Optional::get) + .toList(); + + // Redis에 캐싱되어있는 count 값을 RDB로 동기화시킨다. + for (AbtestVariableCount abtestVariableCount : cachedCount) { + // RDB에서 abtestVariable 값을 영속성 컨텍스트에 올린다. (Dirty Checking 대상으로 등록) + AbtestVariable variable = abtestVariableRepository.getById(abtestVariableCount.getVariableId()); + variable.addCount(abtestVariableCount.getCount()); // RDB count update + abtestVariableCount.resetCount(); // Redis reset + } + // reset된 값들을 반영 + abtestVariableCountRedisRepository.saveAll(cachedCount); + // -- syncCacheCount 끝 + + /* + TODO : 해당 부분 설명 필요 + 조건문 진입 시점에서 유저아이디가 Null이 아님을 보장하고있는데 이 로직이 존재하는 이유는? + 기존 + if (userId != null) { + createDeviceIfNotExists(userId, userAgentInfo, accessHistory, abtest); + } +// */ +// if (userId != null) { +// +// userRepository.getById(userId); +// if (accessHistory.getDevice() == null) { +// Device device = deviceRepository.save( +// Device.builder() +// .user(userRepository.getById(userId)) +// .model(userAgentInfo.getModel()) +// .type(userAgentInfo.getType()) +// .build() +// ); +// accessHistory.connectDevice(device); +// } +// Device device = accessHistory.getDevice(); +// if (device.getModel() == null || device.getType() == null) { +// device.setModelInfo(userAgentInfo.getModel(), userAgentInfo.getType()); +// } +// if (!Objects.equals(device.getUser().getId(), userId)) { +// device.changeUser(userRepository.getById(userId)); +// removeBeforeUserCache(accessHistory, abtest); +// } +// } + + // abTest 변수들에 대해서 + Optional cacheVariable = abtest.getAbtestVariables().stream() + .filter(abtestVariable -> + abtestVariableAssignRedisRepository.findByVariableIdAndAccessHistoryId( + abtestVariable.getId(), + accessHistory.getId()).isPresent() + ) + .findAny(); + + AbtestVariable myVariable; + // 캐시가 비어있으면.. + if (cacheVariable.isEmpty()) { + AbtestVariable dbVariable = accessHistory.findVariableByAbtestId(abtest.getId()) + .orElseThrow( + () -> AbtestNotAssignedUserException.withDetail( + "abtestId: " + abtest.getId() + ", " + + "accessHistoryId: " + accessHistory.getId()) + ); + abtestVariableAssignRedisRepository.save( + AbtestVariableAssign.of(dbVariable.getId(), accessHistory.getId())); + myVariable = dbVariable; + } else { + accessHistory.updateLastAccessedAt(clock); + myVariable = cacheVariable.get(); + } + + return AbtestAssignResponse.of( + myVariable, + accessHistory + ); + } } List cacheCount = loadCacheCount(abtest); AbtestVariable variable = abtest.findAssignVariable(cacheCount); - - if (userId != null) { - createDeviceIfNotExists(userId, userAgentInfo, accessHistory, abtest); - } +// TODO: 설명 필요 +// if (userId != null) { +// createDeviceIfNotExists(userId, userAgentInfo, accessHistory, abtest); +// } accessHistory.addAbtestVariable(variable); - AbtestVariableCount countCache = abtestVariableCountRepository.findOrCreateIfNotExists(variable.getId()); + AbtestVariableCount countCache = abtestVariableCountRedisRepository.findOrCreateIfNotExists(variable.getId()); countCache.addCount(); - abtestVariableCountRepository.save(countCache); + abtestVariableCountRedisRepository.save(countCache); - abtestVariableAssignRepository.save(AbtestVariableAssign.of(variable.getId(), accessHistoryId)); + abtestVariableAssignRedisRepository.save(AbtestVariableAssign.of(variable.getId(), accessHistoryId)); accessHistory.updateLastAccessedAt(clock); return AbtestAssignResponse.of(variable, accessHistory); } @@ -195,92 +281,41 @@ public AbtestAssignResponse assignOrGetVariable( // 기기를 다른 사용자가 사용한 이력이 있는 경우 기존 사용자의 캐시를 삭제 private void removeBeforeUserCache(AccessHistory accessHistory, Abtest abtest) { for (AbtestVariable removeVariable : accessHistory.getVariableBy(abtest)) { - abtestVariableAssignRepository.deleteByVariableIdAndAccessHistoryId(removeVariable.getId(), + abtestVariableAssignRedisRepository.deleteByVariableIdAndAccessHistoryId(removeVariable.getId(), accessHistory.getId()); - AbtestVariableCount countCache = abtestVariableCountRepository.findOrCreateIfNotExists( + AbtestVariableCount countCache = abtestVariableCountRedisRepository.findOrCreateIfNotExists( removeVariable.getId()); countCache.minusCount(); - abtestVariableCountRepository.save(countCache); + abtestVariableCountRedisRepository.save(countCache); } } private List loadCacheCount(Abtest abtest) { return abtest.getAbtestVariables().stream() - .map(abtestVariable -> abtestVariableCountRepository.findOrCreateIfNotExists(abtestVariable.getId())) + .map(abtestVariable -> abtestVariableCountRedisRepository.findOrCreateIfNotExists(abtestVariable.getId())) .toList(); } - private AbtestVariable getMyVariable( - Integer accessHistoryId, - UserAgentInfo userAgentInfo, - Integer userId, - String title - ) { - Abtest abtest = abtestRepository.getByTitle(title); - AccessHistory accessHistory = accessHistoryRepository.getById(accessHistoryId); - syncCacheCountToDB(abtest); - Optional winner; - if (abtest.getStatus() == AbtestStatus.CLOSED) { - if (abtest.getWinner() != null) { - winner = Optional.of(abtest.getWinner()); - } - throw AbtestWinnerNotDecidedException.withDetail("abtestId: " + abtest.getId()); - } else { - winner = Optional.empty(); - } - - if (winner.isPresent()) { - return winner.get(); - } - if (userId != null) { - createDeviceIfNotExists(userId, userAgentInfo, accessHistory, abtest); - } - Optional cacheVariable = abtest.getAbtestVariables().stream() - .filter(abtestVariable -> - abtestVariableAssignRepository.findByVariableIdAndAccessHistoryId(abtestVariable.getId(), - accessHistory.getId()).isPresent()) - .findAny(); - if (cacheVariable.isEmpty()) { - AbtestVariable dbVariable = accessHistory.findVariableByAbtestId(abtest.getId()) - .orElseThrow(() -> AbtestNotAssignedUserException.withDetail("abtestId: " + abtest.getId() + ", " - + "accessHistoryId: " + accessHistory.getId())); - abtestVariableAssignRepository.save(AbtestVariableAssign.of(dbVariable.getId(), accessHistory.getId())); - return dbVariable; - } - accessHistory.updateLastAccessedAt(clock); - return cacheVariable.get(); - } - - private boolean isAssignedUser(Abtest abtest, Integer accessHistoryId, Integer userId) { - AccessHistory accessHistory = accessHistoryRepository.getById(accessHistoryId); - if (userId != null && accessHistory.getDevice() != null - && !Objects.equals(accessHistory.getDevice().getUser().getId(), userId)) { - return false; - } - return abtest.getAbtestVariables().stream() - .anyMatch(abtestVariable -> accessHistory.hasVariable(abtestVariable.getId())); - } - @Transactional public void syncCacheCountToDB() { - List cacheCount = abtestVariableCountRepository.findAll(); + List cacheCount = abtestVariableCountRedisRepository.findAll(); cacheCount.removeIf(Objects::isNull); cacheCount.forEach(abtestVariableCount -> { Optional variable = abtestVariableRepository.findById(abtestVariableCount.getVariableId()); if (variable.isEmpty()) { - abtestVariableCountRepository.deleteById(abtestVariableCount.getVariableId()); + abtestVariableCountRedisRepository.deleteById(abtestVariableCount.getVariableId()); return; } variable.get().addCount(abtestVariableCount.getCount()); abtestVariableCount.resetCount(); }); - abtestVariableCountRepository.saveAll(cacheCount); + abtestVariableCountRedisRepository.saveAll(cacheCount); } public void syncCacheCountToDB(Abtest abtest) { List cacheCount = abtest.getAbtestVariables().stream() .map(AbtestVariable::getId) - .map(abtestVariableCountRepository::findById) + .map(abtestVariableCountRedisRepository::findById) .filter(Optional::isPresent) .map(Optional::get) .toList(); @@ -289,7 +324,7 @@ public void syncCacheCountToDB(Abtest abtest) { variable.addCount(abtestVariableCount.getCount()); abtestVariableCount.resetCount(); }); - abtestVariableCountRepository.saveAll(cacheCount); + abtestVariableCountRedisRepository.saveAll(cacheCount); } public AbtestUsersResponse getUsersByName(String userName) { @@ -311,10 +346,10 @@ public void assignVariableByAdmin(Integer abtestId, AbtestAdminAssignRequest req validateDuplicatedVariables(beforeVariable, afterVariable); abtest.assignVariableByAdmin(accessHistory, request.variableName()); beforeVariable.ifPresent( - abtestVariable -> abtestVariableAssignRepository.deleteByVariableIdAndAccessHistoryId( + abtestVariable -> abtestVariableAssignRedisRepository.deleteByVariableIdAndAccessHistoryId( abtestVariable.getId(), accessHistory.getId())); - abtestVariableAssignRepository.save(AbtestVariableAssign.of(afterVariable.getId(), accessHistory.getId())); + abtestVariableAssignRedisRepository.save(AbtestVariableAssign.of(afterVariable.getId(), accessHistory.getId())); } private static void validateDuplicatedVariables( diff --git a/src/main/java/in/koreatech/koin/global/auth/UserId.java b/src/main/java/in/koreatech/koin/global/auth/UserId.java index 8af4dc7fd..c7eb0b58f 100644 --- a/src/main/java/in/koreatech/koin/global/auth/UserId.java +++ b/src/main/java/in/koreatech/koin/global/auth/UserId.java @@ -6,6 +6,8 @@ import java.lang.annotation.Retention; import java.lang.annotation.Target; +import javax.annotation.Nullable; + import io.swagger.v3.oas.annotations.Hidden; /** @@ -14,6 +16,7 @@ * Nullable: 사용자 ID가 없을 수도 있다. */ @Hidden // Swagger 문서에 표시하지 않음 +@Nullable @Target(PARAMETER) @Retention(RUNTIME) public @interface UserId {