forked from oppia/oppia-android
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix part of oppia#5025: App and OS Deprecation Milestone 2 - Add prot…
…os and the DeprecationController (oppia#4999) <!-- READ ME FIRST: Please fill in the explanation section below and check off every point from the Essential Checklist! --> ## Explanation <!-- - Explain what your PR does. If this PR fixes an existing bug, please include - "Fixes #bugnum:" in the explanation so that GitHub can auto-close the issue - when this PR is merged. --> Fix part of oppia#5025: When this PR is merged, it will; - Add a new `deprecation.proto` file that will allow the storage of deprecation responses as well as provide the various deprecation types. - Add the `OPTIONAL_UPDATE_AVAILABLE` and the `OS_IS_DEPRECATED` startup modes on the `onboarding.proto` file for the two new startup modes being introduced. - Create a `DeprecationController` class and add tests for the class in the `DeprecationControllerTest`. - Modify BUILD.bazel files to provide the new proto files and the deprecation controller. - Add `DeprecationControllerTest` to the `OppiaParameterizedTestRunner` file exemptions on the `file_content_validation_checks.textproto`. ## Essential Checklist <!-- Please tick the relevant boxes by putting an "x" in them. --> - [x] The PR title and explanation each start with "Fix #bugnum: " (If this PR fixes part of an issue, prefix the title with "Fix part of #bugnum: ...".) - [x] Any changes to [scripts/assets](https://github.com/oppia/oppia-android/tree/develop/scripts/assets) files have their rationale included in the PR explanation. - [x] The PR follows the [style guide](https://github.com/oppia/oppia-android/wiki/Coding-style-guide). - [x] The PR does not contain any unnecessary code changes from Android Studio ([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#undo-unnecessary-changes)). - [x] The PR is made from a branch that's **not** called "develop" and is up-to-date with "develop". - [x] The PR is **assigned** to the appropriate reviewers ([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#clarification-regarding-assignees-and-reviewers-section)). --------- Co-authored-by: Kenneth Murerwa <[email protected]> Co-authored-by: Adhiambo Peres <[email protected]>
- Loading branch information
1 parent
f357362
commit 9692306
Showing
9 changed files
with
520 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
117 changes: 117 additions & 0 deletions
117
domain/src/main/java/org/oppia/android/domain/onboarding/DeprecationController.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
package org.oppia.android.domain.onboarding | ||
|
||
import kotlinx.coroutines.Deferred | ||
import org.oppia.android.app.model.DeprecationNoticeType | ||
import org.oppia.android.app.model.DeprecationResponse | ||
import org.oppia.android.app.model.DeprecationResponseDatabase | ||
import org.oppia.android.data.persistence.PersistentCacheStore | ||
import org.oppia.android.domain.oppialogger.OppiaLogger | ||
import org.oppia.android.util.data.AsyncResult | ||
import org.oppia.android.util.data.DataProvider | ||
import org.oppia.android.util.data.DataProviders | ||
import org.oppia.android.util.data.DataProviders.Companion.transform | ||
import javax.inject.Inject | ||
import javax.inject.Singleton | ||
|
||
private const val GET_DEPRECATION_RESPONSE_PROVIDER_ID = "get_deprecation_response_provider_id" | ||
private const val ADD_DEPRECATION_RESPONSE_PROVIDER_ID = "add_deprecation_response_provider_id" | ||
|
||
/** | ||
* Controller for persisting and retrieving the user's deprecation responses. This will be used to | ||
* handle deprecations once the user opens the app. | ||
*/ | ||
@Singleton | ||
class DeprecationController @Inject constructor( | ||
cacheStoreFactory: PersistentCacheStore.Factory, | ||
private val oppiaLogger: OppiaLogger, | ||
private val dataProviders: DataProviders | ||
) { | ||
/** Create an instance of [PersistentCacheStore] that contains a [DeprecationResponseDatabase]. */ | ||
private val deprecationStore by lazy { | ||
cacheStoreFactory.create( | ||
"deprecation_store", | ||
DeprecationResponseDatabase.getDefaultInstance() | ||
) | ||
} | ||
|
||
/** Enum states for the possible outcomes of a deprecation action. */ | ||
private enum class DeprecationResponseActionStatus { | ||
/** Indicates that the deprecation response read/write operation succeeded. */ | ||
SUCCESS | ||
} | ||
|
||
init { | ||
// Prime the cache ahead of time so that the deprecation response can be retrieved | ||
// synchronously. | ||
deprecationStore.primeInMemoryAndDiskCacheAsync( | ||
updateMode = PersistentCacheStore.UpdateMode.UPDATE_ALWAYS, | ||
publishMode = PersistentCacheStore.PublishMode.PUBLISH_TO_IN_MEMORY_CACHE | ||
).invokeOnCompletion { primeFailure -> | ||
primeFailure?.let { | ||
oppiaLogger.e( | ||
"DeprecationController", | ||
"Failed to prime cache ahead of data retrieval for DeprecationController.", | ||
primeFailure | ||
) | ||
} | ||
} | ||
} | ||
|
||
private val deprecationDataProvider by lazy { fetchDeprecationProvider() } | ||
|
||
private fun fetchDeprecationProvider(): DataProvider<DeprecationResponseDatabase> { | ||
return deprecationStore.transform( | ||
GET_DEPRECATION_RESPONSE_PROVIDER_ID | ||
) { deprecationResponsesDatabase -> | ||
DeprecationResponseDatabase.newBuilder().apply { | ||
appDeprecationResponse = deprecationResponsesDatabase.appDeprecationResponse | ||
osDeprecationResponse = deprecationResponsesDatabase.osDeprecationResponse | ||
}.build() | ||
} | ||
} | ||
|
||
/** | ||
* Returns a [DataProvider] containing the the [DeprecationResponseDatabase], which in turn | ||
* affects what initial app flow the user is directed to. | ||
*/ | ||
fun getDeprecationDatabase(): DataProvider<DeprecationResponseDatabase> = deprecationDataProvider | ||
|
||
/** | ||
* Stores a new [DeprecationResponse] to the cache. | ||
* | ||
* @param deprecationResponse the deprecation response to be stored | ||
* @return [AsyncResult] of the deprecation action | ||
*/ | ||
fun saveDeprecationResponse(deprecationResponse: DeprecationResponse): DataProvider<Any?> { | ||
val deferred = deprecationStore.storeDataWithCustomChannelAsync( | ||
updateInMemoryCache = true | ||
) { deprecationResponseDb -> | ||
val deprecationBuilder = deprecationResponseDb.toBuilder().apply { | ||
if (deprecationResponse.deprecationNoticeType == DeprecationNoticeType.APP_DEPRECATION) | ||
appDeprecationResponse = deprecationResponse | ||
else | ||
osDeprecationResponse = deprecationResponse | ||
} | ||
.build() | ||
Pair(deprecationBuilder, DeprecationResponseActionStatus.SUCCESS) | ||
} | ||
|
||
return dataProviders.createInMemoryDataProviderAsync(ADD_DEPRECATION_RESPONSE_PROVIDER_ID) { | ||
return@createInMemoryDataProviderAsync getDeferredResult(deferred) | ||
} | ||
} | ||
|
||
/** | ||
* Retrieves the [DeprecationResponse] from the cache. | ||
* | ||
* @param deferred a deferred instance of the [DeprecationResponseActionStatus] | ||
* @return [AsyncResult] | ||
*/ | ||
private suspend fun getDeferredResult( | ||
deferred: Deferred<DeprecationResponseActionStatus> | ||
): AsyncResult<Any?> { | ||
return when (deferred.await()) { | ||
DeprecationResponseActionStatus.SUCCESS -> AsyncResult.Success(null) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.