Fixed
Status Update
Comments
su...@google.com <su...@google.com> #2
Related bug - https://issuetracker.google.com/issues/124511903
Initial loads in LimitOffsetPagingSource run in transaction but subsequent loads do not because of cost of transaction. Loads rely on count query to return correct LoadResult.
If count query is outdated, i.e. large amount of data deleted, LimitOffsetPagingSource can return i.e. empty/wrong data and incorrect itemsBefore/itemsAfter/prevKey/nextKey. This can happen if outdated PagingSource doesn't get invalidated in time.
Initial loads in LimitOffsetPagingSource run in transaction but subsequent loads do not because of cost of transaction. Loads rely on count query to return correct LoadResult.
If count query is outdated, i.e. large amount of data deleted, LimitOffsetPagingSource can return i.e. empty/wrong data and incorrect itemsBefore/itemsAfter/prevKey/nextKey. This can happen if outdated PagingSource doesn't get invalidated in time.
su...@google.com <su...@google.com> #3
Project: platform/frameworks/support
Branch: androidx-main
commit 6bd2347ff259c28b34789c8569b7a298d2a8fd8d
Author: Clara Fok <clarafok@google.com>
Date: Fri Jul 09 12:53:22 2021
Implement Invalid return type in PagingSource
Added third return type for LoadResult sealed class in PagingSource. It
was added as a support feature to handle race scenarios between data loads
and database invalidations, such as if Room's InvalidationTracker does
not propagate invalidation signal to the PagingSource in time and the
PagingSource continues querying an updated database. This can result in
data being loaded onto a stale PageFetcherSnapshot causing duplicated or
missing data. Related bug regarding race scenario in Room b/191806126 .
For example, if data was deleted and items shifted positions,
positionally-keyed paging sources can end up loading duplicated items.
Paging handles this return type by discarding the loaded data and
invalidating the paging source. This will trigger a new paging source to
be generated. This return type is also supported for Paging2 APIs
leveraging PagingSource such as LivePagedList and RxPagedList.
Aside from handling invalid data due to races, this return type can be
leveraged in general where the database or network returns potentially
invalid or stale data that needs to be discarded.
Bug: 192013267
Test: ./gradlew :paging:paging-common:test
Relnote: "A third LoadResult return type LoadResult.Invalid is added to
PagingSource. When a PagingSource.load returns
LoadResult.Invalid, paging will discard the loaded data and
invalidate the PagingSource. This return type is designed to
handle potentially invalid or stale data that can be returned
from the database or network.
For example, if the underlying database gets written into but
the PagingSource does not invalidate in time, it may return
inconsistent results if its implementation depends on the
immutability of the backing dataset it loads from (e.g., LIMIT
OFFSET style db implementations). In this scenario, it is
recommended to check for invalidation after loading and to
return LoadResult.Invalid, which causes Paging to discard any
pending or future load requests to this PagingSource and
invalidate it.
This return type is also supported by Paging2 API that leverages
LivePagedList or RxPagedList. When using a PagingSource with
Paging2's PagedList APIs, the PagedList is immediately detached,
stopping further attempts to load data on this PagedList and
triggers invalidation on the PagingSource.
LoadResult is a sealed class, which means this is a
source-incomptabile change such that use cases directly using
PagingSource.load results will have to handle LoadResult.Invalid
at compile time. For example, Kotlin users leveraging
exhaustive-when to check return type will have to add a check
for Invalid type."
Change-Id: Id6bd3f2544f1ba97a95a0d590353438a95fedf2a
M paging/common/api/current.txt
M paging/common/api/public_plus_experimental_current.txt
M paging/common/api/restricted_current.txt
M paging/common/src/main/kotlin/androidx/paging/PageFetcherSnapshot.kt
M paging/common/src/main/kotlin/androidx/paging/PagedList.kt
M paging/common/src/main/kotlin/androidx/paging/PagingSource.kt
M paging/common/src/test/kotlin/androidx/paging/PageFetcherSnapshotTest.kt
M paging/common/src/test/kotlin/androidx/paging/PageFetcherTest.kt
M paging/common/src/test/kotlin/androidx/paging/PagedListTest.kt
M paging/common/src/test/kotlin/androidx/paging/PagingDataDifferTest.kt
M paging/common/src/test/kotlin/androidx/paging/PagingSourceTest.kt
M paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/v3room/V3RemoteMediator.kt
M paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/v3room/V3RoomViewModel.kt
https://android-review.googlesource.com/1747297
Branch: androidx-main
commit 6bd2347ff259c28b34789c8569b7a298d2a8fd8d
Author: Clara Fok <clarafok@google.com>
Date: Fri Jul 09 12:53:22 2021
Implement Invalid return type in PagingSource
Added third return type for LoadResult sealed class in PagingSource. It
was added as a support feature to handle race scenarios between data loads
and database invalidations, such as if Room's InvalidationTracker does
not propagate invalidation signal to the PagingSource in time and the
PagingSource continues querying an updated database. This can result in
data being loaded onto a stale PageFetcherSnapshot causing duplicated or
missing data. Related bug regarding race scenario in Room
For example, if data was deleted and items shifted positions,
positionally-keyed paging sources can end up loading duplicated items.
Paging handles this return type by discarding the loaded data and
invalidating the paging source. This will trigger a new paging source to
be generated. This return type is also supported for Paging2 APIs
leveraging PagingSource such as LivePagedList and RxPagedList.
Aside from handling invalid data due to races, this return type can be
leveraged in general where the database or network returns potentially
invalid or stale data that needs to be discarded.
Bug: 192013267
Test: ./gradlew :paging:paging-common:test
Relnote: "A third LoadResult return type LoadResult.Invalid is added to
PagingSource. When a PagingSource.load returns
LoadResult.Invalid, paging will discard the loaded data and
invalidate the PagingSource. This return type is designed to
handle potentially invalid or stale data that can be returned
from the database or network.
For example, if the underlying database gets written into but
the PagingSource does not invalidate in time, it may return
inconsistent results if its implementation depends on the
immutability of the backing dataset it loads from (e.g., LIMIT
OFFSET style db implementations). In this scenario, it is
recommended to check for invalidation after loading and to
return LoadResult.Invalid, which causes Paging to discard any
pending or future load requests to this PagingSource and
invalidate it.
This return type is also supported by Paging2 API that leverages
LivePagedList or RxPagedList. When using a PagingSource with
Paging2's PagedList APIs, the PagedList is immediately detached,
stopping further attempts to load data on this PagedList and
triggers invalidation on the PagingSource.
LoadResult is a sealed class, which means this is a
source-incomptabile change such that use cases directly using
PagingSource.load results will have to handle LoadResult.Invalid
at compile time. For example, Kotlin users leveraging
exhaustive-when to check return type will have to add a check
for Invalid type."
Change-Id: Id6bd3f2544f1ba97a95a0d590353438a95fedf2a
M paging/common/api/current.txt
M paging/common/api/public_plus_experimental_current.txt
M paging/common/api/restricted_current.txt
M paging/common/src/main/kotlin/androidx/paging/PageFetcherSnapshot.kt
M paging/common/src/main/kotlin/androidx/paging/PagedList.kt
M paging/common/src/main/kotlin/androidx/paging/PagingSource.kt
M paging/common/src/test/kotlin/androidx/paging/PageFetcherSnapshotTest.kt
M paging/common/src/test/kotlin/androidx/paging/PageFetcherTest.kt
M paging/common/src/test/kotlin/androidx/paging/PagedListTest.kt
M paging/common/src/test/kotlin/androidx/paging/PagingDataDifferTest.kt
M paging/common/src/test/kotlin/androidx/paging/PagingSourceTest.kt
M paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/v3room/V3RemoteMediator.kt
M paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/v3room/V3RoomViewModel.kt
xm...@gmail.com <xm...@gmail.com> #4
Project: platform/frameworks/support
Branch: androidx-main
commit 3882ac8364fd905c9935d38c93f84599009226d6
Author: Clara Fok <clarafok@google.com>
Date: Fri Jul 09 14:17:48 2021
Implement LoadResult.Invalid to handle race
For non-initial loads in LimitOffsetPagingSource, loads will run Room
InvalidationTracker's refreshVersionSync to synchronously check if
tables have been invalidated and notify observers. If invalidated,
load will return LoadResult.Invalid.
Paging3 will handle Invalid return type by invalidating the paging
source and closing the page event flow, such that no more loads will be
attempted on this paging source.
Note that refreshVersionSync is a temporary solution for
LimitOffsetPagingSource to check table invalidation. Another solution
that does not require a transaction is in development. Related b/192269858 .
Bug: 191806126
Test: ./gradlew :room:integration-tests:room-testapp-kotlin:cC
Test: ./gradlew room:room-paging:cC
Change-Id: I48634ab95949bae608374f5156a4edd0500a74a3
M room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/PagingSourceTest.kt
M room/room-paging/build.gradle
M room/room-paging/src/androidTest/kotlin/androidx/room/paging/LimitOffsetPagingSourceTest.kt
M room/room-paging/src/main/kotlin/androidx/room/paging/LimitOffsetPagingSource.kt
https://android-review.googlesource.com/1761130
Branch: androidx-main
commit 3882ac8364fd905c9935d38c93f84599009226d6
Author: Clara Fok <clarafok@google.com>
Date: Fri Jul 09 14:17:48 2021
Implement LoadResult.Invalid to handle race
For non-initial loads in LimitOffsetPagingSource, loads will run Room
InvalidationTracker's refreshVersionSync to synchronously check if
tables have been invalidated and notify observers. If invalidated,
load will return LoadResult.Invalid.
Paging3 will handle Invalid return type by invalidating the paging
source and closing the page event flow, such that no more loads will be
attempted on this paging source.
Note that refreshVersionSync is a temporary solution for
LimitOffsetPagingSource to check table invalidation. Another solution
that does not require a transaction is in development. Related
Bug: 191806126
Test: ./gradlew :room:integration-tests:room-testapp-kotlin:cC
Test: ./gradlew room:room-paging:cC
Change-Id: I48634ab95949bae608374f5156a4edd0500a74a3
M room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/PagingSourceTest.kt
M room/room-paging/build.gradle
M room/room-paging/src/androidTest/kotlin/androidx/room/paging/LimitOffsetPagingSourceTest.kt
M room/room-paging/src/main/kotlin/androidx/room/paging/LimitOffsetPagingSource.kt
su...@google.com <su...@google.com> #5
If a worker is running and you try to cancel it, you will get an onStopped call inside your Worker.
xm...@gmail.com <xm...@gmail.com> #6
Good function, thank you
hu...@gmail.com <hu...@gmail.com> #7
I use WorkManager.getInstance().cancelWorkById() to cancel a running task, but it is neither stopped nor call onStopped(). I am using version 1.0.0-alpha08. Is there any change breaking this feature?
su...@google.com <su...@google.com> #8
Can you please share the code?
ra...@google.com <ra...@google.com> #9
Can you please post a sample app that we can use to reproduce this problem ?
hu...@gmail.com <hu...@gmail.com> #10
try the source code I attached
ra...@google.com <ra...@google.com> #11
I am unable to reproduce this problem locally.
Here are my logs:
WorkSpec W Backoff delay duration less than minimum value
NetworkSecurityConfig D No Network Security Config specified, using platform default
System.out I ---------------------------------------------------- onStopped: true
zygote64 I Do partial code cache collection, code=60KB, data=58KB
I After code cache collection, code=60KB, data=58KB
I Increasing code cache capacity to 256KB
DownloadWorker D Download canceled
WorkerWrapper I Work interrupted for Work [ id=a1a95295-7152-46bf-8e56-81e1d7f72a75, tags={ vn.hunghd.downloader.DownloadWorker } ]
WorkSpec W Backoff delay duration less than minimum value
zygote64 I Compiler allocated 6MB to compile void android.view.ViewRootImpl.performTraversals()
DownloadWorker D Content-Type = application/pdf
D Content-Length = 8620159
D fileName = Android-Programming-Cookbook.pdf
System.out I ---------------------------------------------------- onStopped: true
zygote64 I Do full code cache collection, code=109KB, data=120KB
I After code cache collection, code=109KB, data=96KB
DownloadWorker D Download canceled
WorkerWrapper I Work interrupted for Work [ id=d3df7224-deaa-40d6-a7d1-ff4b827fac63, tags={ vn.hunghd.downloader.DownloadWorker } ]
WorkSpec W Backoff delay duration less than minimum value
DownloadWorker D Content-Type = application/pdf
D Content-Length = 2017026
D fileName = iOS_Programming_Guide.pdf
System.out I ---------------------------------------------------- onStopped: true
DownloadWorker D Download canceled
WorkerWrapper I Work interrupted for Work [ id=cee67199-c137-45df-9193-a38e26f45a68, tags={ vn.hunghd.downloader.DownloadWorker } ]
zygote64 I Do partial code cache collection, code=119KB, data=107KB
I After code cache collection, code=119KB, data=107KB
I Increasing code cache capacity to 512KB
The onStopped method is getting called. Sometimes the download finishes before you have have a chance to cancel.
Here are my logs:
WorkSpec W Backoff delay duration less than minimum value
NetworkSecurityConfig D No Network Security Config specified, using platform default
System.out I ---------------------------------------------------- onStopped: true
zygote64 I Do partial code cache collection, code=60KB, data=58KB
I After code cache collection, code=60KB, data=58KB
I Increasing code cache capacity to 256KB
DownloadWorker D Download canceled
WorkerWrapper I Work interrupted for Work [ id=a1a95295-7152-46bf-8e56-81e1d7f72a75, tags={ vn.hunghd.downloader.DownloadWorker } ]
WorkSpec W Backoff delay duration less than minimum value
zygote64 I Compiler allocated 6MB to compile void android.view.ViewRootImpl.performTraversals()
DownloadWorker D Content-Type = application/pdf
D Content-Length = 8620159
D fileName = Android-Programming-Cookbook.pdf
System.out I ---------------------------------------------------- onStopped: true
zygote64 I Do full code cache collection, code=109KB, data=120KB
I After code cache collection, code=109KB, data=96KB
DownloadWorker D Download canceled
WorkerWrapper I Work interrupted for Work [ id=d3df7224-deaa-40d6-a7d1-ff4b827fac63, tags={ vn.hunghd.downloader.DownloadWorker } ]
WorkSpec W Backoff delay duration less than minimum value
DownloadWorker D Content-Type = application/pdf
D Content-Length = 2017026
D fileName = iOS_Programming_Guide.pdf
System.out I ---------------------------------------------------- onStopped: true
DownloadWorker D Download canceled
WorkerWrapper I Work interrupted for Work [ id=cee67199-c137-45df-9193-a38e26f45a68, tags={ vn.hunghd.downloader.DownloadWorker } ]
zygote64 I Do partial code cache collection, code=119KB, data=107KB
I After code cache collection, code=119KB, data=107KB
I Increasing code cache capacity to 512KB
The onStopped method is getting called. Sometimes the download finishes before you have have a chance to cancel.
su...@google.com <su...@google.com> #12
One thing to note is that your UI isn't always very responsive. There have been times where I have clicked the cancel buttons multiple times and not have the onClickListener invoked. I suspect this has something to do with your local broadcast model but I haven't investigated it further. This may be the reason you aren't seeing the cancelation; the job simply finishes before it can be canceled.
ri...@disneystreaming.com <ri...@disneystreaming.com> #13
I have a similar issue where onStopped is not called. I am also able to reproduce the issue using the attached project.
From what I can determine, the call is processed via a ConstraintTrackingWorker which does not call thru to the delegate's `onStopped` method.
Component used: WorkManager
Version used: 1.0.0-alpha08
Devices/Android versions reproduced on: Nexus 6p, Pixel
From what I can determine, the call is processed via a ConstraintTrackingWorker which does not call thru to the delegate's `onStopped` method.
Component used: WorkManager
Version used: 1.0.0-alpha08
Devices/Android versions reproduced on: Nexus 6p, Pixel
su...@google.com <su...@google.com> #14
Oh I see, the problem is only on certain API levels in that case. Sorry, I didn't realize that - I thought it was happening on all API levels.
su...@google.com <su...@google.com> #15
Actually this bug is fixed; I'll create a new bug for the issue you reported: https://issuetracker.google.com/114125093
ri...@disneystreaming.com <ri...@disneystreaming.com> #16
thx
Description
Version used: 1.0.0-alpha06
Devices/Android versions reproduced on: Samsung S8+ 8.0
When i uploading a file use a work, do uploading code like okhttp upload file, i wanna cancel this uploading work, because the okhttp support cancel the uploading (okttp3.Call.cancel()), so work class should have cancel function, the implement can cancel the job