Skip to content

Commit

Permalink
M7l1 repo (#28)
Browse files Browse the repository at this point in the history
* m7l1 - InMemory repo

* m7l1 - InMemory repo: clean up

* m7l1 - InMemory repo: Biz

* m7l1 - InMemory repo: Ktor

* m7l1 - InMemory repo: Spring

* m7l1 - Repository: Refining

(cherry picked from commit 1d7e2418fc1c7ca1c2935532935d1dfdec173b98)
  • Loading branch information
svok authored and phaeton03 committed Jun 23, 2024
1 parent 64eed5c commit 319ae87
Show file tree
Hide file tree
Showing 16 changed files with 29 additions and 126 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ abstract class V2AdRepoBaseTest {
debug = AdDebug(mode = workMode),
),
) { response ->
val responseObj = response.body<AdCreateResponse>()
val responseObj = response.body<IResponse>() as AdCreateResponse
assertEquals(200, response.status.value)
assertEquals(uuidNew, responseObj.ad?.id)
assertEquals(ad.title, responseObj.ad?.title)
Expand All @@ -78,7 +78,7 @@ abstract class V2AdRepoBaseTest {
debug = AdDebug(mode = workMode),
),
) { response ->
val responseObj = response.body<AdReadResponse>()
val responseObj = response.body<IResponse>() as AdReadResponse
assertEquals(200, response.status.value)
assertEquals(uuidOld, responseObj.ad?.id)
}
Expand All @@ -95,7 +95,7 @@ abstract class V2AdRepoBaseTest {
debug = AdDebug(mode = workMode),
),
) { response ->
val responseObj = response.body<AdUpdateResponse>()
val responseObj = response.body<IResponse>() as AdUpdateResponse
assertEquals(200, response.status.value)
assertEquals(ad.id, responseObj.ad?.id)
assertEquals(ad.title, responseObj.ad?.title)
Expand All @@ -115,7 +115,7 @@ abstract class V2AdRepoBaseTest {
debug = AdDebug(mode = workMode),
),
) { response ->
val responseObj = response.body<AdDeleteResponse>()
val responseObj = response.body<IResponse>() as AdDeleteResponse
assertEquals(200, response.status.value)
assertEquals(uuidOld, responseObj.ad?.id)
}
Expand All @@ -130,7 +130,7 @@ abstract class V2AdRepoBaseTest {
debug = AdDebug(mode = workMode),
),
) { response ->
val responseObj = response.body<AdSearchResponse>()
val responseObj = response.body<IResponse>() as AdSearchResponse
assertEquals(200, response.status.value)
assertNotEquals(0, responseObj.ads?.size)
assertEquals(uuidOld, responseObj.ads?.first()?.id)
Expand All @@ -145,7 +145,7 @@ abstract class V2AdRepoBaseTest {
debug = AdDebug(mode = workMode),
),
) { response ->
val responseObj = response.body<AdOffersResponse>()
val responseObj = response.body<IResponse>() as AdOffersResponse
assertEquals(200, response.status.value)
assertNotEquals(0, responseObj.ads?.size)
assertEquals(uuidSup, responseObj.ads?.first()?.id)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ abstract class V1AdRepoBaseTest {
debug = AdDebug(mode = workMode),
),
) { response ->
val responseObj = response.body<AdCreateResponse>()
val responseObj = response.body<IResponse>() as AdCreateResponse
assertEquals(200, response.status.value)
assertEquals(uuidNew, responseObj.ad?.id)
assertEquals(ad.title, responseObj.ad?.title)
Expand All @@ -77,7 +77,7 @@ abstract class V1AdRepoBaseTest {
debug = AdDebug(mode = workMode),
),
) { response ->
val responseObj = response.body<AdReadResponse>()
val responseObj = response.body<IResponse>() as AdReadResponse
assertEquals(200, response.status.value)
assertEquals(uuidOld, responseObj.ad?.id)
}
Expand All @@ -94,7 +94,7 @@ abstract class V1AdRepoBaseTest {
debug = AdDebug(mode = workMode),
),
) { response ->
val responseObj = response.body<AdUpdateResponse>()
val responseObj = response.body<IResponse>() as AdUpdateResponse
assertEquals(200, response.status.value)
assertEquals(ad.id, responseObj.ad?.id)
assertEquals(ad.title, responseObj.ad?.title)
Expand All @@ -114,7 +114,7 @@ abstract class V1AdRepoBaseTest {
debug = AdDebug(mode = workMode),
),
) { response ->
val responseObj = response.body<AdDeleteResponse>()
val responseObj = response.body<IResponse>() as AdDeleteResponse
assertEquals(200, response.status.value)
assertEquals(uuidOld, responseObj.ad?.id)
}
Expand All @@ -128,7 +128,7 @@ abstract class V1AdRepoBaseTest {
debug = AdDebug(mode = workMode),
),
) { response ->
val responseObj = response.body<AdSearchResponse>()
val responseObj = response.body<IResponse>() as AdSearchResponse
assertEquals(200, response.status.value)
assertNotEquals(0, responseObj.ads?.size)
assertEquals(uuidOld, responseObj.ads?.first()?.id)
Expand All @@ -143,7 +143,7 @@ abstract class V1AdRepoBaseTest {
debug = AdDebug(mode = workMode),
),
) { response ->
val responseObj = response.body<AdOffersResponse>()
val responseObj = response.body<IResponse>() as AdOffersResponse
assertEquals(200, response.status.value)
assertNotEquals(0, responseObj.ads?.size)
assertEquals(uuidSup, responseObj.ads?.first()?.id)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ internal abstract class AdRepoBaseV2Test {
prepareCtx(MkplAdStub.prepareResult {
id = MkplAdId(uuidNew)
ownerId = MkplUserId.NONE
lock = MkplAdLock(uuidNew)
// lock = MkplAdLock.NONE
lock = MkplAdLock.NONE
})
.toTransportCreate()
)
Expand All @@ -50,10 +49,7 @@ internal abstract class AdRepoBaseV2Test {
ad = MkplAdStub.prepareResult { title = "add" }.toTransportUpdate(),
debug = debug,
),
prepareCtx(MkplAdStub.prepareResult {
title = "add"
lock = MkplAdLock(uuidNew)
})
prepareCtx(MkplAdStub.prepareResult { title = "add" })
.toTransportUpdate()
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ class BizRepoDeleteTest {
ownerId = userId,
adType = MkplDealSide.DEMAND,
visibility = MkplVisibility.VISIBLE_PUBLIC,
lock = MkplAdLock("123-234-abc-ABC"),
)
private val repo = AdRepositoryMock(
invokeReadAd = {
Expand All @@ -51,7 +50,7 @@ class BizRepoDeleteTest {
fun repoDeleteSuccessTest() = runTest {
val adToUpdate = MkplAd(
id = MkplAdId("123"),
lock = MkplAdLock("123-234-abc-ABC"),
lock = MkplAdLock("123"),
)
val ctx = MkplContext(
command = command,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class BizRepoUpdateTest {
description = "xyz",
adType = MkplDealSide.DEMAND,
visibility = MkplVisibility.VISIBLE_TO_GROUP,
lock = MkplAdLock("123-234-abc-ABC"),
lock = MkplAdLock("123"),
)
val ctx = MkplContext(
command = command,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ fun repoNotFoundTest(command: MkplCommand) = runTest {
description = "xyz",
adType = MkplDealSide.DEMAND,
visibility = MkplVisibility.VISIBLE_TO_GROUP,
lock = MkplAdLock("123-234-abc-ABC"),
lock = MkplAdLock("123"),
),
)
processor.exec(ctx)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ abstract class BaseBizValidationTest {
private val repo = AdRepoInitialized(
repo = AdRepoInMemory(),
initObjects = listOf(
MkplAdStub.prepareResult { },
MkplAdStub.get(),
),
)
private val settings by lazy { MkplCorSettings(repoTest = repo) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ package ru.otus.otuskotlin.marketplace.common.repo

import ru.otus.otuskotlin.marketplace.common.models.MkplAd
import ru.otus.otuskotlin.marketplace.common.models.MkplAdId
import ru.otus.otuskotlin.marketplace.common.models.MkplAdLock

data class DbAdIdRequest(
val id: MkplAdId,
val lock: MkplAdLock = MkplAdLock.NONE,
) {
constructor(ad: MkplAd): this(ad.id, ad.lock)
constructor(ad: MkplAd): this(ad.id)
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
package ru.otus.otuskotlin.marketplace.common.repo

import ru.otus.otuskotlin.marketplace.common.helpers.errorSystem
import ru.otus.otuskotlin.marketplace.common.models.MkplAd
import ru.otus.otuskotlin.marketplace.common.models.MkplAdId
import ru.otus.otuskotlin.marketplace.common.models.MkplAdLock
import ru.otus.otuskotlin.marketplace.common.models.MkplError
import ru.otus.otuskotlin.marketplace.common.repo.exceptions.RepoConcurrencyException
import ru.otus.otuskotlin.marketplace.common.repo.exceptions.RepoException

const val ERROR_GROUP_REPO = "repo"

Expand All @@ -27,38 +22,3 @@ val errorEmptyId = DbAdResponseErr(
message = "Id must not be null or blank"
)
)

fun errorRepoConcurrency(
oldAd: MkplAd,
expectedLock: MkplAdLock,
exception: Exception = RepoConcurrencyException(
id = oldAd.id,
expectedLock = expectedLock,
actualLock = oldAd.lock,
),
) = DbAdResponseErrWithData(
ad = oldAd,
err = MkplError(
code = "$ERROR_GROUP_REPO-concurrency",
group = ERROR_GROUP_REPO,
field = "lock",
message = "The object with ID ${oldAd.id.asString()} has been changed concurrently by another user or process",
exception = exception,
)
)

fun errorEmptyLock(id: MkplAdId) = DbAdResponseErr(
MkplError(
code = "$ERROR_GROUP_REPO-lock-empty",
group = ERROR_GROUP_REPO,
field = "lock",
message = "Lock for Ad ${id.asString()} is empty that is not admitted"
)
)

fun errorDb(e: RepoException) = DbAdResponseErr(
errorSystem(
violationCode = "dbLockEmpty",
e = e
)
)
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import kotlinx.coroutines.sync.withLock
import ru.otus.otuskotlin.marketplace.common.helpers.errorSystem
import ru.otus.otuskotlin.marketplace.common.models.*
import ru.otus.otuskotlin.marketplace.common.repo.*
import ru.otus.otuskotlin.marketplace.common.repo.exceptions.RepoEmptyLockException
import ru.otus.otuskotlin.marketplace.repo.common.IRepoAdInitializable
import kotlin.time.Duration
import kotlin.time.Duration.Companion.minutes
Expand All @@ -31,7 +30,7 @@ class AdRepoInMemory(

override suspend fun createAd(rq: DbAdRequest): IDbAdResponse = tryAdMethod {
val key = randomUuid()
val ad = rq.ad.copy(id = MkplAdId(key), lock = MkplAdLock(randomUuid()))
val ad = rq.ad.copy(id = MkplAdId(key))
val entity = AdEntity(ad)
mutex.withLock {
cache.put(key, entity)
Expand All @@ -53,16 +52,13 @@ class AdRepoInMemory(
val rqAd = rq.ad
val id = rqAd.id.takeIf { it != MkplAdId.NONE } ?: return@tryAdMethod errorEmptyId
val key = id.asString()
val oldLock = rqAd.lock.takeIf { it != MkplAdLock.NONE } ?: return errorEmptyLock(id)

mutex.withLock {
val oldAd = cache.get(key)?.toInternal()
when {
oldAd == null -> errorNotFound(id)
oldAd.lock == MkplAdLock.NONE -> errorDb(RepoEmptyLockException(id))
oldAd.lock != oldLock -> errorRepoConcurrency(oldAd, oldLock)
else -> {
val newAd = rqAd.copy(lock = MkplAdLock(randomUuid()))
val newAd = rqAd.copy()
val entity = AdEntity(newAd)
cache.put(key, entity)
DbAdResponseOk(newAd)
Expand All @@ -75,14 +71,11 @@ class AdRepoInMemory(
override suspend fun deleteAd(rq: DbAdIdRequest): IDbAdResponse = tryAdMethod {
val id = rq.id.takeIf { it != MkplAdId.NONE } ?: return@tryAdMethod errorEmptyId
val key = id.asString()
val oldLock = rq.lock.takeIf { it != MkplAdLock.NONE } ?: return errorEmptyLock(id)

mutex.withLock {
val oldAd = cache.get(key)?.toInternal()
when {
oldAd == null -> errorNotFound(id)
oldAd.lock == MkplAdLock.NONE -> errorDb(RepoEmptyLockException(id))
oldAd.lock != oldLock -> errorRepoConcurrency(oldAd, oldLock)
else -> {
cache.invalidate(key)
DbAdResponseOk(oldAd)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import ru.otus.otuskotlin.marketplace.repo.inmemory.AdRepoInMemory

class AdRepoInMemoryCreateTest : RepoAdCreateTest() {
override val repo = AdRepoInitialized(
AdRepoInMemory(randomUuid = { lockNew.asString() }),
AdRepoInMemory(randomUuid = { uuidNew.asString() }),
initObjects = initObjects,
)
}
Expand Down Expand Up @@ -32,7 +32,7 @@ class AdRepoInMemorySearchTest : RepoAdSearchTest() {

class AdRepoInMemoryUpdateTest : RepoAdUpdateTest() {
override val repo = AdRepoInitialized(
AdRepoInMemory(randomUuid = { lockNew.asString() }),
AdRepoInMemory(),
initObjects = initObjects,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,16 @@ package ru.otus.otuskotlin.marketplace.backend.repo.tests
import ru.otus.otuskotlin.marketplace.common.models.*

abstract class BaseInitAds(private val op: String): IInitObjects<MkplAd> {
open val lockOld: MkplAdLock = MkplAdLock("20000000-0000-0000-0000-000000000001")
open val lockBad: MkplAdLock = MkplAdLock("20000000-0000-0000-0000-000000000009")

fun createInitTestModel(
suf: String,
ownerId: MkplUserId = MkplUserId("owner-123"),
adType: MkplDealSide = MkplDealSide.DEMAND,
lock: MkplAdLock = lockOld,
) = MkplAd(
id = MkplAdId("ad-repo-$op-$suf"),
title = "$suf stub",
description = "$suf stub description",
ownerId = ownerId,
visibility = MkplVisibility.VISIBLE_TO_OWNER,
adType = adType,
lock = lock,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import kotlin.test.*

abstract class RepoAdCreateTest {
abstract val repo: IRepoAdInitializable
protected open val lockNew: MkplAdLock = MkplAdLock("20000000-0000-0000-0000-000000000002")
protected open val uuidNew = MkplAdId("10000000-0000-0000-0000-000000000001")

private val createObj = MkplAd(
title = "create object",
Expand All @@ -22,8 +22,9 @@ abstract class RepoAdCreateTest {
@Test
fun createSuccess() = runRepoTest {
val result = repo.createAd(DbAdRequest(createObj))
val expected = createObj
assertIs<DbAdResponseOk>(result)
val expected = createObj.copy(id = result.data.id)
assertEquals(uuidNew, result.data.id)
assertEquals(expected.title, result.data.title)
assertEquals(expected.description, result.data.description)
assertEquals(expected.adType, result.data.adType)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,40 +11,28 @@ import kotlin.test.assertNotNull
abstract class RepoAdDeleteTest {
abstract val repo: IRepoAd
protected open val deleteSucc = initObjects[0]
protected open val deleteConc = initObjects[1]
protected open val notFoundId = MkplAdId("ad-repo-delete-notFound")

@Test
fun deleteSuccess() = runRepoTest {
val lockOld = deleteSucc.lock
val result = repo.deleteAd(DbAdIdRequest(deleteSucc.id, lock = lockOld))
val result = repo.deleteAd(DbAdIdRequest(deleteSucc.id))
assertIs<DbAdResponseOk>(result)
assertEquals(deleteSucc.title, result.data.title)
assertEquals(deleteSucc.description, result.data.description)
}

@Test
fun deleteNotFound() = runRepoTest {
val result = repo.readAd(DbAdIdRequest(notFoundId, lock = lockOld))
val result = repo.readAd(DbAdIdRequest(notFoundId))

assertIs<DbAdResponseErr>(result)
val error = result.errors.find { it.code == "repo-not-found" }
assertNotNull(error)
}

@Test
fun deleteConcurrency() = runRepoTest {
val result = repo.deleteAd(DbAdIdRequest(deleteConc.id, lock = lockBad))

assertIs<DbAdResponseErrWithData>(result)
val error = result.errors.find { it.code == "repo-concurrency" }
assertNotNull(error)
}

companion object : BaseInitAds("delete") {
override val initObjects: List<MkplAd> = listOf(
createInitTestModel("delete"),
createInitTestModel("deleteLock"),
)
}
}
Loading

0 comments on commit 319ae87

Please sign in to comment.