Skip to content

Commit

Permalink
Merge pull request #21 from sopt-makers/feat/#20-interface-separation
Browse files Browse the repository at this point in the history
Feat/#20 interface separation
  • Loading branch information
softmoca authored Jan 16, 2025
2 parents 2b41f0f + a4ff349 commit 957d64a
Show file tree
Hide file tree
Showing 22 changed files with 471 additions and 247 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import sopt.org.homepage.aboutsopt.dto.GetAboutSoptResponseDto;
import sopt.org.homepage.aboutsopt.service.AboutSoptService;

@RestController
@RequiredArgsConstructor
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package sopt.org.homepage.aboutsopt.service;

import sopt.org.homepage.aboutsopt.dto.GetAboutSoptResponseDto;

public interface AboutSoptService {
/**
* 특정 기수의 AboutSopt 정보를 조회.
*
* @param generation 조회할 기수. null인 경우 최근 기수 정보를 조회.
* @return AboutSopt 정보 및 활동 기록이 포함된 응답 DTO
*/
GetAboutSoptResponseDto getAboutSopt(Integer generation);

/**
* 특정 기수의 스터디 수를 조회.
*
* @param generation 조회할 기수
* @return 해당 기수의 스터디 수
*/
Integer getStudyCount(Integer generation);
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package sopt.org.homepage.aboutsopt;
package sopt.org.homepage.aboutsopt.service;

import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import sopt.org.homepage.aboutsopt.dto.AboutSoptResponseDto;
Expand All @@ -11,28 +10,28 @@
import sopt.org.homepage.aboutsopt.entity.AboutSoptEntity;
import sopt.org.homepage.aboutsopt.entity.CoreValueEntity;
import sopt.org.homepage.aboutsopt.repository.AboutSoptRepository;
import sopt.org.homepage.common.service.GenerationService;
import sopt.org.homepage.exception.NotFoundException;
import sopt.org.homepage.internal.crew.CrewService;
import sopt.org.homepage.internal.playground.PlaygroundService;
import sopt.org.homepage.main.entity.MainEntity;
import sopt.org.homepage.main.repository.MainRepository;
import sopt.org.homepage.main.service.MainService;
import sopt.org.homepage.project.ProjectService;
import sopt.org.homepage.project.service.ProjectService;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class AboutSoptService {
public class AboutSoptServiceImpl implements AboutSoptService {
private static final int MINIMUM_PROJECT_COUNT = 10;

private final AboutSoptRepository aboutSoptRepository;
private final ObjectProvider<MainService> mainServiceProvider;
private final CrewService crewService;
private final PlaygroundService playgroundService;
private final ProjectService projectService;
private final GenerationService generationService;

@Override
public GetAboutSoptResponseDto getAboutSopt(Integer generation) {

int currentGeneration = generation != null ? generation : mainServiceProvider.getObject().getLatestGeneration();
int currentGeneration = generation != null ? generation : generationService.getLatestGeneration();


AboutSoptEntity aboutSopt = aboutSoptRepository.findByIdAndIsPublishedTrue(Long.valueOf(currentGeneration))
Expand All @@ -45,7 +44,7 @@ public GetAboutSoptResponseDto getAboutSopt(Integer generation) {
var studyCount = crewService.getStudyCount(targetGeneration);

return GetAboutSoptResponseDto.builder()
.aboutSopt(convertToResponseDto(aboutSopt))
.aboutSopt(convertToAboutSoptDto(aboutSopt))
.activitiesRecords(GetAboutSoptResponseDto.ActivitiesRecords.builder()
.activitiesMemberCount(members.numberOfMembersAtGeneration())
.projectCounts(projects.size())
Expand All @@ -54,6 +53,11 @@ public GetAboutSoptResponseDto getAboutSopt(Integer generation) {
.build();
}

@Override
public Integer getStudyCount(Integer generation) {
return crewService.getStudyCount(generation);
}

private int determineTargetGeneration(int currentGeneration) {
return findGenerationWithMinimumProjects(currentGeneration, currentGeneration - 5); // 5기수 전까지(무한 루프 방지)
}
Expand All @@ -71,7 +75,9 @@ private int findGenerationWithMinimumProjects(int currentGeneration, int minGene
return findGenerationWithMinimumProjects(currentGeneration - 1, minGeneration);
}

private AboutSoptResponseDto convertToResponseDto(AboutSoptEntity entity) {


private AboutSoptResponseDto convertToAboutSoptDto(AboutSoptEntity entity) {
return AboutSoptResponseDto.builder()
.id((long) entity.getId())
.isPublished(entity.isPublished())
Expand All @@ -98,4 +104,4 @@ private CoreValueResponseDto convertToCoreValueDto(CoreValueEntity coreValue) {
.imageUrl(coreValue.getImageUrl())
.build();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package sopt.org.homepage.common.service;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import sopt.org.homepage.main.entity.MainEntity;
import sopt.org.homepage.main.repository.MainRepository;

@Service
@RequiredArgsConstructor
public class GenerationService {
private final MainRepository mainRepository;

public int getLatestGeneration() {
MainEntity mainEntity = mainRepository.findFirstByOrderByGenerationDesc();
return mainEntity.getGeneration();
}
}
Original file line number Diff line number Diff line change
@@ -1,141 +1,18 @@
package sopt.org.homepage.internal.playground;

import java.util.ArrayList;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.core.type.TypeReference;
import sopt.org.homepage.cache.CacheService;
import sopt.org.homepage.common.constants.CacheType;
import sopt.org.homepage.common.util.ArrayUtil;
import sopt.org.homepage.config.AuthConfig;
import sopt.org.homepage.internal.playground.dto.PlaygroundMemberListResponse;
import sopt.org.homepage.internal.playground.dto.PlaygroundProjectAxiosResponseDto;
import sopt.org.homepage.internal.playground.dto.PlaygroundProjectResponseDto;
import sopt.org.homepage.internal.playground.dto.PlaygroundUserResponse;
import sopt.org.homepage.project.dto.request.GetProjectsRequestDto;
import sopt.org.homepage.project.dto.response.ProjectDetailResponseDto;
import sopt.org.homepage.project.dto.response.ProjectsResponseDto;
import sopt.org.homepage.common.mapper.ResponseMapper;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;


@Slf4j
@RequiredArgsConstructor
@Service
public class PlaygroundService {
private final PlaygroundClient playgroundClient;
private final ResponseMapper responseMapper;
private final AuthConfig authConfig;
private final ArrayUtil arrayUtil;

private final CacheService cacheService;
private static final String PROJECT_CACHE_KEY = "all_projects";



public PlaygroundUserResponse getPlaygroundUserInfo(String authToken) {
return playgroundClient.getPlaygroundUser(authToken);
}

public List<ProjectsResponseDto> getAllProjects(GetProjectsRequestDto projectRequest) {
// 캐시에서 데이터 조회 시도
List<PlaygroundProjectResponseDto> projectListResponse = cacheService.get(
CacheType.PROJECT_LIST, PROJECT_CACHE_KEY, new TypeReference<>() {
}
);

if (projectListResponse == null) { // 캐시 미스인 경우 API 호출
try {
projectListResponse = getProjectsWithPagination();
cacheService.put(CacheType.PROJECT_LIST, PROJECT_CACHE_KEY, projectListResponse);
} catch (Exception e) {
log.error("Projcet API Failed to fetch projects", e);
return Collections.emptyList();
}
}

List<ProjectsResponseDto> result = new ArrayList<>();
var filter = projectRequest.getFilter();
var platform = projectRequest.getPlatform();

var uniqueResponse = arrayUtil.dropDuplication(projectListResponse, PlaygroundProjectResponseDto::name);

var uniqueLinkResponse = uniqueResponse.stream()
.map(response -> response.ProjectWithLink(
arrayUtil.dropDuplication(response.links(), PlaygroundProjectResponseDto.ProjectLinkResponse::linkId)
))
.toList();


if (uniqueLinkResponse.isEmpty()) {
return Collections.emptyList();
}

for (var data : projectListResponse) {
result.add(responseMapper.toProjectResponse(data));
}

if (filter != null) {
result = result.stream()
.filter(element -> element.getCategory().project().equals(filter))
.collect(Collectors.toList());
}
if (platform != null) {
result = result.stream()
.filter(element -> element.getServiceType().contains(platform))
.collect(Collectors.toList());
}

return result;
}


public List<PlaygroundProjectResponseDto> getProjectsWithPagination() {
final int limit = 20;
int cursor = 0;
int totalCount = 10;
List<PlaygroundProjectResponseDto> response = new ArrayList<>();

for (int i = 0; i < totalCount + 1; i = i + limit) {
PlaygroundProjectAxiosResponseDto projectData = playgroundClient.getAllProjects(
authConfig.getPlaygroundToken(),
limit,
cursor
);

if (projectData.projectList().isEmpty()) {
break;
}

totalCount = projectData.totalCount();
response.addAll(projectData.projectList());

int lastDataIdx = projectData.projectList().size() - 1;
cursor = projectData.projectList().get(lastDataIdx).id().intValue();

if (!projectData.hasNext()) {
break;
}
}

return response;
}


public ProjectDetailResponseDto getProjectDetail(Long projectId){
var projectResponse = playgroundClient.getProjectDetail(authConfig.getPlaygroundToken(), projectId);
if (projectResponse == null) {
throw new RuntimeException("프로젝트 데이터를 가져오지 못했습니다.");
}

return responseMapper.toProjectDetailResponse(projectResponse);
}

public PlaygroundMemberListResponse getAllMembers(Integer generation) {
return playgroundClient.getAllMembers(authConfig.getPlaygroundToken(), null, generation);
}
}
public interface PlaygroundService {
PlaygroundUserResponse getPlaygroundUserInfo(String authToken);
List<ProjectsResponseDto> getAllProjects(GetProjectsRequestDto projectRequest);
List<PlaygroundProjectResponseDto> getProjectsWithPagination();
ProjectDetailResponseDto getProjectDetail(Long projectId);
PlaygroundMemberListResponse getAllMembers(Integer generation);
}
Loading

0 comments on commit 957d64a

Please sign in to comment.