defer errors on upload to media check

This commit is contained in:
Damien Elmes 2020-02-05 13:35:40 +10:00
parent d38c2c12d5
commit 98279add15
6 changed files with 42 additions and 21 deletions

View file

@ -97,6 +97,8 @@ message SyncError {
CLIENT_TOO_OLD = 3;
AUTH_FAILED = 4;
SERVER_MESSAGE = 5;
MEDIA_CHECK_REQUIRED = 6;
RESYNC_REQUIRED = 7;
}
SyncErrorKind kind = 2;
}

View file

@ -44,20 +44,6 @@ class MediaSyncState:
removed_files: int = 0
# fixme: sync.rs fixmes
# fixme: maximum size when uploading
# fixme: concurrent modifications during upload step
# fixme: mediaSanity
# elif evt == "mediaSanity":
# showWarning(
# _(
# """\
# A problem occurred while syncing media. Please use Tools>Check Media, then \
# sync again to correct the issue."""
# )
# )
LogEntry = Union[MediaSyncState, str]
@ -170,6 +156,14 @@ class MediaSyncer:
"AnkiWeb encountered a problem. Please try again in a few minutes."
)
)
elif kind == SyncErrorKind.MEDIA_CHECK_REQUIRED:
showWarning(_("Please use the Tools>Check Media menu option."))
elif kind == SyncErrorKind.RESYNC_REQUIRED:
showWarning(
_(
"Please sync again, and post on the support forum if this message keeps appearing."
)
)
else:
showWarning(_("Unexpected error: {}").format(str(exc)))
elif isinstance(exc, NetworkError):

View file

@ -87,6 +87,8 @@ impl std::convert::From<SyncErrorKind> for i32 {
SyncErrorKind::ClientTooOld => V::ClientTooOld,
SyncErrorKind::AuthFailed => V::AuthFailed,
SyncErrorKind::ServerMessage => V::ServerMessage,
SyncErrorKind::MediaCheckRequired => V::MediaCheckRequired,
SyncErrorKind::ResyncRequired => V::ResyncRequired,
SyncErrorKind::Other => V::Other,
}) as i32
}

View file

@ -129,6 +129,8 @@ pub enum SyncErrorKind {
AuthFailed,
ServerMessage,
Other,
MediaCheckRequired,
ResyncRequired,
}
fn error_for_status_code(info: String, code: StatusCode) -> AnkiError {

View file

@ -244,6 +244,12 @@ delete from media where fname=?"
.collect();
Ok(map?)
}
pub(super) fn force_resync(&mut self) -> Result<()> {
self.db
.execute_batch("delete from media; update meta set lastUsn=0, usn=0")
.map_err(Into::into)
}
}
#[cfg(test)]

View file

@ -1,7 +1,7 @@
// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use crate::err::{AnkiError, Result};
use crate::err::{AnkiError, Result, SyncErrorKind};
use crate::media::database::{MediaDatabaseContext, MediaDatabaseMetadata, MediaEntry};
use crate::media::files::{
add_file_from_ankiweb, data_for_file, normalize_filename, remove_files, AddedFile,
@ -22,6 +22,10 @@ use std::{io, time};
static SYNC_MAX_FILES: usize = 25;
static SYNC_MAX_BYTES: usize = (2.5 * 1024.0 * 1024.0) as usize;
static SYNC_SINGLE_FILE_MAX_BYTES: usize = 100 * 1024 * 1024;
// fixme: non-normalized filenames on ankiweb
// fixme: concurrent modifications during upload step
/// The counts are not cumulative - the progress hook should accumulate them.
#[derive(Debug)]
@ -182,8 +186,11 @@ where
if data == "OK" {
Ok(())
} else {
// fixme: force resync, handle better
Err(AnkiError::server_message("resync required"))
self.ctx.transact(|ctx| ctx.force_resync())?;
Err(AnkiError::SyncError {
info: "".into(),
kind: SyncErrorKind::ResyncRequired,
})
}
} else {
Err(AnkiError::server_message(resp.err))
@ -556,16 +563,17 @@ fn zip_files(media_folder: &Path, files: &[MediaEntry]) -> Result<Vec<u8>> {
let normalized = normalize_filename(&file.fname);
if let Cow::Owned(_) = normalized {
// fixme: non-string err, or should ignore instead
return Err(AnkiError::sync_misc("invalid file found"));
return Err(media_check_required());
}
let file_data = data_for_file(media_folder, &file.fname)?;
if let Some(data) = &file_data {
if data.is_empty() {
// fixme: should ignore these, not error
return Err(AnkiError::sync_misc("0 byte file found"));
return Err(media_check_required());
}
if data.len() > SYNC_SINGLE_FILE_MAX_BYTES {
return Err(media_check_required());
}
accumulated_size += data.len();
zip.start_file(format!("{}", idx), options)?;
@ -605,6 +613,13 @@ fn version_string() -> String {
format!("anki,{},{}", version(), std::env::consts::OS)
}
fn media_check_required() -> AnkiError {
AnkiError::SyncError {
info: "".into(),
kind: SyncErrorKind::MediaCheckRequired,
}
}
#[derive(Serialize)]
struct FinalizeRequest {
local: u32,