Fix: Crash caused by ConcurrentModificationException in SyncService

This commit is contained in:
machiav3lli 2022-02-02 02:35:30 +01:00
parent 3f454c5199
commit f18d7051f5

View File

@ -84,12 +84,15 @@ class SyncService : ConnectionService<SyncService.Binder>() {
val cancelledTask = val cancelledTask =
cancelCurrentTask { request == SyncRequest.FORCE && it.task?.repositoryId in ids } cancelCurrentTask { request == SyncRequest.FORCE && it.task?.repositoryId in ids }
cancelTasks { !it.manual && it.repositoryId in ids } cancelTasks { !it.manual && it.repositoryId in ids }
val currentIds = tasks.asSequence().map { it.repositoryId }.toSet() val currentIds =
synchronized(tasks) { tasks.map { it.repositoryId }.toSet() }
val manual = request != SyncRequest.AUTO val manual = request != SyncRequest.AUTO
tasks += ids.asSequence().filter { synchronized(tasks) {
it !in currentIds && tasks += ids.filter {
it != currentTask?.task?.repositoryId it !in currentIds &&
}.map { Task(it, manual) } it != currentTask?.task?.repositoryId
}.map { Task(it, manual) }
}
handleNextTask(cancelledTask?.hasUpdates == true) handleNextTask(cancelledTask?.hasUpdates == true)
if (request != SyncRequest.AUTO && started == Started.AUTO) { if (request != SyncRequest.AUTO && started == Started.AUTO) {
started = Started.MANUAL started = Started.MANUAL
@ -101,8 +104,7 @@ class SyncService : ConnectionService<SyncService.Binder>() {
fun sync(request: SyncRequest) { fun sync(request: SyncRequest) {
GlobalScope.launch { GlobalScope.launch {
val ids = db.repositoryDao.all val ids = db.repositoryDao.all.filter { it.enabled }.map { it.id }.toList()
.asSequence().filter { it.enabled }.map { it.id }.toList()
sync(ids, request) sync(ids, request)
} }
} }
@ -131,7 +133,7 @@ class SyncService : ConnectionService<SyncService.Binder>() {
db.repositoryDao.put(repository.enable(enabled)) db.repositoryDao.put(repository.enable(enabled))
if (enabled) { if (enabled) {
if (repository.id != currentTask?.task?.repositoryId && !tasks.any { it.repositoryId == repository.id }) { if (repository.id != currentTask?.task?.repositoryId && !tasks.any { it.repositoryId == repository.id }) {
tasks += Task(repository.id, true) synchronized(tasks) { tasks += Task(repository.id, true) }
handleNextTask(false) handleNextTask(false)
} }
} else { } else {
@ -191,15 +193,15 @@ class SyncService : ConnectionService<SyncService.Binder>() {
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
if (intent?.action == ACTION_CANCEL) { if (intent?.action == ACTION_CANCEL) {
tasks.clear() synchronized(tasks) { tasks.clear() }
val cancelledTask = cancelCurrentTask { it.task != null } val cancelledTask = cancelCurrentTask { it.task != null }
handleNextTask(cancelledTask?.hasUpdates == true) handleNextTask(cancelledTask?.hasUpdates == true)
} }
return START_NOT_STICKY return START_NOT_STICKY
} }
private fun cancelTasks(condition: (Task) -> Boolean): Boolean { private fun cancelTasks(condition: (Task) -> Boolean): Boolean = synchronized(tasks) {
return tasks.removeAll(condition) tasks.removeAll(condition)
} }
private fun cancelCurrentTask(condition: ((CurrentTask) -> Boolean)): CurrentTask? { private fun cancelCurrentTask(condition: ((CurrentTask) -> Boolean)): CurrentTask? {