Skip to content

Commit cddaafa

Browse files
committed
added MongoDBGamepediaCache.kt and kodein modules.
1 parent dd8eb97 commit cddaafa

File tree

8 files changed

+106
-62
lines changed

8 files changed

+106
-62
lines changed

core/build.gradle.kts

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import com.github.lamba92.gradle.utils.ktor
44

55
plugins {
66
id("dragalia-gradle-plugin")
7+
kotlin("plugin.serialization")
78
}
89

910
kotlin {

core/src/jvmMain/kotlin/com/github/lamba92/dragalialost/core/datasource/MongoDBGamepediaCache.kt

+73-45
Original file line numberDiff line numberDiff line change
@@ -3,58 +3,70 @@ package com.github.lamba92.dragalialost.core.datasource
33
import com.github.lamba92.dragalialost.data.datasource.GamepediaDatasourceCache
44
import com.github.lamba92.dragalialost.data.datasource.queries.*
55
import com.github.lamba92.dragalialost.data.rawresponses.*
6+
import com.mongodb.MongoWriteException
67
import kotlinx.coroutines.flow.asFlow
78
import kotlinx.coroutines.flow.collect
89
import kotlinx.coroutines.flow.onEach
910
import kotlinx.coroutines.runBlocking
11+
import kotlinx.serialization.Serializable
12+
import org.litote.kmongo.coroutine.CoroutineClient
13+
import org.litote.kmongo.coroutine.CoroutineCollection
1014
import org.litote.kmongo.coroutine.CoroutineDatabase
1115

12-
class MongoDBGamepediaCache private constructor(db: CoroutineDatabase) : GamepediaDatasourceCache {
16+
class MongoDBGamepediaCache private constructor(
17+
private val client: CoroutineClient,
18+
db: CoroutineDatabase
19+
) : GamepediaDatasourceCache {
1320

1421
companion object {
1522

16-
private suspend fun createCollections(db: CoroutineDatabase) {
17-
db.createCollection("adventurers")
18-
db.createCollection("dragons")
19-
db.createCollection("wyrmprints")
20-
db.createCollection("weapons")
21-
db.createCollection("abilities")
22-
db.createCollection("coAbilities")
23-
db.createCollection("skillsById")
24-
db.createCollection("skillsByName")
25-
db.createCollection("abilityLimitedGroup")
26-
db.createCollection("abilityGroup")
27-
db.createCollection("adventurerIcons")
28-
db.createCollection("adventurerPortraits")
29-
db.createCollection("dragonIcons")
30-
db.createCollection("dragonPortraits")
31-
db.createCollection("wyrmprintIcons")
32-
db.createCollection("wyrmprintPortraits")
33-
db.createCollection("abilityIcons")
34-
db.createCollection("coAbilityIcons")
35-
db.createCollection("skillIcons")
36-
}
23+
private suspend fun createCollections(db: CoroutineDatabase) = listOf(
24+
"adventurers", "dragons", "wyrmprints", "weapons", "abilities",
25+
"coAbilities", "skillsById", "skillsByName", "abilityLimitedGroup", "abilityGroup", "adventurerIcons",
26+
"adventurerPortraits", "dragonIcons", "dragonPortraits", "wyrmprintIcons", "wyrmprintPortraits",
27+
"abilityIcons", "coAbilityIcons", "skillIcons"
28+
).filter { it !in db.listCollectionNames() }
29+
.forEach { db.createCollection(it) }
3730

38-
suspend fun initialize(db: CoroutineDatabase): MongoDBGamepediaCache {
31+
suspend fun initialize(db: CoroutineDatabase, client: CoroutineClient): MongoDBGamepediaCache {
3932
createCollections(db)
40-
return MongoDBGamepediaCache(db)
33+
return MongoDBGamepediaCache(client, db)
4134
}
4235

43-
fun initializeBlocking(db: CoroutineDatabase) =
36+
fun initializeBlocking(db: CoroutineDatabase, client: CoroutineClient) =
4437
runBlocking {
45-
initialize(db)
38+
initialize(db, client)
4639
}
4740
}
4841

42+
@Serializable
4943
private data class AdventurerDocument(val _id: String, val data: AdventurerJSON)
44+
45+
@Serializable
5046
private data class DragonDocument(val _id: String, val data: DragonJSON)
47+
48+
@Serializable
5149
private data class WyrmprintDocument(val _id: String, val data: WyrmprintJSON)
50+
51+
@Serializable
5252
private data class WeaponDocument(val _id: String, val data: WeaponJSON)
53+
54+
@Serializable
5355
private data class AbilityDocument(val _id: String, val data: AbilityJSON)
56+
57+
@Serializable
5458
private data class CoAbilityDocument(val _id: String, val data: CoAbilityJSON)
59+
60+
@Serializable
5561
private data class SkillDocument(val _id: String, val data: SkillJSON)
62+
63+
@Serializable
5664
private data class AbilityLimitedGroupDocument(val _id: String, val data: AbilityLimitedGroupJSON)
65+
66+
@Serializable
5767
private data class AbilityGroupDocument(val _id: String, val data: AbilityGroupJSON)
68+
69+
@Serializable
5870
private data class ImageInfoDocument(val _id: String, val data: ImageInfoJSON)
5971

6072
private val adventurersCollection =
@@ -155,10 +167,10 @@ class MongoDBGamepediaCache private constructor(db: CoroutineDatabase) : Gameped
155167
abilityGroupsCollection.findOneById(id)?.data
156168

157169
override suspend fun getAdventurerIconById(id: String, variationId: String, rarity: Int) =
158-
adventurerIconsCollection.findOne("${id}_${variationId}_$rarity")?.data
170+
adventurerIconsCollection.findOneById("${id}_${variationId}_$rarity")?.data
159171

160172
override suspend fun getAdventurerPortraitById(id: String, variationId: String, rarity: Int) =
161-
adventurerPortraitsCollection.findOne("${id}_${variationId}_$rarity")?.data
173+
adventurerPortraitsCollection.findOneById("${id}_${variationId}_$rarity")?.data
162174

163175
override suspend fun getDragonIconById(id: String) =
164176
dragonIconsCollection.findOneById(id)?.data
@@ -221,53 +233,69 @@ class MongoDBGamepediaCache private constructor(db: CoroutineDatabase) : Gameped
221233
) =
222234
true
223235

236+
// private suspend fun <T> CoroutineClient.transaction(action: suspend (ClientSession) -> T) =
237+
// startSession().let {
238+
// it.startTransaction()
239+
// val r = action(it)
240+
// it.commitTransactionAndAwait()
241+
// r
242+
// }
243+
244+
private suspend fun <T : Any> CoroutineCollection<T>.insertOrUpdate(id: Any, document: T) {
245+
try {
246+
insertOne(document)
247+
} catch (e: MongoWriteException) {
248+
updateOneById(id, document)
249+
}
250+
}
251+
224252
override suspend fun cacheAbilityGroupsByGroupId(groupId: String, data: AbilityGroupJSON): Boolean {
225-
abilityGroupsCollection.updateOneById(groupId, AbilityGroupDocument(groupId, data))
253+
abilityGroupsCollection.insertOrUpdate(groupId, AbilityGroupDocument(groupId, data))
226254
return true
227255
}
228256

229257
override suspend fun cacheAdventurerByIds(id: String, variationId: String, data: AdventurerJSON): Boolean {
230-
adventurersCollection.updateOneById("${id}_$variationId", AdventurerDocument("${id}_$variationId", data))
258+
adventurersCollection.insertOrUpdate("${id}_$variationId", AdventurerDocument("${id}_$variationId", data))
231259
return true
232260
}
233261

234262
override suspend fun cacheDragonById(id: String, data: DragonJSON): Boolean {
235-
dragonsCollection.updateOneById(id, DragonDocument(id, data))
263+
dragonsCollection.insertOrUpdate(id, DragonDocument(id, data))
236264
return true
237265
}
238266

239267
override suspend fun cacheWyrmprintById(id: String, data: WyrmprintJSON): Boolean {
240-
wyrmprintsCollection.updateOneById(id, WyrmprintDocument(id, data))
268+
wyrmprintsCollection.insertOrUpdate(id, WyrmprintDocument(id, data))
241269
return true
242270
}
243271

244272
override suspend fun cacheWeaponById(id: String, data: WeaponJSON): Boolean {
245-
weaponsCollection.updateOneById(id, WeaponDocument(id, data))
273+
weaponsCollection.insertOrUpdate(id, WeaponDocument(id, data))
246274
return true
247275
}
248276

249277
override suspend fun cacheAbilityById(id: String, data: AbilityJSON): Boolean {
250-
abilitiesCollection.updateOneById(id, AbilityDocument(id, data))
278+
abilitiesCollection.insertOrUpdate(id, AbilityDocument(id, data))
251279
return true
252280
}
253281

254282
override suspend fun cacheCoAbilityById(id: String, data: CoAbilityJSON): Boolean {
255-
coAbilitiesCollection.updateOneById(id, CoAbilityDocument(id, data))
283+
coAbilitiesCollection.insertOrUpdate(id, CoAbilityDocument(id, data))
256284
return true
257285
}
258286

259287
override suspend fun cacheSkillById(id: String, data: SkillJSON): Boolean {
260-
skillsByIdCollection.updateOneById(id, SkillDocument(id, data))
288+
skillsByIdCollection.insertOrUpdate(id, SkillDocument(id, data))
261289
return true
262290
}
263291

264292
override suspend fun cacheSkillByName(name: String, data: SkillJSON): Boolean {
265-
skillsByNameCollection.updateOneById(name, SkillDocument(name, data))
293+
skillsByNameCollection.insertOrUpdate(name, SkillDocument(name, data))
266294
return true
267295
}
268296

269297
override suspend fun cacheAbilityLimitedGroupById(id: String, data: AbilityLimitedGroupJSON): Boolean {
270-
abilityLimitedGroupsCollection.updateOneById(id, AbilityLimitedGroupDocument(id, data))
298+
abilityLimitedGroupsCollection.insertOrUpdate(id, AbilityLimitedGroupDocument(id, data))
271299
return true
272300
}
273301

@@ -298,37 +326,37 @@ class MongoDBGamepediaCache private constructor(db: CoroutineDatabase) : Gameped
298326
}
299327

300328
override suspend fun cacheDragonIconById(id: String, data: ImageInfoJSON): Boolean {
301-
dragonIconsCollection.updateOneById(id, ImageInfoDocument(id, data))
329+
dragonIconsCollection.insertOrUpdate(id, ImageInfoDocument(id, data))
302330
return true
303331
}
304332

305333
override suspend fun cacheDragonPortraitById(id: String, data: ImageInfoJSON): Boolean {
306-
dragonPortraitsCollection.updateOneById(id, ImageInfoDocument(id, data))
334+
dragonPortraitsCollection.insertOrUpdate(id, ImageInfoDocument(id, data))
307335
return true
308336
}
309337

310338
override suspend fun cacheWyrmprintIconByIds(id: String, vestige: Int, data: ImageInfoJSON): Boolean {
311-
wyrmprintIconsCollection.updateOneById("${id}_$vestige", ImageInfoDocument("${id}_$vestige", data))
339+
wyrmprintIconsCollection.insertOrUpdate("${id}_$vestige", ImageInfoDocument("${id}_$vestige", data))
312340
return true
313341
}
314342

315343
override suspend fun cacheWyrmprintPortraitByIds(id: String, vestige: Int, data: ImageInfoJSON): Boolean {
316-
wyrmprintPortraitsCollection.updateOneById("${id}_$vestige", ImageInfoDocument("${id}_$vestige", data))
344+
wyrmprintPortraitsCollection.insertOrUpdate("${id}_$vestige", ImageInfoDocument("${id}_$vestige", data))
317345
return true
318346
}
319347

320348
override suspend fun cacheAbilityIconByFileName(fileName: String, data: ImageInfoJSON): Boolean {
321-
abilityIconsCollection.updateOneById(fileName, ImageInfoDocument(fileName, data))
349+
abilityIconsCollection.insertOrUpdate(fileName, ImageInfoDocument(fileName, data))
322350
return true
323351
}
324352

325353
override suspend fun cacheCoAbilityIconByFileName(fileName: String, data: ImageInfoJSON): Boolean {
326-
coAbilityIconsCollection.updateOneById(fileName, ImageInfoDocument(fileName, data))
354+
coAbilityIconsCollection.insertOrUpdate(fileName, ImageInfoDocument(fileName, data))
327355
return true
328356
}
329357

330358
override suspend fun cacheSkillIconByIconName(fileName: String, data: ImageInfoJSON): Boolean {
331-
skillIconsCollection.updateOneById(fileName, ImageInfoDocument(fileName, data))
359+
skillIconsCollection.insertOrUpdate(fileName, ImageInfoDocument(fileName, data))
332360
return true
333361
}
334362

data/src/commonMain/kotlin/com/github/lamba92/dragalialost/data/mappers/GenderMapper.kt

+5-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ import com.github.lamba92.dragalialost.domain.entities.enums.Gender
55
class GenderMapper : SingleFromRemoteMapper<String, Gender> {
66

77
override fun fromRemoteSingle(remote: String) =
8-
Gender.values().first { it.name.toLowerCase() == remote.toLowerCase() }
8+
try {
9+
Gender.valueOf(remote.toUpperCase())
10+
} catch (e: IllegalArgumentException) {
11+
Gender.OTHER
12+
}
913

1014
}

data/src/commonMain/kotlin/com/github/lamba92/dragalialost/data/mappers/RaceMapper.kt

+5-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ import com.github.lamba92.dragalialost.domain.entities.enums.Race.NOT_AVAILABLE
55

66
class RaceMapper : SingleFromRemoteMapper<String, Race> {
77
override fun fromRemoteSingle(remote: String) =
8-
if (remote.isBlank()) NOT_AVAILABLE
9-
else Race.values().first { it.name.toLowerCase() == remote.toLowerCase() }
8+
try {
9+
Race.valueOf(remote.toUpperCase())
10+
} catch (e: IllegalArgumentException) {
11+
NOT_AVAILABLE
12+
}
1013
}

data/src/commonMain/kotlin/com/github/lamba92/dragalialost/data/repositories/DragaliaLostRepositoryImplementation.kt

+9-6
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ class DragaliaLostRepositoryImplementation(
7878
}
7979
.map { adventurerMapper(it) }
8080
.filter { it in query }
81+
.catch {
82+
println("An adventurer errored: $it")
83+
}
8184
.toList()
8285

8386
@ExperimentalCoroutinesApi
@@ -115,10 +118,10 @@ class DragaliaLostRepositoryImplementation(
115118
)
116119
}
117120
}
118-
// .catch {
119-
// println("A dragon errored: $it")
120-
// }
121121
.map { dragonMapper(it) }
122+
.catch {
123+
println("An dragon errored: $it")
124+
}
122125
.filter { it in query }
123126
.toList()
124127

