From 793b3b52fa74f69ce297814f53ff359cc0d4d80a Mon Sep 17 00:00:00 2001 From: rnentjes Date: Sat, 6 Sep 2025 13:37:34 +0200 Subject: [PATCH] Add detailed documentation in README.md for setup and usage --- readme.md | 182 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 readme.md diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..3c2ff54 --- /dev/null +++ b/readme.md @@ -0,0 +1,182 @@ +# Simple Persistence for Kotlin + +A lightweight, file-based persistence library for Kotlin applications that provides a simple way to store, retrieve, and query objects. + +## Available on Maven Central + +```kotlin +// Gradle Kotlin DSL +implementation("nl.astraeus:simple-persistence-kotlin:1.1.5") +``` + +```groovy +// Gradle Groovy DSL +implementation 'nl.astraeus:simple-persistence-kotlin:1.1.5' +``` + +```xml + + + nl.astraeus + simple-persistence-kotlin + 1.1.5 + +``` + +## Features + +- Simple and intuitive API for persisting Kotlin objects +- Transaction support with ACID properties +- Optimistic locking to handle concurrent modifications +- Flexible indexing for efficient querying +- Object references and collections handling +- Encryption support for sensitive data +- Snapshot and transaction log capabilities +- File-based storage with automatic cleanup + +## Quick Start + +### Define your model + +```kotlin +class Person( + override var id: Long = 0, + override var version: Long = 0, + val name: String, + val age: Int, + company: Company? = null +) : Persistable, Cloneable { + var company: Company? by nullableReference(company) + + companion object { + private const val serialVersionUID: Long = 1L + } +} + +class Company( + override var id: Long = 0, + override var version: Long = 0, + val name: String +) : Persistable, Cloneable { + val persons: MutableCollection = referenceCollection() + + companion object { + private const val serialVersionUID: Long = 1L + } +} +``` + +### Initialize the persistence manager + +```kotlin +val persistent = Persistent( + directory = File("data", "my-app"), + indexes = arrayOf( + index("name") { p -> (p as? Person)?.name ?: "" }, + index("age") { p -> (p as? Person)?.age ?: -1 }, + index("name") { p -> (p as? Company)?.name ?: "" } + ) +) +``` + +### Perform CRUD operations + +```kotlin +// Create or update +persistent.transaction { + val person = Person( + id = 1L, + name = "John Doe", + age = 30 + ) + + val company = Company( + id = 1L, + name = "ACME Inc." + ) + + person.company = company + company.persons.add(person) + + store(person) + store(company) +} + +// Read +persistent.query { + val person = find(1L) + println("Found person: $person") + + // Query by index + val persons: List = findByIndex("age", 30) + + // Search with predicate + val results = search(Person::class) { p -> p.name.startsWith("John") } +} + +// Delete +persistent.transaction { + val person = find(1L) + if (person != null) { + delete(person) + } +} +``` + +## How it works + +- In-memory model: Your objects live in memory during normal operation for fast reads and writes. +- Durable writes: Every create/update/delete inside a transaction is appended to on-disk transaction log files (*.trn). This is a write-ahead log approach. +- Startup recovery: On application startup, the library replays the transaction logs (and any snapshot, if present) to rebuild the in-memory model. +- Snapshots: You can create a compact on-disk snapshot (*.snp) of the current in-memory state. On the next startup, the snapshot is loaded first and only the newer transaction log files are replayed. This keeps startup time low without losing durability. + +Tip: Call snapshot() periodically (or on controlled shutdown) and use removeOldFiles() to prune obsolete logs after a successful snapshot. + +## Advanced Features + +### Indexing + +```kotlin +// Define complex indexes +val persistent = Persistent( + directory = File("data", "my-app"), + indexes = arrayOf( + index("ageOver30") { p -> ((p as? Person)?.age ?: 0) > 30 } + ) +) + +// Query using indexes +persistent.query { + findByIndex("ageOver30", true).forEach { person -> + println("Person over 30: ${person.name}") + } +} +``` + +### Transactions + +```kotlin +// Read-only query +persistent.query { + // Only read operations allowed +} + +// Read-write transaction +persistent.transaction { + // Both read and write operations allowed +} +``` + +### Snapshots and Maintenance + +```kotlin +// Create a snapshot of the current state +persistent.snapshot() + +// Remove old transaction log files +persistent.removeOldFiles() +``` + +## License + +This project is licensed under the MIT License - see the LICENSE file for details.