Skip to content

Commit

Permalink
Fix part of oppia#5025: App and OS Deprecation Milestone 2 - Add prot…
Browse files Browse the repository at this point in the history
…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
3 people authored Jul 12, 2023
1 parent f357362 commit 9692306
Show file tree
Hide file tree
Showing 9 changed files with 520 additions and 0 deletions.
1 change: 1 addition & 0 deletions domain/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ TEST_DEPS = [
"//domain/src/main/java/org/oppia/android/domain/classify/rules/textinput:text_input_rule_module",
"//domain/src/main/java/org/oppia/android/domain/feedbackreporting:prod_module",
"//domain/src/main/java/org/oppia/android/domain/feedbackreporting:report_schema_version",
"//domain/src/main/java/org/oppia/android/domain/onboarding:deprecation_controller",
"//domain/src/main/java/org/oppia/android/domain/onboarding:retriever_prod_module",
"//domain/src/main/java/org/oppia/android/domain/onboarding:state_controller",
"//domain/src/main/java/org/oppia/android/domain/oppialogger:prod_module",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,17 @@ kt_android_library(
name = "state_controller",
srcs = [
"AppStartupStateController.kt",
"DeprecationController.kt",
],
visibility = ["//:oppia_api_visibility"],
deps = [
":exploration_meta_data_retriever",
"//data/src/main/java/org/oppia/android/data/persistence:cache_store",
"//domain/src/main/java/org/oppia/android/domain/oppialogger:oppia_logger",
"//model/src/main/proto:deprecation_java_proto_lite",
"//model/src/main/proto:onboarding_java_proto_lite",
"//third_party:javax_inject_javax_inject",
"//utility",
"//utility/src/main/java/org/oppia/android/util/data:data_provider",
"//utility/src/main/java/org/oppia/android/util/data:data_providers",
"//utility/src/main/java/org/oppia/android/util/extensions:bundle_extensions",
Expand Down Expand Up @@ -55,4 +58,24 @@ kt_android_library(
],
)

kt_android_library(
name = "deprecation_controller",
srcs = [
"DeprecationController.kt",
],
visibility = ["//:oppia_api_visibility"],
deps = [
":exploration_meta_data_retriever",
"//data/src/main/java/org/oppia/android/data/persistence:cache_store",
"//domain/src/main/java/org/oppia/android/domain/oppialogger:oppia_logger",
"//model/src/main/proto:deprecation_java_proto_lite",
"//model/src/main/proto:onboarding_java_proto_lite",
"//third_party:javax_inject_javax_inject",
"//utility",
"//utility/src/main/java/org/oppia/android/util/data:data_provider",
"//utility/src/main/java/org/oppia/android/util/data:data_providers",
"//utility/src/main/java/org/oppia/android/util/extensions:bundle_extensions",
],
)

dagger_rules()
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)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,35 @@ oppia_android_test(
],
)

oppia_android_test(
name = "DeprecationControllerTest",
srcs = ["DeprecationControllerTest.kt"],
custom_package = "org.oppia.android.domain.onboarding",
test_class = "org.oppia.android.domain.onboarding.DeprecationControllerTest",
test_manifest = "//domain:test_manifest",
deps = [
":dagger",
"//domain",
"//domain/src/main/java/org/oppia/android/domain/onboarding:deprecation_controller",
"//domain/src/main/java/org/oppia/android/domain/onboarding:retriever_prod_module",
"//domain/src/main/java/org/oppia/android/domain/oppialogger:prod_module",
"//domain/src/main/java/org/oppia/android/domain/oppialogger/analytics:prod_module",
"//testing",
"//testing/src/main/java/org/oppia/android/testing/data:data_provider_test_monitor",
"//testing/src/main/java/org/oppia/android/testing/junit:oppia_parameterized_test_runner",
"//testing/src/main/java/org/oppia/android/testing/junit:parameterized_robolectric_test_runner",
"//testing/src/main/java/org/oppia/android/testing/robolectric:test_module",
"//testing/src/main/java/org/oppia/android/testing/threading:test_module",
"//third_party:com_google_truth_truth",
"//third_party:junit_junit",
"//third_party:org_mockito_mockito-core",
"//third_party:org_robolectric_robolectric",
"//third_party:robolectric_android-all",
"//utility/src/main/java/org/oppia/android/util/locale:prod_module",
"//utility/src/main/java/org/oppia/android/util/logging:prod_module",
"//utility/src/main/java/org/oppia/android/util/networking:debug_module",
"//utility/src/main/java/org/oppia/android/util/system:prod_module",
],
)

dagger_rules()
Loading

0 comments on commit 9692306

Please sign in to comment.