@@ -164,9 +167,9 @@ class DragaliaLostRepositoryImplementation(
164167
)
165168
}
166169
}
167-
// .catch {
168-
// println("A wyrmprint errored: $it")
169-
// }
170+
.catch {
171+
println("A wyrmprint errored: $it")
172+
}
170173
.map { wyrmprintMapper(it) }
171174
.filter { it in query }
172175
.toList()
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
package com.github.lamba92.dragalialost.domain.entities.enums
22

33
enum class Gender {
4-
MALE, FEMALE
5-
}
4+
MALE, FEMALE, OTHER
5+
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
package com.github.lamba92.dragalialost.domain.entities.enums
22

33
enum class Race {
4-
HUMAN, DRAGON, CRYSTALIA, SYLVAN, QILIN, TUTELARY, NOT_AVAILABLE, Android
4+
HUMAN, DRAGON, CRYSTALIA, SYLVAN, QILIN, TUTELARY, NOT_AVAILABLE, ANDROID, PLANT, ROKKAN
55
}

kodein-di/src/jvmMain/kotlin/com/github/lamba92/dragalialost/di/JvmUtils.kt

+10-5
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,29 @@ import org.kodein.di.Kodein
66
import org.kodein.di.erased.bind
77
import org.kodein.di.erased.instance
88
import org.kodein.di.erased.singleton
9+
import org.litote.kmongo.coroutine.CoroutineClient
910
import org.litote.kmongo.coroutine.CoroutineDatabase
1011
import org.litote.kmongo.coroutine.coroutine
1112
import org.litote.kmongo.reactivestreams.KMongo
1213

