Catch out 507 HTTP error when using WebDAV
Nextcloud has a bug that lets us write chunked transfers over quota: https://github.com/nextcloud/server/issues/7993 However, when we upload small files, we can get the proper 507 response and thus detect out of space situations and warn the user about them.
This commit is contained in:
parent
066b147315
commit
bb562a4cb2
7 changed files with 34 additions and 5 deletions
|
@ -32,7 +32,7 @@ class KoinInstrumentationTestApp : App() {
|
|||
|
||||
single { spyk(BackupNotificationManager(context)) }
|
||||
single { spyk(FullBackup(get(), get(), get(), get(), get())) }
|
||||
single { spyk(KVBackup(get(), get(), get(), get(), get())) }
|
||||
single { spyk(KVBackup(get(), get(), get(), get(), get(), get())) }
|
||||
single { spyk(InputFactory()) }
|
||||
|
||||
single { spyk(FullRestore(get(), get(), get(), get(), get())) }
|
||||
|
|
|
@ -9,6 +9,7 @@ import android.content.Context
|
|||
import android.net.ConnectivityManager
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
|
||||
import androidx.annotation.WorkerThread
|
||||
import at.bitfire.dav4jvm.exception.HttpException
|
||||
import java.io.IOException
|
||||
|
||||
abstract class StorageProperties<T> {
|
||||
|
@ -37,5 +38,12 @@ abstract class StorageProperties<T> {
|
|||
}
|
||||
|
||||
fun Exception.isOutOfSpace(): Boolean {
|
||||
return this is IOException && message?.contains("No space left on device") == true
|
||||
return when (this) {
|
||||
is IOException -> message?.contains("No space left on device") == true ||
|
||||
(cause as? HttpException)?.code == 507
|
||||
|
||||
is HttpException -> code == 507
|
||||
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -382,6 +382,7 @@ internal class BackupCoordinator(
|
|||
onPackageBackedUp(packageInfo, BackupType.FULL, size)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Error calling onPackageBackedUp for $packageName", e)
|
||||
if (e.isOutOfSpace()) nm.onInsufficientSpaceError()
|
||||
result = TRANSPORT_PACKAGE_REJECTED
|
||||
}
|
||||
result
|
||||
|
|
|
@ -19,6 +19,7 @@ val backupModule = module {
|
|||
KVBackup(
|
||||
pluginManager = get(),
|
||||
settingsManager = get(),
|
||||
nm = get(),
|
||||
inputFactory = get(),
|
||||
crypto = get(),
|
||||
dbManager = get(),
|
||||
|
|
|
@ -14,7 +14,9 @@ import com.stevesoltys.seedvault.crypto.Crypto
|
|||
import com.stevesoltys.seedvault.header.VERSION
|
||||
import com.stevesoltys.seedvault.header.getADForKV
|
||||
import com.stevesoltys.seedvault.plugins.StoragePluginManager
|
||||
import com.stevesoltys.seedvault.plugins.isOutOfSpace
|
||||
import com.stevesoltys.seedvault.settings.SettingsManager
|
||||
import com.stevesoltys.seedvault.ui.notification.BackupNotificationManager
|
||||
import java.io.IOException
|
||||
import java.util.zip.GZIPOutputStream
|
||||
|
||||
|
@ -34,6 +36,7 @@ private val TAG = KVBackup::class.java.simpleName
|
|||
internal class KVBackup(
|
||||
private val pluginManager: StoragePluginManager,
|
||||
private val settingsManager: SettingsManager,
|
||||
private val nm: BackupNotificationManager,
|
||||
private val inputFactory: InputFactory,
|
||||
private val crypto: Crypto,
|
||||
private val dbManager: KvDbManager,
|
||||
|
@ -214,6 +217,7 @@ internal class KVBackup(
|
|||
TRANSPORT_OK
|
||||
} catch (e: IOException) {
|
||||
Log.e(TAG, "Error uploading DB", e)
|
||||
if (e.isOutOfSpace()) nm.onInsufficientSpaceError()
|
||||
TRANSPORT_ERROR
|
||||
} finally {
|
||||
this.state = null
|
||||
|
|
|
@ -63,8 +63,14 @@ internal class CoordinatorIntegrationTest : TransportTest() {
|
|||
@Suppress("Deprecation")
|
||||
private val legacyPlugin = mockk<LegacyStoragePlugin>()
|
||||
private val backupPlugin = mockk<StoragePlugin<*>>()
|
||||
private val kvBackup =
|
||||
KVBackup(storagePluginManager, settingsManager, inputFactory, cryptoImpl, dbManager)
|
||||
private val kvBackup = KVBackup(
|
||||
pluginManager = storagePluginManager,
|
||||
settingsManager = settingsManager,
|
||||
nm = notificationManager,
|
||||
inputFactory = inputFactory,
|
||||
crypto = cryptoImpl,
|
||||
dbManager = dbManager,
|
||||
)
|
||||
private val fullBackup = FullBackup(
|
||||
pluginManager = storagePluginManager,
|
||||
settingsManager = settingsManager,
|
||||
|
|
|
@ -14,6 +14,7 @@ import com.stevesoltys.seedvault.header.VERSION
|
|||
import com.stevesoltys.seedvault.header.getADForKV
|
||||
import com.stevesoltys.seedvault.plugins.StoragePlugin
|
||||
import com.stevesoltys.seedvault.plugins.StoragePluginManager
|
||||
import com.stevesoltys.seedvault.ui.notification.BackupNotificationManager
|
||||
import io.mockk.CapturingSlot
|
||||
import io.mockk.Runs
|
||||
import io.mockk.coEvery
|
||||
|
@ -34,10 +35,18 @@ import kotlin.random.Random
|
|||
internal class KVBackupTest : BackupTest() {
|
||||
|
||||
private val pluginManager = mockk<StoragePluginManager>()
|
||||
private val notificationManager = mockk<BackupNotificationManager>()
|
||||
private val dataInput = mockk<BackupDataInput>()
|
||||
private val dbManager = mockk<KvDbManager>()
|
||||
|
||||
private val backup = KVBackup(pluginManager, settingsManager, inputFactory, crypto, dbManager)
|
||||
private val backup = KVBackup(
|
||||
pluginManager = pluginManager,
|
||||
settingsManager = settingsManager,
|
||||
nm = notificationManager,
|
||||
inputFactory = inputFactory,
|
||||
crypto = crypto,
|
||||
dbManager = dbManager
|
||||
)
|
||||
|
||||
private val db = mockk<KVDb>()
|
||||
private val plugin = mockk<StoragePlugin<*>>()
|
||||
|
|
Loading…
Reference in a new issue