Skip to content

Commit

Permalink
challenge rank persistent layer 구현 (#217)
Browse files Browse the repository at this point in the history
## Checklist
- [ ] 충분한 양의 자동화 테스트를 작성했는가?
  - 계단정복지도 서비스는 사이드 프로젝트로 진행되는 만큼 충분한 QA 없이 배포되는 경우가 많습니다. 따라서 자동화 테스트를 꼼꼼하게 작성하는 것이 서비스 품질을 유지하는 데 매우 중요합니다.
  • Loading branch information
bellatoris authored Oct 29, 2023
1 parent 1a13f2f commit ada091d
Show file tree
Hide file tree
Showing 5 changed files with 192 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package club.staircrusher.challenge.infra.adapter.out.persistence

import club.staircrusher.challenge.application.port.out.persistence.ChallengeRankRepository
import club.staircrusher.challenge.domain.model.ChallengeRank
import club.staircrusher.challenge.infra.adapter.out.persistence.sqldelight.toDomainModel
import club.staircrusher.challenge.infra.adapter.out.persistence.sqldelight.toPersistenceModel
import club.staircrusher.infra.persistence.sqldelight.DB
import club.staircrusher.stdlib.di.annotation.Component

@Component
class ChallengeRankRepository(
private val db: DB
): ChallengeRankRepository {
private val queries = db.challengeRankQueries

override fun findTopNUsers(challengeId: String, n: Int): List<ChallengeRank> {
return queries.findTopNUsers(challengeId, n.toLong())
.executeAsList()
.map { it.toDomainModel() }
}

override fun findByUserId(challengeId: String, userId: String): ChallengeRank? {
return queries.findByUserId(challengeId, userId)
.executeAsOneOrNull()
?.toDomainModel()
}

override fun findByRank(challengeId: String, rank: Long): ChallengeRank? {
return queries.findByRank(challengeId, rank)
.executeAsOneOrNull()
?.toDomainModel()
}

override fun findNextRank(challengeId: String, rank: Long): ChallengeRank? {
return queries.findNextRank(challengeId, rank)
.executeAsOneOrNull()
?.toDomainModel()
}

override fun findLastRank(challengeId: String): Long? {
return queries.findLastRank(challengeId).executeAsOneOrNull()?.max
}

override fun findByContributionCount(challengeId: String, contributionCount: Int): ChallengeRank? {
return queries.findByContributionCount(challengeId, contributionCount)
.executeAsOneOrNull()
?.toDomainModel()
}

override fun findAll(challengeId: String): List<ChallengeRank> {
return queries.findAll(challengeId)
.executeAsList()
.map { it.toDomainModel() }
}

override fun save(entity: ChallengeRank): ChallengeRank {
queries.save(entity.toPersistenceModel())
return entity
}

override fun saveAll(entities: Collection<ChallengeRank>) {
entities.forEach { save(it) }
}

override fun removeAll() {
queries.removeAll()
}

override fun removeAll(challengeId: String) {
queries.removeAllByChallengeId(challengeId)
}

override fun findById(id: String): ChallengeRank {
return findByIdOrNull(id) ?: throw IllegalArgumentException("ChallengeRank of id $id does not exist.")
}

override fun findByIdOrNull(id: String): ChallengeRank? {
return queries.findById(id)
.executeAsOneOrNull()
?.toDomainModel()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@ import club.staircrusher.api.spec.dto.ListChallengesItemDto
import club.staircrusher.challenge.domain.model.ChallengeContribution
import club.staircrusher.challenge.domain.model.ChallengeParticipation
import club.staircrusher.challenge.domain.model.ChallengeStatus
import club.staircrusher.challenge.domain.model.ChallengeRank
import club.staircrusher.infra.persistence.sqldelight.migration.Challenge
import club.staircrusher.infra.persistence.sqldelight.migration.Challenge_contribution
import club.staircrusher.infra.persistence.sqldelight.migration.Challenge_participation
import club.staircrusher.infra.persistence.sqldelight.migration.Challenge_rank
import club.staircrusher.infra.persistence.sqldelight.query.challenge.FindByUidAndTime
import club.staircrusher.infra.persistence.sqldelight.query.challenge.JoinedChallenges
import club.staircrusher.infra.persistence.sqldelight.query.challenge.NotJoinedChallenges
import club.staircrusher.stdlib.time.toOffsetDateTime
import java.time.Instant

Expand Down Expand Up @@ -137,3 +141,23 @@ fun FindByUidAndTime.toChallenge() = club.staircrusher.challenge.domain.model.Ch
createdAt = created_at.toInstant(),
updatedAt = updated_at.toInstant()
)

fun ChallengeRank.toPersistenceModel() = Challenge_rank(
id = id,
challenge_id = challengeId,
user_id = userId,
contribution_count = contributionCount,
rank = rank,
created_at = createdAt.toOffsetDateTime(),
updated_at = updatedAt.toOffsetDateTime()
)

fun Challenge_rank.toDomainModel() = ChallengeRank(
id = id,
challengeId = challenge_id,
userId = user_id,
contributionCount = contribution_count,
rank = rank,
createdAt = created_at.toInstant(),
updatedAt = updated_at.toInstant()
)
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.SerializationFeature
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import javax.sql.DataSource

@Component
Expand All @@ -49,7 +50,7 @@ class DB(dataSource: DataSource) : TransactionManager {
}

override fun convertElementFromTextColumn(text: String): ClubQuestTargetBuilding {
return objectMapper.readValue(text, ClubQuestTargetBuilding::class.java)
return objectMapper.readValue(text)
}

}
Expand All @@ -71,7 +72,7 @@ class DB(dataSource: DataSource) : TransactionManager {
}

override fun convertElementFromTextColumn(text: String): ChallengeCondition {
return objectMapper.readValue(text, ChallengeCondition::class.java)
return objectMapper.readValue(text)
}

}
Expand All @@ -93,6 +94,7 @@ class DB(dataSource: DataSource) : TransactionManager {
val challengeQueries = scc.challengeQueries
val challengeContributionQueries = scc.challengeContributionQueries
val challengeParticipationQueries = scc.challengeParticipationQueries
val challengeRankQueries = scc.challengeRankQueries


override fun <T> doInTransaction(block: Transaction<T>.() -> T): T {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
CREATE TABLE IF NOT EXISTS challenge_rank (
id VARCHAR(36) NOT NULL,
challenge_id VARCHAR(36) NOT NULL,
user_id VARCHAR(36) NOT NULL,
contribution_count INT NOT NULL,
rank BIGINT NOT NULL,
created_at TIMESTAMP(6) WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP(6) WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id)
);

CREATE INDEX idx_challenge_rank_1 ON challenge_rank(challenge_id, user_id);
CREATE INDEX idx_challenge_rank_2 ON challenge_rank(challenge_id, rank);
CREATE INDEX idx_challenge_rank_3 ON challenge_rank(challenge_id, contribution_count);
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
save:
INSERT INTO challenge_rank
VALUES :challenge_rank
ON CONFLICT(id) DO UPDATE SET
contribution_count = EXCLUDED.contribution_count,
rank = EXCLUDED.rank,
updated_at = EXCLUDED.updated_at;

removeAll:
DELETE FROM challenge_rank;

findById:
SELECT *
FROM challenge_rank
WHERE challenge_rank.id = :id;

findByUserId:
SELECT *
FROM challenge_rank
WHERE
challenge_rank.challenge_id = :challenge_id AND
challenge_rank.user_id = :user_id;

findTopNUsers:
SELECT *
FROM challenge_rank
WHERE challenge_rank.challenge_id = :challenge_id
ORDER BY challenge_rank.rank ASC
LIMIT :n;

findByRank:
SELECT *
FROM challenge_rank
WHERE
challenge_rank.challenge_id = :challenge_id AND
challenge_rank.rank = :rank
LIMIT 1;

findNextRank:
SELECT *
FROM challenge_rank
WHERE
challenge_rank.challenge_id = :challenge_id AND
challenge_rank.rank < :rank
ORDER BY challenge_rank.rank DESC
LIMIT 1;

findLastRank:
SELECT max(challenge_rank.rank)
FROM challenge_rank
WHERE challenge_rank.challenge_id = :challenge_id;

findAll:
SELECT *
FROM challenge_rank
WHERE challenge_rank.challenge_id = :challenge_id;

findByContributionCount:
SELECT *
FROM challenge_rank
WHERE
challenge_rank.challenge_id = :challenge_id AND
challenge_rank.contribution_count = :contribution_count
LIMIT 1;

removeAllByChallengeId:
DELETE FROM challenge_rank
WHERE challenge_rank.challenge_id = :challenge_id;

0 comments on commit ada091d

Please sign in to comment.