Skip to content

Latest commit

 

History

204 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RiRi: A high-performance C++ in-memory key-value library

Version Status Build C++23 Compiler Last Commit Contributors

RiRi is a fast, lightweight, in-process key-value static library built in C++23.

#include <RiRi.hpp>

RiRi::RapidNode node[] {
    {"riri_key", RiRi::RapidDataType(3.14159265359)},
    {"your_key", RiRi::RapidDataType("exposed")} 
};

RiRi::Commands::SET(node);

Benchmarks are currently getting formalized. For preliminary numbers refer: #30.

Features

  • CRUD operations on typed key-value pairs
  • Native support for strings, integers, booleans, and doubles
  • Bulk operations across multiple keys
  • Rich response system with per-operation status codes for bulk results

For usage examples, see the examples.

Building RiRi

Requires CMake 3.20+ and Clang++ (C++23).

git clone https://github.com/ad4rsh2701/RiRi.git
cd RiRi
cmake -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=clang++
cmake --build build

Clang++ is the supported compiler. GCC/MSVC may work but is untested.

To build tests, add -DRIRI_BUILD_TESTS=ON to the CMake command.

Using RiRi via CMake

Add the following to your CMakeLists.txt

include(FetchContent)
FetchContent_Declare(RiRi
    GIT_REPOSITORY https://github.com/ad4rsh2701/RiRi.git
    GIT_TAG        v0.0.2-miden
)
FetchContent_MakeAvailable(RiRi)
target_link_libraries(your_target PRIVATE RiRi)

Replace v0.0.2-miden with the latest release.

Examples

NOTE: This section is a work in progress. And the API DOCS ARE ON THE WAY! For now, reference the doc-strings of commands at src/include/RiRi/Commands.hpp.

  1. Data Preparation
#include <RiRi.hpp>

// 1. Standard Method (Recommended)
// Create an array of nodes of types `RapidNode` with values to insert/fetch
RiRi::RapidNode nodes[] {
    {"riri_key", RiRi::RapidDataType(3.14159265359)}
};

// 2. Lazy Method
    // Do nothing, literally. 

// this allows you to send multiple nodes to the commands.

RapidNode: is a simple struct that contains a string key and a RapidDataType value.

RapidDataType: is a variant over the types string, int64, double and bool.

  1. Inserting single key-value pairs
using namespace RiRi::Commands;

// Standard Method
auto response = SET(nodes);
// Lazy Method
auto response_lazy = SET("_key", 3.14159265359);

// you can use the response it returned!
if (response.ok()) {
    // do something
}
  1. Fetching single key-value pairs
// Standard Method
auto get_response = GET(nodes); // this is ALLOWED!!
// Lazy Method
auto get_response_lazy = GET("_key");

if (get_response.ok()) {
    auto data = get_response.field();   // data is of type `RapidDataType`
    // do something with the data
}
  1. Inserting bulk key-value pairs
// There is no LAZY method for bulk operations. Span of nodes is required.
RiRi::RapidNode many_nodes[] {
    {"riri_key", RiRi::RapidDataType(3.14159265359)},
    {"riri_key2", RiRi::RapidDataType("raresy")},
    {"riri_key3", RiRi::RapidDataType(true)},
};
auto batched_error_response = SET(many_nodes, RiRi::enableErrorBatched{});
    // this returns a list of keys which failed to get inserted (capped at a fixed entry limit) and why.
    // { {"key": ERROR_CODE}, ... }
    
// if you want the uncapped version
auto batched_response = SET(many_nodes, RiRi::enableBatched{});
  1. Fetching bulk key-value pairs
auto get_response = GET(many_nodes, RiRi::enableBatched{});
// returns a mixed list of keys which failed to get fetched and why, or the value if fetched
// { {"key": value}, {"key2": ERROR_CODE}, ... }

Development

  • Root Data Structure for the Data Store
  • Lower level functions/helpers for modifying the Data Store
  • Custom Response System for handling requests, error, and validation (ref: #30)
  • User level functions/commands for inserting/fetching the data (ref: #32)
  • First library build (ref: #33)
  • Unit Testing (ref: #52, #41)
  • RiRi miden Release
  • Thread Safety and Multi-threading
  • Benchmarking
  • Data Persistence and Recovery

Versioning

RiRi will follow standard and relatively easy to follow version semantics (with slight changes). Here, a table labeling the phases and the version semantics:

Phase Versions Achieved Scope (can change obv)
miden v0.0.1 to v0.0.x Core Architecture and API improvement
alpha v0.1.0 to v0.1.x Multi-Threading and handling asynchronous calls
beta v0.2.0 to v0.x.x Persistence, API freeze and more (no major features)
stable v1.0.0 First actual release

The actual version tag will follow the format v[version number]-[phase]. For instance, v0.0.1 in miden phase will be tagged as v0.0.1-miden.

"miden" is inspired by the Ancient Greek term "midén" (see here), which literally translates to "not even one".

Why miden? Because it symbolizes "zero" or the starting point. Usually, Alpha comes first, but I needed something for the pre-alpha phase ("pre-alpha" is a bit too long), and miden fits while keeping the greek symbolism intact.

License

This project is licensed under the Apache License 2.0. Unless otherwise stated, all files are licensed under the Apache License, Version 2.0. See the LICENSE.txt file for details.

Note: The src/include/ankerl/ directory contains code licensed under the MIT License, see here. And the doctest.h file is licensed under its respective MIT License, see here.

About

A rapid, low-latency, in-memory key-value data engine.

Topics

Resources

Contributing

Stars

9 stars

Watchers

4 watching

Forks

Releases

Contributors

Languages