Support my project by visiting SolomonDB Github and give me a star ⭐️
Weekly Update #1: Baal
Date: October 2022 (26-28/11/2022)
According to the Grand Grimoire, Baal (or Bael) is the head of the infernal powers. He is also the first demon listed in Wierus' Pseudomonarchia daemonum. According to Wierus, Bael is the first king of Hell with estates in the east. He has three heads: a toad, a man, and a cat. He also speaks in a raucous, but well-formed voice, and commands 66 legions. Bael teaches the art of invisibility, and may be the equivalent of Baal or Baalzebub, one of the Seven princes of Hell. - Wikipedia
Commits on Oct 26, 2022
Description
A soft beginning. I just spend some time to read graph database book and learning concepts, requirements needed to construct Solomon DB.
Detail explanation
There are a few interesting learning outcomes acquired here:
These concepts are not too complicated actually. Not talking about native graph database, non-native graph database is more like a database wrapper which has internals built on top of other databases.
- Underlying storage
- Processing engine
- Graph compute engine
Learnt and noted down these concepts in WIKI.md.
As this is the first commit, it only includes code to initialize a codebase and its basic layout for Rust project using cargo new
.
// A simple hello world program (db/src/main.rs)
fn main() {
println!("Hello, world!");
}
Contributors
- Chung Quan Tin (@chungquantin)
Commits on Oct 28, 2022
Description
Add StorageDriver
, new type RocksDBDriver
, macro impl_driver_core
and misc implementation for StorageErr
and Status
.
Detail explanation
Things getting more exciting when we touch advanced syntaxes in Rust: New Type
design pattern and Macro
. Before jumping right into the main point of today changes, one of a missing features in Rust compared to other OOP languages must be mentioned first is the ability to do inheritance.
With what Rust provides so far, it is quite tricky to construct an inheritable struct
object. At first, you may think doing OOP in Rust is quite bad as inheritance is a core component of any OOP design. However, if you learn more about OOP, you will know Inheritance < Composition
. This is quite off topic, but there is a few discussions and articles related to the way Rust do OOP that you should read:
Briefly, even though Rust does not have an obvious OOP feature like inheritance, it still provides several approaches: Trait
, New type
, Macro
or Enum
to do thing in a inheritance way but cleaner as things are separated elegantly.
New Type design pattern for RocksDB Driver
"The newtype
idiom gives compile time guarantees that the right type of value is supplied to a program" - Rust book.
I apply the design to implement RocksDB Driver. The idea is to have a parent struct
called StorageDriver
and we will build a new type RocksDBDriver
from that.
pub struct StorageDriver<T> {
pub db_instance: Option<T>,
pub path: String,
}
pub struct RocksDBDriver(StorageDriver<DB>);
However, NewType
design does not exactly like inheritance. For example, if you want to get field db_instance
from RocksDBDriver
, you can't do self.db_instance
but self.0.db.instance
. Can imagine db_instance
is inside StorageDriver
while StorageDriver
is wrapped inside new type RocksDBDriver
. This would make the syntax looks a bit dirty. The solution I used to handle this case is Macro
.
Macro provides an ability to maximize the power of Rust syntax. I wrote a macro to implement all below methods used inside any impl
calling to impl_driver_core
. Then to get the inner of new type, we just have to use get_core
.
macro_rules! impl_driver_core {
($DbType: ty) => {
fn get_core(self: &mut Self) -> &mut StorageDriver<$DbType> {
&mut self.0
}
};
}
pub(crate) use impl_driver_core;
Struct RocksDBDriver
now becomes:
impl RocksDBDriver {
super::core::impl_driver_core!(DB);
/// # Initializing RocksDB driver
pub fn initialize(self: &mut Self, cf_name: &String, options: rocksdb::Options) {
let core = self.get_core();
...
}
}
Contributors
- Chung Quan Tin (@chungquantin)
Top comments (0)