Skip to content
This repository has been archived by the owner on Jun 20, 2023. It is now read-only.

Commit

Permalink
- initialize coroutine scope within the playbook, revert passing it f…
Browse files Browse the repository at this point in the history
…rom outside

- remove experimental test dependency for coroutines
  • Loading branch information
Fabian-K committed Aug 5, 2020
1 parent fa02304 commit 863b12d
Show file tree
Hide file tree
Showing 13 changed files with 74 additions and 95 deletions.
1 change: 0 additions & 1 deletion Corona-Warn-App/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,6 @@ dependencies {
// TESTING
testImplementation 'junit:junit:4.13'
testImplementation "android.arch.core:core-testing:1.1.1"
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.7'
testImplementation "org.mockito:mockito-core:3.3.3"
testImplementation('org.robolectric:robolectric:4.3.1') {
exclude group: 'com.google.protobuf'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import de.rki.coronawarnapp.http.WebRequestBuilder
import de.rki.coronawarnapp.service.submission.SubmissionConstants
import de.rki.coronawarnapp.storage.LocalData
import de.rki.coronawarnapp.worker.BackgroundWorkScheduler
import kotlinx.coroutines.CoroutineScope
import kotlin.random.Random

class BackgroundNoise {
Expand All @@ -25,11 +24,11 @@ class BackgroundNoise {
BackgroundWorkScheduler.scheduleBackgroundNoisePeriodicWork()
}

suspend fun foregroundScheduleCheck(coroutineScope: CoroutineScope) {
suspend fun foregroundScheduleCheck() {
if (LocalData.isAllowedToSubmitDiagnosisKeys() == true) {
val chance = Random.nextFloat() * 100
if (chance < SubmissionConstants.probabilityToExecutePlaybookWhenOpenApp) {
PlaybookImpl(WebRequestBuilder.getInstance(), coroutineScope)
PlaybookImpl(WebRequestBuilder.getInstance())
.dummy()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import de.rki.coronawarnapp.service.submission.KeyType
import de.rki.coronawarnapp.service.submission.SubmissionConstants
import de.rki.coronawarnapp.util.formatter.TestResult
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import timber.log.Timber
Expand All @@ -14,11 +15,11 @@ import java.util.concurrent.TimeUnit
import kotlin.random.Random

class PlaybookImpl(
private val webRequestBuilder: WebRequestBuilder,
private val coroutineScope: CoroutineScope
private val webRequestBuilder: WebRequestBuilder
) : Playbook {

private val uid = UUID.randomUUID().toString()
private val coroutineScope: CoroutineScope = CoroutineScope(Dispatchers.IO)

override suspend fun initialRegistration(key: String, keyType: KeyType): String {
Timber.i("[$uid] New Initial Registration Playbook")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,25 @@ import de.rki.coronawarnapp.storage.LocalData
import de.rki.coronawarnapp.transaction.SubmitDiagnosisKeysTransaction
import de.rki.coronawarnapp.util.formatter.TestResult
import de.rki.coronawarnapp.worker.BackgroundWorkScheduler
import kotlinx.coroutines.CoroutineScope

object SubmissionService {

suspend fun asyncRegisterDevice(coroutineScope: CoroutineScope) {
suspend fun asyncRegisterDevice() {
val testGUID = LocalData.testGUID()
val testTAN = LocalData.teletan()

when {
testGUID != null -> asyncRegisterDeviceViaGUID(coroutineScope, testGUID)
testTAN != null -> asyncRegisterDeviceViaTAN(coroutineScope, testTAN)
testGUID != null -> asyncRegisterDeviceViaGUID(testGUID)
testTAN != null -> asyncRegisterDeviceViaTAN(testTAN)
else -> throw NoGUIDOrTANSetException()
}
LocalData.devicePairingSuccessfulTimestamp(System.currentTimeMillis())
BackgroundNoise.getInstance().scheduleDummyPattern()
}

private suspend fun asyncRegisterDeviceViaGUID(coroutineScope: CoroutineScope, guid: String) {
private suspend fun asyncRegisterDeviceViaGUID(guid: String) {
val registrationToken =
PlaybookImpl(WebRequestBuilder.getInstance(), coroutineScope).initialRegistration(
PlaybookImpl(WebRequestBuilder.getInstance()).initialRegistration(
guid,
KeyType.GUID
)
Expand All @@ -38,9 +37,9 @@ object SubmissionService {
deleteTestGUID()
}

private suspend fun asyncRegisterDeviceViaTAN(coroutineScope: CoroutineScope, tan: String) {
private suspend fun asyncRegisterDeviceViaTAN(tan: String) {
val registrationToken =
PlaybookImpl(WebRequestBuilder.getInstance(), coroutineScope).initialRegistration(
PlaybookImpl(WebRequestBuilder.getInstance()).initialRegistration(
tan,
KeyType.TELETAN
)
Expand All @@ -49,17 +48,17 @@ object SubmissionService {
deleteTeleTAN()
}

suspend fun asyncSubmitExposureKeys(coroutineScope: CoroutineScope, keys: List<TemporaryExposureKey>) {
suspend fun asyncSubmitExposureKeys(keys: List<TemporaryExposureKey>) {
val registrationToken =
LocalData.registrationToken() ?: throw NoRegistrationTokenSetException()
SubmitDiagnosisKeysTransaction.start(coroutineScope, registrationToken, keys)
SubmitDiagnosisKeysTransaction.start(registrationToken, keys)
}

suspend fun asyncRequestTestResult(coroutineScope: CoroutineScope): TestResult {
suspend fun asyncRequestTestResult(): TestResult {
val registrationToken =
LocalData.registrationToken() ?: throw NoRegistrationTokenSetException()

return PlaybookImpl(WebRequestBuilder.getInstance(), coroutineScope).testResult(registrationToken)
return PlaybookImpl(WebRequestBuilder.getInstance()).testResult(registrationToken)
}

fun containsValidGUID(scanResult: String): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import de.rki.coronawarnapp.service.submission.SubmissionService
import de.rki.coronawarnapp.util.DeviceUIState
import de.rki.coronawarnapp.util.formatter.TestResult
import de.rki.coronawarnapp.worker.BackgroundWorkScheduler
import kotlinx.coroutines.CoroutineScope
import java.util.Date

object SubmissionRepository {
Expand All @@ -15,7 +14,7 @@ object SubmissionRepository {
val testResultReceivedDate = MutableLiveData(Date())
val deviceUIState = MutableLiveData(DeviceUIState.UNPAIRED)

suspend fun refreshUIState(coroutineScope: CoroutineScope) {
suspend fun refreshUIState() {
var uiState = DeviceUIState.UNPAIRED

if (LocalData.numberOfSuccessfulSubmissions() == 1) {
Expand All @@ -26,16 +25,16 @@ object SubmissionRepository {
LocalData.isAllowedToSubmitDiagnosisKeys() == true -> {
DeviceUIState.PAIRED_POSITIVE
}
else -> fetchTestResult(coroutineScope)
else -> fetchTestResult()
}
}
}
deviceUIState.value = uiState
}

private suspend fun fetchTestResult(coroutineScope: CoroutineScope): DeviceUIState {
private suspend fun fetchTestResult(): DeviceUIState {
try {
val testResult = SubmissionService.asyncRequestTestResult(coroutineScope)
val testResult = SubmissionService.asyncRequestTestResult()

if (testResult == TestResult.POSITIVE) {
LocalData.isAllowedToSubmitDiagnosisKeys(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import de.rki.coronawarnapp.transaction.SubmitDiagnosisKeysTransaction.SubmitDia
import de.rki.coronawarnapp.transaction.SubmitDiagnosisKeysTransaction.SubmitDiagnosisKeysTransactionState.STORE_SUCCESS
import de.rki.coronawarnapp.util.ProtoFormatConverterExtensions.limitKeyCount
import de.rki.coronawarnapp.util.ProtoFormatConverterExtensions.transformKeyHistoryToExternalFormat
import kotlinx.coroutines.CoroutineScope

/**
* The SubmitDiagnosisKeysTransaction is used to define an atomic Transaction for Key Reports. Its states allow an
Expand Down Expand Up @@ -50,7 +49,6 @@ object SubmitDiagnosisKeysTransaction : Transaction() {

/** initiates the transaction. This suspend function guarantees a successful transaction once completed. */
suspend fun start(
coroutineScope: CoroutineScope,
registrationToken: String,
keys: List<TemporaryExposureKey>
) = lockAndExecuteUnique {
Expand All @@ -65,7 +63,7 @@ object SubmitDiagnosisKeysTransaction : Transaction() {
* RETRIEVE TAN & SUBMIT KEYS
****************************************************/
executeState(RETRIEVE_TAN_AND_SUBMIT_KEYS) {
PlaybookImpl(WebRequestBuilder.getInstance(), coroutineScope).submission(
PlaybookImpl(WebRequestBuilder.getInstance()).submission(
registrationToken,
temporaryExposureKeyList
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class MainActivity : AppCompatActivity() {

private fun doBackgroundNoiseCheck() {
lifecycleScope.launch {
BackgroundNoise.getInstance().foregroundScheduleCheck(this)
BackgroundNoise.getInstance().foregroundScheduleCheck()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class SubmissionViewModel : ViewModel() {
fun submitDiagnosisKeys(keys: List<TemporaryExposureKey>) = viewModelScope.launch {
try {
_submissionState.value = ApiRequestState.STARTED
SubmissionService.asyncSubmitExposureKeys(this, keys)
SubmissionService.asyncSubmitExposureKeys(keys)
_submissionState.value = ApiRequestState.SUCCESS
} catch (err: CwaWebException) {
_submissionError.value = Event(err)
Expand All @@ -73,7 +73,7 @@ class SubmissionViewModel : ViewModel() {
fun doDeviceRegistration() = viewModelScope.launch {
try {
_registrationState.value = Event(ApiRequestState.STARTED)
SubmissionService.asyncRegisterDevice(viewModelScope)
SubmissionService.asyncRegisterDevice()
_registrationState.value = Event(ApiRequestState.SUCCESS)
} catch (err: CwaWebException) {
_registrationError.value = Event(err)
Expand All @@ -91,20 +91,12 @@ class SubmissionViewModel : ViewModel() {
}
}

fun refreshDeviceUIState() {
_uiStateState.value = ApiRequestState.STARTED
viewModelScope.launch {
try {
SubmissionRepository.refreshUIState(this)
_uiStateState.value = ApiRequestState.SUCCESS
} catch (err: CwaWebException) {
_uiStateError.value = Event(err)
_uiStateState.value = ApiRequestState.FAILED
} catch (err: Exception) {
err.report(ExceptionCategory.INTERNAL)
}
}
}
fun refreshDeviceUIState() =
executeRequestWithState(
SubmissionRepository::refreshUIState,
_uiStateState,
_uiStateError
)

fun validateAndStoreTestGUID(scanResult: String) {
if (SubmissionService.containsValidGUID(scanResult)) {
Expand All @@ -126,4 +118,23 @@ class SubmissionViewModel : ViewModel() {
LocalData.isAllowedToSubmitDiagnosisKeys(false)
LocalData.initialTestResultReceivedTimestamp(0L)
}

private fun executeRequestWithState(
apiRequest: suspend () -> Unit,
state: MutableLiveData<ApiRequestState>,
exceptionLiveData: MutableLiveData<Event<CwaWebException>>? = null
) {
state.value = ApiRequestState.STARTED
viewModelScope.launch {
try {
apiRequest()
state.value = ApiRequestState.SUCCESS
} catch (err: CwaWebException) {
exceptionLiveData?.value = Event(err)
state.value = ApiRequestState.FAILED
} catch (err: Exception) {
err.report(ExceptionCategory.INTERNAL)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import de.rki.coronawarnapp.http.WebRequestBuilder
import de.rki.coronawarnapp.http.playbook.PlaybookImpl
import kotlinx.coroutines.coroutineScope

/**
* One time background noise worker
Expand All @@ -27,11 +26,11 @@ class BackgroundNoiseOneTimeWorker(
*
* @return Result
*/
override suspend fun doWork(): Result = coroutineScope {
override suspend fun doWork(): Result {
var result = Result.success()

try {
PlaybookImpl(WebRequestBuilder.getInstance(), this)
PlaybookImpl(WebRequestBuilder.getInstance())
.dummy()
} catch (e: Exception) {
// TODO: Should we even retry here?
Expand All @@ -42,6 +41,6 @@ class BackgroundNoiseOneTimeWorker(
}
}

return@coroutineScope result
return result
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import de.rki.coronawarnapp.storage.LocalData
import de.rki.coronawarnapp.util.TimeAndDateExtensions
import de.rki.coronawarnapp.util.formatter.TestResult
import de.rki.coronawarnapp.worker.BackgroundWorkScheduler.stop
import kotlinx.coroutines.coroutineScope
import timber.log.Timber

/**
Expand Down Expand Up @@ -41,7 +40,7 @@ class DiagnosisTestResultRetrievalPeriodicWorker(
* @see LocalData.isTestResultNotificationSent
* @see LocalData.initialPollingForTestResultTimeStamp
*/
override suspend fun doWork(): Result = coroutineScope {
override suspend fun doWork(): Result {

Timber.d("Background job started. Run attempt: $runAttemptCount")
BackgroundWorkHelper.sendDebugNotification(
Expand All @@ -54,7 +53,7 @@ class DiagnosisTestResultRetrievalPeriodicWorker(
"TestResult Executing: Failure", "TestResult failed with $runAttemptCount attempts")

BackgroundWorkScheduler.scheduleDiagnosisKeyPeriodicWork()
return@coroutineScope Result.failure()
return Result.failure()
}
var result = Result.success()
try {
Expand All @@ -63,7 +62,7 @@ class DiagnosisTestResultRetrievalPeriodicWorker(
System.currentTimeMillis()
) < BackgroundConstants.POLLING_VALIDITY_MAX_DAYS
) {
val testResult = SubmissionService.asyncRequestTestResult(this)
val testResult = SubmissionService.asyncRequestTestResult()
initiateNotification(testResult)
} else {
stopWorker()
Expand All @@ -75,7 +74,7 @@ class DiagnosisTestResultRetrievalPeriodicWorker(
BackgroundWorkHelper.sendDebugNotification(
"TestResult Executing: End", "TestResult result: $result ")

return@coroutineScope result
return result
}

/**
Expand Down
Loading

0 comments on commit 863b12d

Please sign in to comment.