# Key-Value Store
A more complex FFI example than the counter, demonstrating
`future_form`'s effect protocol with per-future `Arc<EffectSlot>` for
unlimited concurrent operations.
A stateless Rust service defines key-value operations (Get, Put, Delete,
List) as effects. The host language (Go, Java, or Python) provides the
actual storage as an in-memory map and fulfills effects as they arise.
## What this demonstrates
| _Multiple effect types_ | `Get`, `Put`, `Delete`, `List` — each with structured payloads (key, value, prefix) |
| _Multi-step futures_ | `update` performs Get then Put in sequence, yielding `Pending` twice. A single future can do multiple effect round-trips. |
| _Per-future `Arc<EffectSlot>`_ | Each operation creates a fresh slot. No shared slot on the struct, no capacity limit, no cross-talk between concurrent futures. |
| _Concurrent futures_ | The test creates two Get futures simultaneously and fulfills them independently — proving that per-future slots eliminate the ordering bugs that shared slots would cause. |
| _Host-side storage_ | The Rust code never touches a database or file system. All I/O is delegated to the host via effects. |
## Architecture
```
Go / Java / Python host Rust (kv_bridge + kv_store)
┌────────────────┐ ┌──────────────────────────┐
│ in-memory dict │ │ HostKvStore (stateless) │
│ │ │ │
│ poll loop: │ │ KvStore::<Sendable>:: │
│ kv_poll() │──────────> │ get / put / delete / │
│ effect? │ <──────────│ list / update │
│ fulfill() │──────────> │ │
│ │ │ Arc<EffectSlot> per op │
└────────────────┘ └──────────────────────────┘
```
Each `kv_get`, `kv_put`, etc. call returns an opaque handle backed by
its own `EffectHandle` + `Arc<EffectSlot>`:
```
handle_a ──► EffectHandle ──► Arc<slot_a> (Get "alice")
handle_b ──► EffectHandle ──► Arc<slot_b> (Get "item:1")
independent channels
```
## Structure
```
key_value_store/
├── kv_store/ Domain logic: KvStore<K> trait + HostKvStore impl + 7 tests
├── kv_bridge/ C ABI + JNI bridge with per-future Arc<EffectSlot>
├── go_host/ Go consumer with in-memory map
├── java_host/ Java consumer with in-memory HashMap
├── python_host/ Python consumer with in-memory dict
└── run_test.sh Build + run across Go, Java, and Python hosts
```
## Running
From the workspace root, using `nix develop .#ffi` for foreign toolchains:
```sh
./future_form_ffi/examples/key_value_store/run_test.sh
```
Or run individual hosts:
```sh
# Build the bridge first
cargo build --manifest-path future_form_ffi/examples/key_value_store/kv_bridge/Cargo.toml
# Python
python3 future_form_ffi/examples/key_value_store/python_host/kv_host.py
# Go
cd future_form_ffi/examples/key_value_store/go_host && go run .
# Java
javac future_form_ffi/examples/key_value_store/java_host/KvHost.java -d future_form_ffi/examples/key_value_store/java_host/out
java -cp future_form_ffi/examples/key_value_store/java_host/out -Djava.library.path=future_form_ffi/examples/key_value_store/kv_bridge/target/debug KvHost
```
## Comparison with counter_effects
| _Effect types_ | 2 (GetTimestamp, Log) | 4 (Get, Put, Delete, List) |
| _Multi-step futures_ | No | Yes (update = Get + Put) |
| _Slot ownership_ | Per-struct (one future at a time) | Per-future `Arc` (unlimited) |
| _Concurrent futures_ | No | Yes (tested) |
| _Host languages_ | Go, Java, Python | Go, Java, Python |
| _JNI support_ | Yes | Yes |
| _Complexity_ | Introductory | Intermediate |