
Offers a persistent storage solution using LMDB for efficient key-value storage with ACID transactions, type-safe serialization, and shared environment patterns for state and saga management.
LMDB-based persistent storage implementation for the duks library.
This library provides persistent storage implementations for duks using LMDB (Lightning Memory-Mapped Database). LMDB is an ultra-fast, ultra-compact key-value embedded data store that provides:
Add the dependency to your project:
dependencies {
implementation("io.github.crowded-libs:duks-storage-lmdb:0.1.3")
}The recommended way to use this library is to create a single LMDB environment and pass it to your storage instances:
import duks.storage.lmdb.*
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.encodeToString
import kotlinx.serialization.decodeFromString
// Define your state
@Serializable
data class AppState(
val counter: Int,
val message: String
)
// Create a serializer
class JsonSerializer<T> : Serializer<T> {
override fun serialize(value: T): ByteArray {
return Json.encodeToString(value).encodeToByteArray()
}
override fun deserialize(bytes: ByteArray): T {
return Json.decodeFromString(bytes.decodeToString())
}
}
// Create storage configuration
val config = LmdbStorageConfig(
path = "/path/to/database",
mapSize = 10 * 1024 * 1024 // 10MB
)
// Create the LMDB environment
val env = createLmdbEnv(config)
// Create state storage
val stateStorage = LmdbStateStorage(
env = env,
serializer = JsonSerializer<AppState>()
)
// Create saga storage
val sagaStorage = LmdbSagaStorage(
env = env,
sagaSerializer = JsonSerializer<PersistedSagaInstance>()
)
// Use the storages
val state = AppState(counter = 1, message = "Hello")
stateStorage.save(state)
val sagaInstance = SagaInstance(
id = "saga-123",
sagaName = "OrderSaga",
state = OrderSagaState(orderId = "order-456"),
startedAt = Clock.System.now(),
lastUpdatedAt = Clock.System.now()
)
sagaStorage.save(sagaInstance.id, sagaInstance)
// Remember to close the environment when done
env.close()You can create multiple storage instances with different database names within the same environment:
// Create a shared environment
val env = createLmdbEnv(config)
// Create multiple state storages
val userStateStorage = LmdbStateStorage(
env = env,
serializer = JsonSerializer<UserState>(),
databaseName = "user_state"
)
val configStateStorage = LmdbStateStorage(
env = env,
serializer = JsonSerializer<ConfigState>(),
databaseName = "config_state"
)
val sagaStorage = LmdbSagaStorage(
env = env,
sagaSerializer = JsonSerializer<PersistedSagaInstance>(),
databaseName = "sagas"
)
// Or use the general-purpose key-value storage
val kvStorage = LmdbKeyValueStorage(
env = env,
databaseName = "custom_data"
)For custom use cases, you can use the LmdbKeyValueStorage class directly:
// Define your custom data type
@Serializable
data class UserData(
val id: String,
val name: String,
val email: String
)
// Create type-safe storage
val kvStorage = LmdbKeyValueStorage(
env = env,
serializer = JsonSerializer<UserData>(),
databaseName = "user_data"
)
// Store and retrieve typed data
val user = UserData("123", "John Doe", "john@example.com")
kvStorage.put("user:123", user)
val retrieved = kvStorage.get("user:123")
val exists = kvStorage.exists("user:123")
kvStorage.delete("user:123")
// Get all keys
val allKeys = kvStorage.getAllKeys()The library uses a Serializer interface to allow flexibility in how data is serialized:
interface Serializer<T> {
fun serialize(value: T): ByteArray
fun deserialize(bytes: ByteArray): T
}You can implement this interface using any serialization library:
LmdbKeyValueStorage<T> - Generic key-value storage with built-in serialization
LmdbStateStorage<T> - StateStorage implementation for duks
LmdbKeyValueStorage
LmdbSagaStorage - SagaStorage implementation for duks
LmdbKeyValueStorage
LmdbKeyValueStorage directly for custom storage needsThis library supports the following Kotlin Multiplatform targets:
Apache License 2.0
LMDB-based persistent storage implementation for the duks library.
This library provides persistent storage implementations for duks using LMDB (Lightning Memory-Mapped Database). LMDB is an ultra-fast, ultra-compact key-value embedded data store that provides:
Add the dependency to your project:
dependencies {
implementation("io.github.crowded-libs:duks-storage-lmdb:0.1.3")
}The recommended way to use this library is to create a single LMDB environment and pass it to your storage instances:
import duks.storage.lmdb.*
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.encodeToString
import kotlinx.serialization.decodeFromString
// Define your state
@Serializable
data class AppState(
val counter: Int,
val message: String
)
// Create a serializer
class JsonSerializer<T> : Serializer<T> {
override fun serialize(value: T): ByteArray {
return Json.encodeToString(value).encodeToByteArray()
}
override fun deserialize(bytes: ByteArray): T {
return Json.decodeFromString(bytes.decodeToString())
}
}
// Create storage configuration
val config = LmdbStorageConfig(
path = "/path/to/database",
mapSize = 10 * 1024 * 1024 // 10MB
)
// Create the LMDB environment
val env = createLmdbEnv(config)
// Create state storage
val stateStorage = LmdbStateStorage(
env = env,
serializer = JsonSerializer<AppState>()
)
// Create saga storage
val sagaStorage = LmdbSagaStorage(
env = env,
sagaSerializer = JsonSerializer<PersistedSagaInstance>()
)
// Use the storages
val state = AppState(counter = 1, message = "Hello")
stateStorage.save(state)
val sagaInstance = SagaInstance(
id = "saga-123",
sagaName = "OrderSaga",
state = OrderSagaState(orderId = "order-456"),
startedAt = Clock.System.now(),
lastUpdatedAt = Clock.System.now()
)
sagaStorage.save(sagaInstance.id, sagaInstance)
// Remember to close the environment when done
env.close()You can create multiple storage instances with different database names within the same environment:
// Create a shared environment
val env = createLmdbEnv(config)
// Create multiple state storages
val userStateStorage = LmdbStateStorage(
env = env,
serializer = JsonSerializer<UserState>(),
databaseName = "user_state"
)
val configStateStorage = LmdbStateStorage(
env = env,
serializer = JsonSerializer<ConfigState>(),
databaseName = "config_state"
)
val sagaStorage = LmdbSagaStorage(
env = env,
sagaSerializer = JsonSerializer<PersistedSagaInstance>(),
databaseName = "sagas"
)
// Or use the general-purpose key-value storage
val kvStorage = LmdbKeyValueStorage(
env = env,
databaseName = "custom_data"
)For custom use cases, you can use the LmdbKeyValueStorage class directly:
// Define your custom data type
@Serializable
data class UserData(
val id: String,
val name: String,
val email: String
)
// Create type-safe storage
val kvStorage = LmdbKeyValueStorage(
env = env,
serializer = JsonSerializer<UserData>(),
databaseName = "user_data"
)
// Store and retrieve typed data
val user = UserData("123", "John Doe", "john@example.com")
kvStorage.put("user:123", user)
val retrieved = kvStorage.get("user:123")
val exists = kvStorage.exists("user:123")
kvStorage.delete("user:123")
// Get all keys
val allKeys = kvStorage.getAllKeys()The library uses a Serializer interface to allow flexibility in how data is serialized:
interface Serializer<T> {
fun serialize(value: T): ByteArray
fun deserialize(bytes: ByteArray): T
}You can implement this interface using any serialization library:
LmdbKeyValueStorage<T> - Generic key-value storage with built-in serialization
LmdbStateStorage<T> - StateStorage implementation for duks
LmdbKeyValueStorage
LmdbSagaStorage - SagaStorage implementation for duks
LmdbKeyValueStorage
LmdbKeyValueStorage directly for custom storage needsThis library supports the following Kotlin Multiplatform targets:
Apache License 2.0