일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- nGinder
- Ingress Controller Fake
- 논블록킹 성능
- pinpoint 2.5.3
- intellij
- save/update
- hbase 저장공간 설정
- RedirectService
- jar 배포
- 노드간 통신
- UnsupportedOperationException
- LPOS
- Armeria
- 핀포인트
- 오블완
- 티스토리챌린지
- fake jwt
- 개발 어렵당.ㅠ
- 월급루팡 일지
- pinpoint
- formik
- 플루터
- 애자일 싫타
- OIDC
- ㅉ때
- reids
- Loki 로그
- R2DBC Paging
- jsonMarshaller
- 7879
- Today
- Total
대머리개발자
쿠폰시스템 개발(2) 본문
쿠폰코드 자체를 PK 제약 조건을 설정했기 때문에 중복에 된 이슈는 해결했지만
만약 중복코드가 발생한다면 발생한 만큼 재 생성해야 한다.
예를들어 10,000건에 대한 쿠폰 발행할 때 18건이 중복이 발생했다면 18건을 추가적으로 만들어서 10,000건을 채워야 한다.
현재 쿠폰 발행 테스트할 때는
중복이 발생하지는 않았지만 항상 중복을 가능성이 존재 하기 때문에 쿠폰 발행 건수를 보장하기 위한 코드가 필요하다. (일단 추후 고민s)
fun save(policyId: Long) {
Mono.zip(
Mono.just(Code(policyId = policyId, couponCode = "todo")),
generateCouponCode()
)
.flatMap {
it.t1.couponCode = it.t2
return@flatMap codeRepository.save(it.t1)
}
.subscribe()
}
코드의 정책과 발행한 쿠폰코드의 스트림을 하나로 합쳐서 insert하는 그림이다.
만건에 대한 코드 발행 시간은 1,149ms
이제..
엑셀로 내려 받은 만건의 네이버 쿠폰을 하나씩 읽어서 우리내 쿠폰과 1:1로 맵핑해야 한다.
일단 엑셀 읽기 위한 직관적인 테스트 코드를 작성했다.
fun updateMapping(file: File){
val fis = FileInputStream(file)
val workbook = WorkbookFactory.create(fis)
val sheet = workbook.getSheetAt(0)
for (row in sheet) {
if(row.getCell(0) != null){
print(row.getCell(0).stringCellValue)
}else{
break
}
println()
}
fis.close()
file.delete()
}
AI 친구에게 해당 코드에 대한 클린을 부탁했다. 코틀린스럽게..
fun updateMapping(file: File) {
FileInputStream(file).use { fis ->
val workbook = WorkbookFactory.create(fis)
val sheet = workbook.getSheetAt(0)
sheet.mapNotNull { it.getCell(0)?.stringCellValue }
.takeWhile { it.isNotEmpty() }
.forEach { println(it)}
}
}
만 Row에 대해서 업데이트할 녀석을 하나씩 가져와 업데이트 하는 구조로 생각하고 테스트를 했는데 완전 실패했다.
sheet.mapNotNull { it.getCell(0)?.stringCellValue }
.takeWhile { it.isNotEmpty() }
.forEach {
codeRepository.findCodeToMap(policyId)
.flatMap {
couponCode -> codeRepository.updateLinkCode(couponCode, it)
}.subscribe()
}
비동기로 실행되다 보니 업데이트할 녀석들을 차례차레 가져와야 하는데..텅 퉁 끝!.
만 건 중 대략 40건만 업데이트 되었다. 이 말은 같은 데이터의 row를 계속 업데이트 쳤다는 것이다.
수치로 보자면 250개의 코드를 하나에 맵핑이 하는 그림이다
뭐 어째거나 다시 생각해야 한다. step by step
private fun updateCodesFromSheet(sheet: Sheet, policyId: Long) {
Flux.zip(Flowable.fromIterable(sheet), codeRepository.searchAllByPolicyIdAndLinkCouponCodeNull(policyId))
{ row, code -> updateLinkCode(code, row.getCell(0).stringCellValue) }
.subscribe()
}
1. 연계된 쿠폰코드가 없는 만건과 2.엑셀쉬트를 하나의 스트림으로 합쳐서 업데이트 딱 끝!!
핵심은 각각을 스트림으로 만드는 것에 있다.
일만건 업데이트 진행 하는데....
스트림으로 처리하기 때문에 메모리에 대한 부담도 적다.
(일 만건 전체를 적재해서 처리하는 것이 아니라 스트림 스트림!!)
1. 쿠폰 정책을 만들고 수량 만큼 쿠폰을 생성한다. (save)
2. 네이버 쿠폰과 맵핑처리를 하고 (updateMappings)
3. 쿠폰을 발행한다. (publishCodes)
fun publishCodes(couponCode: String): Mono<String>{
return codeRepository.findById(couponCode)
.filter { it !== null }
.flatMap { code ->
if(code.status == EntityStatus.USE){
return@flatMap Mono.just("이미 사용된 코코코드!")
}else{
return@flatMap ServiceUtils.getPolicyService().get(code.policyId)
.filter { it.publishStartAt.isBefore( LocalDateTime.now()) && it.publishEndAt.isAfter( LocalDateTime.now()) }
.flatMap { policy ->
codeRepository.updateForUseing(couponCode, "userID", policy.expirationPeriod.toInt()).subscribe()
Mono.just( code.linkCouponCode ?: "ok" )
}.switchIfEmpty { Mono.just("발행기간 체체체크!") }
}
}.switchIfEmpty { Mono.just("쿠폰코드 체체체크!") }
}
아직 코틀린도 어색하고 리액티브 스타일도 어색한데 AI를 이용하니
금방금방 만들어지는것 같다.
역시나 클린코드를 돌리면...ㅋㅋ너무 좋다.
const val USED_CODE_MESSAGE = "이미 사용된 코코코드"
const val OK_MESSAGE = "ok"
const val PUBLISH_PERIOD_CHECK_MESSAGE = "발행기간 체체체크!"
const val COUPON_CODE_CHECK_MESSAGE = "쿠폰코드 체체체크!"
const val USER_ID = "userID"
fun publishCodes(couponCode: String): Mono<String> {
val now = LocalDateTime.now()
return codeRepository.findById(couponCode)
.flatMap { code ->
when (code.status) {
EntityStatus.USE -> Mono.just(USED_CODE_MESSAGE)
else -> ServiceUtils.getPolicyService().get(code.policyId)
.filter { policy -> policy.publishStartAt.isBefore(now) && policy.publishEndAt.isAfter(now) }
.flatMap { policy ->
codeRepository.updateForUsing(couponCode, USER_ID, policy.expirationPeriod.toInt())
.then(Mono.just(code.linkCouponCode ?: OK_MESSAGE))
}.switchIfEmpty { Mono.just(PUBLISH_PERIOD_CHECK_MESSAGE) }
}
}.switchIfEmpty { Mono.just(COUPON_CODE_CHECK_MESSAGE) }
}
쿠폰 시스템도 시마이데스!!! 넉넉하게 워크데이 4일 정도 진행..프론트 이제 프론트 친구가 !!야호.너무 좋다.
'개발이야기 > 개념' 카테고리의 다른 글
네이밍 너무 힘들다. (1) | 2024.04.19 |
---|---|
Armeria를 사용하는 이유 (0) | 2024.03.12 |
쿠폰시스템 개발 (1) | 2023.12.17 |
Map vs. DTO (0) | 2023.12.14 |
SPA.. (0) | 2023.12.13 |