Skip to content

Commit 4b0e06b

Browse files
committed
refactor(db-repository): convert message download operations to suspend functions
- Add suspend modifier to Backend.downloadCompleteMessage and related chain - Add suspend to BackendFolder.saveMessage and FetchListener.onFetchResponse - Add suspend to ImapFolder.fetch and ImapSync download methods - Wrap blocking Backend calls with runBlocking(ioDispatcher) in implementations - Add downloadCompleteMessageBlocking wrapper for legacy MessagingController - Add ioDispatcher parameter to DemoBackend and ImapBackend constructors - Replace direct runBlocking calls in Pop3Sync with proper suspend propagation GG-ID: c-e9f0142
1 parent 1fb02e2 commit 4b0e06b

24 files changed

Lines changed: 162 additions & 114 deletions

File tree

‎backend/api/src/main/java/com/fsck/k9/backend/api/Backend.kt‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ interface Backend {
3131
fun downloadMessageStructure(folderServerId: String, messageServerId: String)
3232

3333
@Throws(MessagingException::class)
34-
fun downloadCompleteMessage(folderServerId: String, messageServerId: String)
34+
suspend fun downloadCompleteMessage(folderServerId: String, messageServerId: String)
3535

3636
@Throws(MessagingException::class)
3737
fun setFlag(folderServerId: String, messageServerIds: List<String>, flag: Flag, newState: Boolean)

‎backend/api/src/main/java/com/fsck/k9/backend/api/BackendFolder.kt‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ interface BackendFolder {
2121
fun isMessagePresent(messageServerId: String): Boolean
2222
fun getMessageFlags(messageServerId: String): Set<Flag>
2323
fun setMessageFlag(messageServerId: String, flag: Flag, value: Boolean)
24-
fun saveMessage(message: Message, downloadState: MessageDownloadState)
24+
suspend fun saveMessage(message: Message, downloadState: MessageDownloadState)
2525
fun getOldestMessageDate(): Date?
2626
fun getFolderExtraString(name: String): String?
2727
fun setFolderExtraString(name: String, value: String?)

‎backend/demo/src/main/kotlin/app/k9mail/backend/demo/CommandSendMessage.kt‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ internal class CommandSendMessage(
1313
private val demoStore: DemoStore,
1414
) {
1515

16-
fun sendMessage(message: Message) {
16+
suspend fun sendMessage(message: Message) {
1717
val inboxServerId = demoStore.getInboxFolderId()
1818
val backendFolder = backendStorage.getFolder(inboxServerId)
1919

‎backend/demo/src/main/kotlin/app/k9mail/backend/demo/CommandSync.kt‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ internal class CommandSync(
1010
private val demoStore: DemoStore,
1111
) {
1212

13-
fun sync(folderServerId: String, listener: SyncListener) {
13+
suspend fun sync(folderServerId: String, listener: SyncListener) {
1414
listener.syncStarted(folderServerId)
1515

1616
val folder = demoStore.getFolder(folderServerId)

‎backend/demo/src/main/kotlin/app/k9mail/backend/demo/DemoBackend.kt‎

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,15 @@ import com.fsck.k9.backend.api.SyncListener
1010
import com.fsck.k9.mail.BodyFactory
1111
import com.fsck.k9.mail.Message
1212
import com.fsck.k9.mail.Part
13+
import kotlinx.coroutines.CoroutineDispatcher
14+
import kotlinx.coroutines.Dispatchers
15+
import kotlinx.coroutines.runBlocking
1316
import net.thunderbird.core.common.mail.Flag
1417
import net.thunderbird.feature.mail.folder.api.FolderPathDelimiter
1518

1619
class DemoBackend(
1720
private val backendStorage: BackendStorage,
21+
private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO,
1822
) : Backend {
1923
private val demoStore by lazy { DemoStore() }
2024

@@ -36,9 +40,10 @@ class DemoBackend(
3640
return commandRefreshFolderList.refreshFolderList()
3741
}
3842

39-
override fun sync(folderServerId: String, syncConfig: SyncConfig, listener: SyncListener) {
40-
commandSync.sync(folderServerId, listener)
41-
}
43+
override fun sync(folderServerId: String, syncConfig: SyncConfig, listener: SyncListener) =
44+
runBlocking(ioDispatcher) {
45+
commandSync.sync(folderServerId, listener)
46+
}
4247

4348
override fun downloadMessage(syncConfig: SyncConfig, folderServerId: String, messageServerId: String) {
4449
throw UnsupportedOperationException("not implemented")
@@ -48,7 +53,7 @@ class DemoBackend(
4853
throw UnsupportedOperationException("not implemented")
4954
}
5055

51-
override fun downloadCompleteMessage(folderServerId: String, messageServerId: String) {
56+
override suspend fun downloadCompleteMessage(folderServerId: String, messageServerId: String) {
5257
throw UnsupportedOperationException("not implemented")
5358
}
5459

@@ -113,7 +118,7 @@ class DemoBackend(
113118
return createNewServerId()
114119
}
115120

116-
override fun sendMessage(message: Message) {
121+
override fun sendMessage(message: Message) = runBlocking(ioDispatcher) {
117122
commandSendMessage.sendMessage(message)
118123
}
119124

‎backend/imap/src/main/java/com/fsck/k9/backend/imap/CommandDownloadMessage.kt‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import com.fsck.k9.mail.store.imap.OpenMode
1515

1616
internal class CommandDownloadMessage(private val backendStorage: BackendStorage, private val imapStore: ImapStore) {
1717

18-
fun downloadMessageStructure(folderServerId: String, messageServerId: String) {
18+
suspend fun downloadMessageStructure(folderServerId: String, messageServerId: String) {
1919
val folder = imapStore.getFolder(folderServerId)
2020
try {
2121
folder.open(OpenMode.READ_ONLY)
@@ -33,7 +33,7 @@ internal class CommandDownloadMessage(private val backendStorage: BackendStorage
3333
}
3434
}
3535

36-
fun downloadCompleteMessage(folderServerId: String, messageServerId: String) {
36+
suspend fun downloadCompleteMessage(folderServerId: String, messageServerId: String) {
3737
val folder = imapStore.getFolder(folderServerId)
3838
try {
3939
folder.open(OpenMode.READ_ONLY)
@@ -48,13 +48,13 @@ internal class CommandDownloadMessage(private val backendStorage: BackendStorage
4848
}
4949
}
5050

51-
private fun fetchMessage(remoteFolder: ImapFolder, message: ImapMessage, fetchProfile: FetchProfile) {
51+
private suspend fun fetchMessage(remoteFolder: ImapFolder, message: ImapMessage, fetchProfile: FetchProfile) {
5252
val maxDownloadSize = 0
5353
remoteFolder.fetch(
5454
messages = listOf(element = message),
5555
fetchProfile = fetchProfile,
5656
listener = null,
57-
maxDownloadSize = maxDownloadSize
57+
maxDownloadSize = maxDownloadSize,
5858
)
5959
}
6060
}

‎backend/imap/src/main/java/com/fsck/k9/backend/imap/ImapBackend.kt‎

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ import com.fsck.k9.mail.power.PowerManager
1313
import com.fsck.k9.mail.store.imap.IdleRefreshManager
1414
import com.fsck.k9.mail.store.imap.ImapStore
1515
import com.fsck.k9.mail.transport.smtp.SmtpTransport
16+
import kotlinx.coroutines.CoroutineDispatcher
17+
import kotlinx.coroutines.Dispatchers
18+
import kotlinx.coroutines.runBlocking
19+
import kotlinx.coroutines.withContext
1620
import net.thunderbird.core.common.mail.Flag
1721
import net.thunderbird.feature.mail.folder.api.FolderPathDelimiter
1822

@@ -24,6 +28,7 @@ class ImapBackend(
2428
private val idleRefreshManager: IdleRefreshManager,
2529
private val pushConfigProvider: ImapPushConfigProvider,
2630
private val smtpTransport: SmtpTransport,
31+
private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO,
2732
) : Backend {
2833
private val imapSync = ImapSync(accountName, backendStorage, imapStore)
2934
private val commandRefreshFolderList = CommandRefreshFolderList(backendStorage, imapStore)
@@ -53,21 +58,24 @@ class ImapBackend(
5358
return commandRefreshFolderList.refreshFolderList()
5459
}
5560

56-
override fun sync(folderServerId: String, syncConfig: SyncConfig, listener: SyncListener) {
57-
imapSync.sync(folderServerId, syncConfig, listener)
58-
}
61+
override fun sync(folderServerId: String, syncConfig: SyncConfig, listener: SyncListener) =
62+
runBlocking(ioDispatcher) {
63+
imapSync.sync(folderServerId, syncConfig, listener)
64+
}
5965

60-
override fun downloadMessage(syncConfig: SyncConfig, folderServerId: String, messageServerId: String) {
61-
imapSync.downloadMessage(syncConfig, folderServerId, messageServerId)
62-
}
66+
override fun downloadMessage(syncConfig: SyncConfig, folderServerId: String, messageServerId: String) =
67+
runBlocking(ioDispatcher) {
68+
imapSync.downloadMessage(syncConfig, folderServerId, messageServerId)
69+
}
6370

64-
override fun downloadMessageStructure(folderServerId: String, messageServerId: String) {
71+
override fun downloadMessageStructure(folderServerId: String, messageServerId: String) = runBlocking(ioDispatcher) {
6572
commandDownloadMessage.downloadMessageStructure(folderServerId, messageServerId)
6673
}
6774

68-
override fun downloadCompleteMessage(folderServerId: String, messageServerId: String) {
69-
commandDownloadMessage.downloadCompleteMessage(folderServerId, messageServerId)
70-
}
75+
override suspend fun downloadCompleteMessage(folderServerId: String, messageServerId: String) =
76+
withContext(ioDispatcher) {
77+
commandDownloadMessage.downloadCompleteMessage(folderServerId, messageServerId)
78+
}
7179

7280
override fun setFlag(folderServerId: String, messageServerIds: List<String>, flag: Flag, newState: Boolean) {
7381
commandSetFlag.setFlag(folderServerId, messageServerIds, flag, newState)

‎backend/imap/src/main/java/com/fsck/k9/backend/imap/ImapSync.kt‎

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,12 @@ internal class ImapSync(
3030
private val backendStorage: BackendStorage,
3131
private val imapStore: ImapStore,
3232
) {
33-
fun sync(folder: String, syncConfig: SyncConfig, listener: SyncListener) {
33+
suspend fun sync(folder: String, syncConfig: SyncConfig, listener: SyncListener) {
3434
synchronizeMailboxSynchronous(folder, syncConfig, listener)
3535
}
3636

37-
private fun synchronizeMailboxSynchronous(folder: String, syncConfig: SyncConfig, listener: SyncListener) {
37+
@Suppress("CyclomaticComplexMethod", "LongMethod")
38+
private suspend fun synchronizeMailboxSynchronous(folder: String, syncConfig: SyncConfig, listener: SyncListener) {
3839
Log.i("Synchronizing folder %s:%s", accountName, folder)
3940

4041
var remoteFolder: ImapFolder? = null
@@ -267,7 +268,7 @@ internal class ImapSync(
267268
}
268269
}
269270

270-
fun downloadMessage(syncConfig: SyncConfig, folderServerId: String, messageServerId: String) {
271+
suspend fun downloadMessage(syncConfig: SyncConfig, folderServerId: String, messageServerId: String) {
271272
val backendFolder = backendStorage.getFolder(folderServerId)
272273
val remoteFolder = imapStore.getFolder(folderServerId)
273274
try {
@@ -297,7 +298,8 @@ internal class ImapSync(
297298
* @param inputMessages
298299
* A list of messages objects that store the UIDs of which messages to download.
299300
*/
300-
private fun downloadMessages(
301+
@Suppress("LongMethod")
302+
private suspend fun downloadMessages(
301303
syncConfig: SyncConfig,
302304
remoteFolder: ImapFolder,
303305
backendFolder: BackendFolder,
@@ -463,7 +465,7 @@ internal class ImapSync(
463465
return false
464466
}
465467

466-
private fun fetchUnsyncedMessages(
468+
private suspend fun fetchUnsyncedMessages(
467469
syncConfig: SyncConfig,
468470
remoteFolder: ImapFolder,
469471
unsyncedMessages: List<ImapMessage>,
@@ -483,7 +485,7 @@ internal class ImapSync(
483485
messages = unsyncedMessages,
484486
fetchProfile = fetchProfile,
485487
listener = object : FetchListener {
486-
override fun onFetchResponse(message: ImapMessage, isFirstResponse: Boolean) {
488+
override suspend fun onFetchResponse(message: ImapMessage, isFirstResponse: Boolean) {
487489
try {
488490
if (message.isSet(Flag.DELETED)) {
489491
Log.v(
@@ -519,7 +521,7 @@ internal class ImapSync(
519521
)
520522
}
521523

522-
private fun downloadSmallMessages(
524+
private suspend fun downloadSmallMessages(
523525
remoteFolder: ImapFolder,
524526
backendFolder: BackendFolder,
525527
smallMessages: List<ImapMessage>,
@@ -540,7 +542,7 @@ internal class ImapSync(
540542
messages = smallMessages,
541543
fetchProfile = fetchProfile,
542544
listener = object : FetchListener {
543-
override fun onFetchResponse(message: ImapMessage, isFirstResponse: Boolean) {
545+
override suspend fun onFetchResponse(message: ImapMessage, isFirstResponse: Boolean) {
544546
try {
545547
// Store the updated message locally
546548
backendFolder.saveMessage(message, MessageDownloadState.FULL)
@@ -578,7 +580,7 @@ internal class ImapSync(
578580
Log.d("SYNC: Done fetching small messages for folder %s", folder)
579581
}
580582

581-
private fun downloadLargeMessages(
583+
private suspend fun downloadLargeMessages(
582584
remoteFolder: ImapFolder,
583585
backendFolder: BackendFolder,
584586
largeMessages: List<ImapMessage>,
@@ -634,7 +636,7 @@ internal class ImapSync(
634636
Log.d("SYNC: Done fetching large messages for folder %s", folder)
635637
}
636638

637-
private fun refreshLocalMessageFlags(
639+
private suspend fun refreshLocalMessageFlags(
638640
syncConfig: SyncConfig,
639641
remoteFolder: ImapFolder,
640642
backendFolder: BackendFolder,
@@ -673,7 +675,7 @@ internal class ImapSync(
673675
}
674676
}
675677

676-
private fun downloadSaneBody(
678+
private suspend fun downloadSaneBody(
677679
remoteFolder: ImapFolder,
678680
backendFolder: BackendFolder,
679681
message: ImapMessage,
@@ -703,7 +705,7 @@ internal class ImapSync(
703705
backendFolder.saveMessage(message, MessageDownloadState.PARTIAL)
704706
}
705707

706-
private fun downloadPartial(
708+
private suspend fun downloadPartial(
707709
remoteFolder: ImapFolder,
708710
backendFolder: BackendFolder,
709711
message: ImapMessage,

0 commit comments

Comments
 (0)