···11use clap::Parser;
22-use serde::Deserialize;
32use std::time::Duration;
44-use tokio_postgres::NoTls;
53use url::Url;
6477-use allegedly::{Dt, ExportPage, bin_init, poll_upstream, week_to_pages};
55+use allegedly::{Db, Dt, ExportPage, Op, bin_init, poll_upstream, week_to_pages};
8697const EXPORT_PAGE_QUEUE_SIZE: usize = 0; // rendezvous for now
108const WEEK_IN_SECONDS: u64 = 7 * 86400;
···4038 /// URI string with credentials etc
4139 #[arg(long, env)]
4240 postgres: String,
4343-}
4444-4545-#[derive(Deserialize)]
4646-#[serde(rename_all = "camelCase")]
4747-struct Op<'a> {
4848- pub did: &'a str,
4949- pub cid: &'a str,
5050- pub created_at: Dt,
5151- pub nullified: bool,
5252- #[serde(borrow)]
5353- pub operation: &'a serde_json::value::RawValue,
5441}
55425643async fn bulk_backfill((upstream, epoch): (Url, u64), tx: flume::Sender<ExportPage>) {
···181168}
182169183170#[tokio::main]
184184-async fn main() {
171171+async fn main() -> anyhow::Result<()> {
185172 bin_init("main");
186173 let args = Args::parse();
187187-188188- log::trace!("connecting postgres...");
189189- let (pg_client, connection) = tokio_postgres::connect(&args.postgres, NoTls)
190190- .await
191191- .unwrap();
192192-193193- // send the connection away to do the actual communication work
194194- // TODO: error and shutdown handling
195195- let conn_task = tokio::task::spawn(async move {
196196- if let Err(e) = connection.await {
197197- eprintln!("connection error: {e}");
198198- }
199199- });
200200-201201- log::trace!("connecting postgres 2...");
202202- let (pg_client2, connection2) = tokio_postgres::connect(&args.postgres, NoTls)
203203- .await
204204- .unwrap();
205205-206206- // send the connection away to do the actual communication work
207207- // TODO: error and shutdown handling
208208- let conn_task2 = tokio::task::spawn(async move {
209209- if let Err(e) = connection2.await {
210210- eprintln!("connection error: {e}");
211211- }
212212- });
213213-174174+ let db = Db::new(&args.postgres);
214175 let (tx, rx) = flume::bounded(EXPORT_PAGE_QUEUE_SIZE);
215176177177+ log::trace!("connecting postgres for export task...");
178178+ let pg_client = db.connect().await?;
216179 let export_task = tokio::task::spawn(export_upstream(
217180 args.upstream,
218181 (args.upstream_bulk, args.bulk_epoch),
219182 tx,
220220- pg_client2,
183183+ pg_client,
221184 ));
185185+186186+ log::trace!("connecting postgres for writer task...");
187187+ let pg_client = db.connect().await?;
222188 let writer_task = tokio::task::spawn(write_pages(rx, pg_client));
223189224190 tokio::select! {
225225- z = conn_task => log::warn!("connection task ended: {z:?}"),
226226- z = conn_task2 => log::warn!("connection task ended: {z:?}"),
227191 z = export_task => log::warn!("export task ended: {z:?}"),
228192 z = writer_task => log::warn!("writer task ended: {z:?}"),
229193 };
230194231195 log::error!("todo: shutdown");
196196+197197+ Ok(())
232198}
+2
src/lib.rs
···2233mod backfill;
44mod client;
55+mod plc_pg;
56mod poll;
6778pub use backfill::week_to_pages;
89pub use client::CLIENT;
1010+pub use plc_pg::Db;
911pub use poll::poll_upstream;
10121113pub type Dt = chrono::DateTime<chrono::Utc>;
+31
src/plc_pg.rs
···11+use tokio_postgres::{Client, Error as PgError, NoTls, connect};
22+33+/// a little tokio-postgres helper
44+#[derive(Debug, Clone)]
55+pub struct Db {
66+ pg_uri: String,
77+}
88+99+impl Db {
1010+ pub fn new(pg_uri: &str) -> Self {
1111+ Self {
1212+ pg_uri: pg_uri.to_string(),
1313+ }
1414+ }
1515+1616+ pub async fn connect(&self) -> Result<Client, PgError> {
1717+ log::trace!("connecting postgres...");
1818+ let (client, connection) = connect(&self.pg_uri, NoTls).await?;
1919+2020+ // send the connection away to do the actual communication work
2121+ // apparently the connection will complete when the client drops
2222+ tokio::task::spawn(async move {
2323+ connection
2424+ .await
2525+ .inspect_err(|e| log::error!("connection ended with error: {e}"))
2626+ .unwrap();
2727+ });
2828+2929+ Ok(client)
3030+ }
3131+}