Skip to content

Commit 00ccb2b

Browse files
duyquang6Rjected
andauthored
feat(persistence): implement RocksDB provider (#20071)
Co-authored-by: Dan Cline <[email protected]>
1 parent addb51f commit 00ccb2b

File tree

8 files changed

+715
-1
lines changed

8 files changed

+715
-1
lines changed

.github/workflows/lint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ jobs:
9898
matrix:
9999
partition: [1, 2]
100100
total_partitions: [2]
101-
timeout-minutes: 30
101+
timeout-minutes: 60
102102
steps:
103103
- uses: actions/checkout@v6
104104
- uses: rui314/setup-mold@v1

Cargo.lock

Lines changed: 37 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,9 @@ c-kzg = "2.1.5"
652652
# config
653653
toml = "0.8"
654654

655+
# rocksdb
656+
rocksdb = { version = "0.24" }
657+
655658
# otlp obs
656659
opentelemetry_sdk = "0.31"
657660
opentelemetry = "0.31"

crates/storage/provider/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ tokio = { workspace = true, features = ["sync"], optional = true }
6262
# parallel utils
6363
rayon.workspace = true
6464

65+
[target.'cfg(unix)'.dependencies]
66+
# rocksdb: jemalloc is recommended production workload
67+
rocksdb = { workspace = true, features = ["jemalloc"] }
68+
6569
[dev-dependencies]
6670
reth-db = { workspace = true, features = ["test-utils"] }
6771
reth-primitives-traits = { workspace = true, features = ["arbitrary", "test-utils"] }

crates/storage/provider/src/providers/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@ pub use blockchain_provider::BlockchainProvider;
2929
mod consistent;
3030
pub use consistent::ConsistentProvider;
3131

32+
// RocksDB currently only supported on Unix platforms
33+
// Windows support is planned for future releases
34+
#[cfg(unix)]
35+
mod rocksdb;
36+
#[cfg(unix)]
37+
pub use rocksdb::{RocksDBBuilder, RocksDBProvider};
38+
3239
/// Helper trait to bound [`NodeTypes`] so that combined with database they satisfy
3340
/// [`ProviderNodeTypes`].
3441
pub trait NodeTypesForProvider
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
use std::{collections::HashMap, time::Duration};
2+
3+
use itertools::Itertools;
4+
use metrics::{Counter, Histogram};
5+
use reth_db::Tables;
6+
use reth_metrics::Metrics;
7+
use strum::{EnumIter, IntoEnumIterator};
8+
9+
const ROCKSDB_TABLES: &[&str] = &[Tables::TransactionHashNumbers.name()];
10+
11+
/// Metrics for the `RocksDB` provider.
12+
#[derive(Debug)]
13+
pub(crate) struct RocksDBMetrics {
14+
operations: HashMap<(&'static str, RocksDBOperation), RocksDBOperationMetrics>,
15+
}
16+
17+
impl Default for RocksDBMetrics {
18+
fn default() -> Self {
19+
let mut operations = ROCKSDB_TABLES
20+
.iter()
21+
.copied()
22+
.cartesian_product(RocksDBOperation::iter())
23+
.map(|(table, operation)| {
24+
(
25+
(table, operation),
26+
RocksDBOperationMetrics::new_with_labels(&[
27+
("table", table),
28+
("operation", operation.as_str()),
29+
]),
30+
)
31+
})
32+
.collect::<HashMap<_, _>>();
33+
34+
// Add special "Batch" entry for batch write operations
35+
operations.insert(
36+
("Batch", RocksDBOperation::BatchWrite),
37+
RocksDBOperationMetrics::new_with_labels(&[
38+
("table", "Batch"),
39+
("operation", RocksDBOperation::BatchWrite.as_str()),
40+
]),
41+
);
42+
43+
Self { operations }
44+
}
45+
}
46+
47+
impl RocksDBMetrics {
48+
/// Records operation metrics with the given operation label and table name.
49+
pub(crate) fn record_operation(
50+
&self,
51+
operation: RocksDBOperation,
52+
table: &'static str,
53+
duration: Duration,
54+
) {
55+
let metrics =
56+
self.operations.get(&(table, operation)).expect("operation metrics should exist");
57+
58+
metrics.calls_total.increment(1);
59+
metrics.duration_seconds.record(duration.as_secs_f64());
60+
}
61+
}
62+
63+
/// `RocksDB` operations that are tracked
64+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, EnumIter)]
65+
pub(crate) enum RocksDBOperation {
66+
Get,
67+
Put,
68+
Delete,
69+
BatchWrite,
70+
}
71+
72+
impl RocksDBOperation {
73+
const fn as_str(&self) -> &'static str {
74+
match self {
75+
Self::Get => "get",
76+
Self::Put => "put",
77+
Self::Delete => "delete",
78+
Self::BatchWrite => "batch-write",
79+
}
80+
}
81+
}
82+
83+
/// Metrics for a specific `RocksDB` operation on a table
84+
#[derive(Metrics, Clone)]
85+
#[metrics(scope = "rocksdb.provider")]
86+
pub(crate) struct RocksDBOperationMetrics {
87+
/// Total number of calls
88+
calls_total: Counter,
89+
/// Duration of operations
90+
duration_seconds: Histogram,
91+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
//! [`RocksDBProvider`] implementation
2+
3+
mod metrics;
4+
mod provider;
5+
pub use provider::{RocksDBBuilder, RocksDBProvider};

0 commit comments

Comments
 (0)