diff --git a/hammond-data/src/index_feed.rs b/hammond-data/src/index_feed.rs index 0fb426e..1c2d23b 100644 --- a/hammond-data/src/index_feed.rs +++ b/hammond-data/src/index_feed.rs @@ -98,7 +98,7 @@ pub fn index_loop(db: &Arc>, force: bool) -> Result<()> pub fn complete_index_from_source( req: &mut reqwest::Response, source: &Source, - mutex: &Arc>, + db: &Arc>, ) -> Result<()> { use std::io::Read; use std::str::FromStr; @@ -107,57 +107,66 @@ pub fn complete_index_from_source( req.read_to_string(&mut buf)?; let chan = rss::Channel::from_str(&buf)?; - complete_index(mutex, &chan, source)?; + complete_index(&db, &chan, source)?; Ok(()) } fn complete_index( - connection: &Arc>, + db: &Arc>, chan: &rss::Channel, parent: &Source, ) -> Result<()> { let pd = { - let db = connection.lock().unwrap(); - index_channel(&db, chan, parent)? + let conn = db.lock().unwrap(); + index_channel(&conn, chan, parent)? }; - - index_channel_items(connection, chan.items(), &pd); - + index_channel_items(db, chan.items(), &pd); Ok(()) } -fn index_channel(db: &SqliteConnection, chan: &rss::Channel, parent: &Source) -> Result { +fn index_channel(con: &SqliteConnection, chan: &rss::Channel, parent: &Source) -> Result { let pd = feedparser::parse_podcast(chan, parent.id()); // Convert NewPodcast to Podcast - let pd = insert_return_podcast(db, &pd)?; + let pd = insert_return_podcast(con, &pd)?; Ok(pd) } -fn index_channel_items(connection: &Arc>, it: &[rss::Item], pd: &Podcast) { - it.par_iter() +fn index_channel_items(db: &Arc>, it: &[rss::Item], pd: &Podcast) { + let episodes: Vec<_> = it.par_iter() .map(|x| feedparser::parse_episode(x, pd.id())) - .for_each(|x| { - let db = connection.lock().unwrap(); - let e = index_episode(&db, &x); + .collect(); + + let conn = db.lock().unwrap(); + let e = conn.transaction::<(), Error, _>(|| { + episodes.iter().for_each(|x| { + let e = index_episode(&conn, &x); if let Err(err) = e { error!("Failed to index episode: {:?}.", x); error!("Error msg: {}", err); }; }); + Ok(()) + }); + drop(conn); + + if let Err(err) = e { + error!("Episodes Transcaction Failed."); + error!("Error msg: {}", err); + }; } // Maybe this can be refactored into an Iterator for lazy evaluation. -pub fn fetch_feeds(connection: &Arc>, force: bool) -> Result> { - let tempdb = connection.lock().unwrap(); - let mut feeds = dbqueries::get_sources(&tempdb)?; - drop(tempdb); +pub fn fetch_feeds(db: &Arc>, force: bool) -> Result> { + let mut feeds = { + let conn = db.lock().unwrap(); + dbqueries::get_sources(&conn)? + }; let results: Vec = feeds .par_iter_mut() .filter_map(|x| { - let db = connection.lock().unwrap(); - let l = refresh_source(&db, x, force); + let l = refresh_source(db, x, force); if l.is_ok() { l.ok() } else { @@ -172,7 +181,7 @@ pub fn fetch_feeds(connection: &Arc>, force: bool) -> Re } pub fn refresh_source( - connection: &SqliteConnection, + db: &Arc>, feed: &mut Source, force: bool, ) -> Result { @@ -212,7 +221,7 @@ pub fn refresh_source( // _ => (), // }; - feed.update_etag(connection, &req)?; + feed.update_etag(db, &req)?; Ok(Feed(req, feed.clone())) } diff --git a/hammond-data/src/models.rs b/hammond-data/src/models.rs index cf43dc9..a36abfa 100644 --- a/hammond-data/src/models.rs +++ b/hammond-data/src/models.rs @@ -3,6 +3,8 @@ use diesel::SaveChangesDsl; use SqliteConnection; use reqwest::header::{ETag, LastModified}; +use std::sync::{Arc, Mutex}; + use schema::{episode, podcast, source}; use errors::*; @@ -178,7 +180,11 @@ impl<'a> Source { /// Extract Etag and LastModifier from req, and update self and the /// corresponding db row. - pub fn update_etag(&mut self, con: &SqliteConnection, req: &reqwest::Response) -> Result<()> { + pub fn update_etag( + &mut self, + db: &Arc>, + req: &reqwest::Response, + ) -> Result<()> { let headers = req.headers(); // let etag = headers.get_raw("ETag").unwrap(); @@ -191,7 +197,8 @@ impl<'a> Source { { self.http_etag = etag.map(|x| x.tag().to_string().to_owned()); self.last_modified = lmod.map(|x| format!("{}", x)); - self.save_changes::(con)?; + let con = db.lock().unwrap(); + self.save_changes::(&*con)?; } Ok(()) diff --git a/hammond-gtk/src/utils.rs b/hammond-gtk/src/utils.rs index 89d3692..c03cee5 100644 --- a/hammond-gtk/src/utils.rs +++ b/hammond-gtk/src/utils.rs @@ -73,9 +73,7 @@ pub fn refresh_feed(db: &Arc>, stack: >k::Stack, sourc let mut source = source.clone(); // TODO: add timeout option and error reporting. thread::spawn(clone!(db => move || { - let db_ = db.lock().unwrap(); - let foo_ = hammond_data::index_feed::refresh_source(&db_, &mut source, false); - drop(db_); + let foo_ = hammond_data::index_feed::refresh_source(&db, &mut source, false); if let Ok(x) = foo_ { let Feed(mut req, s) = x; diff --git a/hammond-gtk/src/views/podcasts_view.rs b/hammond-gtk/src/views/podcasts_view.rs index 2fd90cf..4b1d4d2 100644 --- a/hammond-gtk/src/views/podcasts_view.rs +++ b/hammond-gtk/src/views/podcasts_view.rs @@ -75,6 +75,8 @@ pub fn populate_podcasts_flowbox( stack.remove(&old); stack.add_named(&pdw, "pdw"); stack.set_visible_child(&pdw); + // aggresive memory cleanup + // probably not needed old.destroy(); println!("Hello World!, child activated"); })); @@ -167,5 +169,8 @@ pub fn update_podcasts_view(db: &Arc>, stack: >k::Stac stack.add_named(&grid, "pd_grid"); // preserve the visible widget stack.set_visible_child_name(&vis); + + // aggresive memory cleanup + // probably not needed old.destroy(); } diff --git a/hammond-gtk/src/widgets/episode.rs b/hammond-gtk/src/widgets/episode.rs index 3c6b578..062392f 100644 --- a/hammond-gtk/src/widgets/episode.rs +++ b/hammond-gtk/src/widgets/episode.rs @@ -168,16 +168,16 @@ fn receive() -> glib::Continue { glib::Continue(false) } -pub fn episodes_listbox(connection: &Arc>, pd_title: &str) -> gtk::ListBox { +pub fn episodes_listbox(db: &Arc>, pd_title: &str) -> gtk::ListBox { // TODO: handle unwraps. - let m = connection.lock().unwrap(); - let pd = dbqueries::load_podcast_from_title(&m, pd_title).unwrap(); - let mut episodes = dbqueries::get_pd_episodes(&m, &pd).unwrap(); - drop(m); + let conn = db.lock().unwrap(); + let pd = dbqueries::load_podcast_from_title(&conn, pd_title).unwrap(); + let mut episodes = dbqueries::get_pd_episodes(&conn, &pd).unwrap(); + drop(conn); let list = gtk::ListBox::new(); episodes.iter_mut().for_each(|ep| { - let w = epidose_widget(connection, ep, pd_title); + let w = epidose_widget(db, ep, pd_title); list.add(&w) }); diff --git a/hammond-gtk/src/widgets/podcast.rs b/hammond-gtk/src/widgets/podcast.rs index 97bd006..4c45ea5 100644 --- a/hammond-gtk/src/widgets/podcast.rs +++ b/hammond-gtk/src/widgets/podcast.rs @@ -12,7 +12,7 @@ use std::sync::{Arc, Mutex}; use widgets::episode::episodes_listbox; pub fn podcast_widget( - connection: &Arc>, + db: &Arc>, title: Option<&str>, description: Option<&str>, image: Option, @@ -29,7 +29,7 @@ pub fn podcast_widget( if let Some(t) = title { title_label.set_text(t); - let listbox = episodes_listbox(connection, t); + let listbox = episodes_listbox(db, t); view.add(&listbox); } @@ -84,6 +84,9 @@ pub fn on_flowbox_child_activate( stack.remove(&old); stack.add_named(&pdw, "pdw"); stack.set_visible_child(&pdw); + + // aggresive memory cleanup + // probably not needed old.destroy(); println!("Hello World!, child activated"); }