From 1175a5426622f685bd29bd667893eef478eac479 Mon Sep 17 00:00:00 2001 From: Timofey Date: Wed, 8 Jan 2020 22:32:43 +0300 Subject: [PATCH] Synchronize feed updates --- podcasts-gtk/src/app.rs | 22 +++++++++++++++++++++- podcasts-gtk/src/utils.rs | 19 ++++++++++--------- podcasts-gtk/src/window.rs | 4 +++- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/podcasts-gtk/src/app.rs b/podcasts-gtk/src/app.rs index 4876bd0..5d34959 100644 --- a/podcasts-gtk/src/app.rs +++ b/podcasts-gtk/src/app.rs @@ -34,7 +34,7 @@ use gettextrs::{bindtextdomain, setlocale, textdomain, LocaleCategory}; use crossbeam_channel::Receiver; use fragile::Fragile; -use podcasts_data::Show; +use podcasts_data::{Show, Source}; use crate::settings; use crate::stacks::PopulatedState; @@ -138,7 +138,9 @@ pub(crate) enum Action { HeaderBarShowTile(String), HeaderBarNormal, MarkAllPlayerNotification(Arc), + UpdateFeed(Option>), ShowUpdateNotif(Receiver), + StopUpdating, RemoveShow(Arc), ErrorNotification(String), InitEpisode(i32), @@ -248,6 +250,17 @@ impl PdApplication { let notif = InAppNotification::new(&err, 6000, callback, undo_cb); notif.show(&window.overlay); } + Action::UpdateFeed(source) => { + if window.updating.get() { + info!("Ignoring feed update request (another one is already running)") + } else { + window.updating.set(true); + utils::refresh_feed(source, window.sender.clone()) + } + } + Action::StopUpdating => { + window.updating.set(false); + } Action::ShowUpdateNotif(receiver) => { let sender = window.sender.clone(); let callback = move |revealer: gtk::Revealer| match receiver.try_recv() { @@ -255,9 +268,15 @@ impl PdApplication { Err(TryRecvError::Disconnected) => glib::Continue(false), Ok(_) => { revealer.set_reveal_child(false); + + sender + .send(Action::StopUpdating) + .expect("Action channel blew up somehow"); + sender .send(Action::RefreshAllViews) .expect("Action channel blew up somehow"); + glib::Continue(false) } }; @@ -269,6 +288,7 @@ impl PdApplication { let old = window.updater.replace(Some(updater)); old.map(|i| i.destroy()); + window .updater .borrow() diff --git a/podcasts-gtk/src/utils.rs b/podcasts-gtk/src/utils.rs index 981a3bd..77a81f1 100644 --- a/podcasts-gtk/src/utils.rs +++ b/podcasts-gtk/src/utils.rs @@ -203,10 +203,10 @@ pub(crate) fn cleanup(cleanup_date: DateTime) { .ok(); } -pub(crate) fn refresh(source: Option, sender: Sender) -where - S: IntoIterator + Send + 'static, -{ +/// Schedule feed refresh +/// If `source` is None, Refreshes all sources in the database. +/// Current implementation ignores update request if another update is already running +pub(crate) fn refresh(source: Option>, sender: Sender) { // If we try to update the whole db, // Exit early if `source` table is empty if source.is_none() { @@ -220,15 +220,16 @@ where }; } - refresh_feed(source, sender) + sender + .send(Action::UpdateFeed(source)) + .expect("Action channel blew up somehow") } /// Update the rss feed(s) originating from `source`. /// If `source` is None, Fetches all the `Source` entries in the database and updates them. -fn refresh_feed(source: Option, sender: Sender) -where - S: IntoIterator + Send + 'static, -{ +/// Do not call this function directly unless you are sure no other updates are running. +/// Use `refresh()` instead +pub(crate) fn refresh_feed(source: Option>, sender: Sender) { rayon::spawn(move || { let (up_sender, up_receiver) = bounded(1); sender diff --git a/podcasts-gtk/src/window.rs b/podcasts-gtk/src/window.rs index e73daa1..7227eb3 100644 --- a/podcasts-gtk/src/window.rs +++ b/podcasts-gtk/src/window.rs @@ -36,7 +36,7 @@ use crate::widgets::about_dialog; use crate::widgets::appnotif::InAppNotification; use crate::widgets::player; -use std::cell::RefCell; +use std::cell::{Cell, RefCell}; use std::ops::Deref; use std::rc::Rc; @@ -65,6 +65,7 @@ pub struct MainWindow { pub(crate) content: Rc, pub(crate) headerbar: Rc
, pub(crate) player: player::PlayerWrapper, + pub(crate) updating: Cell, pub(crate) updater: RefCell>, pub(crate) sender: Sender, pub(crate) receiver: Receiver, @@ -158,6 +159,7 @@ impl MainWindow { headerbar: header, content, player, + updating: Cell::new(false), updater, sender, receiver,