allow aborting a media sync while http req in flight

The progress handling code needs a rethink, as we now have two separate
ways to flag that the media sync should abort. In the future, it may
make sense to switch to polling the backend for progress, instead of
passing a callback in.
This commit is contained in:
Damien Elmes 2020-04-01 09:49:25 +10:00
parent cb5b122c7c
commit c9da4bc1a6
5 changed files with 36 additions and 5 deletions

View file

@ -55,6 +55,7 @@ message BackendInput {
Empty all_deck_config = 43; Empty all_deck_config = 43;
Empty new_deck_config = 44; Empty new_deck_config = 44;
int64 remove_deck_config = 45; int64 remove_deck_config = 45;
Empty abort_media_sync = 46;
} }
} }
@ -70,6 +71,7 @@ message BackendOutput {
string format_time_span = 31; string format_time_span = 31;
string studied_today = 32; string studied_today = 32;
string congrats_learn_msg = 33; string congrats_learn_msg = 33;
Empty abort_media_sync = 46;
// fallible commands // fallible commands
TemplateRequirementsOut template_requirements = 16; TemplateRequirementsOut template_requirements = 16;

View file

@ -519,6 +519,9 @@ class RustBackend:
def remove_deck_config(self, dcid: int) -> None: def remove_deck_config(self, dcid: int) -> None:
self._run_command(pb.BackendInput(remove_deck_config=dcid)) self._run_command(pb.BackendInput(remove_deck_config=dcid))
def abort_media_sync(self):
self._run_command(pb.BackendInput(abort_media_sync=pb.Empty()))
def translate_string_in( def translate_string_in(
key: TR, **kwargs: Union[str, int, float] key: TR, **kwargs: Union[str, int, float]

View file

@ -123,6 +123,7 @@ class MediaSyncer:
return return
self._log_and_notify(tr(TR.SYNC_MEDIA_ABORTING)) self._log_and_notify(tr(TR.SYNC_MEDIA_ABORTING))
self._want_stop = True self._want_stop = True
self.mw.col.backend.abort_media_sync()
def is_syncing(self) -> bool: def is_syncing(self) -> bool:
return self._syncing return self._syncing

View file

@ -39,6 +39,7 @@ slog-envlogger = "2.2.0"
serde_repr = "0.1.5" serde_repr = "0.1.5"
num_enum = "0.4.2" num_enum = "0.4.2"
unicase = "2.6.0" unicase = "2.6.0"
futures = "0.3.4"
# pinned until rusqlite 0.22 comes out # pinned until rusqlite 0.22 comes out
[target.'cfg(target_vendor="apple")'.dependencies.rusqlite] [target.'cfg(target_vendor="apple")'.dependencies.rusqlite]

View file

@ -30,6 +30,7 @@ use crate::timestamp::TimestampSecs;
use crate::types::Usn; use crate::types::Usn;
use crate::{backend_proto as pb, log}; use crate::{backend_proto as pb, log};
use fluent::FluentValue; use fluent::FluentValue;
use futures::future::{AbortHandle, Abortable};
use log::error; use log::error;
use prost::Message; use prost::Message;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
@ -47,6 +48,7 @@ pub struct Backend {
progress_callback: Option<ProtoProgressCallback>, progress_callback: Option<ProtoProgressCallback>,
i18n: I18n, i18n: I18n,
server: bool, server: bool,
media_sync_abort: Option<AbortHandle>,
} }
enum Progress<'a> { enum Progress<'a> {
@ -135,6 +137,7 @@ impl Backend {
progress_callback: None, progress_callback: None,
i18n, i18n,
server, server,
media_sync_abort: None,
} }
} }
@ -274,6 +277,10 @@ impl Backend {
self.remove_deck_config(dcid)?; self.remove_deck_config(dcid)?;
OValue::RemoveDeckConfig(pb::Empty {}) OValue::RemoveDeckConfig(pb::Empty {})
} }
Value::AbortMediaSync(_) => {
self.abort_media_sync();
OValue::AbortMediaSync(pb::Empty {})
}
}) })
} }
@ -481,9 +488,7 @@ impl Backend {
}) })
} }
// fixme: will block other db access fn sync_media(&mut self, input: SyncMediaIn) -> Result<()> {
fn sync_media(&self, input: SyncMediaIn) -> Result<()> {
let mut guard = self.col.lock().unwrap(); let mut guard = self.col.lock().unwrap();
let col = guard.as_mut().unwrap(); let col = guard.as_mut().unwrap();
@ -503,19 +508,38 @@ impl Backend {
} }
fn sync_media_inner( fn sync_media_inner(
&self, &mut self,
input: pb::SyncMediaIn, input: pb::SyncMediaIn,
folder: PathBuf, folder: PathBuf,
db: PathBuf, db: PathBuf,
log: Logger, log: Logger,
) -> Result<()> { ) -> Result<()> {
let (abort_handle, abort_reg) = AbortHandle::new_pair();
self.media_sync_abort = Some(abort_handle);
let callback = |progress: &MediaSyncProgress| { let callback = |progress: &MediaSyncProgress| {
self.fire_progress_callback(Progress::MediaSync(progress)) self.fire_progress_callback(Progress::MediaSync(progress))
}; };
let mgr = MediaManager::new(&folder, &db)?; let mgr = MediaManager::new(&folder, &db)?;
let mut rt = Runtime::new().unwrap(); let mut rt = Runtime::new().unwrap();
rt.block_on(mgr.sync_media(callback, &input.endpoint, &input.hkey, log)) let sync_fut = mgr.sync_media(callback, &input.endpoint, &input.hkey, log);
let abortable_sync = Abortable::new(sync_fut, abort_reg);
let ret = match rt.block_on(abortable_sync) {
Ok(sync_result) => sync_result,
Err(_) => {
// aborted sync
Ok(())
}
};
self.media_sync_abort = None;
ret
}
fn abort_media_sync(&mut self) {
if let Some(handle) = self.media_sync_abort.take() {
handle.abort();
}
} }
fn check_media(&self) -> Result<pb::MediaCheckOut> { fn check_media(&self) -> Result<pb::MediaCheckOut> {