Use coroutines in CaldavSynchronizer

pull/1051/head
Alex Baker 4 years ago
parent e2c897e43c
commit 5658fca41f

@ -12,7 +12,7 @@ import at.bitfire.dav4jvm.exception.UnauthorizedException
import at.bitfire.dav4jvm.property.* import at.bitfire.dav4jvm.property.*
import at.bitfire.dav4jvm.property.GetETag.Companion.fromResponse import at.bitfire.dav4jvm.property.GetETag.Companion.fromResponse
import at.bitfire.ical4android.ICalendar.Companion.prodId import at.bitfire.ical4android.ICalendar.Companion.prodId
import com.todoroo.astrid.dao.TaskDaoBlocking import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.data.Task import com.todoroo.astrid.data.Task
import com.todoroo.astrid.helper.UUIDHelper import com.todoroo.astrid.helper.UUIDHelper
import com.todoroo.astrid.service.TaskDeleter import com.todoroo.astrid.service.TaskDeleter
@ -30,7 +30,7 @@ import org.tasks.billing.Inventory
import org.tasks.caldav.iCalendar.Companion.fromVtodo import org.tasks.caldav.iCalendar.Companion.fromVtodo
import org.tasks.data.CaldavAccount import org.tasks.data.CaldavAccount
import org.tasks.data.CaldavCalendar import org.tasks.data.CaldavCalendar
import org.tasks.data.CaldavDaoBlocking import org.tasks.data.CaldavDao
import org.tasks.data.CaldavTask import org.tasks.data.CaldavTask
import org.tasks.time.DateTimeUtils import org.tasks.time.DateTimeUtils
import timber.log.Timber import timber.log.Timber
@ -46,8 +46,8 @@ import javax.net.ssl.SSLException
class CaldavSynchronizer @Inject constructor( class CaldavSynchronizer @Inject constructor(
@param:ApplicationContext private val context: Context, @param:ApplicationContext private val context: Context,
private val caldavDao: CaldavDaoBlocking, private val caldavDao: CaldavDao,
private val taskDao: TaskDaoBlocking, private val taskDao: TaskDao,
private val localBroadcastManager: LocalBroadcastManager, private val localBroadcastManager: LocalBroadcastManager,
private val taskDeleter: TaskDeleter, private val taskDeleter: TaskDeleter,
private val inventory: Inventory, private val inventory: Inventory,
@ -60,7 +60,7 @@ class CaldavSynchronizer @Inject constructor(
} }
} }
fun sync(account: CaldavAccount) { suspend fun sync(account: CaldavAccount) {
if (!inventory.hasPro()) { if (!inventory.hasPro()) {
setError(account, context.getString(R.string.requires_pro_subscription)) setError(account, context.getString(R.string.requires_pro_subscription))
return return
@ -98,7 +98,7 @@ class CaldavSynchronizer @Inject constructor(
} }
@Throws(IOException::class, DavException::class, KeyManagementException::class, NoSuchAlgorithmException::class) @Throws(IOException::class, DavException::class, KeyManagementException::class, NoSuchAlgorithmException::class)
private fun synchronize(account: CaldavAccount) { private suspend fun synchronize(account: CaldavAccount) {
val caldavClient = client.forAccount(account) val caldavClient = client.forAccount(account)
val resources = caldavClient.calendars val resources = caldavClient.calendars
val urls = resources.map { it.href.toString() }.toHashSet() val urls = resources.map { it.href.toString() }.toHashSet()
@ -131,7 +131,7 @@ class CaldavSynchronizer @Inject constructor(
setError(account, "") setError(account, "")
} }
private fun setError(account: CaldavAccount, message: String?) { private suspend fun setError(account: CaldavAccount, message: String?) {
account.error = message account.error = message
caldavDao.update(account) caldavDao.update(account)
localBroadcastManager.broadcastRefreshList() localBroadcastManager.broadcastRefreshList()
@ -141,7 +141,7 @@ class CaldavSynchronizer @Inject constructor(
} }
@Throws(DavException::class) @Throws(DavException::class)
private fun sync(caldavCalendar: CaldavCalendar, resource: at.bitfire.dav4jvm.Response, httpClient: OkHttpClient) { private suspend fun sync(caldavCalendar: CaldavCalendar, resource: at.bitfire.dav4jvm.Response, httpClient: OkHttpClient) {
Timber.d("sync(%s)", caldavCalendar) Timber.d("sync(%s)", caldavCalendar)
val httpUrl = resource.href val httpUrl = resource.href
pushLocalChanges(caldavCalendar, httpClient, httpUrl) pushLocalChanges(caldavCalendar, httpClient, httpUrl)
@ -210,7 +210,7 @@ class CaldavSynchronizer @Inject constructor(
localBroadcastManager.broadcastRefresh() localBroadcastManager.broadcastRefresh()
} }
private fun pushLocalChanges( private suspend fun pushLocalChanges(
caldavCalendar: CaldavCalendar, httpClient: OkHttpClient, httpUrl: HttpUrl) { caldavCalendar: CaldavCalendar, httpClient: OkHttpClient, httpUrl: HttpUrl) {
for (task in caldavDao.getDeleted(caldavCalendar.uuid!!)) { for (task in caldavDao.getDeleted(caldavCalendar.uuid!!)) {
deleteRemoteResource(httpClient, httpUrl, task) deleteRemoteResource(httpClient, httpUrl, task)
@ -224,7 +224,7 @@ class CaldavSynchronizer @Inject constructor(
} }
} }
private fun deleteRemoteResource( private suspend fun deleteRemoteResource(
httpClient: OkHttpClient, httpUrl: HttpUrl, caldavTask: CaldavTask): Boolean { httpClient: OkHttpClient, httpUrl: HttpUrl, caldavTask: CaldavTask): Boolean {
try { try {
if (!isNullOrEmpty(caldavTask.`object`)) { if (!isNullOrEmpty(caldavTask.`object`)) {
@ -246,7 +246,7 @@ class CaldavSynchronizer @Inject constructor(
} }
@Throws(IOException::class) @Throws(IOException::class)
private fun pushTask(task: Task, httpClient: OkHttpClient, httpUrl: HttpUrl) { private suspend fun pushTask(task: Task, httpClient: OkHttpClient, httpUrl: HttpUrl) {
Timber.d("pushing %s", task) Timber.d("pushing %s", task)
val caldavTask = caldavDao.getTask(task.id) ?: return val caldavTask = caldavDao.getTask(task.id) ?: return
if (task.isDeleted) { if (task.isDeleted) {

@ -4,12 +4,14 @@ import android.content.Context
import androidx.hilt.Assisted import androidx.hilt.Assisted
import androidx.hilt.work.WorkerInject import androidx.hilt.work.WorkerInject
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
import org.tasks.LocalBroadcastManager import org.tasks.LocalBroadcastManager
import org.tasks.analytics.Firebase import org.tasks.analytics.Firebase
import org.tasks.caldav.CaldavSynchronizer import org.tasks.caldav.CaldavSynchronizer
import org.tasks.data.CaldavAccount.Companion.TYPE_LOCAL
import org.tasks.data.CaldavDao import org.tasks.data.CaldavDao
import org.tasks.data.GoogleTaskListDao import org.tasks.data.GoogleTaskListDao
import org.tasks.etesync.EteSynchronizer import org.tasks.etesync.EteSynchronizer
@ -43,7 +45,7 @@ class SyncWork @WorkerInject constructor(
preferences.isSyncOngoing = true preferences.isSyncOngoing = true
localBroadcastManager.broadcastRefresh() localBroadcastManager.broadcastRefresh()
try { try {
sync() caldavJobs().plus(googleTaskJobs()).forEach { it.await() }
} catch (e: Exception) { } catch (e: Exception) {
firebase.reportException(e) firebase.reportException(e)
} finally { } finally {
@ -53,9 +55,9 @@ class SyncWork @WorkerInject constructor(
return Result.success() return Result.success()
} }
@Throws(InterruptedException::class) private suspend fun caldavJobs(): List<Deferred<Unit>> = coroutineScope {
private suspend fun sync() = coroutineScope { caldavDao.getAccounts()
val deferredCaldav = caldavDao.getAccounts() .filterNot { it.accountType == TYPE_LOCAL }
.map { .map {
async(Dispatchers.IO) { async(Dispatchers.IO) {
if (it.isCaldavAccount) { if (it.isCaldavAccount) {
@ -65,16 +67,16 @@ class SyncWork @WorkerInject constructor(
} }
} }
} }
val deferredGoogleTasks = googleTaskListDao }
private suspend fun googleTaskJobs(): List<Deferred<Unit>> = coroutineScope {
googleTaskListDao
.getAccounts() .getAccounts()
.mapIndexed { i, account -> .mapIndexed { i, account ->
async(Dispatchers.IO) { async(Dispatchers.IO) {
googleTaskSynchronizer.sync(account, i) googleTaskSynchronizer.sync(account, i)
} }
} }
deferredCaldav
.plus(deferredGoogleTasks)
.forEach { it.await() }
} }
companion object { companion object {

Loading…
Cancel
Save