Wrap backend in an outer Arc

Necessary to allow backend commands that run in the background instead
of blocking.
This commit is contained in:
Damien Elmes 2023-09-07 14:10:50 +10:00
parent ffd392de21
commit 9595101065
3 changed files with 28 additions and 22 deletions

View file

@ -14,11 +14,13 @@ mod import_export;
mod ops; mod ops;
mod sync; mod sync;
use std::ops::Deref;
use std::result; use std::result;
use std::sync::Arc; use std::sync::Arc;
use std::sync::Mutex; use std::sync::Mutex;
use std::thread::JoinHandle; use std::thread::JoinHandle;
use futures::future::AbortHandle;
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use prost::Message; use prost::Message;
use reqwest::Client; use reqwest::Client;
@ -28,20 +30,31 @@ use tokio::runtime::Runtime;
use crate::backend::dbproxy::db_command_bytes; use crate::backend::dbproxy::db_command_bytes;
use crate::backend::sync::SyncState; use crate::backend::sync::SyncState;
use crate::prelude::*; use crate::prelude::*;
use crate::progress::AbortHandleSlot;
use crate::progress::Progress; use crate::progress::Progress;
use crate::progress::ProgressState; use crate::progress::ProgressState;
use crate::progress::ThrottlingProgressHandler; use crate::progress::ThrottlingProgressHandler;
pub struct Backend { #[derive(Clone)]
col: Arc<Mutex<Option<Collection>>>, #[repr(transparent)]
pub struct Backend(Arc<BackendInner>);
impl Deref for Backend {
type Target = BackendInner;
fn deref(&self) -> &Self::Target {
&self.0
}
}
pub struct BackendInner {
col: Mutex<Option<Collection>>,
pub(crate) tr: I18n, pub(crate) tr: I18n,
server: bool, server: bool,
sync_abort: AbortHandleSlot, sync_abort: Mutex<Option<AbortHandle>>,
progress_state: Arc<Mutex<ProgressState>>, progress_state: Arc<Mutex<ProgressState>>,
runtime: OnceCell<Runtime>, runtime: OnceCell<Runtime>,
state: Arc<Mutex<BackendState>>, state: Mutex<BackendState>,
backup_task: Arc<Mutex<Option<JoinHandle<Result<()>>>>>, backup_task: Mutex<Option<JoinHandle<Result<()>>>>,
web_client: OnceCell<Client>, web_client: OnceCell<Client>,
} }
@ -64,20 +77,20 @@ pub fn init_backend(init_msg: &[u8]) -> result::Result<Backend, String> {
impl Backend { impl Backend {
pub fn new(tr: I18n, server: bool) -> Backend { pub fn new(tr: I18n, server: bool) -> Backend {
Backend { Backend(Arc::new(BackendInner {
col: Arc::new(Mutex::new(None)), col: Mutex::new(None),
tr, tr,
server, server,
sync_abort: Arc::new(Mutex::new(None)), sync_abort: Mutex::new(None),
progress_state: Arc::new(Mutex::new(ProgressState { progress_state: Arc::new(Mutex::new(ProgressState {
want_abort: false, want_abort: false,
last_progress: None, last_progress: None,
})), })),
runtime: OnceCell::new(), runtime: OnceCell::new(),
state: Arc::new(Mutex::new(BackendState::default())), state: Mutex::new(BackendState::default()),
backup_task: Arc::new(Mutex::new(None)), backup_task: Mutex::new(None),
web_client: OnceCell::new(), web_client: OnceCell::new(),
} }))
} }
pub fn i18n(&self) -> &I18n { pub fn i18n(&self) -> &I18n {

View file

@ -1,8 +1,6 @@
// Copyright: Ankitects Pty Ltd and contributors // Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use std::sync::Arc;
use anki_proto::sync::sync_status_response::Required; use anki_proto::sync::sync_status_response::Required;
use anki_proto::sync::SyncStatusResponse; use anki_proto::sync::SyncStatusResponse;
use futures::future::AbortHandle; use futures::future::AbortHandle;
@ -13,7 +11,6 @@ use tracing::warn;
use super::Backend; use super::Backend;
use crate::prelude::*; use crate::prelude::*;
use crate::progress::AbortHandleSlot;
use crate::sync::collection::normal::ClientSyncState; use crate::sync::collection::normal::ClientSyncState;
use crate::sync::collection::normal::SyncActionRequired; use crate::sync::collection::normal::SyncActionRequired;
use crate::sync::collection::normal::SyncOutput; use crate::sync::collection::normal::SyncOutput;
@ -154,7 +151,7 @@ impl Backend {
fn sync_abort_handle( fn sync_abort_handle(
&self, &self,
) -> Result<( ) -> Result<(
scopeguard::ScopeGuard<AbortHandleSlot, impl FnOnce(AbortHandleSlot)>, scopeguard::ScopeGuard<Backend, impl FnOnce(Backend)>,
AbortRegistration, AbortRegistration,
)> { )> {
let (abort_handle, abort_reg) = AbortHandle::new_pair(); let (abort_handle, abort_reg) = AbortHandle::new_pair();
@ -171,8 +168,8 @@ impl Backend {
); );
} }
// Clear the abort handle after the caller is done and drops the guard. // Clear the abort handle after the caller is done and drops the guard.
let guard = scopeguard::guard(Arc::clone(&self.sync_abort), |sync_abort| { let guard = scopeguard::guard(self.clone(), |backend| {
sync_abort.lock().unwrap().take(); backend.sync_abort.lock().unwrap().take();
}); });
Ok((guard, abort_reg)) Ok((guard, abort_reg))
} }

View file

@ -8,7 +8,6 @@ use std::sync::Mutex;
use anki_i18n::I18n; use anki_i18n::I18n;
use anki_proto::collection::progress::ComputeRetention; use anki_proto::collection::progress::ComputeRetention;
use anki_proto::collection::progress::ComputeWeights; use anki_proto::collection::progress::ComputeWeights;
use futures::future::AbortHandle;
use crate::dbcheck::DatabaseCheckProgress; use crate::dbcheck::DatabaseCheckProgress;
use crate::error::AnkiError; use crate::error::AnkiError;
@ -123,9 +122,6 @@ pub struct ProgressState {
pub last_progress: Option<Progress>, pub last_progress: Option<Progress>,
} }
// fixme: this should support multiple abort handles.
pub(crate) type AbortHandleSlot = Arc<Mutex<Option<AbortHandle>>>;
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub enum Progress { pub enum Progress {
MediaSync(MediaSyncProgress), MediaSync(MediaSyncProgress),