Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a39f3c02 authored by Fahim Salam Chowdhury's avatar Fahim Salam Chowdhury 👽
Browse files

Refactor performSync method of syncAdapter

parent 845002e8
Loading
Loading
Loading
Loading
Loading
+3 −47
Original line number Diff line number Diff line
@@ -54,7 +54,8 @@ open class CalendarsSyncAdapterService : SyncAdapterService() {
                   - this is is an automatic sync (i.e. manual syncs are run regardless of sync conditions)
                 */
                if (!extras.containsKey(ContentResolver.SYNC_EXTRAS_MANUAL) &&
                    !checkSyncConditions(accountSettings)) {
                    !checkSyncConditions(accountSettings)
                ) {
                    return
                }

@@ -86,52 +87,7 @@ open class CalendarsSyncAdapterService : SyncAdapterService() {
                        authority,
                        syncResult,
                        calendar
                    ).let {
                        val authState = accountSettings.credentials().authState
                        if (authState != null) {
                            if (authState.needsTokenRefresh) {
                                val tokenRequest = authState.createTokenRefreshRequest()
                                val clientSecretString = accountSettings.credentials().clientSecret
                                val clientSecret =
                                    OpenIdUtils.getClientAuthentication(clientSecretString)

                                AuthorizationService(context).performTokenRequest(
                                    tokenRequest,
                                    clientSecret
                                ) { tokenResponse, ex ->
                                    authState.update(tokenResponse, ex)
                                    accountSettings.credentials(
                                        Credentials(
                                            account.name,
                                            null,
                                            authState,
                                            null,
                                            clientSecret = clientSecretString
                                        )
                                    )
                                    it.accountSettings.credentials(
                                        Credentials(
                                            it.account.name,
                                            null,
                                            authState,
                                            null,
                                            clientSecret = clientSecretString
                                        )
                                    )
                                    object : AsyncTask<Void, Void, Void>() {
                                        override fun doInBackground(vararg params: Void): Void? {
                                            it.performSyncWithRetry()
                                            return null
                                        }
                                    }.execute()
                                }
                            } else {
                                it.performSyncWithRetry()
                            }
                        } else {
                            it.performSyncWithRetry()
                        }
                    }
                    ).performSync()
                }
            } catch (e: Exception) {
                Logger.log.log(Level.SEVERE, "Couldn't sync calendars", e)
+1 −42
Original line number Diff line number Diff line
@@ -67,48 +67,7 @@ open class ContactsSyncAdapterService: SyncAdapterService() {
                Logger.log.info("Synchronizing address book: ${addressBook.url}")
                Logger.log.info("Taking settings from: ${addressBook.mainAccount}")

                ContactsSyncManager(context, account, accountSettings, httpClient.value, extras, authority, syncResult, provider, addressBook).let {
                    val authState = accountSettings.credentials().authState
                    if (authState != null) {
                        if (authState.needsTokenRefresh) {
                            val tokenRequest = authState.createTokenRefreshRequest()
                            val clientSecretString = accountSettings.credentials().clientSecret
                            val clientSecret = OpenIdUtils.getClientAuthentication(clientSecretString)

                            AuthorizationService(context).performTokenRequest(tokenRequest, clientSecret) { tokenResponse, ex ->
                                authState.update(tokenResponse, ex)
                                accountSettings.credentials(
                                    Credentials(
                                        account.name,
                                        null,
                                        authState,
                                        null,
                                        clientSecret = clientSecretString
                                    )
                                )
                                it.accountSettings.credentials(
                                    Credentials(
                                        it.account.name,
                                        null,
                                        authState,
                                        null,
                                        clientSecret = clientSecretString
                                    )
                                )
                                object : AsyncTask<Void, Void, Void>() {
                                    override fun doInBackground(vararg params: Void): Void? {
                                        it.performSyncWithRetry()
                                        return null
                                    }
                                }.execute()
                            }
                        } else {
                            it.performSyncWithRetry()
                        }
                    } else {
                        it.performSyncWithRetry()
                    }
                }
                ContactsSyncManager(context, account, accountSettings, httpClient.value, extras, authority, syncResult, provider, addressBook).performSync()
            } catch(e: Exception) {
                Logger.log.log(Level.SEVERE, "Couldn't sync contacts", e)
            }
+1 −3
Original line number Diff line number Diff line
@@ -68,9 +68,7 @@ class JtxSyncAdapterService: SyncAdapterService() {
                val collections = JtxCollection.find(account, provider, context, LocalJtxCollection.Factory, null, null)
                for (collection in collections) {
                    Logger.log.info("Synchronizing $collection")
                    JtxSyncManager(context, account, accountSettings, extras, httpClient.value, authority, syncResult, collection).let {
                        it.performSync()
                    }
                    JtxSyncManager(context, account, accountSettings, extras, httpClient.value, authority, syncResult, collection).performSync()
                }

            } catch (e: TaskProvider.ProviderTooOldException) {
+53 −3
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import at.bitfire.dav4jvm.property.ScheduleTag
import at.bitfire.dav4jvm.property.SyncToken
import at.bitfire.davdroid.*
import at.bitfire.davdroid.db.AppDatabase
import at.bitfire.davdroid.db.Credentials
import at.bitfire.davdroid.db.SyncState
import at.bitfire.davdroid.db.SyncStats
import at.bitfire.davdroid.log.Logger
@@ -44,6 +45,8 @@ import dagger.hilt.InstallIn
import dagger.hilt.android.EntryPointAccessors
import dagger.hilt.components.SingletonComponent
import kotlinx.coroutines.*
import net.openid.appauth.AuthState
import net.openid.appauth.AuthorizationService
import okhttp3.HttpUrl
import okhttp3.RequestBody
import org.apache.commons.io.FileUtils
@@ -56,6 +59,7 @@ import java.net.ConnectException
import java.net.HttpURLConnection
import java.security.cert.CertificateException
import java.util.*
import java.util.concurrent.Executors
import java.util.concurrent.LinkedBlockingQueue
import java.util.concurrent.ThreadPoolExecutor
import java.util.concurrent.TimeUnit
@@ -75,6 +79,8 @@ abstract class SyncManager<ResourceType: LocalResource<*>, out CollectionType: L
    val localCollection: CollectionType
) {

    private val executor = Executors.newSingleThreadExecutor()

    @EntryPoint
    @InstallIn(SingletonComponent::class)
    interface SyncManagerEntryPoint {
@@ -90,6 +96,10 @@ abstract class SyncManager<ResourceType: LocalResource<*>, out CollectionType: L
        const val DEBUG_INFO_MAX_RESOURCE_DUMP_SIZE = 100*FileUtils.ONE_KB.toInt()
        const val MAX_MULTIGET_RESOURCES = 10

        const val DEFAULT_RETRY_AFTER = 5
        const val DEFAULT_SECOND_RETRY_AFTER = 8
        const val DEFAULT_MAX_RETRY_TIME = 21

        var _workDispatcher: WeakReference<CoroutineDispatcher>? = null
        /**
         * We use our own dispatcher to
@@ -135,8 +145,48 @@ abstract class SyncManager<ResourceType: LocalResource<*>, out CollectionType: L
    /**
     * Call performSync with default retry values
     */
    fun performSyncWithRetry() {
        performSync(5, 8, 21)
    fun performSync() {
        val authState = accountSettings.credentials().authState

        if (authState == null || !authState.needsTokenRefresh) {
            performSync(DEFAULT_RETRY_AFTER, DEFAULT_SECOND_RETRY_AFTER, DEFAULT_MAX_RETRY_TIME)
            return
        }

        refreshAuthTokenAndSync(authState)
    }

    private fun refreshAuthTokenAndSync(authState: AuthState) {
        val tokenRequest = authState.createTokenRefreshRequest()
        val clientSecretString = accountSettings.credentials().clientSecret
        val clientSecret = OpenIdUtils.getClientAuthentication(clientSecretString)

        AuthorizationService(context).performTokenRequest(tokenRequest, clientSecret) { tokenResponse, ex ->
            authState.update(tokenResponse, ex)
            accountSettings.credentials(
                Credentials(
                    account.name,
                    null,
                    authState,
                    null,
                    clientSecret = clientSecretString
                )
            )

            accountSettings.credentials(
                Credentials(
                    account.name,
                    null,
                    authState,
                    null,
                    clientSecret = clientSecretString
                )
            )

            executor.execute {
                performSync(DEFAULT_RETRY_AFTER, DEFAULT_SECOND_RETRY_AFTER, DEFAULT_MAX_RETRY_TIME)
            }
        }
    }

    /**
@@ -146,7 +196,7 @@ abstract class SyncManager<ResourceType: LocalResource<*>, out CollectionType: L
     * @param secondRetryAfter optional param, in seconds. Used to calculate fibonnacci sequence for rety on unhandled exception
     * @param maxRetryTime optional param, in seconds. On unhandled exception, max time the method should retry.
     */
    fun performSync(retryAfter: Int = Int.MIN_VALUE, secondRetryAfter: Int = Int.MIN_VALUE, maxRetryTime: Int = Int.MIN_VALUE) {
    fun performSync(retryAfter: Int, secondRetryAfter: Int, maxRetryTime: Int) {
        // dismiss previous error notifications
        notificationManager.cancel(notificationTag, NotificationUtils.NOTIFY_SYNC_ERROR)

+1 −43
Original line number Diff line number Diff line
@@ -73,49 +73,7 @@ open class TasksSyncAdapterService: SyncAdapterService() {
                        .sortedByDescending { priorityTaskLists.contains(it.id) }
                for (taskList in taskLists) {
                    Logger.log.info("Synchronizing task list #${taskList.id} [${taskList.syncId}]")
                    TasksSyncManager(context, account, accountSettings, httpClient.value, extras, authority, syncResult, taskList).let {
                        val authState = accountSettings.credentials().authState

                        if (authState != null) {
                            if (authState.needsTokenRefresh) {
                                val tokenRequest = authState.createTokenRefreshRequest()
                                val clientSecretString = accountSettings.credentials().clientSecret
                                val clientSecret = OpenIdUtils.getClientAuthentication(clientSecretString)

                                AuthorizationService(context).performTokenRequest(tokenRequest, clientSecret) { tokenResponse, ex ->
                                    authState.update(tokenResponse, ex)
                                    accountSettings.credentials(
                                        Credentials(
                                            account.name,
                                            null,
                                            authState,
                                            null,
                                            clientSecret = clientSecretString
                                        )
                                    )
                                    it.accountSettings.credentials(
                                        Credentials(
                                            it.account.name,
                                            null,
                                            authState,
                                            null,
                                            clientSecret = clientSecretString
                                        )
                                    )
                                    object : AsyncTask<Void, Void, Void>() {
                                        override fun doInBackground(vararg params: Void): Void? {
                                            it.performSyncWithRetry()
                                            return null
                                        }
                                    }.execute()
                                }
                            } else {
                                it.performSyncWithRetry()
                            }
                        } else {
                            it.performSyncWithRetry()
                        }
                    }
                    TasksSyncManager(context, account, accountSettings, httpClient.value, extras, authority, syncResult, taskList).performSync()
                }
            } catch (e: TaskProvider.ProviderTooOldException) {
                SyncUtils.notifyProviderTooOld(context, e)