13-
fun dragaliaMongoDBCacheModule(host: String, port: Int, dbName: String) =
14+
fun dragaliaMongoDBCacheModule(host: String = "localhost", port: Int = 27017, dbName: String = "db") =
1415
Kodein.Module("Dragalia Lost Cache Module") {
16+
bind<CoroutineClient>() with singleton {
17+
KMongo.createClient("mongodb://$host:$port").coroutine
18+
}
1519
bind<CoroutineDatabase>() with singleton {
16-
KMongo.createClient("mongodb://$host:$port").coroutine.getDatabase(dbName)
20+
instance<CoroutineClient>().getDatabase(dbName)
1721
}
1822
bind<GamepediaDatasourceCache>() with singleton {
19-
MongoDBGamepediaCache.initializeBlocking(instance())
23+
MongoDBGamepediaCache.initializeBlocking(instance(), instance())
2024
}
2125
}
2226

23-
fun dragaliaMongoDBCacheModule(db: CoroutineDatabase) =
27+
fun dragaliaMongoDBCacheModule(db: CoroutineDatabase, client: CoroutineClient) =
2428
Kodein.Module("Dragalia Lost Cache Module") {
2529
bind<CoroutineDatabase>() with singleton { db }
30+
bind<CoroutineClient>() with singleton { client }
2631
bind<GamepediaDatasourceCache>() with singleton {
27-
MongoDBGamepediaCache.initializeBlocking(instance())
32+
MongoDBGamepediaCache.initializeBlocking(instance(), instance())
2833
}
2934
}

0 commit comments

Comments
 (0)