Skip to content

Commit

Permalink
Catch out 507 HTTP error when using WebDAV
Browse files Browse the repository at this point in the history
Nextcloud has a bug that lets us write chunked transfers over quota:
nextcloud/server#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.
  • Loading branch information
grote committed May 9, 2024
1 parent c27040e commit ba28918
Show file tree
Hide file tree
Showing 7 changed files with 34 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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())) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down Expand Up @@ -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
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ val backupModule = module {
KVBackup(
pluginManager = get(),
settingsManager = get(),
nm = get(),
inputFactory = get(),
crypto = get(),
dbManager = get(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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<*>>()
Expand Down

0 comments on commit ba28918

Please sign in to comment.