Remove part file(s) in case of failure

Will not always delete part files in case of crashes
This commit is contained in:
Benoit Marty 2021-07-19 11:08:03 +02:00
parent 9c1bec94c9
commit 7643cc506d
2 changed files with 14 additions and 2 deletions

View file

@ -97,6 +97,9 @@ internal class DefaultFileService @Inject constructor(
} }
} }
var atomicFileCreator1: AtomicFileCreator? = null
var atomicFileCreator2: AtomicFileCreator? = null
if (existingDownload != null) { if (existingDownload != null) {
// FIXME If the first downloader cancels then we'll unfortunately be cancelled too. // FIXME If the first downloader cancels then we'll unfortunately be cancelled too.
return existingDownload.await() return existingDownload.await()
@ -133,7 +136,7 @@ internal class DefaultFileService @Inject constructor(
// Write the file to cache (encrypted version if the file is encrypted) // Write the file to cache (encrypted version if the file is encrypted)
// Write to a part file first, so if we abort before done, we don't have a broken cached file // Write to a part file first, so if we abort before done, we don't have a broken cached file
val atomicFileCreator = AtomicFileCreator(cachedFiles.file) val atomicFileCreator = AtomicFileCreator(cachedFiles.file).also { atomicFileCreator1 = it }
writeToFile(source.inputStream(), atomicFileCreator.partFile) writeToFile(source.inputStream(), atomicFileCreator.partFile)
response.close() response.close()
atomicFileCreator.commit() atomicFileCreator.commit()
@ -150,7 +153,7 @@ internal class DefaultFileService @Inject constructor(
// Ensure the parent folder exists // Ensure the parent folder exists
cachedFiles.decryptedFile.parentFile?.mkdirs() cachedFiles.decryptedFile.parentFile?.mkdirs()
// Write to a part file first, so if we abort before done, we don't have a broken cached file // Write to a part file first, so if we abort before done, we don't have a broken cached file
val atomicFileCreator = AtomicFileCreator(cachedFiles.decryptedFile) val atomicFileCreator = AtomicFileCreator(cachedFiles.decryptedFile).also { atomicFileCreator2 = it }
val decryptSuccess = cachedFiles.file.inputStream().use { inputStream -> val decryptSuccess = cachedFiles.file.inputStream().use { inputStream ->
atomicFileCreator.partFile.outputStream().buffered().use { outputStream -> atomicFileCreator.partFile.outputStream().buffered().use { outputStream ->
MXEncryptedAttachments.decryptAttachment( MXEncryptedAttachments.decryptAttachment(
@ -181,6 +184,11 @@ internal class DefaultFileService @Inject constructor(
} }
toNotify?.completeWith(result) toNotify?.completeWith(result)
result.onFailure {
atomicFileCreator1?.cancel()
atomicFileCreator2?.cancel()
}
return result.getOrThrow() return result.getOrThrow()
} }

View file

@ -32,6 +32,10 @@ internal class AtomicFileCreator(private val file: File) {
} }
} }
fun cancel() {
partFile.delete()
}
fun commit() { fun commit() {
partFile.renameTo(file) partFile.renameTo(file)
} }