Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโ€™ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hang-Log Prod 2.2.0 Release #783

Merged
merged 17 commits into from
Jan 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
98b4798
MDC๋ฅผ ์‚ฌ์šฉํ•ด ๋กœ๊ทธ์— ํด๋ผ์ด์–ธํŠธ REQUEST ์•„์ด๋””๊ฐ€ ์ถœ๋ ฅ๋˜๊ฒŒ ๋ณ€๊ฒฝ (#737)
hgo641 Nov 2, 2023
aaf08ac
DB Replication ์‹œ P6spy ๋กœ๊น…์œผ๋กœ ์ธํ•˜์—ฌ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ (#741)
mcodnjs Nov 6, 2023
dd39856
refactor: ์—ฐ๊ด€๊ด€๊ณ„ ๋ ˆ๊ฑฐ์‹œ ์‚ญ์ œ (#746)
LJW25 Nov 6, 2023
55227a6
์ปค์Šคํ…€ ์˜ˆ์™ธ ์ฝ”๋“œ ๋ฌธ์„œํ™” (#744)
mcodnjs Nov 6, 2023
ce24ac9
๋™๊ธฐ, ๋น„๋™๊ธฐ ์˜ˆ์™ธ ํ•ธ๋“ค๋ง ์‹œ MDC๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์Šฌ๋ž™ ์˜ˆ์™ธ ์•Œ๋ฆผ (#749)
mcodnjs Nov 14, 2023
1f59ee8
RefreshToken์„ Redis๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ (#750)
jjongwa Nov 15, 2023
7017f5c
์ข‹์•„์š” ์ˆ˜ ๋ฐ ์ข‹์•„์š” ๋ณ€๊ฒฝ ์ด๋ ฅ ์บ์‹ฑ (#752)
jjongwa Nov 20, 2023
d837c55
Update README.md
hgo641 Dec 9, 2023
cda070c
feat: react query version up (#760)
ashleysyheo Dec 9, 2023
9c519ed
refactor/#761: suspense ์‚ฌ์šฉํ•˜๋Š” useQuery๋ฅผ useSuspenseQuery๋กœ ๊ต์ฒด (#762)
ashleysyheo Dec 9, 2023
e704d57
๋„์‹œ ์ค‘๋ณต ์กฐํšŒ ์˜ค๋ฅ˜ ์ˆ˜์ • (#765)
LJW25 Dec 23, 2023
61d4aa6
QueryKey ๋ถˆ์ผ์น˜๋กœ ์ธํ•ด ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ (#767)
dladncks1217 Dec 23, 2023
a5aef12
queryKey๋ถˆ์ผ์น˜๋กœ ์ธํ•œ myTrip ์ƒ์„ธ์ •๋ณด ํŽ˜์ด์ง€ ์˜ค๋ฅ˜ ์ˆ˜์ • (#769)
dladncks1217 Dec 24, 2023
c6eca9b
ํ”„๋กœ๋•์…˜ ์—๋Ÿฌ ์ถ”์  ๊ฐœ์„ ์„ ์œ„ํ•œ Sentry ํ™˜๊ฒฝ ๊ตฌ์ถ• (#770)
dladncks1217 Dec 27, 2023
c7f3a04
kakao ์‚ฌ์šฉ์ž ์ •๋ณด ๋ฐ›์•„์˜ค๋Š” response ๋ณ€๊ฒฝ (#772)
mcodnjs Jan 4, 2024
c9cc187
๋””์ž์ธ์‹œ์Šคํ…œ ์ปดํฌ๋„ŒํŠธ ๊ฐœ์„ ์— ์˜ํ•œ ์ฝ”๋“œ ์ˆ˜์ • (Carousel) (#776)
dladncks1217 Jan 11, 2024
abf7d87
Yarn Berry + Workspace ๋„์ž…, ํ”„๋ก ํŠธ์—”๋“œ ํŒจํ‚ค์ง€ ๋ชจ๋…ธ๋ ˆํฌ ์ „ํ™˜ (ํ–‰๋ก ์„œ๋น„์Šค + ๋””์ž์ธ์‹œ์Šคํ…œ + ์–ด๋“œ๋ฏผ ํ†ตโ€ฆ
dladncks1217 Jan 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
18 changes: 11 additions & 7 deletions .github/workflows/frontend-e2e-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,23 @@ on:
branches:
- develop
paths:
- frontend/**
- .github/**
- frontend-monorepo/packages/hanglog-service/**

defaults:
run:
working-directory: frontend

working-directory: frontend-monorepo/packages/hanglog-service
jobs:
run-dev:
if: contains(github.event.pull_request.labels.*.name, 'FE')
if: contains(github.event.pull_request.labels.*.name, 'FE-Service')
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3

- name: build design-system
run: yarn run build:design-system

- name: Create env file
run: |
touch .env
Expand All @@ -28,13 +30,15 @@ jobs:
cat .env

- name: Cypress run
uses: cypress-io/github-action@v5
uses: cypress-io/github-action@v6
with:
browser: chrome
start: npm run serve:dev
start: yarn run serve:dev
wait-on: "http://localhost:3000"
record: false
working-directory: ./frontend
working-directory: ./frontend-monorepo/packages/hanglog-service
install-command: yarn install
command: yarn run --binaries-only cypress run
env:
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down
10 changes: 3 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,26 +39,22 @@

### ํ”„๋ก ํŠธ์—”๋“œ

<img width="70%" alt="แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2023-10-18 แ„‹แ…ฉแ„’แ…ฎ 5 32 31" src="https://github.com/woowacourse-teams/2023-hang-log/assets/45068522/db073e79-a6cc-4bda-844b-58ac17d95e90">
<img width="80%" alt="แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2024-01-22 แ„‹แ…ฉแ„’แ…ฎ 11 43 48" src="https://github.com/woowacourse-teams/2023-hang-log/assets/45068522/9284b40e-c931-4f04-ac78-9c97a548338e">

### ๋ฐฑ์—”๋“œ

<img width="70%" alt="แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2023-10-18 แ„‹แ…ฉแ„’แ…ฎ 5 32 13" src="https://github.com/woowacourse-teams/2023-hang-log/assets/45068522/9cb02663-f540-4659-8d35-6fbde5c3cf2d">
<img width="80%" alt="แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2024-01-22 แ„‹แ…ฉแ„’แ…ฎ 11 43 16" src="https://github.com/woowacourse-teams/2023-hang-log/assets/45068522/b64dde4f-9467-4427-a361-e2301657efa4">

### ์ธํ”„๋ผ

<img width="70%" alt="แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2023-10-18 แ„‹แ…ฉแ„’แ…ฎ 5 32 49" src="https://github.com/woowacourse-teams/2023-hang-log/assets/45068522/15309fe5-bda5-4793-8e65-af52e7b4a4e9">
<img width="80%" alt="แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2024-01-22 แ„‹แ…ฉแ„’แ…ฎ 11 44 27" src="https://github.com/woowacourse-teams/2023-hang-log/assets/45068522/d0e03eb4-e159-405b-b22e-3d3fa79b99b7">

<br>

## ์„œ๋น„์Šค ์š”์ฒญ ํ๋ฆ„๋„

![์„œ๋น„์Šค์š”์ฒญํ๋ฆ„๋„](https://github.com/woowacourse-teams/2023-hang-log/assets/102305630/dc9c1562-068d-4c73-84ef-d93e9051b679)

## ์ธํ”„๋ผ ๊ตฌ์กฐ๋„

![์ธํ”„๋ผ ๊ตฌ์กฐ๋„](https://github.com/woowacourse-teams/2023-hang-log/assets/102305630/656caaa3-125d-48ed-b996-e2858be4d36c)

## CI/CD

![CICD](https://github.com/woowacourse-teams/2023-hang-log/assets/64852591/a55b3a1c-ce12-49d2-b4da-5b394c4de6c1)
Expand Down
2 changes: 1 addition & 1 deletion backend/backend-submodule
6 changes: 6 additions & 0 deletions backend/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
implementation 'com.amazonaws:aws-java-sdk-s3:1.12.528'
implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.0'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'

testImplementation 'io.rest-assured:rest-assured:5.3.1'
testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'
Expand All @@ -43,10 +45,14 @@ dependencies {

annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation "org.junit.jupiter:junit-jupiter:5.8.1"
testImplementation "org.testcontainers:testcontainers:1.17.6"
testImplementation "org.testcontainers:junit-jupiter:1.17.6"

implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'io.micrometer:micrometer-registry-prometheus'

implementation 'com.github.maricn:logback-slack-appender:1.6.1'

implementation 'org.flywaydb:flyway-core'
implementation 'org.flywaydb:flyway-mysql'
Expand Down
11 changes: 11 additions & 0 deletions backend/docker/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,14 @@ services:
- ./db/mysql/data:/var/lib/mysql
- ./db/mysql/config:/etc/mysql/conf.d
- ./db/mysql/init:/docker-entrypoint-initdb.d

redis:
image: redis:alpine
command: redis-server --port 6379
container_name: hanglog_redis
hostname: root
labels:
- "name=redis"
- "mode=standalone"
ports:
- 16379:6379
3 changes: 3 additions & 0 deletions backend/src/docs/asciidoc/docs.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
| ์„œ๋ฒ„ ์—๋Ÿฌ
|===

=== Exception codes
[[exception-codes]]
include::{snippets}/exception-code-controller-test/get-exception-codes/exception-response-fields.adoc[]

== ์—ฌํ–‰ API

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,14 @@
import hanglog.community.dto.response.CommunityTripResponse;
import hanglog.community.dto.response.RecommendTripListResponse;
import hanglog.global.exception.BadRequestException;
import hanglog.like.domain.LikeCount;
import hanglog.like.domain.LikeInfo;
import hanglog.like.domain.MemberLike;
import hanglog.like.dto.LikeElement;
import hanglog.like.dto.LikeElements;
import hanglog.like.repository.LikeRepository;
import hanglog.like.domain.repository.LikeCountRepository;
import hanglog.like.domain.repository.LikeRepository;
import hanglog.like.domain.repository.MemberLikeRepository;
import hanglog.trip.domain.Trip;
import hanglog.trip.domain.repository.TripCityRepository;
import hanglog.trip.domain.repository.TripRepository;
Expand All @@ -25,6 +30,7 @@
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Pageable;
Expand All @@ -45,6 +51,8 @@ public class CommunityService {
private final CityRepository cityRepository;
private final RecommendStrategies recommendStrategies;
private final PublishedTripRepository publishedTripRepository;
private final LikeCountRepository likeCountRepository;
private final MemberLikeRepository memberLikeRepository;

@Transactional(readOnly = true)
public CommunityTripListResponse getCommunityTripsByPage(final Accessor accessor, final Pageable pageable) {
Expand Down Expand Up @@ -119,20 +127,31 @@ public TripDetailResponse getTripDetail(final Accessor accessor, final Long trip
final LocalDateTime publishedDate = publishedTripRepository.findByTripId(tripId)
.orElseThrow(() -> new BadRequestException(NOT_FOUND_TRIP_ID))
.getCreatedAt();
final LikeElements likeElements = new LikeElements(likeRepository.findLikeCountAndIsLikeByTripIds(
accessor.getMemberId(),
List.of(tripId)
));
final Map<Long, LikeInfo> likeInfoByTrip = likeElements.toLikeMap();

final LikeElement likeElement = getLikeElement(accessor.getMemberId(), tripId);
final Boolean isWriter = trip.isWriter(accessor.getMemberId());

return TripDetailResponse.publishedTrip(
trip,
cities,
isWriter,
isLike(likeInfoByTrip, tripId),
getLikeCount(likeInfoByTrip, tripId),
likeElement.isLike(),
likeElement.getLikeCount(),
publishedDate
);
}

private LikeElement getLikeElement(final Long memberId, final Long tripId) {
final Optional<LikeCount> likeCount = likeCountRepository.findById(tripId);
final Optional<MemberLike> memberLike = memberLikeRepository.findById(memberId);
if (likeCount.isPresent() && memberLike.isPresent()) {
final Map<Long, Boolean> tripLikeStatusMap = memberLike.get().getLikeStatusForTrip();
if (tripLikeStatusMap.containsKey(tripId)) {
return new LikeElement(tripId, likeCount.get().getCount(), tripLikeStatusMap.get(tripId));
}
return new LikeElement(tripId, likeCount.get().getCount(), false);
}
return likeRepository.findLikeCountAndIsLikeByTripId(memberId, tripId)
.orElseGet(() -> new LikeElement(tripId, 0, false));
}
}
3 changes: 1 addition & 2 deletions backend/src/main/java/hanglog/expense/domain/Expense.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

import hanglog.category.domain.Category;
import hanglog.global.BaseEntity;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
Expand Down Expand Up @@ -37,7 +36,7 @@ public class Expense extends BaseEntity {
@Embedded
private Amount amount;

@ManyToOne(fetch = LAZY, cascade = CascadeType.PERSIST)
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "category_id", nullable = false)
private Category category;

Expand Down
30 changes: 30 additions & 0 deletions backend/src/main/java/hanglog/global/config/AsyncConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package hanglog.global.config;

import hanglog.global.decorator.MdcTaskDecorator;
import hanglog.global.exception.AsyncExceptionHandler;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {

@Bean
public TaskExecutor taskExecutor() {
final ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(8);
taskExecutor.setTaskDecorator(new MdcTaskDecorator());
taskExecutor.setThreadNamePrefix("async-task-");
return taskExecutor;
}

@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncExceptionHandler();
}
}
23 changes: 23 additions & 0 deletions backend/src/main/java/hanglog/global/config/RedisConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package hanglog.global.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;

@Configuration
@EnableRedisRepositories
public class RedisConfig {

@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;

@Bean
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory(host, port);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package hanglog.global.decorator;

import java.util.Map;
import org.slf4j.MDC;
import org.springframework.core.task.TaskDecorator;

public class MdcTaskDecorator implements TaskDecorator {

@Override
public Runnable decorate(final Runnable runnable) {
final Map<String, String> copyOfContextMap = MDC.getCopyOfContextMap();
return () -> {
if (copyOfContextMap != null) {
MDC.setContextMap(copyOfContextMap);
}
runnable.run();
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import java.lang.reflect.Method;
import lombok.RequiredArgsConstructor;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
Expand All @@ -11,6 +12,7 @@
public class ConnectionProxyHandler implements MethodInterceptor {

private static final String JDBC_PREPARE_STATEMENT_METHOD_NAME = "prepareStatement";
private static final String HIKARI_CONNECTION_NAME = "HikariProxyConnection";

private final Object connection;
private final LoggingForm loggingForm;
Expand All @@ -30,7 +32,14 @@ public Object invoke(@Nonnull final MethodInvocation invocation) throws Throwabl
}

private boolean hasPreparedStatementInvoked(final MethodInvocation invocation) {
return invocation.getMethod().getName().equals(JDBC_PREPARE_STATEMENT_METHOD_NAME);
final Object targetObject = invocation.getThis();
if (targetObject == null) {
return false;
}
final Class<?> targetClass = targetObject.getClass();
final Method targetMethod = invocation.getMethod();
return targetClass.getName().contains(HIKARI_CONNECTION_NAME) &&
targetMethod.getName().equals(JDBC_PREPARE_STATEMENT_METHOD_NAME);
}

private boolean hasConnection(final Object result) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package hanglog.global.exception;

import java.lang.reflect.Method;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {

@Override
public void handleUncaughtException(final Throwable ex, final Method method, final Object... params) {
log.error(ex.getMessage(), ex);
}
}
9 changes: 9 additions & 0 deletions backend/src/main/java/hanglog/global/filter/MdcKey.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package hanglog.global.filter;

public enum MdcKey {
REQUEST_ID,
REQUEST_METHOD,
REQUEST_URI,
REQUEST_TIME,
REQUEST_IP;
}
45 changes: 45 additions & 0 deletions backend/src/main/java/hanglog/global/filter/MdcLoggingFilter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package hanglog.global.filter;

import static hanglog.global.filter.MdcKey.REQUEST_ID;
import static hanglog.global.filter.MdcKey.REQUEST_IP;
import static hanglog.global.filter.MdcKey.REQUEST_METHOD;
import static hanglog.global.filter.MdcKey.REQUEST_TIME;
import static hanglog.global.filter.MdcKey.REQUEST_URI;

import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.UUID;
import org.slf4j.MDC;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class MdcLoggingFilter implements Filter {

@Override
public void doFilter(
final ServletRequest request,
final ServletResponse response,
final FilterChain chain
) throws IOException, ServletException {
setMdc((HttpServletRequest) request);
chain.doFilter(request, response);
MDC.clear();
}

private void setMdc(final HttpServletRequest request) {
MDC.put(REQUEST_ID.name(), UUID.randomUUID().toString());
MDC.put(REQUEST_METHOD.name(), request.getMethod());
MDC.put(REQUEST_URI.name(), request.getRequestURI());
MDC.put(REQUEST_TIME.name(), LocalDateTime.now().toString());
MDC.put(REQUEST_IP.name(), request.getRemoteAddr());
}
}
Loading