-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: ✏️ 매일 정기 푸시 알림 배치 성능 개선 (#137)
* chore: application-domain.yml jdbc url query parameter 수정 * style: step config 파일 삭제 -> job config에 통합 * style: dto 패키지 경로 common 하위로 수정 * fix: notificaion batch insert ; 제거 && batch size 1000으로 수정 * feat: where 함수형 인터페이스 정의 * feat: where expression 정의 * feat: order expression 상수 정의 * feat: expression 상수 정의 * feat: querydsl_no_offset_options 추상 클래스 정의 * feat: no offset의 타입이 number인 경우를 위한 구현체 정의 * rename: 정적 팩토리 메서드 주석에 주의 사항 추가 * feat: no offset의 타입이 string인 경우를 위한 구현체 정의 * feat: querydsl_paging_item_reader 추가 * feat: querydsl_no_offset_paging_item_reader 정의 * fix: repository_item_reader -> querydsl_no_offset_paging_item_reader 변경 * fix: @job_scope 및 @step_scope 추가 && step reader 수정 * fix: device_token_custom_repository 제거 * test: device_token_cutome_repository 테스트 제거 * style: device_token_owner 경로 domain -> batch로 수정 * test: redisson 테스트 ignore 처리 * chore: batch application db connection pool 2개로 수정
- Loading branch information
1 parent
4f51e7b
commit 381f3ea
Showing
27 changed files
with
745 additions
and
328 deletions.
There are no files selected for viewing
3 changes: 1 addition & 2 deletions
3
.../batch/dto/DailySpendingNotification.java → ...common/dto/DailySpendingNotification.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
.../domains/device/dto/DeviceTokenOwner.java → ...ay/batch/common/dto/DeviceTokenOwner.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
69 changes: 69 additions & 0 deletions
69
...ch/src/main/java/kr/co/pennyway/batch/common/reader/QuerydslNoOffsetPagingItemReader.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package kr.co.pennyway.batch.common.reader; | ||
|
||
import com.querydsl.jpa.JPQLQuery; | ||
import com.querydsl.jpa.impl.JPAQuery; | ||
import com.querydsl.jpa.impl.JPAQueryFactory; | ||
import jakarta.persistence.EntityManagerFactory; | ||
import jakarta.persistence.EntityTransaction; | ||
import kr.co.pennyway.batch.common.reader.options.QuerydslNoOffsetOptions; | ||
import org.springframework.util.ClassUtils; | ||
import org.springframework.util.CollectionUtils; | ||
|
||
import java.util.function.Function; | ||
|
||
public class QuerydslNoOffsetPagingItemReader<T> extends QuerydslPagingItemReader<T> { | ||
private QuerydslNoOffsetOptions<T> options; | ||
|
||
private QuerydslNoOffsetPagingItemReader() { | ||
super(); | ||
setName(ClassUtils.getShortName(QuerydslNoOffsetPagingItemReader.class)); | ||
} | ||
|
||
public QuerydslNoOffsetPagingItemReader(EntityManagerFactory entityManagerFactory, | ||
int pageSize, | ||
QuerydslNoOffsetOptions<T> options, | ||
Function<JPAQueryFactory, JPAQuery<T>> queryFunction) { | ||
super(entityManagerFactory, pageSize, queryFunction); | ||
setName(ClassUtils.getShortName(QuerydslNoOffsetPagingItemReader.class)); | ||
this.options = options; | ||
} | ||
|
||
@Override | ||
@SuppressWarnings("unchecked") | ||
protected void doReadPage() { | ||
|
||
EntityTransaction tx = getTxOrNull(); | ||
|
||
JPQLQuery<T> query = createQuery().limit(getPageSize()); | ||
|
||
initResults(); | ||
|
||
fetchQuery(query, tx); | ||
|
||
resetCurrentIdIfNotLastPage(); | ||
} | ||
|
||
@Override | ||
protected JPAQuery<T> createQuery() { | ||
JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager); | ||
JPAQuery<T> query = queryFunction.apply(queryFactory); | ||
options.initKeys(query, getPage()); // 제일 첫번째 페이징시 시작해야할 ID 찾기 | ||
|
||
return options.createQuery(query, getPage()); | ||
} | ||
|
||
private void resetCurrentIdIfNotLastPage() { | ||
if (isNotEmptyResults()) { | ||
options.resetCurrentId(getLastItem()); | ||
} | ||
} | ||
|
||
// 조회결과가 Empty이면 results에 null이 담긴다 | ||
private boolean isNotEmptyResults() { | ||
return !CollectionUtils.isEmpty(results) && results.get(0) != null; | ||
} | ||
|
||
private T getLastItem() { | ||
return results.get(results.size() - 1); | ||
} | ||
} |
141 changes: 141 additions & 0 deletions
141
...yway-batch/src/main/java/kr/co/pennyway/batch/common/reader/QuerydslPagingItemReader.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
package kr.co.pennyway.batch.common.reader; | ||
|
||
import com.querydsl.jpa.JPQLQuery; | ||
import com.querydsl.jpa.impl.JPAQuery; | ||
import com.querydsl.jpa.impl.JPAQueryFactory; | ||
import jakarta.persistence.EntityManager; | ||
import jakarta.persistence.EntityManagerFactory; | ||
import jakarta.persistence.EntityTransaction; | ||
import org.springframework.batch.item.database.AbstractPagingItemReader; | ||
import org.springframework.dao.DataAccessResourceFailureException; | ||
import org.springframework.util.ClassUtils; | ||
import org.springframework.util.CollectionUtils; | ||
|
||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.concurrent.CopyOnWriteArrayList; | ||
import java.util.function.Function; | ||
|
||
/** | ||
* Querydsl을 이용한 커스텀 PagingItemReader | ||
* <p> | ||
* <a href="https://github.com/jojoldu/spring-batch-querydsl">이동욱님 깃헙 </a> 참고 | ||
*/ | ||
public class QuerydslPagingItemReader<T> extends AbstractPagingItemReader<T> { | ||
|
||
protected final Map<String, Object> jpaPropertyMap = new HashMap<>(); | ||
protected EntityManagerFactory entityManagerFactory; | ||
protected EntityManager entityManager; | ||
protected Function<JPAQueryFactory, JPAQuery<T>> queryFunction; | ||
protected boolean transacted = true; // default value | ||
|
||
protected QuerydslPagingItemReader() { | ||
setName(ClassUtils.getShortName(QuerydslPagingItemReader.class)); | ||
} | ||
|
||
public QuerydslPagingItemReader(EntityManagerFactory entityManagerFactory, | ||
int pageSize, | ||
Function<JPAQueryFactory, JPAQuery<T>> queryFunction) { | ||
this(entityManagerFactory, pageSize, true, queryFunction); | ||
} | ||
|
||
public QuerydslPagingItemReader(EntityManagerFactory entityManagerFactory, | ||
int pageSize, | ||
boolean transacted, | ||
Function<JPAQueryFactory, JPAQuery<T>> queryFunction) { | ||
this(); | ||
this.entityManagerFactory = entityManagerFactory; | ||
this.queryFunction = queryFunction; | ||
setPageSize(pageSize); | ||
setTransacted(transacted); | ||
} | ||
|
||
/** | ||
* Reader의 트랜잭션격리 옵션 <br/> | ||
* - false: 격리 시키지 않고, Chunk 트랜잭션에 의존한다 <br/> | ||
* (hibernate.default_batch_fetch_size 옵션 사용가능) <br/> | ||
* - true: 격리 시킨다 <br/> | ||
* (Reader 조회 결과를 삭제하고 다시 조회했을때 삭제된게 반영되고 조회되길 원할때 사용한다.) | ||
*/ | ||
public void setTransacted(boolean transacted) { | ||
this.transacted = transacted; | ||
} | ||
|
||
@Override | ||
protected void doOpen() throws Exception { | ||
super.doOpen(); | ||
|
||
entityManager = entityManagerFactory.createEntityManager(jpaPropertyMap); | ||
if (entityManager == null) { | ||
throw new DataAccessResourceFailureException("Unable to obtain an EntityManager"); | ||
} | ||
} | ||
|
||
@Override | ||
@SuppressWarnings("unchecked") | ||
protected void doReadPage() { | ||
EntityTransaction tx = getTxOrNull(); | ||
|
||
JPQLQuery<T> query = createQuery() | ||
.offset(getPage() * getPageSize()) | ||
.limit(getPageSize()); | ||
|
||
initResults(); | ||
|
||
fetchQuery(query, tx); | ||
} | ||
|
||
protected EntityTransaction getTxOrNull() { | ||
if (transacted) { | ||
EntityTransaction tx = entityManager.getTransaction(); | ||
tx.begin(); | ||
|
||
entityManager.flush(); | ||
entityManager.clear(); | ||
return tx; | ||
} | ||
|
||
return null; | ||
} | ||
|
||
protected JPAQuery<T> createQuery() { | ||
JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager); | ||
return queryFunction.apply(queryFactory); | ||
} | ||
|
||
protected void initResults() { | ||
if (CollectionUtils.isEmpty(results)) { | ||
results = new CopyOnWriteArrayList<>(); | ||
} else { | ||
results.clear(); | ||
} | ||
} | ||
|
||
/** | ||
* where 의 조건은 id max/min 을 이용한 제한된 범위를 가지게 한다 | ||
* | ||
* @param query | ||
* @param tx | ||
*/ | ||
protected void fetchQuery(JPQLQuery<T> query, EntityTransaction tx) { | ||
if (transacted) { | ||
results.addAll(query.fetch()); | ||
if (tx != null) { | ||
tx.commit(); | ||
} | ||
} else { | ||
List<T> queryResult = query.fetch(); | ||
for (T entity : queryResult) { | ||
entityManager.detach(entity); | ||
results.add(entity); | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
protected void doClose() throws Exception { | ||
entityManager.close(); | ||
super.doClose(); | ||
} | ||
} |
39 changes: 39 additions & 0 deletions
39
pennyway-batch/src/main/java/kr/co/pennyway/batch/common/reader/expression/Expression.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package kr.co.pennyway.batch.common.reader.expression; | ||
|
||
import com.querydsl.core.types.OrderSpecifier; | ||
import com.querydsl.core.types.dsl.BooleanExpression; | ||
import com.querydsl.core.types.dsl.NumberPath; | ||
import com.querydsl.core.types.dsl.StringPath; | ||
|
||
public enum Expression { | ||
ASC(WhereExpression.GT, OrderExpression.ASC), | ||
DESC(WhereExpression.LT, OrderExpression.DESC); | ||
|
||
private final WhereExpression where; | ||
private final OrderExpression order; | ||
|
||
Expression(WhereExpression where, OrderExpression order) { | ||
this.where = where; | ||
this.order = order; | ||
} | ||
|
||
public boolean isAsc() { | ||
return this == ASC; | ||
} | ||
|
||
public BooleanExpression where(StringPath id, int page, String currentId) { | ||
return where.expression(id, page, currentId); | ||
} | ||
|
||
public <N extends Number & Comparable<?>> BooleanExpression where(NumberPath<N> id, int page, N currentId) { | ||
return where.expression(id, page, currentId); | ||
} | ||
|
||
public OrderSpecifier<String> order(StringPath id) { | ||
return isAsc() ? id.asc() : id.desc(); | ||
} | ||
|
||
public <N extends Number & Comparable<?>> OrderSpecifier<N> order(NumberPath<N> id) { | ||
return isAsc() ? id.asc() : id.desc(); | ||
} | ||
} |
5 changes: 5 additions & 0 deletions
5
...ay-batch/src/main/java/kr/co/pennyway/batch/common/reader/expression/OrderExpression.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package kr.co.pennyway.batch.common.reader.expression; | ||
|
||
public enum OrderExpression { | ||
ASC, DESC | ||
} |
35 changes: 35 additions & 0 deletions
35
...ay-batch/src/main/java/kr/co/pennyway/batch/common/reader/expression/WhereExpression.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package kr.co.pennyway.batch.common.reader.expression; | ||
|
||
import com.querydsl.core.types.dsl.BooleanExpression; | ||
import com.querydsl.core.types.dsl.NumberPath; | ||
import com.querydsl.core.types.dsl.StringPath; | ||
|
||
/** | ||
* 첫페이지 조회시에는 >=, <= | ||
* 두번째 페이지부터는 >, < | ||
*/ | ||
public enum WhereExpression { | ||
GT( | ||
(id, page, currentId) -> page == 0 ? id.goe(currentId) : id.gt(currentId), | ||
(id, page, currentId) -> page == 0 ? id.goe(currentId) : id.gt(currentId)), | ||
LT( | ||
(id, page, currentId) -> page == 0 ? id.loe(currentId) : id.lt(currentId), | ||
(id, page, currentId) -> page == 0 ? id.loe(currentId) : id.lt(currentId) | ||
); | ||
|
||
private final WhereStringFunction string; | ||
private final WhereNumberFunction number; | ||
|
||
WhereExpression(WhereStringFunction string, WhereNumberFunction number) { | ||
this.string = string; | ||
this.number = number; | ||
} | ||
|
||
public BooleanExpression expression(StringPath id, int page, String currentId) { | ||
return this.string.apply(id, page, currentId); | ||
} | ||
|
||
public <N extends Number & Comparable<?>> BooleanExpression expression(NumberPath<N> id, int page, N currentId) { | ||
return this.number.apply(id, page, currentId); | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
...atch/src/main/java/kr/co/pennyway/batch/common/reader/expression/WhereNumberFunction.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package kr.co.pennyway.batch.common.reader.expression; | ||
|
||
import com.querydsl.core.types.dsl.BooleanExpression; | ||
import com.querydsl.core.types.dsl.NumberPath; | ||
|
||
@FunctionalInterface | ||
public interface WhereNumberFunction<N extends Number & Comparable<?>> { | ||
BooleanExpression apply(NumberPath<N> id, int page, N currentId); | ||
|
||
} |
9 changes: 9 additions & 0 deletions
9
...atch/src/main/java/kr/co/pennyway/batch/common/reader/expression/WhereStringFunction.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package kr.co.pennyway.batch.common.reader.expression; | ||
|
||
import com.querydsl.core.types.dsl.BooleanExpression; | ||
import com.querydsl.core.types.dsl.StringPath; | ||
|
||
@FunctionalInterface | ||
public interface WhereStringFunction { | ||
BooleanExpression apply(StringPath id, int page, String currentId); | ||
} |
Oops, something went wrong.