A powerful, transactional state management library for Kotlin Multiplatform applications that provides ACID guarantees for application state.
- Introduction
- Installation
- Core Concepts
- Advanced Topics
- Best Practices
- API Reference
- Performance Guidelines
- Testing
- FAQ
Vault is a type-safe, transaction-based state management library designed specifically for Kotlin Multiplatform applications. It provides ACID (Atomicity, Consistency, Isolation, Durability) guarantees while maintaining high performance through lockless architecture.
- π ACID Transactions
- π Side Effect System
- π Bi-directional state
- π― Middleware System
- π Lock-free concurrency
Add to your build.gradle.kts
:
dependencies {
implementation("com.vynatix:vault:1.0.0")
}
States are the fundamental building blocks in Vault. They represent immutable, type-safe data containers.
object UserVault : Vault<UserVault>() {
val profile by state { Profile("", "", 0, "") }
val followers by state { 0 }
val posts by state { emptyList<Post>() }
}
Actions provide atomic state mutations with automatic rollback on failure.
fun updateProfile(newProfile: Profile) = action {
profile mutate newProfile
}
Effects handle side-effects reactively based on state changes.
profile effect {
println("Profile updated: $it")
}
Middleware intercepts transactions for cross-cutting concerns.
class LoggingMiddleware : Middleware<UserVault>() {
override fun onTransactionStarted(context: MiddlewareContext<UserVault>) {
println("Transaction started: ${context.transaction.id}")
}
}
Transactions in Vault provide:
- Atomic state mutations
- Automatic rollback on failure
- State change tracking
- Transaction metadata
val result = vault action {
profile mutate newProfile
followers mutate newFollowerCount
if (someCondition) {
throw RuntimeException("Rollback all changes")
}
}
Bridges enable bi-directional state synchronization:
loggedIn.bridge(object : Bridge<Boolean> {
private val observers = mutableListOf<(Boolean) -> Unit>()
private var value: Boolean? = null
override fun observe(observer: (Boolean) -> Unit): Disposable {
value?.let(observer)
observers.add(observer)
return Disposable { observers.remove(observer) }
}
override fun publish(value: Boolean): Boolean {
this.value = value
observers.forEach { it(value) }
return true
}
})
Vault uses a sophisticated lock-free architecture for high performance:
- Custom
VaultLock
implementation - Reentrant locking support
- Automatic deadlock prevention
- Optimistic concurrency control
-
State Design
- Keep states granular and focused
- Use transformers for validation
- Clean up disposables
- Handle errors appropriately
-
Transaction Management
- Keep transactions atomic and focused
- Use proper error handling
- Clean up resources
- Monitor transaction performance
-
Middleware Usage
- Keep middleware focused on cross-cutting concerns
- Handle errors gracefully
- Monitor middleware performance
- Clean up resources
-
Testing
- Test all state transitions
- Verify rollback behavior
- Test concurrent access
- Validate transformers
-
Lock Management
- Minimize lock duration
- Use appropriate granularity
- Monitor lock contention
- Handle lock timeouts
-
Transaction Optimization
- Keep transactions short
- Batch operations when appropriate
- Monitor transaction performance
- Use appropriate isolation levels
-
Resource Management
- Clean up disposables
- Monitor memory usage
- Handle resource leaks
- Use appropriate pooling
Vault provides comprehensive testing support through its TestVault
implementation:
class TestVault : Vault<TestVault>() {
val counter by state { 0 }
val text by state { "" }
val list by state { listOf<Int>() }
}
class StressTestRunner(
private val iterations: Int = 100000,
private val concurrentVaults: Int = 50,
private val complexOperations: Boolean = true
) {
// Stress testing implementation
}
A: Vault uses a lock-free architecture with optimistic concurrency control. Each state has its own lock, and transactions are automatically rolled back on conflicts.
A: All state changes within a failed transaction are automatically rolled back to their previous values.
A: Yes, Vault is designed for Kotlin Multiplatform and works across all supported platforms.
A: Vault uses proper resource cleanup through disposables and automatic transaction cleanup.
The base class for all vault implementations:
abstract class Vault<Self : Vault<Self>> {
fun middlewares(vararg middleware: Middleware<Self>)
fun action(action: Self.() -> Unit): TransactionResult
fun <T : Any> state(transformer: Transformer<T>? = null, initialize: Initializer<T>)
}
Represents an immutable state container:
interface State<T : Any> {
val value: T
}
Handles atomic state mutations:
class Transaction(val id: String) {
val status: TransactionStatus
val modifiedProperties: Set<State<out Any>>
fun rollback()
fun commit()
}
Intercepts transaction lifecycle events:
open class Middleware<T : Vault<T>> {
fun onTransactionStarted(context: MiddlewareContext<T>)
fun onTransactionCompleted(context: MiddlewareContext<T>)
fun onTransactionError(context: MiddlewareContext<T>, error: Throwable)
}
For more details, please refer to the API documentation or the source code.