Skip to content
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

빈자리 알림 로직 추가 #110

Merged
merged 4 commits into from
Jul 6, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 5 additions & 12 deletions api/src/main/kotlin/handler/VacancyNotifcationHandler.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.wafflestudio.snu4t.handler

import com.wafflestudio.snu4t.middleware.SnuttRestApiDefaultMiddleware
import com.wafflestudio.snu4t.vacancynotification.dto.VacancyNotificationDto
import com.wafflestudio.snu4t.vacancynotification.service.VacancyNotificationService
import org.springframework.stereotype.Component
import org.springframework.web.reactive.function.server.ServerRequest
Expand All @@ -19,25 +18,19 @@ class VacancyNotifcationHandler(
val lectureId = req.pathVariable("lectureId")

vacancyNotificationService.addVacancyNotification(userId, lectureId)
.let { VacancyNotificationDto(it) }
null
}

suspend fun getVacancyNotifications(req: ServerRequest): ServerResponse = handle(req) {
suspend fun getVacancyNotificationLectures(req: ServerRequest): ServerResponse = handle(req) {
val userId = req.userId

vacancyNotificationService.getVacancyNotifications(userId)
vacancyNotificationService.getVacancyNotificationLectures(userId)
}

suspend fun getVacancyNotification(req: ServerRequest): ServerResponse = handle(req) {
val userId = req.userId
val lectureId = req.pathVariable("lectureId")

vacancyNotificationService.getVacancyNotification(userId, lectureId)
}
suspend fun deleteVacancyNotification(req: ServerRequest): ServerResponse = handle(req) {
val id = req.pathVariable("id")
val lectureId = req.pathVariable("lectureId")

vacancyNotificationService.deleteVacancyNotification(id)
vacancyNotificationService.deleteVacancyNotification(lectureId)
null
}
}
5 changes: 2 additions & 3 deletions api/src/main/kotlin/router/MainRouter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,9 @@ class MainRouter(
fun vacancyNotificationRoute() = coRouter {
path("/v1").nest {
"/vacancy-notifications".nest {
GET("", vacancyNotificationHandler::getVacancyNotifications)
GET("/lectures/{lectureId}", vacancyNotificationHandler::getVacancyNotification)
GET("/lectures", vacancyNotificationHandler::getVacancyNotificationLectures)
POST("/lectures/{lectureId}", vacancyNotificationHandler::addVacancyNotification)
DELETE("/{id}", vacancyNotificationHandler::deleteVacancyNotification)
DELETE("/lectures/{lectureId}", vacancyNotificationHandler::deleteVacancyNotification)
}
}
}
Expand Down
16 changes: 12 additions & 4 deletions api/src/main/kotlin/router/docs/VacancyNotificationDocs.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package com.wafflestudio.snu4t.router.docs

import com.wafflestudio.snu4t.vacancynotification.dto.VacancyNotificationDto
import com.wafflestudio.snu4t.lectures.data.Lecture
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.Parameter
import io.swagger.v3.oas.annotations.enums.ParameterIn
import io.swagger.v3.oas.annotations.media.ArraySchema
import io.swagger.v3.oas.annotations.media.Content
import io.swagger.v3.oas.annotations.media.Schema
import io.swagger.v3.oas.annotations.responses.ApiResponse
Expand All @@ -13,22 +14,29 @@ import org.springframework.http.MediaType
import org.springframework.web.bind.annotation.RequestMethod

@RouterOperations(
RouterOperation(
path = "/v1/vacancy-notifications/lectures", method = [RequestMethod.GET], produces = [MediaType.APPLICATION_JSON_VALUE],
operation = Operation(
operationId = "getVacancyNotificationLectures",
responses = [ApiResponse(responseCode = "200", content = [Content(array = ArraySchema(schema = Schema(implementation = Lecture::class)))])]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

우리 지난 번에 얘기한 건데 #70 (comment)

db entity 를 그대로 응답에 반환하지 않고 변환해서 전달하면 좋을 거 같아.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이거 안그래도 반영중이었음
너무 리뷰가 빨랐음ㅋㅋㅋ

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@davin111 후속 리뷰는?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

내 pr 도 리뷰 좀..!

),
),
RouterOperation(
path = "/v1/vacancy-notifications/lectures/{lectureId}", method = [RequestMethod.POST], produces = [MediaType.APPLICATION_JSON_VALUE],
operation = Operation(
operationId = "addVacancyNotification",
parameters = [
Parameter(`in` = ParameterIn.PATH, name = "lectureId", required = true),
],
responses = [ApiResponse(responseCode = "200", content = [Content(schema = Schema(implementation = VacancyNotificationDto::class))])]
responses = [ApiResponse(responseCode = "200", content = [Content(schema = Schema())])]
),
),
RouterOperation(
path = "/v1/vacancy-notifications/{id}", method = [RequestMethod.DELETE], produces = [MediaType.APPLICATION_JSON_VALUE],
path = "/v1/vacancy-notifications/lectures/{lectureId}", method = [RequestMethod.DELETE], produces = [MediaType.APPLICATION_JSON_VALUE],
operation = Operation(
operationId = "deleteVacancyNotification",
parameters = [
Parameter(`in` = ParameterIn.PATH, name = "id", required = true),
Parameter(`in` = ParameterIn.PATH, name = "lectureId", required = true),
],
responses = [ApiResponse(responseCode = "200", content = [Content(schema = Schema())])]
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.wafflestudio.snu4t.coursebook.service.CoursebookService
import com.wafflestudio.snu4t.sugangsnu.common.service.SugangSnuNotificationService
import com.wafflestudio.snu4t.sugangsnu.common.utils.nextCoursebook
import com.wafflestudio.snu4t.sugangsnu.job.sync.service.SugangSnuSyncService
import com.wafflestudio.snu4t.vacancynotification.service.VacancyNotificationService
import kotlinx.coroutines.runBlocking
import org.springframework.batch.core.Job
import org.springframework.batch.core.Step
Expand All @@ -29,6 +30,7 @@ class SugangSnuSyncJobConfig {
sugangSnuSyncService: SugangSnuSyncService,
coursebookService: CoursebookService,
sugangSnuNotificationService: SugangSnuNotificationService,
vacancyNotificationService: VacancyNotificationService,
): Step = StepBuilder("fetchSugangSnuStep", jobRepository).tasklet(
{ _, _ ->
runBlocking {
Expand All @@ -38,6 +40,7 @@ class SugangSnuSyncJobConfig {
sugangSnuNotificationService.notifyUserLectureChanges(updateResult)
} else {
val newCoursebook = existingCoursebook.nextCoursebook()
vacancyNotificationService.deleteAll()
sugangSnuSyncService.addCoursebook(newCoursebook)
sugangSnuNotificationService.notifyCoursebookUpdate(newCoursebook)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,4 @@ data class VacancyNotification(
@Indexed
@Field(targetType = FieldType.OBJECT_ID)
val lectureId: String,
@Indexed
@Field(targetType = FieldType.OBJECT_ID)
val coursebookId: String,
)

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ import org.springframework.data.repository.kotlin.CoroutineCrudRepository
interface VacancyNotificationRepository : CoroutineCrudRepository<VacancyNotification, String> {
fun findAllByLectureId(lectureId: String): Flow<VacancyNotification>
fun findAllByUserId(userId: String): Flow<VacancyNotification>
suspend fun findFirstByUserIdAndLectureId(userId: String, lectureId: String): VacancyNotification
suspend fun deleteByLectureId(lectureId: String)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,37 @@ import com.wafflestudio.snu4t.common.exception.DuplicateVacancyNotificationExcep
import com.wafflestudio.snu4t.common.exception.InvalidRegistrationForPreviousSemesterCourseException
import com.wafflestudio.snu4t.common.exception.LectureNotFoundException
import com.wafflestudio.snu4t.coursebook.service.CoursebookService
import com.wafflestudio.snu4t.lectures.service.LectureService
import com.wafflestudio.snu4t.lectures.data.Lecture
import com.wafflestudio.snu4t.lectures.repository.LectureRepository
import com.wafflestudio.snu4t.vacancynotification.data.VacancyNotification
import com.wafflestudio.snu4t.vacancynotification.repository.VacancyNotificationRepository
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.toList
import org.springframework.dao.DuplicateKeyException
import org.springframework.stereotype.Service

interface VacancyNotificationService {
suspend fun getVacancyNotificationLectures(userId: String): List<Lecture>
suspend fun addVacancyNotification(userId: String, lectureId: String): VacancyNotification
suspend fun getVacancyNotifications(userId: String): List<VacancyNotification>
suspend fun getVacancyNotification(userId: String, lectureId: String): VacancyNotification
suspend fun deleteVacancyNotification(id: String)
suspend fun deleteVacancyNotification(lectureId: String)
suspend fun deleteAll()
}

@Service
class VacancyNotificationServiceImpl(
private val vacancyNotificationRepository: VacancyNotificationRepository,
private val lectureService: LectureService,
private val lectureRepository: LectureRepository,
private val coursebookService: CoursebookService
) : VacancyNotificationService {
override suspend fun getVacancyNotificationLectures(userId: String): List<Lecture> =
vacancyNotificationRepository.findAllByUserId(userId).map { it.lectureId }
.let { lectureRepository.findAllById(it) }.toList()

override suspend fun addVacancyNotification(userId: String, lectureId: String): VacancyNotification =
coroutineScope {
val deferredLecture = async { lectureService.getByIdOrNull(lectureId) }
val deferredLecture = async { lectureRepository.findById(lectureId) }
val deferredLatestCoursebook = async { coursebookService.getLatestCoursebook() }
val (lecture, latestCoursebook) = deferredLecture.await() to deferredLatestCoursebook.await()

Expand All @@ -37,17 +43,15 @@ class VacancyNotificationServiceImpl(
throw InvalidRegistrationForPreviousSemesterCourseException
}

trySave(VacancyNotification(userId = userId, lectureId = lectureId, coursebookId = latestCoursebook.id!!))
trySave(VacancyNotification(userId = userId, lectureId = lectureId))
}

override suspend fun getVacancyNotifications(userId: String): List<VacancyNotification> =
vacancyNotificationRepository.findAllByUserId(userId).toList()

override suspend fun getVacancyNotification(userId: String, lectureId: String): VacancyNotification =
vacancyNotificationRepository.findFirstByUserIdAndLectureId(userId, lectureId)
override suspend fun deleteVacancyNotification(lectureId: String) {
vacancyNotificationRepository.deleteByLectureId(lectureId)
}

override suspend fun deleteVacancyNotification(id: String) {
vacancyNotificationRepository.deleteById(id)
override suspend fun deleteAll() {
vacancyNotificationRepository.deleteAll()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이거 mongodb 성능 괜찮으려나?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

drop table 할걸?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아니네.. 흠

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

사실 데이터가 많다면 컬렉션 삭제, 재생성하고 인덱스 재생성하면 더 빠를텐데 DDL날리는것도 좀 그렇고 걍 써도 될듯

}

private suspend fun trySave(vacancyNotification: VacancyNotification) =
Expand Down