Skip to content

feat: foreground service for sending pending messages (WPB-26422)#4971

Open
sbakhtiarov wants to merge 1 commit into
developfrom
feat/pending-messages-service
Open

feat: foreground service for sending pending messages (WPB-26422)#4971
sbakhtiarov wants to merge 1 commit into
developfrom
feat/pending-messages-service

Conversation

@sbakhtiarov

@sbakhtiarov sbakhtiarov commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

https://wearezeta.atlassian.net/browse/WPB-26422

https://wearezeta.atlassian.net/browse/WPB-26422

What's new in this PR?

Issues

Current solution for sending pending messages after restoring Internet connection does not work when application is not in opened by user.

Causes (Optional)

Caused by recent Android restrictions for background work:

  • WorkManager work started when the application is in background is not allowed call setForeground.
  • Without "setForeground" call the work cannot make network calls.

Solutions

Use foreground service which is waiting for connection and retry sending pending messages.

@pull-request-size

Copy link
Copy Markdown

Ups 🫰🟨

This PR is too big. Please try to break it up into smaller PRs.

@sbakhtiarov sbakhtiarov force-pushed the feat/pending-messages-service branch 2 times, most recently from 3e5917a to d2ec791 Compare June 16, 2026 09:58
@codecov

codecov Bot commented Jun 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 36.31579% with 121 lines in your changes missing coverage. Please review.
✅ Project coverage is 48.68%. Comparing base (2d2fb18) to head (d2ec791).

⚠️ Current head d2ec791 differs from pull request most recent head c78640a

Please upload reports for the commit c78640a to get more accurate results.

Files with missing lines Patch % Lines
...droid/services/PendingMessagesForegroundService.kt 23.96% 92 Missing ⚠️
...tion/broadcastreceivers/DynamicReceiversManager.kt 0.00% 22 Missing ⚠️
...otlin/com/wire/android/services/ServicesManager.kt 0.00% 4 Missing ⚠️
...dcastreceivers/PendingMessagesScheduledReceiver.kt 91.66% 0 Missing and 1 partial ⚠️
...ire/android/util/lifecycle/SyncLifecycleManager.kt 91.66% 1 Missing ⚠️
...wire/android/notification/NotificationConstants.kt 0.00% 1 Missing ⚠️

❌ Your patch check has failed because the patch coverage (36.31%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #4971      +/-   ##
===========================================
- Coverage    48.86%   48.68%   -0.18%     
===========================================
  Files          646      646              
  Lines        23215    23319     +104     
  Branches      3563     3568       +5     
===========================================
+ Hits         11343    11353      +10     
- Misses       10813    10917     +104     
+ Partials      1059     1049      -10     
Files with missing lines Coverage Δ
.../kotlin/com/wire/android/GlobalObserversManager.kt 92.10% <100.00%> (+2.45%) ⬆️
...dcastreceivers/PendingMessagesScheduledReceiver.kt 91.66% <91.66%> (ø)
...ire/android/util/lifecycle/SyncLifecycleManager.kt 92.68% <91.66%> (+4.44%) ⬆️
...wire/android/notification/NotificationConstants.kt 17.39% <0.00%> (-0.80%) ⬇️
...otlin/com/wire/android/services/ServicesManager.kt 69.64% <0.00%> (-5.36%) ⬇️
...tion/broadcastreceivers/DynamicReceiversManager.kt 0.00% <0.00%> (ø)
...droid/services/PendingMessagesForegroundService.kt 23.96% <23.96%> (ø)

... and 14 files with indirect coverage changes


Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2d2fb18...c78640a. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment on lines +104 to +107
scope.launch {
run(userId)
stopSelf(startId)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see a problem here - onStartCommand can be executed multiple times, so for instance when you have 2 accounts logged in and both have some pending messages - then ACTION_SENDING_OF_PENDING_MESSAGES_SCHEDULED will be called twice with each userId and here two coroutines will start for each user.
It's using stopSelf with startId, but this logic is designed for sequential or single-task services, it does not understand concurrent operations, like multiple userIds processing side-by-side. If a newer startId completes first, it tells the OS "I am the latest command, we can shut down now," which triggers onDestroy() and risks killing the entire process while the first userId is still being processed, because the scope is cancelled in onDestroy, or the OS may cut off the internet and/or resources for the first coroutine which hasn't finished yet. 🤔
Also, if another onStartCommand appears when some other just called stopSelf but the service hasn't been fully closed, then OS may decide to keep that service, but scope is already closed and dead.

PendingMessagesForegroundSyncHandler(coreLogic, sendPendingMessagesAfterForegroundSync).sendPendingMessagesForCurrentSession(userId)
}

private fun networkAvailability(): Flow<Boolean> = callbackFlow {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we reuse our NetworkStateObserver here instead of implementing and registering another network callback?


private fun createNotification(waitingForConnection: Boolean): Notification =
NotificationCompat.Builder(this, PENDING_MESSAGES_SYNC_CHANNEL_ID)
.setContentText(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We had some issues on huawei devices crashing with "bad foreground notification" when it didn't have setContentTitle as well

@sbakhtiarov sbakhtiarov force-pushed the feat/pending-messages-service branch from d2ec791 to c78640a Compare June 23, 2026 14:25
@github-actions

Copy link
Copy Markdown
Contributor

@sbakhtiarov looks like you are rolling back kalium to a previous commitish.

This means that the PR's target branch (develop) is using a newer version of Kalium, and the changes in this PR will rollback Kalium to an older version.

develop This PR
56eda02b2af8c135318272348bc48af40d71815f 09ea2aeceaf73b8d0f4934722890f60bc1c3f94d

Is this intentional?

@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants