-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #11 from y9san9/master
KDS 3.0
- Loading branch information
Showing
54 changed files
with
749 additions
and
652 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,6 @@ | ||
object AppInfo { | ||
const val PACKAGE = "fun.kotlingang.kds" | ||
const val VERSION = "2.6" | ||
const val ARTIFACT_ID = "kds" | ||
const val VERSION = "3.0.3" | ||
const val NAME = "Kotlin Data Storage" | ||
const val DESCRIPTION = "Multiplatform Coroutine-Based Kotlin Library for storing data via kotlinx.serialization" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1 @@ | ||
import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler | ||
|
||
|
||
val KotlinDependencyHandler.utils get() = project(":utils") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1 @@ | ||
rootProject.name = "kds" | ||
|
||
include("utils") |
4 changes: 4 additions & 0 deletions
4
src/commonJsMain/kotlin/fun/kotlingang/kds/sync/synchronized.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
package `fun`.kotlingang.kds.sync | ||
|
||
|
||
internal actual inline fun <R> platformSynchronized(lock: Any, block: () -> R) = block() |
8 changes: 8 additions & 0 deletions
8
src/commonJsMain/kotlin/fun/kotlingang/kds/test/launchTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package `fun`.kotlingang.kds.test | ||
|
||
import `fun`.kotlingang.kds.extensions.any.unit | ||
import kotlinx.coroutines.CoroutineScope | ||
import kotlinx.coroutines.launch | ||
|
||
|
||
actual fun CoroutineScope.launchTest(block: suspend CoroutineScope.() -> Unit) = launch { block() }.unit |
54 changes: 54 additions & 0 deletions
54
src/commonMain/kotlin/fun/kotlingang/kds/KAsyncDataStorage.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
@file:Suppress("MemberVisibilityCanBePrivate") | ||
|
||
package `fun`.kotlingang.kds | ||
|
||
import `fun`.kotlingang.kds.composition.AsyncCommitPerformer | ||
import `fun`.kotlingang.kds.composition.AsyncCommittable | ||
import `fun`.kotlingang.kds.manager.AsyncDataManager | ||
import `fun`.kotlingang.kds.sync.platformSynchronized | ||
import kotlinx.coroutines.* | ||
import kotlinx.coroutines.sync.Mutex | ||
import kotlinx.coroutines.sync.withLock | ||
import kotlinx.serialization.json.Json | ||
import kotlinx.serialization.json.JsonElement | ||
|
||
|
||
class KAsyncDataStorage @OptIn(DelicateCoroutinesApi::class) constructor ( | ||
json: Json = Json, | ||
scope: CoroutineScope = GlobalScope + SupervisorJob() + CoroutineName("KDS Coroutine"), | ||
private val manager: AsyncDataManager | ||
) : KBlockingDataStorage(json, manager) { | ||
private var asyncData: Map<String, JsonElement>? = null | ||
|
||
override fun getOrLoadData() = platformSynchronized(lock = this) { | ||
asyncData ?: manager.loadDataBlocking().parseData().also { asyncData = it } | ||
}.toMutableMap() | ||
|
||
private val loadDataMutex = Mutex() | ||
|
||
/** | ||
* The worst case may be when data will be loaded twice but it is not problem | ||
* since library is recommended to use on small data. | ||
* *It is impossible when using functions with their contacts. | ||
*/ | ||
suspend fun loadData() = loadDataMutex.withLock { | ||
if(asyncData != null) { | ||
val data = manager.loadData().parseData() | ||
platformSynchronized(lock = this) { | ||
if (asyncData != null) { | ||
asyncData = data | ||
} | ||
} | ||
} | ||
} | ||
|
||
private val commitPerformer = AsyncCommitPerformer(scope) { manager.saveData(data.encodeData()) } | ||
|
||
suspend fun commit() = commitPerformer.commit() | ||
fun launchCommit() = commitPerformer.launchCommit() | ||
|
||
override fun performAutoSave() { | ||
if(autoSave) | ||
launchCommit() | ||
} | ||
} |
94 changes: 94 additions & 0 deletions
94
src/commonMain/kotlin/fun/kotlingang/kds/KBlockingDataStorage.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
@file:Suppress("MemberVisibilityCanBePrivate") | ||
|
||
package `fun`.kotlingang.kds | ||
|
||
import `fun`.kotlingang.kds.annotation.DelicateKDSApi | ||
import `fun`.kotlingang.kds.composition.AutoSaveController | ||
import `fun`.kotlingang.kds.composition.JsonReferencesProxy | ||
import `fun`.kotlingang.kds.extensions.any.unit | ||
import `fun`.kotlingang.kds.manager.BlockingDataManager | ||
import `fun`.kotlingang.kds.mutate.* | ||
import kotlinx.serialization.* | ||
import kotlinx.serialization.json.Json | ||
import kotlinx.serialization.json.JsonElement | ||
|
||
|
||
open class KBlockingDataStorage ( | ||
val json: Json = Json, | ||
private val manager: BlockingDataManager | ||
) { | ||
@DelicateKDSApi | ||
val autoSaveController = AutoSaveController() | ||
@OptIn(DelicateKDSApi::class) | ||
val autoSave by autoSaveController::autoSave | ||
|
||
/** | ||
* [mutate], [mutateBlocking], [mutateCommit] should be used instead | ||
*/ | ||
@DelicateKDSApi | ||
inline fun withoutSave(crossinline block: () -> Unit) { | ||
autoSaveController.turnOff() | ||
block() | ||
autoSaveController.tryTurnOn() | ||
} | ||
|
||
protected open fun getOrLoadData() = manager.loadDataBlocking().parseData().toMutableMap() | ||
|
||
private val dataProxy by lazy { | ||
JsonReferencesProxy(json, getOrLoadData()) | ||
} | ||
|
||
protected val data get() = dataProxy.publicData | ||
|
||
fun loadDataBlocking() = dataProxy.unit | ||
|
||
/** | ||
* Stores all references to data in case references were changed | ||
*/ | ||
@DelicateKDSApi | ||
fun applyMutations() = dataProxy.applyMutations() | ||
|
||
@DelicateKDSApi | ||
fun <T> set(name: String, serializer: KSerializer<T>, value: T) { | ||
dataProxy.set(name, serializer, value) | ||
performAutoSave() | ||
} | ||
|
||
@DelicateKDSApi | ||
inline fun <reified T> set(name: String, value: @Serializable T) = | ||
set(name, json.serializersModule.serializer(), value) | ||
|
||
@DelicateKDSApi | ||
fun <T> get(name: String, serializer: KSerializer<T>, default: () -> T) = | ||
dataProxy.get(name, serializer, default) | ||
|
||
@DelicateKDSApi | ||
inline fun <reified T> get(name: String, noinline default: () -> T) = | ||
get(name, json.serializersModule.serializer(), default) | ||
|
||
fun exists(name: String) = dataProxy.exists(name) | ||
|
||
fun clear(name: String) { | ||
dataProxy.clear(name) | ||
performAutoSave() | ||
} | ||
|
||
fun clear() { | ||
dataProxy.clear() | ||
performAutoSave() | ||
} | ||
|
||
fun commitBlocking() = manager.saveDataBlocking(data.encodeData()) | ||
|
||
/** | ||
* For [KBlockingDataStorage] auto save way is blocking way while | ||
* for [KAsyncDataStorage] auto save way is async way | ||
*/ | ||
protected open fun performAutoSave() { | ||
if(autoSave) | ||
commitBlocking() | ||
} | ||
|
||
protected fun String.parseData() = json.decodeFromString<Map<String, JsonElement>>(string = this) | ||
protected fun Map<String, JsonElement>.encodeData() = json.encodeToString(value = this) | ||
} |
Oops, something went wrong.