20240219 (월) 대용량 트래픽 프로젝트 - 동시성 제어 프로젝트 4일차

2024. 2. 19. 20:47TIL

오늘 진행한 것

1. Category페이지네이션 작성

2. CreateTicketTest 코드작성

 

우선

1. Category페이지네이션 작성

처음엔

CategoryResponse 안에 Goods리스트를 같이 포함하여 반환할까 생각해서 Response에 goodsList를 추가하였다.

하지만 승환님의 의견에 따라 우리의 와이어프레임기준으로는 goodsList를 반환하는건 따로 구현이 되어있고,

https://www.notion.so/A05-e753a98e639a4c3f9403b9d1e9623e8a?pvs=4#da0eaf516d7f42b6a163b4ee29f5d6d9

(위는 우리가 작성한 S.A.의 와이어프레임 사진 링크)

카테고리는 그냥 링크의 역할만 해주면 될것 같아서 Response에서 goodsList를 빼기로하였다.

class CategoryRepositoryImpl : QueryDslSupport(), CustomCategoryRepository {

    private val category = QCategory.category
    override fun findByPageable(pageable: Pageable): Page<Category> {

        val totalCount = queryFactory.select(category.count()).from(category).fetchOne() ?: 0L

        val contents = queryFactory.select(category)
            .offset(pageable.offset)
            .limit(pageable.pageSize.toLong())
            .orderBy(*getOrderSpecifier(pageable, category))
            .fetch()

        return PageImpl(contents, pageable, totalCount)
    }

    private fun getOrderSpecifier(pageable: Pageable, path: EntityPathBase<*>): Array<OrderSpecifier<*>> {
        val pathBuilder = PathBuilder(path.type, path.metadata)

        return pageable.sort.toList().map { order ->
            OrderSpecifier(
                if (order.isAscending) Order.ASC else Order.DESC,
                pathBuilder.get(order.property) as Expression<Comparable<*>>
            )
        }.toTypedArray()
    }
}

하지만 조금더 생각해보면 사실 카테고리에 페이지네이션도 필요 없는거 아닌가 생각이 들긴한다..

일단은 공부해본다는 생각으로 추가해본다.

 

2. CreateTicketTest 코드작성

테스트코드 전문 보다는 일단 내가 직접 만들어본 코드를 먼저 붙여본다.

Given("멀티스레드 환경에서"){
        val threadCount = 100
        val executorService = Executors.newFixedThreadPool(20)
        val countDownLatch = CountDownLatch(threadCount)

        When("동시에 총 100개의 티켓을 구매하면") {
            repeat(threadCount) {
                executorService.submit {
                    try {
                        ticketService.createTicket(user.id!!, createTicketReq)
                    } finally {
                        countDownLatch.countDown()
                    }
                }
            }
            countDownLatch.await()

            val viewCount = goods.ticketAmount-goods.ticket.size

            Then("티켓의 남은 양은 0이 되어야 한다.") {
                assertThat(viewCount).isEqualTo(100)
            }
        }
    }

우리가 해야하는 동시성 제어 프로젝트에서는 우선 테스트를 할수있는 코드부터 작성해야한다.

테스트를 진행하기 위해선 동시에 100개 남짓의 코드가 실행이 되어야하고, 이를 도와주기위해선 스레드와 코루틴이 있다.

현재 위에 코드는 스레드를 이용한 코드이고 코루틴을 이용하는 방법은 조금더 알아보아야한다.

 

위의 테스트 코드는 티켓을 동시에 20명이 5번정도 총 100번을 구매했을 시에 총 티켓을 구매한 사람의 수가 오차없이 100명이 되어야한다.

 

하지만 지금으로서는 DB랑 연결이 되어있지않은상태(인텔리J에선 연결되어 있지만 테스트코드가 현재 DB를 경유하고 있지 않음)이다.

 

이를 연결시켜서 테스트해보는게 관건인듯 하다.


제출은 이번주 금요일이고 우선 테스트코드 작성은 일단락 된것 같으니 DB연결방법과 동시성 문제가 발생했을시에 이를 해결할 Redis를 공부하면 될것 같다.