grapple_db

Crates.iograpple_db
lib.rsgrapple_db
version0.3.1
created_at2025-06-03 17:31:27.883134+00
updated_at2025-06-11 20:59:39.27206+00
descriptionLibrary with clients for different databases with lightweight interface
homepage
repositoryhttps://github.com/grapple228/rust_grapple_db.git
max_upload_size
id1699325
size248,216
Green Apple (Grapple228)

documentation

README

grapple_db

grapple_db is a library designed to simplify interactions with various databases. It offers a flexible architecture that allows you to select the database client you need and utilize it according to your requirements. The library can be easily integrated into your project using feature flags.

Table of Contents

Description

  • Support for Multiple Database Clients: Effortlessly switch between different database clients by specifying the desired features during the build process.
  • Configurable Connection Settings: Easily define and manage connection parameters for each database client.
  • Simplified Operation Execution: Perform CRUD (Create, Read, Update, Delete) operations with minimal effort.
  • Batch Processing Capabilities: Execute multiple operations in a single batch to enhance performance.
  • Streaming Data Support: Efficiently handle large datasets with built-in support for streaming data processing.
  • Intuitive User Interface: Enjoy a user-friendly interface for executing queries and managing database interactions.

Features

  • scylla: enable ScyllaDb (Cassandra) client
  • redis: enable Redis/Valkey client

Defaults: []

Installation

To include grapple_db in your project, add it to your dependencies. For example:

# Example for Cargo.toml (Rust)
[dependencies]
grapple_db = { version = "0.2", features = ["scylla", "redis"] }
scylla = "1.2.0" # for scylla feature

Redis examples

Full code example for tuples can be found in /examples/redis_tuple.rs
Full code example for models can be found in /examples/redis_model.rs

Create Client

// Default
let client = Client::default().await?;

// From url
let client = Client::from_url("redis://127.0.0.1:6379").await?;

// From config
use grapple_db::redis::pool::Config;
let cfg = Config::from_url("redis://127.0.0.1:6379");

let client = Client::connect(&cfg).await?;

Define Model

Tuple

use grapple_db::redis::Client;

let id = "tuple_id".to_string();
let value = 3;

let tuple = (id, value);

Custom model

// Imports
use grapple_db::redis; // If have original redis-rs, then it not needed
use grapple_db::redis::{macros::FromRedisValue, RedisModel};

// Define struct
#[derive(Debug, Default, serde::Serialize, serde::Deserialize, FromRedisValue)]
pub struct Model {
    a: i32,
    b: i32,
}

// Implement trait
impl RedisModel for Model {
    fn key(&self) -> redis::Result<String> {
        // Key for model
        Ok(format!("{}.{}", self.a, self.b))
    }
}

Get

Tuple

let value: Option<i32> = client.get(&key).await?;

Model

let key = model.key()?;
let value: Option<Model> = client.get(&key).await?;

Set

Tuple

let tuple = (id, value);
client.set(&tuple).await?;

Custom Model

let model = Model::default();
client.set(&model).await?;

Del

client.del(&key).await?;

Batch

Delete Batch

client.mdel(&keys).await?;

Set batch

client.mset(&models).await?;

Get batch

client.mget(&keys).await?;

Other

let key = model.key()?;
let val = client.exists(&key).await?;

let val = client.rename(&key).await?;

Not covered methods

// For not coveded methods use connection and operate over it
client.connection().await?
    .client_setname::<_, String>("my_client_name".to_string()).await?;

Scylla Examples

Full code example can be found in /examples/scylla.rs

Create Client

// With default configuring
let client = Client::default()

// With custom configuring
let con_params = ConnectionParams::default();
let client = Client::connect(&con_params).await?;

Define model

Any of the models could be used with the same client

use grapple_db::scylla::{
    charybdis,
    macros::charybdis_model,
    types::{Text},
};

#[charybdis_model(
    table_name = users,
    partition_keys = [id],
    clustering_keys = [],

    global_secondary_indexes = [name],
    local_secondary_indexes = [],
)]
#[derive(Debug, Clone, Default)]
pub struct User {
    id: Uuid,
    name: Option<Text>,

    pwd: Option<Text>,
}

Get

// Any find method that returns one entity
let query = User::find_<any>()
let result = client.get(query).await?;

Insert

let model = User::default();
client.insert(&model).await?;

Update

let model = User::default();
client.update(&model).await?;

Delete

let model = User::default();
client.delete(&model).await?;

Count

// Any find method that returns stream
let query = User::find_<any>()
let count = client.count(query).await?;

Stream

// Any find method that returns stream
let query = User::find_<any>()
let stream = client.stream(query).await?;

// Iterate as you want
// There are also available pagable stream
let per_page = 3;
let mut pagable_stream = PagableCharybdisStream::new(stream, per_page);
let mut entities_count = 0;

while let Some(entities) = pagable_stream.next_page().await {
    for entity in entities {
        // Do something with entity
        println!("{:?}", entity);
    }

    entities_count += &entities.len();
}

Batch (Insert, Update, Delete) - multiple queries at once

let chunk_size = 300;
let entities: Vec<User> = vec![];

client.insert_many(&entities, chunk_size).await?;
client.update_many(&entities, chunk_size).await?;
client.delete_many(&entities, chunk_size).await?;

let queries = entities.iter().map(|u| User::find_by_id(u.id.clone())).collect::<Vec<_>>();
let got: Vec<User> = client.get_many(queries).await?;

Benchmarking

I utilized the original benchmarks from the Carybdis ORM, which compared the Scylla Driver with its own performance, and incorporated code from my library. The time difference is minimal and using my library is easier for my use case.

You can check the performance difference by running:

cargo bench --features scylla --bench scylla_bench

Benchmark code available at /benches/scylla_bench.rs

Benchmark results available at /benches/scylla_bench.md

Plans for future

  • Implement client for Postgres DB
  • Implement client for Mongo DB

Acknowledgments

The scylla feature is built on top of the Charybdis ORM, which provides essential functionality for ScyllaDB interactions. For more details on its features and usage, you can find in repo: Git

Contributing

Contributions are welcome! If you have suggestions for improvements or new features, feel free to open an issue or submit a pull request. I wrote this library for my own use, so it may not fit everyone's needs, but your input is appreciated!

License

This project is licensed under the MIT License. See the LICENSE file for details.

Commit count: 0

cargo fmt