Skip to content

Commit a1b415d

Browse files
committed
chore: rostra dev db-dump
1 parent 8f75fe5 commit a1b415d

File tree

10 files changed

+115
-7
lines changed

10 files changed

+115
-7
lines changed

Cargo.lock

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

crates/rostra-client-db/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ rostra-util-fmt = { workspace = true }
3838
dedup-chan = { workspace = true }
3939
rostra-util = { workspace = true }
4040
serde = { workspace = true }
41+
serde_json = { workspace = true }
4142
snafu = { workspace = true }
4243
rand = { workspace = true }
4344
tokio = { workspace = true }

crates/rostra-client-db/src/lib.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod models;
44
mod process_event_content_ops;
55
mod process_event_ops;
66
pub mod social;
7+
mod table_ops;
78
mod tables;
89
mod tx_ops;
910

@@ -78,6 +79,13 @@ impl WriteTransactionCtx {
7879
}
7980
}
8081

82+
#[derive(Debug, Snafu)]
83+
pub enum TableDumpError {
84+
#[snafu(display("Unknown table `{name}`"))]
85+
UnknownTable { name: String },
86+
}
87+
pub type TableDumpResult<T> = std::result::Result<T, TableDumpError>;
88+
8189
#[derive(Debug, Snafu)]
8290
pub enum DbError {
8391
Database {
@@ -149,6 +157,7 @@ pub struct Database {
149157
}
150158

151159
impl Database {
160+
const MAX_CONTENT_LEN: u32 = 1_000_000u32;
152161
pub async fn mk_db_path(
153162
data_dir: &Path,
154163
self_id: RostraId,
@@ -234,7 +243,30 @@ impl Database {
234243
tokio::task::block_in_place(|| self.inner.as_raw_mut().compact())
235244
}
236245

237-
const MAX_CONTENT_LEN: u32 = 1_000_000u32;
246+
pub async fn dump_table(&self, name: &str) -> TableDumpResult<()> {
247+
self.read_with(|tx| {
248+
match name {
249+
"events" => Self::dump_table_dbtx(tx, &tables::events::TABLE)?,
250+
"events_content" => Self::dump_table_dbtx(tx, &tables::events_content::TABLE)?,
251+
"social_posts" => Self::dump_table_dbtx(tx, &tables::social_posts::TABLE)?,
252+
"social_posts_replies" => {
253+
Self::dump_table_dbtx(tx, &tables::social_posts_replies::TABLE)?
254+
}
255+
"social_posts_reactions" => {
256+
Self::dump_table_dbtx(tx, &tables::social_posts_reactions::TABLE)?
257+
}
258+
_ => {
259+
return Ok(Err(UnknownTableSnafu {
260+
name: name.to_string(),
261+
}
262+
.build()));
263+
}
264+
}
265+
Ok(Ok(()))
266+
})
267+
.await
268+
.expect("Database panic")
269+
}
238270

239271
pub fn self_followees_subscribe(
240272
&self,
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use redb_bincode::ReadTransaction;
2+
3+
use crate::{Database, DbResult};
4+
5+
impl Database {
6+
pub(crate) fn dump_table_dbtx<K, V>(
7+
dbtx: &ReadTransaction,
8+
def: &redb_bincode::TableDefinition<'_, K, V>,
9+
) -> DbResult<()>
10+
where
11+
V: bincode::Decode + bincode::Encode + serde::Serialize,
12+
K: bincode::Decode + bincode::Encode + serde::Serialize,
13+
{
14+
let tbl = dbtx.open_table(def)?;
15+
for record in tbl.range(..)? {
16+
let (k, v) = record?;
17+
println!(
18+
"{} => {}",
19+
serde_json::to_string(&k.value()).expect("Can't fail"),
20+
serde_json::to_string(&v.value()).expect("Can't fail")
21+
)
22+
}
23+
Ok(())
24+
}
25+
}

crates/rostra-client-db/src/tables.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use ids::{IdsFolloweesRecord, IdsFollowersRecord, IdsPersonaRecord, IdsUnfollowe
66
use rostra_core::event::{IrohNodeId, PersonaId};
77
use rostra_core::id::{RestRostraId, RostraId, ShortRostraId};
88
use rostra_core::{ShortEventId, Timestamp};
9+
use serde::Serialize;
910

1011
pub use self::event::EventsHeadsTableRecord;
1112
pub(crate) mod event;
@@ -75,9 +76,9 @@ pub struct Latest<T> {
7576
pub inner: T,
7677
}
7778

78-
#[derive(Debug, Encode, Decode, Clone, Copy)]
79+
#[derive(Debug, Encode, Serialize, Decode, Clone, Copy)]
7980
pub struct SocialPostsRepliesRecord;
80-
#[derive(Debug, Encode, Decode, Clone, Copy)]
81+
#[derive(Debug, Encode, Serialize, Decode, Clone, Copy)]
8182
pub struct SocialPostsReactionsRecord;
8283

8384
#[derive(Debug, Encode, Decode, Clone)]
@@ -114,6 +115,7 @@ pub struct SocialPostRecordV0 {
114115
Debug,
115116
Encode,
116117
Decode,
118+
Serialize,
117119
Clone,
118120
// Note: needs to be default so we can track number of replies even before we get what was
119121
// replied to

crates/rostra-client-db/src/tables/event.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ use std::borrow::Cow;
33
use bincode::{Decode, Encode};
44
use rostra_core::event::{EventContentUnsized, EventExt, SignedEvent};
55
use rostra_core::ShortEventId;
6+
use serde::Serialize;
67

7-
#[derive(Debug, Encode, Decode, Clone)]
8+
#[derive(Debug, Encode, Decode, Clone, Serialize)]
89
pub enum EventContentState<'a> {
910
/// The event content is present and we processed it without problems
1011
Present(Cow<'a, EventContentUnsized>),
@@ -27,7 +28,7 @@ pub enum EventContentState<'a> {
2728

2829
pub type EventContentStateOwned = EventContentState<'static>;
2930

30-
#[derive(Debug, Encode, Decode, Clone)]
31+
#[derive(Debug, Encode, Decode, Clone, Serialize)]
3132
pub struct EventRecord {
3233
pub signed: SignedEvent,
3334
}

crates/rostra-core/src/event/content.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
use std::borrow::Borrow;
22
use std::ops;
33
use std::sync::Arc;
4+
#[cfg(feature = "serde")]
5+
mod serde;
46

57
#[derive(Debug)]
68
#[cfg_attr(feature = "bincode", derive(::bincode::Encode))]
79
#[repr(transparent)]
810
pub struct EventContentUnsized([u8]);
911

12+
impl std::fmt::Display for EventContentUnsized {
13+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14+
data_encoding::HEXLOWER.encode_write(self.as_slice(), f)
15+
}
16+
}
1017
impl EventContentUnsized {
1118
pub fn as_slice(&self) -> &[u8] {
1219
&self.0
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
use serde::Serialize;
2+
3+
use super::EventContentUnsized;
4+
5+
impl Serialize for EventContentUnsized {
6+
fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
7+
where
8+
S: ::serde::Serializer,
9+
{
10+
if s.is_human_readable() {
11+
s.serialize_str(&self.to_string())
12+
} else {
13+
s.serialize_bytes(&self.0)
14+
}
15+
}
16+
}

crates/rostra/src/cli.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,4 +131,11 @@ pub enum DevCmd {
131131
},
132132
/// Run tests
133133
Test,
134+
/// Dump database
135+
DbDump {
136+
#[arg(long)]
137+
table: String,
138+
#[arg(long)]
139+
rostra_id: RostraId,
140+
},
134141
}

crates/rostra/src/main.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ use futures::future::pending;
1010
use rostra_client::error::{ConnectError, IdResolveError, IdSecretReadError, InitError, PostError};
1111
use rostra_client::multiclient::MultiClient;
1212
use rostra_client::Client;
13-
use rostra_client_db::DbError;
13+
use rostra_client_db::{Database, DbError};
1414
use rostra_core::id::RostraIdSecretKey;
1515
use rostra_p2p::connection::{Connection, PingRequest, PingResponse};
1616
use rostra_p2p::RpcError;
17-
use rostra_util_error::FmtCompact as _;
17+
use rostra_util_error::{BoxedError, FmtCompact as _};
1818
use rostra_web_ui::{Server, WebUiServerError};
1919
use snafu::{FromString, ResultExt, Snafu, Whatever};
2020
use tokio::time::Instant;
@@ -49,6 +49,8 @@ pub enum CliError {
4949
DataDir { source: io::Error },
5050
#[snafu(display("Database error: {source}"))]
5151
Database { source: DbError },
52+
#[snafu(display("Miscellaneous error: {source}"))]
53+
Other { source: BoxedError },
5254
}
5355

5456
pub type CliResult<T> = std::result::Result<T, CliError>;
@@ -157,6 +159,20 @@ async fn handle_cmd(opts: Opts) -> CliResult<serde_json::Value> {
157159

158160
serde_json::to_value(&resp).expect("Can't fail")
159161
}
162+
cli::DevCmd::DbDump {
163+
rostra_id: id,
164+
table,
165+
} => {
166+
let db_path = Database::mk_db_path(opts.global.data_dir(), id)
167+
.await
168+
.context(DataDirSnafu)?;
169+
170+
let db = Database::open(&db_path, id).await.context(DatabaseSnafu)?;
171+
172+
db.dump_table(&table).await.boxed().context(OtherSnafu)?;
173+
174+
serde_json::to_value(serde_json::Value::Null).expect("Can't fail")
175+
}
160176
},
161177
cli::OptsCmd::Serve { secret_file } => {
162178
let secret_id = if let Some(secret_file) = secret_file {

0 commit comments

Comments
 (0)