Skip to content

Disable periodic sync workers that don't exist anymore #602

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import at.bitfire.davdroid.ui.NotificationUtils
import at.bitfire.ical4android.TaskProvider
import dagger.hilt.android.testing.HiltAndroidRule
import dagger.hilt.android.testing.HiltAndroidTest
import org.junit.After
import org.junit.AfterClass
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
Expand Down Expand Up @@ -97,6 +96,28 @@ class PeriodicSyncWorkerTest {
assertFalse(workScheduledOrRunning(context, workerName))
}

@Test
fun doWork_cancelsItselfOnInvalidAccount() {
val invalidAccount = Account("invalid", context.getString(R.string.account_type))
val authority = CalendarContract.AUTHORITY

// Enable the PeriodicSyncWorker
PeriodicSyncWorker.enable(context, invalidAccount, authority, 15*60, false)
assertTrue(workScheduledOrRunning(context, PeriodicSyncWorker.workerName(account, authority)))

// Run PeriodicSyncWorker as TestWorker
val inputData = workDataOf(
PeriodicSyncWorker.ARG_AUTHORITY to authority,
PeriodicSyncWorker.ARG_ACCOUNT_NAME to invalidAccount.name,
PeriodicSyncWorker.ARG_ACCOUNT_TYPE to invalidAccount.type
)
val result = TestWorkerBuilder<PeriodicSyncWorker>(context, executor, inputData).build().doWork()

// Verify that the PeriodicSyncWorker cancelled itself
assertTrue(result is androidx.work.ListenableWorker.Result.Failure)
assertFalse(workScheduledOrRunning(context, PeriodicSyncWorker.workerName(invalidAccount, authority)))
}

@Test
fun doWork_immediatelyEnqueuesSyncWorkerForGivenAuthority() {
val authorities = listOf(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import androidx.work.Worker
import androidx.work.WorkerParameters
import at.bitfire.davdroid.InvalidAccountException
import at.bitfire.davdroid.log.Logger
import at.bitfire.davdroid.settings.AccountSettings
import dagger.assisted.Assisted
Expand Down Expand Up @@ -117,7 +118,13 @@ class PeriodicSyncWorker @AssistedInject constructor(
val authority = inputData.getString(ARG_AUTHORITY) ?: throw IllegalArgumentException("$ARG_AUTHORITY required")
Logger.log.info("Running periodic sync worker: account=$account, authority=$authority")

val accountSettings = AccountSettings(applicationContext, account)
val accountSettings = try {
AccountSettings(applicationContext, account)
} catch (e: InvalidAccountException) {
Logger.log.warning("Account $account doesn't exist anymore, cancelling periodic sync")
disable(applicationContext, account, authority)
return Result.failure()
}
if (!SyncWorker.wifiConditionsMet(applicationContext, accountSettings)) {
Logger.log.info("Sync conditions not met. Won't run sync.")
return Result.failure()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import at.bitfire.davdroid.resource.LocalAddressBook
import at.bitfire.davdroid.resource.LocalTaskList
import at.bitfire.davdroid.settings.AccountSettings
import at.bitfire.davdroid.syncadapter.AccountsCleanupWorker
import at.bitfire.davdroid.syncadapter.PeriodicSyncWorker
import at.bitfire.davdroid.syncadapter.SyncWorker
import at.bitfire.ical4android.TaskProvider
import com.google.accompanist.themeadapter.material.MdcTheme
Expand Down Expand Up @@ -207,13 +208,25 @@ class RenameAccountFragment: DialogFragment() {
}
}

/**
* Called when an account has been renamed.
*
* @param oldAccount the old account
* @param newName the new account
* @param syncIntervals map with entries of type (authority -> sync interval) of the old account
*/
@SuppressLint("Recycle")
@WorkerThread
fun onAccountRenamed(accountManager: AccountManager, oldAccount: Account, newName: String, syncIntervals: List<Pair<String, Long?>>) {
// account has now been renamed
Logger.log.info("Updating account name references")
val context: Application = getApplication()

// disable periodic workers of old account
syncIntervals.forEach { (authority, _) ->
PeriodicSyncWorker.disable(context, oldAccount, authority)
}

// cancel maybe running synchronization
SyncWorker.cancelSync(context, oldAccount)
for (addrBookAccount in accountManager.getAccountsByType(context.getString(R.string.account_type_address_book)))
Expand Down