-
Notifications
You must be signed in to change notification settings - Fork 0
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
학급 open api batch로 가져오기 #40
Changes from 2 commits
de909a3
1dfa66a
356b90f
f8b49cc
0750850
53dcb8b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package com.asap.asapbackend.batch.classroom | ||
|
||
import com.asap.asapbackend.domain.classroom.domain.model.Classroom | ||
import com.asap.asapbackend.domain.school.domain.model.School | ||
|
||
interface ClassroomInfoProvider { | ||
fun retrieveClassroomInfo(batchSize: Int, startIndex: Int): ClassroomDataContainer | ||
|
||
data class ClassroomDataContainer( | ||
val classroomInfo: List<ClassroomInfo>, | ||
val hasNext: Boolean | ||
) | ||
|
||
data class ClassroomInfo( | ||
val school: School, | ||
val grade: Int, | ||
val classNumber: String | ||
) { | ||
fun toClassroom(): Classroom { | ||
return Classroom( | ||
school = school, | ||
grade = grade, | ||
className = classNumber | ||
) | ||
} | ||
} | ||
} | ||
|
||
fun List<ClassroomInfoProvider.ClassroomInfo>.toClassrooms(): List<Classroom> { | ||
return this.map { it.toClassroom() } | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,27 @@ | ||
package com.asap.asapbackend.batch.classroom | ||
|
||
import com.asap.asapbackend.domain.classroom.domain.service.ClassroomAppender | ||
import com.asap.asapbackend.global.util.TransactionUtils | ||
import org.springframework.scheduling.annotation.Scheduled | ||
import org.springframework.web.bind.annotation.GetMapping | ||
import org.springframework.web.bind.annotation.RestController | ||
import org.springframework.stereotype.Component | ||
|
||
@RestController | ||
@Component | ||
class ClassroomScheduler( | ||
private val classroomService: ClassroomService | ||
private val classroomInfoProvider: ClassroomInfoProvider, | ||
private val classroomAppender: ClassroomAppender | ||
) { | ||
@Scheduled(cron = "0 0 4 1 3 ?") // 매년 3월 1일 04:00:00에 실행 | ||
@GetMapping("/addClassroom") | ||
fun addClassroom(){ | ||
classroomService.addClassroom() | ||
@Scheduled(cron = "0 5 4 1 3 ?") // 매년 3월 1일 04:05:00에 실행 | ||
fun addClassroom() { | ||
val batchSize = 100 | ||
var startIndex = 0 | ||
do { | ||
val classroomDataContainer = classroomInfoProvider.retrieveClassroomInfo(batchSize, startIndex) | ||
|
||
startIndex += batchSize | ||
|
||
TransactionUtils.writable { | ||
classroomAppender.addClassroom(classroomDataContainer.classroomInfo.toClassrooms()) | ||
} | ||
} while (classroomDataContainer.hasNext) | ||
} | ||
} |
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package com.asap.asapbackend.client.openapi.classroom | ||
|
||
import com.asap.asapbackend.batch.classroom.ClassroomInfoProvider | ||
import com.asap.asapbackend.client.openapi.classroom.dto.ClassroomOpenApiResponse | ||
import com.asap.asapbackend.domain.school.domain.repository.SchoolRepository | ||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper | ||
import org.springframework.stereotype.Component | ||
import org.springframework.web.reactive.function.client.WebClient | ||
import org.springframework.web.util.UriBuilder | ||
import java.time.Year | ||
|
||
@Component | ||
class ClassroomOpenApiClient( | ||
private val schoolRepository: SchoolRepository | ||
) : ClassroomInfoProvider { | ||
override fun retrieveClassroomInfo(batchSize: Int, startIndex: Int): ClassroomInfoProvider.ClassroomDataContainer { | ||
var endIndex = startIndex + batchSize | ||
val hasNext = schoolRepository.count() > endIndex | ||
if (!hasNext) { | ||
endIndex = schoolRepository.count().toInt() | ||
} | ||
val schools = schoolRepository.findAll().subList(startIndex, endIndex) | ||
val classroomInfoList: MutableList<ClassroomInfoProvider.ClassroomInfo> = mutableListOf() | ||
schools.forEach { school -> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 부분 forEach보다는 map을 사용해서 바로 List<ClassroomInfoProvider.ClassroomInfo>로 바꾸는거는 어때 |
||
val apiUrl = "https://open.neis.go.kr/hub/classInfo" | ||
val classroomInfoResult = WebClient.create(apiUrl).get() | ||
.uri { uriBuilder: UriBuilder -> | ||
uriBuilder | ||
.queryParam("KEY", "32e897d4054342b19fd68dfb1b9ba621") | ||
.queryParam("ATPT_OFCDC_SC_CODE", school.eduOfficeCode) | ||
.queryParam("SD_SCHUL_CODE", school.schoolCode) | ||
.queryParam("AY", Year.now()) | ||
.queryParam("Type", "json") | ||
.build() | ||
} | ||
.retrieve() | ||
.bodyToMono(String::class.java) | ||
.map { | ||
jacksonObjectMapper().readValue(it, ClassroomOpenApiResponse::class.java) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 부분도 spring objectmapper 사용하자 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 바꿨어~ |
||
} | ||
.block() | ||
classroomInfoResult?.classInfo?.forEach { classInfo -> | ||
classInfo.row?.let { rows -> | ||
classroomInfoList.addAll(rows.map { it.toClassroomInfo(school) }) | ||
} | ||
} | ||
} | ||
return ClassroomInfoProvider.ClassroomDataContainer( | ||
classroomInfo = classroomInfoList, | ||
hasNext = hasNext | ||
) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package com.asap.asapbackend.client.openapi.classroom.dto | ||
|
||
import com.asap.asapbackend.batch.classroom.ClassroomInfoProvider | ||
import com.asap.asapbackend.domain.school.domain.model.School | ||
|
||
data class ClassroomOpenApiResponse( | ||
val classInfo: List<ClassInfo>?, | ||
val RESULT: Result? | ||
) | ||
|
||
data class ClassInfo( | ||
val head: List<Head>?, | ||
val row: List<Row>? | ||
) | ||
|
||
data class Head( | ||
val list_total_count: Int?, | ||
val RESULT: Result? | ||
) | ||
|
||
data class Result( | ||
val CODE: String, | ||
val MESSAGE: String | ||
) | ||
|
||
data class Row( | ||
val ATPT_OFCDC_SC_CODE: String?, | ||
val ATPT_OFCDC_SC_NM: String?, | ||
val SD_SCHUL_CODE: String?, | ||
val SCHUL_NM: String?, | ||
val AY: String?, | ||
val GRADE: Int, | ||
val DGHT_CRSE_SC_NM: String?, | ||
val SCHUL_CRSE_SC_NM: String?, | ||
val ORD_SC_NM: String?, | ||
val DDDEP_NM: String?, | ||
val CLASS_NM: String, | ||
val LOAD_DTM: String? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 사용 안하는 필드는 제거하는거 어떄 |
||
) { | ||
fun toClassroomInfo(school: School): ClassroomInfoProvider.ClassroomInfo { | ||
return ClassroomInfoProvider.ClassroomInfo( | ||
school, | ||
GRADE, | ||
CLASS_NM | ||
) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
findall()보다는 page나 커서기반으로 조회하자
모든 데이터를 다 조회하면 성능이 매우 안좋을것같아
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
page로 가져오면 다음 데이터가 있는지 hasNext 프로퍼티가 있어서 위에 hasNext 구하기 위한 쿼리는 없애자
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
굿굿 이런 리뷰 조타
page 단위로 조회하는걸로 수정완
커서랑 페이징 중에 페이징이 메모리 적게 쓴다길래 페이징으로 해봤는데 별로면 말해줘~