-
Notifications
You must be signed in to change notification settings - Fork 2
다음 학기 lectures sync 시 semester tag 자동 update #141
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
base: develop
Are you sure you want to change the base?
Changes from all commits
0d9b136
963c049
8bd28f7
76f4f9c
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 |
|---|---|---|
|
|
@@ -7,12 +7,18 @@ import com.wafflestudio.snuttev.core.domain.lecture.model.SnuttLectureIdMap | |
| import com.wafflestudio.snuttev.core.domain.lecture.repository.LectureRepository | ||
| import com.wafflestudio.snuttev.core.domain.lecture.repository.SemesterLectureRepository | ||
| import com.wafflestudio.snuttev.core.domain.lecture.repository.SnuttLectureIdMapRepository | ||
| import com.wafflestudio.snuttev.core.domain.tag.repository.TagGroupRepository | ||
| import com.wafflestudio.snuttev.core.domain.tag.repository.TagRepository | ||
| import com.wafflestudio.snuttev.core.domain.tag.service.TagService | ||
| import com.wafflestudio.snuttev.sync.model.SnuttSemesterLecture | ||
| import jakarta.persistence.EntityManagerFactory | ||
| import org.springframework.batch.core.ExitStatus | ||
| import org.springframework.batch.core.job.Job | ||
| import org.springframework.batch.core.job.builder.JobBuilder | ||
| import org.springframework.batch.core.listener.StepExecutionListener | ||
| import org.springframework.batch.core.repository.JobRepository | ||
| import org.springframework.batch.core.step.Step | ||
| import org.springframework.batch.core.step.StepExecution | ||
| import org.springframework.batch.core.step.builder.StepBuilder | ||
| import org.springframework.batch.infrastructure.item.ItemProcessor | ||
| import org.springframework.batch.infrastructure.item.ItemWriter | ||
|
|
@@ -37,7 +43,10 @@ class SnuttLectureSyncJobConfig( | |
| private val semesterLectureRepository: SemesterLectureRepository, | ||
| private val lectureRepository: LectureRepository, | ||
| private val snuttLectureIdMapRepository: SnuttLectureIdMapRepository, | ||
| private val tagRepository: TagRepository, | ||
| private val tagGroupRepository: TagGroupRepository, | ||
| private val ratingSyncJob: Job, | ||
| private val tagService: TagService, | ||
| ) { | ||
| companion object { | ||
| private const val JOB_NAME = "SYNC_JOB" | ||
|
|
@@ -84,6 +93,7 @@ class SnuttLectureSyncJobConfig( | |
| .and("semester") | ||
| .isEqualTo(targetSemester), | ||
| ), | ||
| TargetYearSemester(targetYear, targetSemester), | ||
| ), | ||
| ).next(ratingSyncJobStep(jobRepository)) | ||
| .build() | ||
|
|
@@ -111,6 +121,7 @@ class SnuttLectureSyncJobConfig( | |
| private fun customReaderStep( | ||
| jobRepository: JobRepository, | ||
| query: Query, | ||
| targetYearSemester: TargetYearSemester? = null, | ||
| ): Step = | ||
| StepBuilder(CUSTOM_READER_JOB_STEP, jobRepository) | ||
| .chunk<SnuttSemesterLecture, SyncProcessResult>(CHUNK_SIZE) | ||
|
|
@@ -121,6 +132,7 @@ class SnuttLectureSyncJobConfig( | |
| ).reader(reader(query)) | ||
| .processor(processor()) | ||
| .writer(writer()) | ||
| .listener(tagSaveStepListener(targetYearSemester)) | ||
| .build() | ||
|
|
||
| private fun reader(query: Query): MongoCursorItemReader<SnuttSemesterLecture> = | ||
|
|
@@ -187,6 +199,17 @@ class SnuttLectureSyncJobConfig( | |
| snuttLectureIdMapRepository.saveAll(items.map { it.snuttLectureIdMap }) | ||
| } | ||
|
|
||
| private fun tagSaveStepListener(targetYearSemester: TargetYearSemester? = null): StepExecutionListener { | ||
| return object : StepExecutionListener { | ||
| override fun afterStep(stepExecution: StepExecution): ExitStatus { | ||
| if (stepExecution.exitStatus == ExitStatus.COMPLETED && targetYearSemester != null) { | ||
| tagService.saveYearSemesterTagIfNotExists(targetYearSemester.year, targetYearSemester.semester) | ||
|
Author
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. save tag 로직을 tagSerivce로 옮겨서 @transcactional로 묶었습니다 |
||
| } | ||
| return stepExecution.exitStatus | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private fun ratingSyncJobStep(jobRepository: JobRepository): Step = | ||
| StepBuilder(SnuttRatingSyncJobConfig.RATING_SYNC_JOB_NAME, jobRepository) | ||
| .job(ratingSyncJob) | ||
|
|
@@ -198,3 +221,8 @@ data class SyncProcessResult( | |
| val semesterLecture: SemesterLecture, | ||
| val snuttLectureIdMap: SnuttLectureIdMap, | ||
| ) | ||
|
|
||
| data class TargetYearSemester( | ||
| val year: Int, | ||
| val semester: Int, | ||
| ) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,11 +13,11 @@ import java.time.LocalDateTime | |
| open class BaseEntity( | ||
| @Id | ||
| @GeneratedValue(strategy = GenerationType.IDENTITY) | ||
| open val id: Long? = null, | ||
| @Column(name = "created_at", nullable = false) | ||
| open val createdAt: LocalDateTime = LocalDateTime.now(), | ||
| open var id: Long? = null, | ||
| @Column(name = "created_at", nullable = false, updatable = false) | ||
| open var createdAt: LocalDateTime = LocalDateTime.now(), | ||
| @field:UpdateTimestamp | ||
| @Column(name = "updated_at", nullable = false) | ||
| @OptimisticLock(excluded = true) | ||
| open val updatedAt: LocalDateTime? = LocalDateTime.now(), | ||
| open var updatedAt: LocalDateTime? = LocalDateTime.now(), | ||
|
Comment on lines
+16
to
+22
Contributor
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. BaseEntity가 수정된 이유가 뭔가용?
Author
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. Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed: java.lang.NoSuchMethodError: 'void com.wafflestudio.snuttev.core.common.model.BaseEntity.$$_hibernate_write_id(java.lang.Long)'] with root cause 처음에 이렇게 에러 떠서 찾아보니까 BaseEntity id가 val이라 write method를 작성할 수가 없는게 원인이더라고요. 그래서 var로 바꾸니까 제대로 동작했습니다. createdAt이랑 updatedAt도 원래는 val이었는데 충돌 가능성을 낮추기 위해 var로 교체하고, 대신 createdAt은 처음 db에 추가한 이후에 바꾸지 못하도록 updatable=false로 설정했습니다.
Contributor
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. 제가 잘 이해를 못 했는데, 이번에 작성해주신 코드에서 Tag 객체가 생성된 후 id, createdAt, updatedAt을 바꾸는 코드는 없었지만 hibernate에서 에러를 낸 건가용...? |
||
| ) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,9 +2,15 @@ package com.wafflestudio.snuttev.core.common.type | |
|
|
||
| enum class Semester( | ||
| val value: Int, | ||
| val label: String, | ||
| ) { | ||
| SPRING(1), | ||
| SUMMER(2), | ||
| AUTUMN(3), | ||
| WINTER(4), | ||
| SPRING(1, "1"), | ||
| SUMMER(2, "여름"), | ||
| AUTUMN(3, "2"), | ||
| WINTER(4, "겨울"), | ||
| ; | ||
|
|
||
| companion object { | ||
| fun labelOfOrNull(value: Int): String? = entries.firstOrNull { it.value == value }?.label | ||
|
Author
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. invalid semester value일 경우(학기 숫자가 1~4가 아닌 값이 들어올 때) 기존에는 exception을 띄웠었는데, 그냥 로그만 남기고, 리스너에서 tag 저장 작업 중에 리턴하는거로 수정했습니다 |
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| package com.wafflestudio.snuttev.core.domain.tag.service | ||
|
|
||
| import com.wafflestudio.snuttev.core.common.error.TagGroupNotFoundException | ||
| import com.wafflestudio.snuttev.core.common.type.Semester | ||
| import com.wafflestudio.snuttev.core.common.util.cache.Cache | ||
| import com.wafflestudio.snuttev.core.common.util.cache.CacheKey | ||
| import com.wafflestudio.snuttev.core.domain.tag.dto.SearchTagResponse | ||
|
|
@@ -9,14 +10,21 @@ import com.wafflestudio.snuttev.core.domain.tag.dto.TagGroupDto | |
| import com.wafflestudio.snuttev.core.domain.tag.model.Tag | ||
| import com.wafflestudio.snuttev.core.domain.tag.model.TagGroup | ||
| import com.wafflestudio.snuttev.core.domain.tag.repository.TagGroupRepository | ||
| import com.wafflestudio.snuttev.core.domain.tag.repository.TagRepository | ||
| import org.slf4j.LoggerFactory | ||
| import org.springframework.stereotype.Service | ||
| import org.springframework.transaction.annotation.Transactional | ||
|
|
||
| @Service | ||
| class TagService internal constructor( | ||
| private val tagGroupRepository: TagGroupRepository, | ||
| private val tagRepository: TagRepository, | ||
| private val cache: Cache, | ||
| ) { | ||
| companion object { | ||
| private val log = LoggerFactory.getLogger(TagService::class.java) | ||
| } | ||
|
|
||
| @Transactional(readOnly = true) | ||
| fun getMainTags(): TagGroupDto = | ||
| cache.withCache(CacheKey.MAIN_TAGS.build()) { | ||
|
|
@@ -53,4 +61,38 @@ class TagService internal constructor( | |
| description = tag.description, | ||
| ordering = tag.ordering, | ||
| ) | ||
|
|
||
|
Author
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. SnuttLectureSyncJob Config에서 TagService로 옮겨온 로직 변경사항 |
||
| @Transactional | ||
| fun saveYearSemesterTagIfNotExists( | ||
| year: Int, | ||
| semester: Int, | ||
| ) { | ||
| val stringValue = "$year,$semester" | ||
| if (tagRepository.searchTagByStringValue(stringValue) == null) { | ||
| val tagGroup = | ||
| tagGroupRepository.findByName(name = "학기") ?: run { | ||
| log.warn("TagGroup not found. name={}", "학기") | ||
| return | ||
| } | ||
|
|
||
| val semesterName = | ||
| Semester.labelOfOrNull(semester) ?: run { | ||
| log.warn("Invalid semester value. semester={}", semester) | ||
| return | ||
| } | ||
|
|
||
| val name = | ||
| year.toString() + " " + semesterName + "학기" | ||
| val ordering = -1 + tagRepository.findMinOrderingByTagGroupId(tagGroup.id!!) | ||
| tagRepository.save( | ||
| Tag( | ||
| tagGroup = tagGroup, | ||
| name = name, | ||
| ordering = ordering, | ||
| stringValue = stringValue, | ||
| description = null, | ||
| ), | ||
| ) | ||
| } | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.