Skip to content

Commit

Permalink
AND-18021: Add Worker pending list logs
Browse files Browse the repository at this point in the history
  • Loading branch information
kh-mega committed Jan 24, 2024
1 parent 4730989 commit ec8698c
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 37 deletions.
Original file line number Diff line number Diff line change
@@ -1,22 +1,33 @@
package mega.privacy.android.app.service.push

import android.content.Context
import androidx.work.Data
import androidx.work.WorkManager
import com.google.android.gms.tasks.Task
import com.google.firebase.messaging.FirebaseMessaging
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.tasks.await
import mega.privacy.android.app.data.extensions.enqueuePushMessage
import mega.privacy.android.app.data.extensions.enqueueUniqueWorkNewToken
import mega.privacy.android.app.utils.Constants.DEVICE_ANDROID
import mega.privacy.android.domain.qualifier.ApplicationScope
import timber.log.Timber
import java.util.concurrent.Executors
import javax.inject.Inject

@AndroidEntryPoint
class MegaMessageService : FirebaseMessagingService() {

@Inject
@ApplicationScope
lateinit var applicationScope: CoroutineScope

@Inject
lateinit var workManager: WorkManager

override fun onDestroy() {
Timber.d("onDestroy")
super.onDestroy()
Expand All @@ -27,15 +38,17 @@ class MegaMessageService : FirebaseMessagingService() {

val workerData = remoteMessage.data.toWorkerData()

WorkManager.getInstance(this)
.enqueuePushMessage(workerData)
applicationScope.launch {
workManager.enqueuePushMessage(workerData)
}
}

override fun onNewToken(token: String) {
Timber.d("New token: $token")

WorkManager.getInstance(this)
.enqueueUniqueWorkNewToken(token, DEVICE_ANDROID)
applicationScope.launch {
workManager.enqueueUniqueWorkNewToken(token, DEVICE_ANDROID)
}
}

/**
Expand All @@ -49,28 +62,24 @@ class MegaMessageService : FirebaseMessagingService() {
.build()

companion object {
/**
* Mutex to avoid multiple calls to getToken.
*/
private val mutex = Mutex()

/**
* Request push service token, then register it in API as an identifier of the device.
*
* @param context Context.
*/
@JvmStatic
fun getToken(context: Context) {
suspend fun getToken(workManager: WorkManager) {
//project number from google-service.json
Executors.newFixedThreadPool(1).submit {
FirebaseMessaging.getInstance().token.addOnCompleteListener { task: Task<String> ->
if (!task.isSuccessful) {
Timber.w("Get token failed.")
return@addOnCompleteListener
}

// Get new Instance ID token
val token = task.result
Timber.d("Get token: $token")
mutex.withLock {
val token = FirebaseMessaging.getInstance().token.await()

WorkManager.getInstance(context)
.enqueueUniqueWorkNewToken(token, DEVICE_ANDROID)
}
token?.let {
Timber.d("Get token succeeded")
workManager.enqueueUniqueWorkNewToken(token, DEVICE_ANDROID)
} ?: Timber.w("Get token failed.")
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@ import androidx.work.OutOfQuotaPolicy
import androidx.work.WorkManager
import mega.privacy.android.app.fcm.NewTokenWorker
import mega.privacy.android.app.fcm.PushMessageWorker
import mega.privacy.android.data.facade.debugWorkInfo

/**
* Enqueues a [PushMessageWorker] request to manage a push notification.
*
* @param data [Data] containing the push information.
*/
fun WorkManager.enqueuePushMessage(data: Data) {
suspend fun WorkManager.enqueuePushMessage(data: Data) {
debugWorkInfo()

enqueue(
OneTimeWorkRequestBuilder<PushMessageWorker>()
.setInputData(data)
Expand All @@ -28,7 +31,9 @@ fun WorkManager.enqueuePushMessage(data: Data) {
* @param newToken Required token for register pushes.
* @param deviceType Type of device.
*/
fun WorkManager.enqueueUniqueWorkNewToken(newToken: String, deviceType: Int) {
suspend fun WorkManager.enqueueUniqueWorkNewToken(newToken: String, deviceType: Int) {
debugWorkInfo()

enqueueUniqueWork(
NewTokenWorker.WORK_NAME,
ExistingWorkPolicy.REPLACE,
Expand All @@ -42,4 +47,4 @@ fun WorkManager.enqueueUniqueWorkNewToken(newToken: String, deviceType: Int) {
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
.build()
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ import androidx.navigation.NavDestination
import androidx.navigation.NavOptions
import androidx.navigation.fragment.NavHostFragment
import androidx.viewpager2.widget.ViewPager2
import androidx.work.WorkManager
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.appbar.MaterialToolbar
import com.google.android.material.bottomnavigation.BottomNavigationItemView
Expand All @@ -83,6 +84,7 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.kotlin.addTo
import io.reactivex.rxjava3.schedulers.Schedulers
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.launch
Expand Down Expand Up @@ -300,6 +302,7 @@ import mega.privacy.android.domain.exception.QuotaExceededMegaException
import mega.privacy.android.domain.exception.chat.IAmOnAnotherCallException
import mega.privacy.android.domain.exception.chat.MeetingEndedException
import mega.privacy.android.domain.exception.node.ForeignNodeException
import mega.privacy.android.domain.qualifier.ApplicationScope
import mega.privacy.android.domain.qualifier.IoDispatcher
import mega.privacy.android.domain.usecase.GetChatRoomUseCase
import mega.privacy.android.domain.usecase.chat.HasArchivedChatsUseCase
Expand Down Expand Up @@ -452,6 +455,13 @@ class ManagerActivity : TransfersManagementActivity(), MegaRequestListenerInterf
@Inject
lateinit var syncNavigator: SyncNavigator

@Inject
lateinit var workManager: WorkManager

@Inject
@ApplicationScope
lateinit var applicationScope: CoroutineScope

//GET PRO ACCOUNT PANEL
private lateinit var getProLayout: LinearLayout
private lateinit var getProText: TextView
Expand Down Expand Up @@ -1385,7 +1395,9 @@ class ManagerActivity : TransfersManagementActivity(), MegaRequestListenerInterf
megaApi.invalidateCache()
}
dbH.setInvalidateSdkCache(false)
MegaMessageService.getToken(this)
applicationScope.launch {
MegaMessageService.getToken(workManager)
}
userInfoViewModel.getUserInfo()
preloadPayment()
megaApi.isGeolocationEnabled(this)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import androidx.work.OneTimeWorkRequest
import androidx.work.PeriodicWorkRequest
import androidx.work.WorkInfo
import androidx.work.WorkManager
import androidx.work.WorkQuery
import androidx.work.await
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.merge
import mega.privacy.android.data.gateway.WorkManagerGateway
Expand Down Expand Up @@ -41,6 +43,8 @@ internal class WorkManagerFacade @Inject constructor(
) : WorkManagerGateway {

override suspend fun enqueueDeleteOldestCompletedTransfersWorkRequest() {
workManager.debugWorkInfo()

val workRequest =
OneTimeWorkRequest.Builder(DeleteOldestCompletedTransfersWorker::class.java)
.addTag(DeleteOldestCompletedTransfersWorker.DELETE_OLDEST_TRANSFERS_WORKER_TAG)
Expand All @@ -54,7 +58,9 @@ internal class WorkManagerFacade @Inject constructor(
)
}

override fun enqueueDownloadsWorkerRequest() {
override suspend fun enqueueDownloadsWorkerRequest() {
workManager.debugWorkInfo()

val request = OneTimeWorkRequest.Builder(DownloadsWorker::class.java)
.addTag(DownloadsWorker.SINGLE_DOWNLOAD_TAG)
.build()
Expand All @@ -69,6 +75,8 @@ internal class WorkManagerFacade @Inject constructor(
override suspend fun startCameraUploads() {
// Check if CU periodic worker is working. If yes, then don't start a single one
if (!checkWorkerRunning(CAMERA_UPLOAD_TAG)) {
workManager.debugWorkInfo()

Timber.d("No CU periodic process currently running, proceed with one time request")
val cameraUploadWorkRequest = OneTimeWorkRequest.Builder(
CameraUploadsWorker::class.java
Expand Down Expand Up @@ -111,6 +119,9 @@ internal class WorkManagerFacade @Inject constructor(

override suspend fun scheduleCameraUploads() {
scheduleCameraUploadSyncActiveHeartbeat()

workManager.debugWorkInfo()

// periodic work that runs during the last 10 minutes of every one hour period
val cameraUploadWorkRequest = PeriodicWorkRequest.Builder(
CameraUploadsWorker::class.java,
Expand Down Expand Up @@ -139,6 +150,8 @@ internal class WorkManagerFacade @Inject constructor(
* Schedule camera uploads active heartbeat worker
*/
private suspend fun scheduleCameraUploadSyncActiveHeartbeat() {
workManager.debugWorkInfo()

// periodic work that runs during the last 10 minutes of every half an hour period
val cuSyncActiveHeartbeatWorkRequest = PeriodicWorkRequest.Builder(
SyncHeartbeatCameraUploadWorker::class.java,
Expand Down Expand Up @@ -223,3 +236,17 @@ internal class WorkManagerFacade @Inject constructor(
override fun monitorDownloadsStatusInfo() =
workManager.getWorkInfosByTagFlow(DownloadsWorker.SINGLE_DOWNLOAD_TAG)
}

/**
* Prints the list of pending [WorkInfo] in the log.
*/
suspend fun WorkManager.debugWorkInfo() {
getWorkInfosFlow(
WorkQuery.fromStates(
WorkInfo.State.ENQUEUED,
)
).firstOrNull()
?.map { it.tags }
?.let { Timber.d("Worker pending list: $it") }
?: Timber.d("Worker pending list: empty")
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ interface WorkManagerGateway {
/**
* Enqueue unique work request to start download worker to monitor the download transfers as a foreground service
*/
fun enqueueDownloadsWorkerRequest()
suspend fun enqueueDownloadsWorkerRequest()

/**
* Queue a one time work request of camera upload to upload immediately.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ internal class DefaultTransfersRepository @Inject constructor(
workerManagerGateway.enqueueDeleteOldestCompletedTransfersWorkRequest()
}

override fun startDownloadWorker() {
override suspend fun startDownloadWorker() = withContext(ioDispatcher) {
workerManagerGateway.enqueueDownloadsWorkerRequest()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import androidx.work.WorkManager
import androidx.work.WorkerParameters
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import mega.privacy.android.data.facade.debugWorkInfo
import mega.privacy.android.domain.usecase.camerauploads.IsCameraUploadsEnabledUseCase
import mega.privacy.android.domain.usecase.workers.StartCameraUploadUseCase
import timber.log.Timber
Expand Down Expand Up @@ -46,6 +47,8 @@ internal class NewMediaWorker @AssistedInject constructor(
if (isForce
|| isQueuedOrRunning(workManager)
) {
workManager.debugWorkInfo()

val photoCheckBuilder =
OneTimeWorkRequest.Builder(NewMediaWorker::class.java)
photoCheckBuilder.setConstraints(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1087,10 +1087,11 @@ class DefaultTransfersRepositoryTest {
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
inner class WorkerTests {
@Test
fun `test that workerManagerGateway enqueueDownloadsWorkerRequest is called when startDownloadWorker is called`() {
underTest.startDownloadWorker()
verify(workerManagerGateway).enqueueDownloadsWorkerRequest()
}
fun `test that workerManagerGateway enqueueDownloadsWorkerRequest is called when startDownloadWorker is called`() =
runTest {
underTest.startDownloadWorker()
verify(workerManagerGateway).enqueueDownloadsWorkerRequest()
}

@ParameterizedTest
@EnumSource(WorkInfo.State::class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ interface TransferRepository {
/**
* Starts the download worker to monitor the download transfers as a foreground service
*/
fun startDownloadWorker()
suspend fun startDownloadWorker()

/**
* Monitors transfers finished.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ class StartDownloadWorkerUseCase @Inject constructor(
* Invoke.
*
*/
operator fun invoke() = transferRepository.startDownloadWorker()
}
suspend operator fun invoke() = transferRepository.startDownloadWorker()
}

0 comments on commit ec8698c

Please sign in to comment.