Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix part of #5025: App and OS Deprecation Milestone 2 - Add protos and the DeprecationController #4999

Merged
merged 20 commits into from
Jul 12, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
698647d
feat: Add protos for the deprecation feature as well as the deprecati…
kkmurerwa May 29, 2023
10e1e50
fix: Add comments on the DeprecationController to fix kdocs issues
kkmurerwa May 29, 2023
d88c458
chore: Update comments on the deprecation.proto file to better explai…
kkmurerwa Jun 1, 2023
dd0d378
Merge branch 'develop' into app-and-os-deprecation-milestone-2
kkmurerwa Jun 1, 2023
29a4835
fix: Fix failing tests in the DeprecationControllerTest.
kkmurerwa Jun 1, 2023
974ad10
Merge branch 'develop' into app-and-os-deprecation-milestone-2
kkmurerwa Jun 2, 2023
384fec2
fix: Fix failing kdoc regex check
kkmurerwa Jun 2, 2023
409a26c
Merge branch 'develop' into app-and-os-deprecation-milestone-2
kkmurerwa Jun 22, 2023
65c0cd0
Merge branch 'develop' into app-and-os-deprecation-milestone-2
kkmurerwa Jul 3, 2023
700a14a
chore: Fix a few nits and minor code improvements
Jul 3, 2023
6dabebc
Merge branch 'app-and-os-deprecation-milestone-2' of github.com:kkmur…
Jul 3, 2023
1ad6387
chore: Fix linting errors
Jul 3, 2023
20135a1
chore: Fix bazel build file linting issues
Jul 3, 2023
10109b1
chore: Update code comments and fix a few linting issues
Jul 4, 2023
ea10834
Merge branch 'develop' into app-and-os-deprecation-milestone-2
kkmurerwa Jul 4, 2023
2c10b92
Merge branch 'develop' into app-and-os-deprecation-milestone-2
kkmurerwa Jul 10, 2023
15a6a3d
Merge branch 'develop' into app-and-os-deprecation-milestone-2
kkmurerwa Jul 11, 2023
ed972f4
chore: Remove unused DeprecationResponseActionStatus options
Jul 11, 2023
1eef054
Merge branch 'develop' into app-and-os-deprecation-milestone-2
kkmurerwa Jul 12, 2023
27a997e
Merge branch 'develop' into app-and-os-deprecation-milestone-2
adhiamboperes Jul 12, 2023
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 @@ -9,14 +9,17 @@ kt_android_library(
name = "state_controller",
srcs = [
"AppStartupStateController.kt",
"DeprecationController.kt",
adhiamboperes marked this conversation as resolved.
Show resolved Hide resolved
],
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
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 DEPRECATION_PROVIDER_ID = "deprecation_data_provider_id"
adhiamboperes marked this conversation as resolved.
Show resolved Hide resolved
private const val ADD_DEPRECATION_PROVIDER_ID = "add_deprecation_data_provider_id"
adhiamboperes marked this conversation as resolved.
Show resolved Hide resolved

/**
* 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].
*/
adhiamboperes marked this conversation as resolved.
Show resolved Hide resolved
private val deprecationStore by lazy {
cacheStoreFactory.create(
"deprecation_store",
DeprecationResponseDatabase.getDefaultInstance()
)
}

/**
* Enum states for the possible outcomes of a deprecation action.
*/
adhiamboperes marked this conversation as resolved.
Show resolved Hide resolved
private enum class DeprecationActionStatus {
adhiamboperes marked this conversation as resolved.
Show resolved Hide resolved
/** Indicates that the deprecation operation succeeded. */
adhiamboperes marked this conversation as resolved.
Show resolved Hide resolved
SUCCESS,

/** Indicates that a deprecation write operation failed. */
adhiamboperes marked this conversation as resolved.
Show resolved Hide resolved
FAILED_TO_STORE_DEPRECATION_RESPONSE,

/**
* Indicates that a deprecation read operation failed. This is usually the result when a
adhiamboperes marked this conversation as resolved.
Show resolved Hide resolved
* requested [DeprecationResponse] was not found.
*/
DEPRECATION_RESPONSE_NOT_FOUND
}

init {
/**
* Prime the cache ahead of time so that the deprecation response can be retrieved
* synchronously.
*/
adhiamboperes marked this conversation as resolved.
Show resolved Hide resolved
deprecationStore.primeInMemoryAndDiskCacheAsync(
updateMode = PersistentCacheStore.UpdateMode.UPDATE_ALWAYS,
publishMode = PersistentCacheStore.PublishMode.PUBLISH_TO_IN_MEMORY_CACHE
) {
it.toBuilder().build()
}.invokeOnCompletion { primeFailure ->
primeFailure?.let {
oppiaLogger.e(
"DeprecationController",
"Failed to prime cache ahead of data retrieval for DeprecationController.",
primeFailure
)
}
}
}
adhiamboperes marked this conversation as resolved.
Show resolved Hide resolved

private val deprecationDataProvider by lazy { computeDeprecationProvider() }

private fun computeDeprecationProvider(): DataProvider<DeprecationResponseDatabase> {
return deprecationStore.transform(DEPRECATION_PROVIDER_ID) { deprecationResponsesDatabase ->
DeprecationResponseDatabase.newBuilder().apply {
appDeprecationResponse = deprecationResponsesDatabase.appDeprecationResponse
osDeprecationResponse = deprecationResponsesDatabase.osDeprecationResponse
}.build()
}
adhiamboperes marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* 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.
*/
adhiamboperes marked this conversation as resolved.
Show resolved Hide resolved
fun setDeprecationResponse(deprecationResponse: DeprecationResponse): DataProvider<Any?> {
adhiamboperes marked this conversation as resolved.
Show resolved Hide resolved
val deferred = deprecationStore.storeDataWithCustomChannelAsync(
updateInMemoryCache = true
) {
val deprecationBuilder = if (deprecationResponse.deprecationNoticeType
== DeprecationNoticeType.DEPRECATION_NOTICE_TYPE_APP_UPDATE
) {
it.toBuilder()
.setAppDeprecationResponse(deprecationResponse)
.build()
} else {
it.toBuilder()
.setOsDeprecationResponse(deprecationResponse)
.build()
}

Pair(deprecationBuilder, DeprecationActionStatus.SUCCESS)
}

return dataProviders.createInMemoryDataProviderAsync(ADD_DEPRECATION_PROVIDER_ID) {
return@createInMemoryDataProviderAsync getDeferredResult(deferred)
}
}

/**
* Retrieves the [DeprecationResponse] from the cache.
*
* @param deferred a deferred instance of the [DeprecationActionStatus].
* @return [AsyncResult].
adhiamboperes marked this conversation as resolved.
Show resolved Hide resolved
*/
private suspend fun getDeferredResult(
deferred: Deferred<DeprecationActionStatus>
): AsyncResult<Any?> {
return when (deferred.await()) {
DeprecationActionStatus.SUCCESS -> AsyncResult.Success(null)
DeprecationActionStatus.FAILED_TO_STORE_DEPRECATION_RESPONSE -> AsyncResult.Failure(
Exception("Failed to store deprecation response")
)
DeprecationActionStatus.DEPRECATION_RESPONSE_NOT_FOUND -> AsyncResult.Failure(
Exception("Deprecation response not found")
)
}
}
}
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: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",
"//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