Integrating the networked BonsaiDb Server

To access BonsaiDb over the network, you're going to be writing two pieces of code: the server code and the client code.

Your BonsaiDb Server

The first step is to create a Server, which uses local Storage under the hood. This means that if you're already using BonsaiDb in local mode, you can swap your usage of Storage with Server in your server code without running your database through any tools. Here's the setup code from basic-server/examples/basic-server.rs

    let server = Server::open(
        ServerConfiguration::new("server-data.bonsaidb")
            .default_permissions(DefaultPermissions::AllowAll)
            .with_schema::<Shape>()?,
    )
    .await?;
    if server.certificate_chain().await.is_err() {
        server.install_self_signed_certificate(true).await?;
    }
    let certificate = server
        .certificate_chain()
        .await?
        .into_end_entity_certificate();
    server.create_database::<Shape>("my-database", true).await?;

Once you have a server initialized, calling listen_on will begin listening for connections on the port specified. This uses the preferred native protocol which uses UDP. If you find that UDP is not working for your setup or want to put BonsaiDb behind a load balancer that doesn't support UDP, you can enable WebSocket support and call listen_for_websockets_on.

You can call both, but since these functions don't return until the server is shut down, you should spawn them instead:

let task_server = server.clone();
tokio::spawn(async move {
    task_server.listen_on(5645).await
});
let server = server.clone();
tokio::spawn(async move {
    task_server.listen_for_websockets_on("localhost:8080", false).await
});

If you're not running any of your own code on the server, and you're only using one listening method, you can just await the listen method of your choice in your server's main. This code example configures BonsaiDb on UDP port 5645, but this is not an officially registered port.

From the Client

BlockingClient and AsyncClient can support both the native protocol and WebSockets. They determine which protocol to use based on the scheme in the URL:

  • bonsaidb://* will connect using the native BonsaiDb protocol.
  • ws://* or wss://* will connect using WebSockets.

Here's how to connect over BonsaiDb's native protocol, from examples/basic-server/examples/basic-server.rs:

AsyncClient::build(Url::parse("bonsaidb://localhost:5645")?)
    .with_certificate(certificate)
    .build()
    .await?

This is using a pinned certificate to connect. Other methods are supported, but better certificate management is coming soon.

Common Traits

The examples above use types that are powered by common traits, allowing code to be written with generic trait bounds that can operate the same regardless of whether the code is being called locally or remotely.