Skip to content
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 @@ -14,48 +14,32 @@ sealed class ScheduleCommand {
internal data class EverythingCommand(
val action: Action,
val withDelay: Boolean = false,
val blockWhileUnscheduled: (suspend () -> Unit)? = null,
) : ScheduleCommand()

internal data class EventsCommand(
val action: Action,
val withDelay: Boolean = false,
val blockWhileUnscheduled: (suspend () -> Unit)? = null,
) : ScheduleCommand()

internal data class ImagesCommand(
val action: Action,
val blockWhileUnscheduled: (suspend () -> Unit)? = null,
) : ScheduleCommand()

object Everything {
fun reschedule(withDelay: Boolean = false): ScheduleCommand = EverythingCommand(action = Action.RESCHEDULE, withDelay = withDelay)

fun unschedule(): ScheduleCommand = EverythingCommand(action = Action.UNSCHEDULE)

fun rescheduleAfter(
withDelay: Boolean = false,
block: suspend () -> Unit,
): ScheduleCommand = EverythingCommand(action = Action.RESCHEDULE, withDelay = withDelay, blockWhileUnscheduled = block)
}

object Events {
fun reschedule(withDelay: Boolean = false): ScheduleCommand = EventsCommand(action = Action.RESCHEDULE, withDelay = withDelay)

fun unschedule(): ScheduleCommand = EventsCommand(action = Action.UNSCHEDULE)

fun rescheduleAfter(
withDelay: Boolean = false,
block: suspend () -> Unit,
): ScheduleCommand = EventsCommand(action = Action.RESCHEDULE, withDelay = withDelay, blockWhileUnscheduled = block)
}

object Images {
fun reschedule(): ScheduleCommand = ImagesCommand(action = Action.RESCHEDULE)

fun unschedule(): ScheduleCommand = ImagesCommand(action = Action.UNSCHEDULE)

fun rescheduleAfter(block: suspend () -> Unit): ScheduleCommand =
ImagesCommand(action = Action.RESCHEDULE, blockWhileUnscheduled = block)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -129,21 +129,18 @@ internal class SyncOrchestratorImpl @Inject constructor(
override fun execute(command: ScheduleCommand): Job = when (command) {
is ScheduleCommand.EverythingCommand -> executeSchedulingAction(
action = command.action,
blockWhileUnscheduled = command.blockWhileUnscheduled,
unschedule = ::cancelBackgroundWork,
reschedule = { scheduleBackgroundWork(withDelay = command.withDelay) },
)

is ScheduleCommand.EventsCommand -> executeSchedulingAction(
action = command.action,
blockWhileUnscheduled = command.blockWhileUnscheduled,
unschedule = ::cancelEventSync,
reschedule = { rescheduleEventSync(withDelay = command.withDelay) },
)

is ScheduleCommand.ImagesCommand -> executeSchedulingAction(
action = command.action,
blockWhileUnscheduled = command.blockWhileUnscheduled,
unschedule = ::stopImageSync,
reschedule = { rescheduleImageUpSync() },
)
Expand Down Expand Up @@ -214,7 +211,6 @@ internal class SyncOrchestratorImpl @Inject constructor(

private fun executeSchedulingAction(
action: ScheduleCommand.Action,
blockWhileUnscheduled: (suspend () -> Unit)?,
unschedule: () -> Unit,
reschedule: suspend () -> Unit,
): Job = when (action) {
Expand All @@ -223,9 +219,7 @@ internal class SyncOrchestratorImpl @Inject constructor(
Job().apply { complete() }
}
ScheduleCommand.Action.RESCHEDULE -> {
unschedule()
appScope.launch(ioDispatcher) {
blockWhileUnscheduled?.invoke()
reschedule()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,10 @@ internal class ResetLocalRecordsIfConfigChangedUseCase @Inject constructor(
newConfig: ProjectConfiguration,
) {
if (hasPartitionTypeChanged(oldConfig, newConfig)) {
syncOrchestrator
.execute(
ScheduleCommand.Events.rescheduleAfter {
resetDownSyncInfo()
enrolmentRecordRepository.deleteAll()
},
).await()
syncOrchestrator.execute(ScheduleCommand.Events.unschedule()).await()
resetDownSyncInfo()
enrolmentRecordRepository.deleteAll()
syncOrchestrator.execute(ScheduleCommand.Events.reschedule()).await()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ internal inline fun <reified T : ListenableWorker> WorkManager.schedulePeriodicW
workName: String,
repeatInterval: Long,
existingWorkPolicy: ExistingPeriodicWorkPolicy = ExistingPeriodicWorkPolicy.UPDATE,
initialDelay: Long = 0,
initialDelay: Long = -1,
backoffInterval: Long = SyncConstants.DEFAULT_BACKOFF_INTERVAL_MINUTES,
constraints: Constraints = defaultWorkerConstraints(),
tags: List<String> = emptyList(),
Expand All @@ -34,8 +34,13 @@ internal inline fun <reified T : ListenableWorker> WorkManager.schedulePeriodicW
existingWorkPolicy,
PeriodicWorkRequestBuilder<T>(repeatInterval, SyncConstants.SYNC_TIME_UNIT)
.setConstraints(constraints)
.setInitialDelay(initialDelay, SyncConstants.SYNC_TIME_UNIT)
.setBackoffCriteria(BackoffPolicy.LINEAR, backoffInterval, SyncConstants.SYNC_TIME_UNIT)
.let {
if (initialDelay >= 0) {
it.setInitialDelay(initialDelay, SyncConstants.SYNC_TIME_UNIT)
} else {
it
}
}.setBackoffCriteria(BackoffPolicy.LINEAR, backoffInterval, SyncConstants.SYNC_TIME_UNIT)
.let { if (inputData != null) it.setInputData(inputData) else it }
.let { tags.fold(it) { builder, tag -> builder.addTag(tag) } }
.build(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,6 @@ class ScheduleSyncCommandTest {

assertThat(ScheduleCommand.Everything.unschedule())
.isEqualTo(ScheduleCommand.EverythingCommand(action = ScheduleCommand.Action.UNSCHEDULE))

val block: suspend () -> Unit = { }
val command = ScheduleCommand.Everything.rescheduleAfter(withDelay = true, block = block) as ScheduleCommand.EverythingCommand
assertThat(command.action).isEqualTo(ScheduleCommand.Action.RESCHEDULE)
assertThat(command.withDelay).isTrue()
assertThat(command.blockWhileUnscheduled).isSameInstanceAs(block)
}

@Test
Expand All @@ -32,12 +26,6 @@ class ScheduleSyncCommandTest {

assertThat(ScheduleCommand.Events.unschedule())
.isEqualTo(ScheduleCommand.EventsCommand(action = ScheduleCommand.Action.UNSCHEDULE))

val block: suspend () -> Unit = { }
val command = ScheduleCommand.Events.rescheduleAfter(withDelay = false, block = block) as ScheduleCommand.EventsCommand
assertThat(command.action).isEqualTo(ScheduleCommand.Action.RESCHEDULE)
assertThat(command.withDelay).isFalse()
assertThat(command.blockWhileUnscheduled).isSameInstanceAs(block)
}

@Test
Expand All @@ -47,10 +35,5 @@ class ScheduleSyncCommandTest {

assertThat(ScheduleCommand.Images.unschedule())
.isEqualTo(ScheduleCommand.ImagesCommand(action = ScheduleCommand.Action.UNSCHEDULE))

val block: suspend () -> Unit = { }
val command = ScheduleCommand.Images.rescheduleAfter(block) as ScheduleCommand.ImagesCommand
assertThat(command.action).isEqualTo(ScheduleCommand.Action.RESCHEDULE)
assertThat(command.blockWhileUnscheduled).isSameInstanceAs(block)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import io.mockk.every
import io.mockk.impl.annotations.MockK
import io.mockk.verify
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runTest
Expand Down Expand Up @@ -204,31 +203,6 @@ class SyncOrchestratorCommandExecutionTest {
}
}

@Test
fun `rescheduleAfter for schedule events routes to unschedule and reschedule with delay`() = runTest {
every { eventSyncWorkerTagRepository.getAllWorkerTag() } returns "syncWorkers"
every { eventSyncWorkerTagRepository.getPeriodicWorkTags() } returns listOf("tag1", "tag2")

orchestrator
.execute(
ScheduleCommand.Events.rescheduleAfter(withDelay = true) { },
).join()

verify {
workManager.cancelUniqueWork(EVENT_SYNC_WORK_NAME)
workManager.cancelUniqueWork(EVENT_SYNC_WORK_NAME_ONE_TIME)
workManager.cancelAllWorkByTag("syncWorkers")
workManager.enqueueUniquePeriodicWork(
EVENT_SYNC_WORK_NAME,
any(),
match {
it.workSpec.initialDelay > 0 &&
it.tags.containsAll(setOf("tag1", "tag2"))
},
)
}
}

@Test
fun `unschedule events cancels correct workers`() = runTest {
every { eventSyncWorkerTagRepository.getAllWorkerTag() } returns "syncWorkers"
Expand Down Expand Up @@ -349,41 +323,6 @@ class SyncOrchestratorCommandExecutionTest {
verify { workManager.cancelUniqueWork(FILE_UP_SYNC_WORK_NAME) }
}

@Test
fun `rescheduleAfter runs block before rescheduling images`() = runTest {
val blockStarted = Channel<Unit>(Channel.UNLIMITED)
val unblock = Channel<Unit>(Channel.UNLIMITED)
val block: suspend () -> Unit = {
blockStarted.trySend(Unit)
unblock.receive()
}

val job = orchestrator.execute(ScheduleCommand.Images.rescheduleAfter(block))

verify { workManager.cancelUniqueWork(FILE_UP_SYNC_WORK_NAME) }

blockStarted.receive()

verify(exactly = 0) {
workManager.enqueueUniquePeriodicWork(
FILE_UP_SYNC_WORK_NAME,
ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
any(),
)
}

unblock.trySend(Unit)
job.join()

verify {
workManager.enqueueUniquePeriodicWork(
FILE_UP_SYNC_WORK_NAME,
ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
any(),
)
}
}

@Test
fun `reschedules image worker when event sync starts`() = runTest {
val eventStartFlow = MutableSharedFlow<List<WorkInfo>>()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.simprints.infra.sync.config.usecase

import com.google.common.truth.Truth.assertThat
import com.simprints.core.domain.tokenization.asTokenizableEncrypted
import com.simprints.infra.config.store.models.DownSynchronizationConfiguration
import com.simprints.infra.config.store.models.Frequency
Expand Down Expand Up @@ -98,13 +97,11 @@ class ResetLocalRecordsIfConfigChangedUseCaseTest {
),
)

verify { syncOrchestrator.execute(any<ScheduleCommand>()) }
val command = scheduleCommandSlot.captured as ScheduleCommand.EventsCommand
assertThat(command.action).isEqualTo(ScheduleCommand.Action.RESCHEDULE)
assertThat(command.withDelay).isFalse()
assertThat(command.blockWhileUnscheduled).isNotNull()
verify(exactly = 1) {
syncOrchestrator.execute(match<ScheduleCommand.EventsCommand> { it.action == ScheduleCommand.Action.UNSCHEDULE })
syncOrchestrator.execute(match<ScheduleCommand.EventsCommand> { it.action == ScheduleCommand.Action.RESCHEDULE })
}

command.blockWhileUnscheduled?.invoke()
runCurrent()
coVerify {
resetDownSyncInfo()
Expand Down Expand Up @@ -135,13 +132,10 @@ class ResetLocalRecordsIfConfigChangedUseCaseTest {
),
)

verify { syncOrchestrator.execute(any<ScheduleCommand>()) }
val command = scheduleCommandSlot.captured as ScheduleCommand.EventsCommand
assertThat(command.action).isEqualTo(ScheduleCommand.Action.RESCHEDULE)
assertThat(command.blockWhileUnscheduled).isNotNull()

command.blockWhileUnscheduled?.invoke()
runCurrent()
verify(exactly = 1) {
syncOrchestrator.execute(match<ScheduleCommand.EventsCommand> { it.action == ScheduleCommand.Action.UNSCHEDULE })
syncOrchestrator.execute(match<ScheduleCommand.EventsCommand> { it.action == ScheduleCommand.Action.RESCHEDULE })
}
coVerify {
resetDownSyncInfo()
enrolmentRecordRepository.deleteAll()
Expand Down Expand Up @@ -171,13 +165,10 @@ class ResetLocalRecordsIfConfigChangedUseCaseTest {
),
)

verify { syncOrchestrator.execute(any<ScheduleCommand>()) }
val command = scheduleCommandSlot.captured as ScheduleCommand.EventsCommand
assertThat(command.action).isEqualTo(ScheduleCommand.Action.RESCHEDULE)
assertThat(command.blockWhileUnscheduled).isNotNull()

command.blockWhileUnscheduled?.invoke()
runCurrent()
verify(exactly = 1) {
syncOrchestrator.execute(match<ScheduleCommand.EventsCommand> { it.action == ScheduleCommand.Action.UNSCHEDULE })
syncOrchestrator.execute(match<ScheduleCommand.EventsCommand> { it.action == ScheduleCommand.Action.RESCHEDULE })
}
coVerify {
resetDownSyncInfo()
enrolmentRecordRepository.deleteAll()
Expand Down Expand Up @@ -207,13 +198,10 @@ class ResetLocalRecordsIfConfigChangedUseCaseTest {
),
)

verify { syncOrchestrator.execute(any<ScheduleCommand>()) }
val command = scheduleCommandSlot.captured as ScheduleCommand.EventsCommand
assertThat(command.action).isEqualTo(ScheduleCommand.Action.RESCHEDULE)
assertThat(command.blockWhileUnscheduled).isNotNull()

command.blockWhileUnscheduled?.invoke()
runCurrent()
verify(exactly = 1) {
syncOrchestrator.execute(match<ScheduleCommand.EventsCommand> { it.action == ScheduleCommand.Action.UNSCHEDULE })
syncOrchestrator.execute(match<ScheduleCommand.EventsCommand> { it.action == ScheduleCommand.Action.RESCHEDULE })
}
coVerify {
resetDownSyncInfo()
enrolmentRecordRepository.deleteAll()
Expand Down
Loading