···1212bytevec = "0.2.0"
1313chrono = { version = "0.4.42", features = ["serde"] }
1414clap = { version = "4.5.47", features = ["derive", "env"] }
1515+enum_dispatch = "0.3.13"
1516futures = "0.3.31"
1617governor = "0.10.1"
1718http-body-util = "0.1.3"
+8-2
src/backfill.rs
···1313 dest: mpsc::Sender<ExportPage>,
1414 source_workers: usize,
1515 until: Option<Dt>,
1616+ starting_from: Option<i64>,
1617) -> anyhow::Result<&'static str> {
1818+ let starting_from = match starting_from {
1919+ Some(sf) => Week::from_n(sf),
2020+ None => FIRST_WEEK,
2121+ };
2222+1723 // queue up the week bundles that should be available
1824 let weeks = Arc::new(Mutex::new(
1925 until
2020- .map(|u| Week::range(FIRST_WEEK..u.into()))
2121- .unwrap_or(Week::range(FIRST_WEEK..)),
2626+ .map(|u| Week::range(starting_from..u.into()))
2727+ .unwrap_or(Week::range(starting_from..)),
2228 ));
2329 weeks.lock().await.reverse();
2430
+23-10
src/bin/backfill.rs
···11use allegedly::{
22- Db, Dt, ExportPage, FolderSource, HttpSource, RocksDatastore, backfill, backfill_to_pg,
33- backfill_to_rocksdb, bin::GlobalArgs, bin_init, datastore::Datastore, full_pages,
44- pages_to_stdout, poll_upstream,
22+ Db, Dt, ExportPage, FolderSource, HttpSource, RocksDatastore, backfill, bin::GlobalArgs,
33+ bin_init, datastore::Datastore, full_pages, pages_to_stdout, poll_upstream,
54};
65use anyhow::anyhow;
76use clap::Parser;
···5150 /// Cannot be used alongside any postgres-related flag.
5251 #[arg(long, action)]
5352 rocksdb_db_path: Option<PathBuf>,
5353+ /// Start at the week pointed by this UNIX timestamp
5454+ #[arg(long)]
5555+ starting_from: Option<i64>,
5456 /// Stop at the week ending before this date
5557 #[arg(long)]
5658 until: Option<Dt>,
···7274 to_postgres,
7375 postgres_cert,
7476 postgres_reset,
7777+ starting_from,
7578 until,
7679 catch_up,
7780 rocksdb_db_path,
···128131 bulk_tx,
129132 source_workers.unwrap_or(1),
130133 until,
134134+ starting_from,
131135 ));
132136 } else {
133137 tasks.spawn(backfill(
···135139 bulk_tx,
136140 source_workers.unwrap_or(4),
137141 until,
142142+ starting_from,
138143 ));
139144 }
140145···155160 let db = Db::new(pg_url.as_str(), postgres_cert).await?;
156161 log::trace!("connected to postgres");
157162158158- tasks.spawn(backfill_to_pg(
159159- db.clone(),
160160- postgres_reset,
161161- bulk_out,
162162- found_last_tx,
163163- ));
163163+ let db_backfill = db.clone();
164164+ tasks.spawn(async move {
165165+ let mut db_conn = db_backfill.datastore().await?;
166166+ match db_conn.backfill(bulk_out, found_last_tx).await {
167167+ Ok(_) => Ok("backfill"),
168168+ Err(e) => Err(anyhow!(e)),
169169+ }
170170+ });
164171 if catch_up {
165172 tasks.spawn(async move {
166173 let mut db_conn = db.datastore().await?;
···175182 let mut db = RocksDatastore::new(rocksdb_path)?;
176183 log::trace!("opened!");
177184178178- tasks.spawn(backfill_to_rocksdb(db.clone(), bulk_out, found_last_tx));
185185+ let mut db_backfill = db.clone();
186186+ tasks.spawn(async move {
187187+ match db_backfill.backfill(bulk_out, found_last_tx).await {
188188+ Ok(_) => Ok("backfill"),
189189+ Err(e) => Err(anyhow!(e)),
190190+ }
191191+ });
179192 if catch_up {
180193 tasks.spawn(async move {
181194 match db.observe_pages(full_out).await {
+34-11
src/bin/mirror.rs
···11use allegedly::{
22- Db, ExperimentalConf, ListenConf, bin::GlobalArgs, bin_init, datastore::Datastore,
22+ DatastoreEnum, Db, ExperimentalConf, ListenConf, RocksDatastore,
33+ bin::GlobalArgs,
44+ bin_init,
55+ datastore::{Datastore, SendDatastore},
36 poll_upstream, serve,
47};
58use anyhow::anyhow;
···1316 /// the wrapped did-method-plc server
1417 #[arg(long, env = "ALLEGEDLY_WRAP")]
1518 wrap: Url,
1919+ /// Path to the database for RocksDB.
2020+ /// Will be created if it doesn't exist.
2121+ /// Cannot be used alongside any postgres-related flag.
2222+ #[arg(long, action)]
2323+ rocksdb_db_path: Option<PathBuf>,
1624 /// the wrapped did-method-plc server's database (write access required)
1725 #[arg(long, env = "ALLEGEDLY_WRAP_PG")]
1826 wrap_pg: Option<Url>,
···6876 }: GlobalArgs,
6977 Args {
7078 wrap,
7979+ rocksdb_db_path,
7180 wrap_pg,
7281 wrap_pg_cert,
7382 bind,
···106115107116 let mut tasks = JoinSet::new();
108117118118+ let datastore: Option<DatastoreEnum> = if let Some(pg_url) = wrap_pg {
119119+ let db = Db::new(pg_url.clone().as_str(), wrap_pg_cert.clone()).await?;
120120+ let ds = db.datastore().await?;
121121+ Some(DatastoreEnum::Pg(ds))
122122+ } else if let Some(rocksdb_path) = rocksdb_db_path {
123123+ let db = RocksDatastore::new(rocksdb_path)?;
124124+ Some(DatastoreEnum::Rocks(db))
125125+ } else {
126126+ None
127127+ };
128128+109129 let db = if sync {
110110- let wrap_pg = wrap_pg.ok_or(anyhow::anyhow!(
111111- "a wrapped reference postgres must be provided to sync"
112112- ))?;
113113- let db = Db::new(wrap_pg.clone().as_str(), wrap_pg_cert.clone()).await?;
130130+ let ds = match datastore {
131131+ Some(ds) => ds,
132132+ None => {
133133+ return Err(anyhow::anyhow!(
134134+ "a wrapped reference postgres must be provided to sync"
135135+ ));
136136+ }
137137+ };
114138115139 // TODO: allow starting up with polling backfill from beginning?
116140 log::debug!("getting the latest op from the db...");
117117- let latest = db
118118- .get_latest()
141141+ let latest = ds
142142+ .get_latest_timestamp()
119143 .await?
120144 .expect("there to be at least one op in the db. did you backfill?");
121145···127151128152 tasks.spawn(poll_upstream(Some(latest), poll_url, throttle, send_page));
129153154154+ let mut ds_observe = ds.clone();
130155 tasks.spawn(async move {
131131- let db = Db::new(wrap_pg.as_str(), wrap_pg_cert).await?;
132132- let mut db_conn = db.datastore().await?;
133133- match db_conn.observe_pages(recv_page).await {
156156+ match ds_observe.observe_pages(recv_page).await {
134157 Ok(_) => Ok("observe_pages"),
135158 Err(e) => Err(anyhow!(e)),
136159 }
137160 });
138138- Some(db)
161161+ Some(ds)
139162 } else {
140163 None
141164 };
···1717pub use backfill::backfill;
1818pub use cached_value::{CachedValue, Fetcher};
1919pub use client::{CLIENT, UA};
2020+pub use datastore::DatastoreEnum;
2021pub use mirror::{ExperimentalConf, ListenConf, serve};
2121-pub use plc_pg::{Db, backfill_to_pg};
2222+pub use plc_pg::Db;
2223pub use plc_rocksdb::{RocksDatastore, backfill_to_rocksdb};
2324pub use poll::{PageBoundaryState, get_page, poll_upstream};
2425pub use ratelimit::{CreatePlcOpLimiter, GovernorMiddleware, IpLimiters};
+5-4
src/mirror.rs
···11use crate::{
22- CachedValue, CreatePlcOpLimiter, Db, Dt, Fetcher, GovernorMiddleware, IpLimiters, UA, logo,
22+ CachedValue, CreatePlcOpLimiter, DatastoreEnum, Db, Dt, Fetcher, GovernorMiddleware,
33+ IpLimiters, UA, datastore::Datastore, logo,
34};
45use futures::TryStreamExt;
56use governor::Quota;
···181182}
182183183184#[derive(Clone)]
184184-struct GetLatestAt(Db);
185185+struct GetLatestAt(DatastoreEnum);
185186impl Fetcher<Dt> for GetLatestAt {
186187 async fn fetch(&self) -> Result<Dt, Box<dyn std::error::Error>> {
187187- let now = self.0.get_latest().await?.ok_or(anyhow::anyhow!(
188188+ let now = self.0.get_latest_timestamp().await?.ok_or(anyhow::anyhow!(
188189 "expected to find at least one thing in the db"
189190 ))?;
190191 Ok(now)
···388389 plc: Url,
389390 listen: ListenConf,
390391 experimental: ExperimentalConf,
391391- db: Option<Db>,
392392+ db: Option<DatastoreEnum>,
392393) -> anyhow::Result<&'static str> {
393394 log::info!("starting server...");
394395