diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SecretShareManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SecretShareManager.kt index 3ef5a963f1..f55cac5dcd 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SecretShareManager.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SecretShareManager.kt @@ -241,7 +241,7 @@ internal class SecretShareManager @Inject constructor( ) try { withContext(coroutineDispatchers.io) { - sendToDeviceTask.executeRetry(params, 3) + sendToDeviceTask.execute(params) } Timber.tag(loggerTag.value) .d("Secret request sent for $secretName to ${cryptoDeviceInfo.shortDebugString()}") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetKeysBackupLastVersionTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetKeysBackupLastVersionTask.kt index e5621c0cb5..4cd6784f0a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetKeysBackupLastVersionTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetKeysBackupLastVersionTask.kt @@ -33,7 +33,7 @@ internal class DefaultGetKeysBackupLastVersionTask @Inject constructor( override suspend fun execute(params: Unit): KeysBackupLastVersionResult { return try { - val keysVersionResult = executeRequest(globalErrorReceiver) { + val keysVersionResult = executeRequest(globalErrorReceiver, canRetry = true) { roomKeysApi.getKeysBackupLastVersion() } KeysBackupLastVersionResult.KeysBackup(keysVersionResult) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetKeysBackupVersionTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetKeysBackupVersionTask.kt index fe1ca29798..3f84582381 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetKeysBackupVersionTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetKeysBackupVersionTask.kt @@ -31,7 +31,7 @@ internal class DefaultGetKeysBackupVersionTask @Inject constructor( ) : GetKeysBackupVersionTask { override suspend fun execute(params: String): KeysVersionResult { - return executeRequest(globalErrorReceiver) { + return executeRequest(globalErrorReceiver, canRetry = true) { roomKeysApi.getKeysBackupVersion(params) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/StoreSessionsDataTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/StoreSessionsDataTask.kt index 47f2578c43..623fc8a6a5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/StoreSessionsDataTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/StoreSessionsDataTask.kt @@ -37,7 +37,7 @@ internal class DefaultStoreSessionsDataTask @Inject constructor( ) : StoreSessionsDataTask { override suspend fun execute(params: StoreSessionsDataTask.Params): BackupKeysResult { - return executeRequest(globalErrorReceiver) { + return executeRequest(globalErrorReceiver, canRetry = true) { roomKeysApi.storeSessionsData( params.version, params.keysBackupData diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/UpdateKeysBackupVersionTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/UpdateKeysBackupVersionTask.kt index 2b3d044ab7..66f4adf524 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/UpdateKeysBackupVersionTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/UpdateKeysBackupVersionTask.kt @@ -36,7 +36,7 @@ internal class DefaultUpdateKeysBackupVersionTask @Inject constructor( ) : UpdateKeysBackupVersionTask { override suspend fun execute(params: UpdateKeysBackupVersionTask.Params) { - return executeRequest(globalErrorReceiver) { + return executeRequest(globalErrorReceiver, canRetry = true) { roomKeysApi.updateKeysBackupVersion(params.version, params.keysBackupVersionBody) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/network/RequestSender.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/network/RequestSender.kt index 2b7a1fdff1..e4670a6142 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/network/RequestSender.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/network/RequestSender.kt @@ -59,6 +59,7 @@ import org.matrix.android.sdk.internal.crypto.tasks.UploadKeysTask import org.matrix.android.sdk.internal.crypto.tasks.UploadSignaturesTask import org.matrix.android.sdk.internal.crypto.tasks.UploadSigningKeysTask import org.matrix.android.sdk.internal.di.MoshiProvider +import org.matrix.android.sdk.internal.network.DEFAULT_REQUEST_RETRY_COUNT import org.matrix.android.sdk.internal.network.parsing.CheckNumberType import org.matrix.android.sdk.internal.session.room.send.SendResponse import timber.log.Timber @@ -87,13 +88,10 @@ internal class RequestSender @Inject constructor( private val getRoomSessionDataTask: GetRoomSessionDataTask, private val moshi: Moshi, ) { - companion object { - const val REQUEST_RETRY_COUNT = 3 - } suspend fun claimKeys(request: Request.KeysClaim): String { val claimParams = ClaimOneTimeKeysForUsersDeviceTask.Params(request.oneTimeKeys) - val response = oneTimeKeysForUsersDeviceTask.executeRetry(claimParams, REQUEST_RETRY_COUNT) + val response = oneTimeKeysForUsersDeviceTask.execute(claimParams) val adapter = MoshiProvider .providesMoshi() .adapter(KeysClaimResponse::class.java) @@ -102,7 +100,7 @@ internal class RequestSender @Inject constructor( suspend fun queryKeys(request: Request.KeysQuery): String { val params = DownloadKeysForUsersTask.Params(request.users, null) - val response = downloadKeysForUsersTask.executeRetry(params, REQUEST_RETRY_COUNT) + val response = downloadKeysForUsersTask.execute(params) val adapter = moshi.adapter(KeysQueryResponse::class.java) return adapter.toJson(response)!! } @@ -111,35 +109,35 @@ internal class RequestSender @Inject constructor( val body = moshi.adapter(Map::class.java).fromJson(request.body)!! val params = UploadKeysTask.Params(body) - val response = uploadKeysTask.executeRetry(params, REQUEST_RETRY_COUNT) + val response = uploadKeysTask.execute(params) val adapter = moshi.adapter(KeysUploadResponse::class.java) return adapter.toJson(response)!! } - suspend fun sendVerificationRequest(request: OutgoingVerificationRequest) { + suspend fun sendVerificationRequest(request: OutgoingVerificationRequest, retryCount: Int = DEFAULT_REQUEST_RETRY_COUNT) { when (request) { - is OutgoingVerificationRequest.InRoom -> sendRoomMessage(request) - is OutgoingVerificationRequest.ToDevice -> sendToDevice(request) + is OutgoingVerificationRequest.InRoom -> sendRoomMessage(request, retryCount) + is OutgoingVerificationRequest.ToDevice -> sendToDevice(request, retryCount) } } - private suspend fun sendRoomMessage(request: OutgoingVerificationRequest.InRoom): SendResponse { - return sendRoomMessage(request.eventType, request.roomId, request.content, request.requestId) + private suspend fun sendRoomMessage(request: OutgoingVerificationRequest.InRoom, retryCount: Int): SendResponse { + return sendRoomMessage(request.eventType, request.roomId, request.content, request.requestId, retryCount) } - suspend fun sendRoomMessage(request: Request.RoomMessage): String { - val sendResponse = sendRoomMessage(request.eventType, request.roomId, request.content, request.requestId) + suspend fun sendRoomMessage(request: Request.RoomMessage, retryCount: Int = DEFAULT_REQUEST_RETRY_COUNT): String { + val sendResponse = sendRoomMessage(request.eventType, request.roomId, request.content, request.requestId, retryCount) val responseAdapter = moshi.adapter(SendResponse::class.java) return responseAdapter.toJson(sendResponse) } - suspend fun sendRoomMessage(eventType: String, roomId: String, content: String, transactionId: String): SendResponse { + suspend fun sendRoomMessage(eventType: String, roomId: String, content: String, transactionId: String, retryCount: Int = DEFAULT_REQUEST_RETRY_COUNT): SendResponse { val paramsAdapter = moshi.adapter(Map::class.java) val jsonContent = paramsAdapter.fromJson(content) val event = Event(eventType, transactionId, jsonContent, roomId = roomId) - val params = SendVerificationMessageTask.Params(event) - return sendVerificationMessageTask.get().executeRetry(params, REQUEST_RETRY_COUNT) + val params = SendVerificationMessageTask.Params(event, retryCount) + return sendVerificationMessageTask.get().execute(params) } suspend fun sendSignatureUpload(request: Request.SignatureUpload): String { @@ -154,7 +152,7 @@ internal class RequestSender @Inject constructor( val paramsAdapter = moshi.adapter>>(Map::class.java) val signatures = paramsAdapter.fromJson(body)!! val params = UploadSignaturesTask.Params(signatures) - val response = signaturesUploadTask.executeRetry(params, REQUEST_RETRY_COUNT) + val response = signaturesUploadTask.execute(params) val responseAdapter = moshi.adapter(SignatureUploadResponse::class.java) return responseAdapter.toJson(response)!! } @@ -183,9 +181,8 @@ internal class RequestSender @Inject constructor( failure = failure, interceptor = interactiveAuthInterceptor, retryBlock = { authUpdate -> - uploadSigningKeysTask.executeRetry( - uploadSigningKeysParams.copy(userAuthParam = authUpdate), - REQUEST_RETRY_COUNT + uploadSigningKeysTask.execute( + uploadSigningKeysParams.copy(userAuthParam = authUpdate) ) } ) != UiaResult.SUCCESS @@ -196,15 +193,15 @@ internal class RequestSender @Inject constructor( } } - suspend fun sendToDevice(request: Request.ToDevice) { - sendToDevice(request.eventType, request.body, request.requestId) + suspend fun sendToDevice(request: Request.ToDevice, retryCount: Int = DEFAULT_REQUEST_RETRY_COUNT) { + sendToDevice(request.eventType, request.body, request.requestId, retryCount) } - suspend fun sendToDevice(request: OutgoingVerificationRequest.ToDevice) { - sendToDevice(request.eventType, request.body, request.requestId) + suspend fun sendToDevice(request: OutgoingVerificationRequest.ToDevice, retryCount: Int = DEFAULT_REQUEST_RETRY_COUNT) { + sendToDevice(request.eventType, request.body, request.requestId, retryCount) } - suspend fun sendToDevice(eventType: String, body: String, transactionId: String) { + private suspend fun sendToDevice(eventType: String, body: String, transactionId: String, retryCount: Int) { val adapter = moshi .newBuilder() .add(CheckNumberType.JSON_ADAPTER_FACTORY) @@ -215,16 +212,16 @@ internal class RequestSender @Inject constructor( val userMap = MXUsersDevicesMap() userMap.join(jsonBody) - val sendToDeviceParams = SendToDeviceTask.Params(eventType, userMap, transactionId) - sendToDeviceTask.executeRetry(sendToDeviceParams, REQUEST_RETRY_COUNT) + val sendToDeviceParams = SendToDeviceTask.Params(eventType, userMap, transactionId, retryCount) + sendToDeviceTask.execute(sendToDeviceParams) } suspend fun getKeyBackupVersion(version: String): KeysVersionResult? = getKeyBackupVersion { - getKeysBackupVersionTask.executeRetry(version, 3) + getKeysBackupVersionTask.execute(version) } suspend fun getKeyBackupLastVersion(): KeysBackupLastVersionResult? = getKeyBackupVersion { - getKeysBackupLastVersionTask.executeRetry(Unit, 3) + getKeysBackupLastVersionTask.execute(Unit) } private inline fun getKeyBackupVersion(block: () -> T?): T? { @@ -261,27 +258,32 @@ internal class RequestSender @Inject constructor( Map::class.java, String::class.java, RoomKeysBackupData::class.java - )) + ) + ) val keys = adapter.fromJson(request.rooms)!! val params = StoreSessionsDataTask.Params(request.version, KeysBackupData(keys)) - val response = backupRoomKeysTask.executeRetry(params, REQUEST_RETRY_COUNT) + val response = backupRoomKeysTask.execute(params) val responseAdapter = moshi.adapter(BackupKeysResult::class.java) return responseAdapter.toJson(response)!! } suspend fun updateBackup(keysBackupVersion: KeysVersionResult, body: UpdateKeysBackupVersionBody) { val params = UpdateKeysBackupVersionTask.Params(keysBackupVersion.version, body) - updateKeysBackupVersionTask.executeRetry(params, REQUEST_RETRY_COUNT) + updateKeysBackupVersionTask.execute(params) } suspend fun downloadBackedUpKeys(version: String, roomId: String, sessionId: String): KeysBackupData { val data = getRoomSessionDataTask.execute(GetRoomSessionDataTask.Params(roomId, sessionId, version)) - return KeysBackupData(mutableMapOf( - roomId to RoomKeysBackupData(mutableMapOf( - sessionId to data - )) - )) + return KeysBackupData( + mutableMapOf( + roomId to RoomKeysBackupData( + mutableMapOf( + sessionId to data + ) + ) + ) + ) } suspend fun downloadBackedUpKeys(version: String, roomId: String): KeysBackupData { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/ClaimOneTimeKeysForUsersDeviceTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/ClaimOneTimeKeysForUsersDeviceTask.kt index a16cb11eae..3474f0af40 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/ClaimOneTimeKeysForUsersDeviceTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/ClaimOneTimeKeysForUsersDeviceTask.kt @@ -39,7 +39,7 @@ internal class DefaultClaimOneTimeKeysForUsersDevice @Inject constructor( override suspend fun execute(params: ClaimOneTimeKeysForUsersDeviceTask.Params): KeysClaimResponse { val body = KeysClaimBody(oneTimeKeys = params.usersDevicesKeyTypesMap) - return executeRequest(globalErrorReceiver) { + return executeRequest(globalErrorReceiver, canRetry = true) { cryptoApi.claimOneTimeKeysForUsersDevices(body) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/DownloadKeysForUsersTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/DownloadKeysForUsersTask.kt index 86f02866ae..70af859ddb 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/DownloadKeysForUsersTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/DownloadKeysForUsersTask.kt @@ -97,7 +97,7 @@ internal class DefaultDownloadKeysForUsers @Inject constructor( ) } else { // No need to chunk, direct request - executeRequest(globalErrorReceiver) { + executeRequest(globalErrorReceiver, canRetry = true) { cryptoApi.downloadKeysForUsers( KeysQueryBody( deviceKeys = params.userIds.associateWith { emptyList() }, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendToDeviceTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendToDeviceTask.kt index fc4d422360..c069e716c3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendToDeviceTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendToDeviceTask.kt @@ -19,6 +19,7 @@ package org.matrix.android.sdk.internal.crypto.tasks import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.internal.crypto.api.CryptoApi import org.matrix.android.sdk.internal.crypto.model.rest.SendToDeviceBody +import org.matrix.android.sdk.internal.network.DEFAULT_REQUEST_RETRY_COUNT import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task @@ -32,7 +33,9 @@ internal interface SendToDeviceTask : Task { // the content to send. Map from user_id to device_id to content dictionary. val contentMap: MXUsersDevicesMap, // the transactionId. If not provided, a transactionId will be created by the task - val transactionId: String? = null + val transactionId: String? = null, + // Number of retry before failing + val retryCount:Int = DEFAULT_REQUEST_RETRY_COUNT ) } @@ -54,7 +57,7 @@ internal class DefaultSendToDeviceTask @Inject constructor( return executeRequest( globalErrorReceiver, canRetry = true, - maxRetriesCount = 3 + maxRetriesCount = params.retryCount ) { cryptoApi.sendToDevice( eventType = params.eventType, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendVerificationMessageTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendVerificationMessageTask.kt index 60c195e449..ec3a39af0a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendVerificationMessageTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendVerificationMessageTask.kt @@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.crypto.tasks import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.room.send.SendState import org.matrix.android.sdk.internal.crypto.CryptoSessionInfoProvider +import org.matrix.android.sdk.internal.network.DEFAULT_REQUEST_RETRY_COUNT import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.room.RoomAPI @@ -29,7 +30,10 @@ import javax.inject.Inject internal interface SendVerificationMessageTask : Task { data class Params( - val event: Event + // The event to sent + val event: Event, + // Number of retry before failing + val retryCount: Int = DEFAULT_REQUEST_RETRY_COUNT ) } @@ -45,7 +49,7 @@ internal class DefaultSendVerificationMessageTask @Inject constructor( val localId = event.eventId!! try { localEchoRepository.updateSendState(localId, event.roomId, SendState.SENDING) - val response = executeRequest(globalErrorReceiver) { + val response = executeRequest(globalErrorReceiver, canRetry = true, maxRetriesCount = params.retryCount) { roomAPI.send( txId = localId, roomId = event.roomId ?: "", diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadKeysTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadKeysTask.kt index 71fbcd5cb3..7710cda29e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadKeysTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadKeysTask.kt @@ -38,7 +38,7 @@ internal class DefaultUploadKeysTask @Inject constructor( override suspend fun execute(params: UploadKeysTask.Params): KeysUploadResponse { Timber.i("## Uploading device keys -> $params.body") - return executeRequest(globalErrorReceiver) { + return executeRequest(globalErrorReceiver, canRetry = true) { cryptoApi.uploadKeys(params.body) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadSigningKeysTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadSigningKeysTask.kt index 0a0df11bd3..17d1b779fb 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadSigningKeysTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadSigningKeysTask.kt @@ -60,7 +60,7 @@ internal class DefaultUploadSigningKeysTask @Inject constructor( } private suspend fun doRequest(uploadQuery: UploadSigningKeysBody) { - val keysQueryResponse = executeRequest(globalErrorReceiver) { + val keysQueryResponse = executeRequest(globalErrorReceiver, canRetry = true) { cryptoApi.uploadSigningKeys(uploadQuery) } if (keysQueryResponse.failures?.isNotEmpty() == true) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/Request.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/Request.kt index 695e7525af..a32c8e87cf 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/Request.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/Request.kt @@ -39,10 +39,13 @@ import java.io.IOException * @param maxRetriesCount the max number of retries * @param requestBlock a suspend lambda to perform the network request */ + +internal const val DEFAULT_REQUEST_RETRY_COUNT = 4 + internal suspend inline fun executeRequest(globalErrorReceiver: GlobalErrorReceiver?, canRetry: Boolean = false, maxDelayBeforeRetry: Long = 32_000L, - maxRetriesCount: Int = 4, + maxRetriesCount: Int = DEFAULT_REQUEST_RETRY_COUNT, noinline requestBlock: suspend () -> DATA): DATA { var currentRetryCount = 0 var currentDelay = 1_000L diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultToDeviceService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultToDeviceService.kt index 1b6883f38a..33e11613e5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultToDeviceService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultToDeviceService.kt @@ -37,13 +37,12 @@ internal class DefaultToDeviceService @Inject constructor( } override suspend fun sendToDevice(eventType: String, contentMap: MXUsersDevicesMap, txnId: String?) { - sendToDeviceTask.executeRetry( + sendToDeviceTask.execute( SendToDeviceTask.Params( eventType = eventType, contentMap = contentMap, transactionId = txnId - ), - 3 + ) ) }