Improve code again

This commit is contained in:
Benoit Marty 2025-11-19 17:53:12 +01:00
parent 477b15428e
commit a40988894b
7 changed files with 48 additions and 35 deletions

View file

@ -0,0 +1,10 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.push.impl.workmanager
class DataForWorkManagerIsTooBig : Exception()

View file

@ -29,9 +29,9 @@ class SyncNotificationWorkManagerRequest(
private val workerDataConverter: WorkerDataConverter,
private val buildVersionSdkIntProvider: BuildVersionSdkIntProvider,
) : WorkManagerRequest {
override fun build(): List<Result<WorkRequest>> {
override fun build(): Result<List<WorkRequest>> {
if (notificationEventRequests.isEmpty()) {
return listOf(Result.failure(InvalidParameterException("notificationEventRequests cannot be empty")))
return Result.failure(InvalidParameterException("notificationEventRequests cannot be empty"))
}
Timber.d("Scheduling ${notificationEventRequests.size} notification requests with WorkManager for $sessionId")
return workerDataConverter.serialize(notificationEventRequests).map {

View file

@ -24,21 +24,22 @@ import timber.log.Timber
class WorkerDataConverter(
private val json: JsonProvider,
) {
fun serialize(notificationEventRequests: List<NotificationEventRequest>): List<Result<Data>> {
fun serialize(notificationEventRequests: List<NotificationEventRequest>): Result<List<Data>> {
// First try to serialize all requests at once. In the vast majority of cases this will work.
return serializeRequests(notificationEventRequests)
.fold(
onSuccess = {
listOf(Result.success(it))
},
onFailure = {
// Perform serialization on sublists, workDataOf may have failed because of size limit
.map { listOf(it) }
.recoverCatching {
if (it is DataForWorkManagerIsTooBig) {
// Perform serialization on sublists, workDataOf have failed because of size limit
Timber.w(it, "Failed to serialize ${notificationEventRequests.size} notification requests, trying with chunks of $CHUNK_SIZE.")
notificationEventRequests.chunked(CHUNK_SIZE).map { chunk ->
serializeRequests(chunk)
// TODO Do not split rooms
notificationEventRequests.chunked(CHUNK_SIZE).mapNotNull { chunk ->
serializeRequests(chunk).getOrNull()
}
},
)
} else {
throw it
}
}
}
private fun serializeRequests(notificationEventRequests: List<NotificationEventRequest>): Result<Data> {
@ -48,7 +49,11 @@ class WorkerDataConverter(
}
.mapCatchingExceptions { str ->
// Note: workDataOf can fail if the data is too large
workDataOf(REQUESTS_KEY to str)
try {
workDataOf(REQUESTS_KEY to str)
} catch (_: IllegalStateException) {
throw DataForWorkManagerIsTooBig()
}
}
}