Skip to content

Commit

Permalink
Merge pull request #44 from Leets-Official/refactor/#43
Browse files Browse the repository at this point in the history
refactor: GitHub API 통신 방식 변경
  • Loading branch information
yechan-kim authored Feb 21, 2025
2 parents f3aaff2 + aa29d39 commit c17f296
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 94 deletions.
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/feature.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
name: Feature
about: 새로운 기능을 제안하기 위한 이슈 템플릿
title: "[FEARTURE]"
title: "[FEATURE]"
labels: "feature"
assignees: ''

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public ApiResponse<CommitResponse> fetchCommits() {

@Operation(
summary = "커밋 기록 업데이트 (테스트)",
description = "테스트를 위해, 7월 1일부터 커밋 기록을 가져와 DB에 저장하고 사용자의 정보를 최신화 합니다.")
description = "테스트를 위해, 최근 3개월의 커밋 기록을 가져와 DB에 저장하고 사용자의 정보를 최신화 합니다.")
@PostMapping("update/test")
public ApiResponse<CommitResponse> fetchCommitsTest() {
return ApiResponse.onSuccess(fetchCommitsTest.execute());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.leets.commitatobe.domain.commit.service;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
Expand All @@ -19,8 +18,6 @@
import com.leets.commitatobe.domain.user.domain.User;
import com.leets.commitatobe.domain.user.repository.UserRepository;
import com.leets.commitatobe.domain.user.service.UserQueryService;
import com.leets.commitatobe.global.exception.ApiException;
import com.leets.commitatobe.global.response.code.status.ErrorStatus;

import lombok.RequiredArgsConstructor;

Expand Down Expand Up @@ -59,11 +56,7 @@ public CommitResponse execute() {

for (String fullName : repos) {
CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
try {
gitHubService.countCommits(fullName, gitHubId, finalDateTime);
} catch (IOException e) {
throw new ApiException(ErrorStatus._GIT_URL_INCORRECT);
}
gitHubService.countCommits(fullName, gitHubId, finalDateTime);
}, executor);
futures.add(voidCompletableFuture);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.leets.commitatobe.domain.commit.service;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
Expand All @@ -19,8 +18,6 @@
import com.leets.commitatobe.domain.user.domain.User;
import com.leets.commitatobe.domain.user.repository.UserRepository;
import com.leets.commitatobe.domain.user.service.UserQueryService;
import com.leets.commitatobe.global.exception.ApiException;
import com.leets.commitatobe.global.response.code.status.ErrorStatus;

import lombok.RequiredArgsConstructor;

Expand All @@ -42,7 +39,7 @@ public CommitResponse execute() {
LocalDateTime dateTime = user.getLastCommitUpdateTime();

if (dateTime == null) {
dateTime = LocalDateTime.of(2024, 7, 1, 0, 0, 0);
dateTime = LocalDateTime.now().minusMonths(3);
}

try {
Expand All @@ -56,11 +53,7 @@ public CommitResponse execute() {

for (String fullName : repos) {
CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
try {
gitHubService.countCommits(fullName, gitHubId, finalDateTime);
} catch (IOException e) {
throw new ApiException(ErrorStatus._GIT_URL_INCORRECT);
}
gitHubService.countCommits(fullName, gitHubId, finalDateTime);
}, executor);
futures.add(voidCompletableFuture);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
package com.leets.commitatobe.domain.commit.service;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
Expand All @@ -15,15 +10,21 @@
import java.util.List;
import java.util.Map;
import java.util.concurrent.ForkJoinPool;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.ExchangeStrategies;
import org.springframework.web.reactive.function.client.WebClient;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

import reactor.core.publisher.Mono;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

Expand All @@ -34,14 +35,21 @@ public class GitHubService {
private final String GITHUB_API_URL = "https://api.github.com";
private String AUTH_TOKEN;
private final Map<LocalDateTime, Integer> commitsByDate = new HashMap<>();
private final WebClient webClient = WebClient.builder()
.baseUrl(GITHUB_API_URL)
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
.defaultHeader(HttpHeaders.ACCEPT, "application/vnd.github+json")
.exchangeStrategies(ExchangeStrategies.builder()
.codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(1024 * 1024)) // 1MB
.build())
.build();

@Value("${server-uri}")
private String SERVER_URI;

// GitHub repository 이름 저장
public List<String> fetchRepos(String gitHubUsername) throws IOException {
URL url = new URL(GITHUB_API_URL + "/user/repos?type=all&sort=pushed&per_page=100");
HttpURLConnection connection = getConnection(url);
JsonArray repos = fetchJsonArray(connection);
public List<String> fetchRepos(String gitHubUsername) {
JsonArray repos = getConnection("/user/repos?type=all&sort=pushed&per_page=100");

if (repos == null) {
return new ArrayList<>();
Expand All @@ -56,26 +64,18 @@ public List<String> fetchRepos(String gitHubUsername) throws IOException {
ForkJoinPool forkJoinPool = new ForkJoinPool(Runtime.getRuntime().availableProcessors());
return forkJoinPool.submit(() ->
repoFullNames.parallelStream()
.filter(fullName -> {
try {
return isContributor(fullName, gitHubUsername);
} catch (IOException e) {
return false;
}
})
.collect(Collectors.toList())
.filter(fullName -> isContributor(fullName, gitHubUsername))
.toList()
).join();
}

// 자신이 해당 repository의 기여자 인지 확인
private boolean isContributor(String fullName, String gitHubUsername) throws IOException {
private boolean isContributor(String fullName, String gitHubUsername) {
if (fullName.contains(gitHubUsername)) {
return true;
}

URL url = new URL(GITHUB_API_URL + "/repos/" + fullName + "/contributors");
HttpURLConnection connection = getConnection(url);
JsonArray contributors = fetchJsonArray(connection);
JsonArray contributors = getConnection("/repos/" + fullName + "/contributors");

if (contributors == null) {
return false;
Expand All @@ -94,14 +94,18 @@ private boolean isContributor(String fullName, String gitHubUsername) throws IOE
}

// commit을 일별로 정리
public void countCommits(String fullName, String gitHubUsername, LocalDateTime date) throws IOException {
public void countCommits(String fullName, String gitHubUsername, LocalDateTime date) {
int page = 1;
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

while (true) {
URL url = new URL(GITHUB_API_URL + "/repos/" + fullName + "/commits?page=" + page + "&per_page=100");
HttpURLConnection connection = getConnection(url);
JsonArray commits = fetchJsonArray(connection);
JsonArray commits;

try {
commits = getConnection("/repos/" + fullName + "/commits?page=" + page + "&per_page=100");
} catch (Exception e) {
return;
}

if (commits == null || commits.isEmpty()) {
return;
Expand Down Expand Up @@ -134,49 +138,23 @@ public void countCommits(String fullName, String gitHubUsername, LocalDateTime d
}

// http 연결
private HttpURLConnection getConnection(URL url) throws IOException {
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Authorization", "token " + AUTH_TOKEN);
connection.setRequestProperty("Accept", "application/vnd.github.v3+json");

// AUTH_TOKEN 유효한지 확인
int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) {
// AUTH_TOKEN이 유효하지 않으면 리다이렉트
URL loginUrl = new URL(SERVER_URI + "/login/github");
connection = (HttpURLConnection)loginUrl.openConnection();
connection.setInstanceFollowRedirects(true);
connection.connect();
}

return connection;
}

// 응답을 jsonObject로 반환
private JsonObject fetchJsonObject(HttpURLConnection connection) throws IOException {
int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
try (BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
return JsonParser.parseReader(in).getAsJsonObject();
}
} else {
System.err.println(responseCode);
return null;
}
}

// 응답을 JsonArray로 반환
private JsonArray fetchJsonArray(HttpURLConnection connection) throws IOException {
int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
try (BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
return JsonParser.parseReader(in).getAsJsonArray();
}
} else {
System.err.println(responseCode);
return null;
}
private JsonArray getConnection(String url) {
Mono<JsonArray> response = webClient.get()
.uri(url)
.header(HttpHeaders.AUTHORIZATION, "Bearer " + AUTH_TOKEN)
.retrieve()
.onStatus(status -> status == HttpStatus.UNAUTHORIZED, clientResponse ->
// AUTH_TOKEN이 유효하지 않으면 리다이렉트
webClient.get()
.uri(SERVER_URI + "/login/github")
.retrieve()
.bodyToMono(Void.class)
.then(Mono.error(new RuntimeException("Unauthorized")))
)
.bodyToMono(String.class)
.map(res -> JsonParser.parseString(res).getAsJsonArray());

return response.block();
}

// commit 시간 추출
Expand Down
7 changes: 4 additions & 3 deletions src/main/resources/application-dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ spring:
jpa:
show-sql: true
hibernate:
ddl-auto: create
ddl-auto: update
properties:
hibernate:
format_sql: true
use_sql_comments: true
format_sql: false
use_sql_comments: false
show_sql: false
defer-datasource-initialization: true

sql:
Expand Down
7 changes: 4 additions & 3 deletions src/main/resources/application-prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ spring:
jpa:
show-sql: true
hibernate:
ddl-auto: create
ddl-auto: update
properties:
hibernate:
format_sql: true
use_sql_comments: true
format_sql: false
use_sql_comments: false
show_sql: false
defer-datasource-initialization: true

sql:
Expand Down

0 comments on commit c17f296

Please sign in to comment.