# FoundationDB Rust Client API

This is a wrapper library around the FoundationDB (Fdb) C API. It implements futures based interfaces over the Fdb future C implementations.

## Prerequisites

* Rust 1.85.1 or more,
* FoundationDB's client installed.

## Platform Support

Support for different platforms ("targets") are organized into three tiers, each with a different set of guarantees. For more information on the policies for targets at each tier, see the [Target Tier Policy](#target-tier-policy).

| Platform       | Tier   | Notes                                                                                                                               |
|----------------|--------|-------------------------------------------------------------------------------------------------------------------------------------|
| linux x86_64   | 1      |                                                                                                                                     |
| osx x86_64     | 2      |                                                                                                                                     |
| osx Silicon    | 2      |                                                                                                                                     |
| Windows x86_64 | 3      | [Windows build has been officially discontinue, now maintained by the community](https://github.com/apple/foundationdb/issues/5135) |

For more information on the policies for targets at each tier, see the

## Target Tier Policy

### Tier 1

`Tier 1` targets can be thought of as "guaranteed to work". This means that:

* we are actively checking correctness with the [BindingTester](https://github.com/apple/foundationdb/blob/master/bindings/bindingtester/spec/bindingApiTester.md),
* we are running classic Rust tests on each pull requests,
* you can use the crate on the platform.


### Tier 2

`Tier 2` targets can be thought of as "guaranteed to build". This means that:

* we are running classic Rust tests on each pull requests,
* you can use the crate on the platform.

But we are not checking correctness.

### Tier 3

`Tier 3` targets are platforms we would like to have as Tier 2. You might be able to compile, but no CI has been set up.

## Getting Started

### Install FoundationDB

You first need to install FoundationDB. You can follow the official documentation:

* [Getting Started on Linux](https://apple.github.io/foundationdb/getting-started-linux.html)
* [Getting started on macOS](https://apple.github.io/foundationdb/getting-started-mac.html)

### Add dependencies on foundationdb-rs

```shell
cargo add foundationdb -F embedded-fdb-include
cargo add futures
```

This Rust crate is not tied to any Async Runtime.

### Exposed features

| Features               | Notes                                                                          |
|------------------------|--------------------------------------------------------------------------------|
| `fdb-5_1`              | Support for FoundationDB 5.1.X                                                 |
| `fdb-5_2`              | Support for FoundationDB 5.2.X                                                 |
| `fdb-6_0`              | Support for FoundationDB 6.0.X                                                 |
| `fdb-6_1`              | Support for FoundationDB 6.1.X                                                 |
| `fdb-6_2`              | Support for FoundationDB 6.2.X                                                 |
| `fdb-6_3`              | Support for FoundationDB 6.3.X                                                 |
| `fdb-7_0`              | Support for FoundationDB 7.0.X                                                 |
| `fdb-7_1`              | Support for FoundationDB 7.1.X                                                 |
| `fdb-7_3`              | Support for FoundationDB 7.3.X                                                 |
| `fdb-7_4`              | Support for FoundationDB 7.4.X                                                 |
| `embedded-fdb-include` | Use the locally embedded FoundationDB fdb_c.h and fdb.options files to compile |
| `uuid`                 | Support for the uuid crate for Tuples                                          |
| `num-bigint`           | Support for the bigint crate for Tuples                                        |
| `tenant-experimental`  | Experimental support for tenants. Require at least 7.1                         |
| `trace`                | Enable tracing on transaction related operations                               |

### Hello, World using the crate

We are going to use the Tokio runtime for this example:

```rust
use futures::prelude::*;

#[tokio::main]
async fn main() {
    // Safe because drop is called before the program exits
    let network = unsafe { foundationdb::boot() };

    // Have fun with the FDB API
    hello_world().await.expect("could not run the hello world");

    // shutdown the client
    drop(network);
}

async fn hello_world() -> foundationdb::FdbResult<()> {
    let db = foundationdb::Database::default()?;

    // write a value in a retryable closure
    match db
        .run(|trx, _maybe_committed| async move {
            trx.set(b"hello", b"world");
            Ok(())
        })
        .await
    {
        Ok(_) => println!("transaction committed"),
        Err(_) => eprintln!("cannot commit transaction"),
    };

    // read a value
    match db
        .run(|trx, _maybe_committed| async move { Ok(trx.get(b"hello", false).await.unwrap()) })
        .await
    {
        Ok(slice) => assert_eq!(b"world", slice.unwrap().as_ref()),
        Err(_) => eprintln!("cannot commit transaction"),
    }

    Ok(())
}
```

## Additional notes

### The class-scheduling tutorial

The official FoundationDB's tutorial is called the [Class Scheduling](https://apple.github.io/foundationdb/class-scheduling.html). You can find the Rust version in the [examples](https://github.com/foundationdb-rs/foundationdb-rs/tree/main/foundationdb/examples).

### The blob tutorial

The official FoundationDB documentation provides also [another topic](https://apple.github.io/foundationdb/largeval.html#modeling-large-values)
which is further discussed inside a [design recipe](https://apple.github.io/foundationdb/blob.html).
A Rust implementation can be found [here](https://github.com/foundationdb-rs/foundationdb-rs/tree/main/foundationdb/examples/blob.rs).

Another [example](https://github.com/foundationdb-rs/foundationdb-rs/tree/main/foundationdb/examples/blob-with-manifest.rs),
explores how to use subspaces to attach metadata to our blob.

### Must-read documentations

* [Developer Guide](https://apple.github.io/foundationdb/developer-guide.html)
* [Data Modeling Guide](https://apple.github.io/foundationdb/data-modeling.html)

### Initialization

Due to limitations in the C API, the Client and it's associated Network can only be initialized and run once per the life of a process. Generally the `foundationdb::boot` function will be enough to initialize the Client. See `foundationdb::api` for more configuration options of the Fdb Client.

###  Migration from 0.4 to 0.5

The initialization of foundationdb API has changed due to undefined behavior being possible with only safe code (issues #170, #181, pulls #179, #182).

Previously you had to wrote `foundationdb::boot().expect("failed to initialize Fdb");`, now this can be converted to:

```rust
// Safe because drop is called before the program exits
let network = unsafe { foundationdb::boot() };

// do stuff

// cleanly shutdown the client
drop(network);
```

### API stability

_WARNING_ Until the 1.0 release of this library, the API may be in constant flux.
