# feltdb
An embedded, durable state store for Rust. Records live in an append-only log on local disk. Several
records can change in one atomic transaction, a write can be conditional on the version you read, and a
transaction can carry an identity so that a retry after an uncertain outcome is recognized instead of
applied twice.
```toml
[dependencies]
feltdb = "0.2"
serde_json = "1"
```
```rust
use feltdb::{FeltDb, FlowError};
use serde_json::json;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let db = FeltDb::open("app.db")?;
// Create only if absent. A second create is refused in a way you can branch on.
db.insert_if_absent("orders:o-1", json!({ "status": "pending" }))?;
assert!(matches!(
db.insert_if_absent("orders:o-1", json!({})),
Err(FlowError::PreconditionFailed(_))
));
Ok(())
}
```
The crate documentation on docs.rs has a longer, tested example covering atomic transactions and safe
retries.
## What you can rely on
- Acknowledged writes and committed transaction ids survive closing and reopening the database, and a
process kill.
- An interrupted, unacknowledged append is discarded on open and reported; its retry is treated as a
first use.
- A transaction id names one payload. Reusing an id with a different payload hash fails with
`FlowError::TransactionIdPayloadMismatch` and writes nothing.
## What is not promised
- **Power-loss durability is unproven.** A flush hands bytes to the operating system; it does not force
them to stable storage. What survives a power cut depends on the filesystem, mount options and the
drive. See the repository's
[crash durability](https://github.com/rkendel1/flow_db/blob/main/docs/architecture/crash-durability.md)
note.
- **Only the supported API is covered by semver.** While the version is `0.x`, a breaking change to a
supported item is a minor-version bump. Everything behind the `unstable-internals` feature (fault
injection, diagnostics, implementation modules) carries no promise at all; do not enable it in
application code. The supported surface is listed in
[the Rust API contract](https://github.com/rkendel1/flow_db/blob/main/docs/reference/feltdb-rust-api.md).
- Plain `insert`, `update` and `delete` are unconditional: `insert` replaces, `update` of a missing key
creates it, `delete` of a missing key succeeds. Use `insert_if_absent` or `compare_and_set_json` when
you need a guard.
## Targets
Built and tested on native targets. `wasm32-wasip1` compiles. `wasm32-unknown-unknown` compiles only if
your crate enables `getrandom`'s `js` feature.
## Binaries
The package also builds `feltdb-authority`, `feltdb-authority-client` and `feltdb_node`, the process
authority and its client. `cargo install feltdb` installs them. Most applications want only the library.
## Minimum Rust version
1.96, the oldest toolchain the project's CI builds and tests with.
## License
MIT. See [LICENSE](LICENSE).