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

Download fails to complete when exception is encountered #1654

Open
ellykits opened this issue Oct 6, 2022 · 3 comments
Open

Download fails to complete when exception is encountered #1654

ellykits opened this issue Oct 6, 2022 · 3 comments
Assignees
Labels
effort:small Small effort - 2 days P1 High priority issue type:bug Something isn't working

Comments

@ellykits
Copy link
Collaborator

ellykits commented Oct 6, 2022

Describe the bug
When an exception occurs while downloading a resource, the com.google.android.fhir.sync.download.DownloaderImpl attempts to emit a com.google.android.fhir.sync.DownloadState.Failure failure in the catch block which results to a FATAL_EXCEPTION.

Component
Core library

To Reproduce
Steps to reproduce the behavior:

  1. Attempt downloading a resource that has an exception. (Example in our use case was an Encounter resource missing a coding.code)

Expected behavior
In case of a Resource sync failure com.google.android.fhir.sync.DownloadState.Failure should be emitted with the parameter ResourceSyncException wrapping the sync exception without violating the flow exception transparency.

Error logs

FATAL EXCEPTION: main
                                                                                                    Process: org.smartregister.fhircore.ecbis, PID: 10487
                                                                                                    java.lang.IllegalStateException: Flow exception transparency is violated:
                                                                                                        Previous 'emit' call has thrown exception java.lang.NullPointerException: coding.code must not be null, but then emission attempt of value 'Failure(syncError=ResourceSyncException(resourceType=Encounter, exception=java.lang.NullPointerException: coding.code must not be null))' has been detected.
                                                                                                        Emissions from 'catch' blocks are prohibited in order to avoid unspecified behaviour, 'Flow.catch' operator can be used instead.
                                                                                                        For a more detailed explanation, please refer to Flow documentation.
                                                                                                    	at kotlinx.coroutines.flow.internal.SafeCollector.exceptionTransparencyViolated(SafeCollector.kt:140)
                                                                                                    	at kotlinx.coroutines.flow.internal.SafeCollector.checkContext(SafeCollector.kt:104)
                                                                                                    	at kotlinx.coroutines.flow.internal.SafeCollector.emit(SafeCollector.kt:83)
                                                                                                    	at kotlinx.coroutines.flow.internal.SafeCollector.emit(SafeCollector.kt:66)
                                                                                                    	at com.google.android.fhir.sync.download.DownloaderImpl$download$2.invokeSuspend(DownloaderImpl.kt:56)
                                                                                                    	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
                                                                                                    	at kotlinx.coroutines.flow.internal.SafeCollector.invokeSuspend(SafeCollector.kt:48)
                                                                                                    	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
                                                                                                    	at kotlinx.coroutines.flow.internal.SafeCollector.invokeSuspend(SafeCollector.kt:48)
                                                                                                    	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
                                                                                                    	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
                                                                                                    	at android.os.Handler.handleCallback(Handler.java:938)
                                                                                                    	at android.os.Handler.dispatchMessage(Handler.java:99)
                                                                                                    	at android.os.Looper.loop(Looper.java:223)
                                                                                                    	at android.app.ActivityThread.main(ActivityThread.java:7656)
                                                                                                    	at java.lang.reflect.Method.invoke(Native Method)
                                                                                                    	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
                                                                                                    	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
                                                                                                    	Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@1662c1a, Dispatchers.Main.immediate]

Libraries used:
org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.2
org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.2

@ellykits
Copy link
Collaborator Author

ellykits commented Oct 6, 2022

This exception when you run SyncJob#run method in a try-catch block. Also happens when you use the catch operator on each emitted flow state.

  coroutineScope {
      syncStateFlow
        .onEach {
            //handle sync state
        }
        .catch { throwable -> Timber.e(throwable) }      
        .launchIn(this)
   }

@omarismail94
Copy link
Contributor

@ellykits @maimoonak @f-odhiambo I created a new PR to use the flow catch feature to handle invalid resources, and added unit tests. Please see PR #1917 . From my experimentation, this should catch errors thrown after resources have been successfully downloaded, but cannot be synced into the db

@jingtang10
Copy link
Collaborator

@aditya-07 is working on a design right now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
effort:small Small effort - 2 days P1 High priority issue type:bug Something isn't working
Projects
Status: In Progress
5 participants