Automatically fix broken registrations/webhooks (#3875)

This commit is contained in:
Joris Pelgröm 2023-09-19 21:38:50 +02:00 committed by GitHub
parent 14907facb4
commit 3915ec6d8f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 31 additions and 11 deletions

View file

@ -49,9 +49,8 @@ class FirebaseCloudMessagingService : FirebaseMessagingService() {
launch {
try {
serverManager.integrationRepository(it.id).updateRegistration(
DeviceRegistration(
pushToken = token
)
deviceRegistration = DeviceRegistration(pushToken = token),
allowReregistration = false
)
} catch (e: Exception) {
Log.e(TAG, "Issue updating token", e)

View file

@ -10,7 +10,7 @@ import kotlinx.coroutines.flow.Flow
interface IntegrationRepository {
suspend fun registerDevice(deviceRegistration: DeviceRegistration)
suspend fun updateRegistration(deviceRegistration: DeviceRegistration)
suspend fun updateRegistration(deviceRegistration: DeviceRegistration, allowReregistration: Boolean = true)
suspend fun getRegistration(): DeviceRegistration
suspend fun deletePreferences()

View file

@ -117,7 +117,7 @@ class IntegrationRepositoryImpl @AssistedInject constructor(
}
}
override suspend fun updateRegistration(deviceRegistration: DeviceRegistration) {
override suspend fun updateRegistration(deviceRegistration: DeviceRegistration, allowReregistration: Boolean) {
val request =
IntegrationRequest(
"update_registration",
@ -126,9 +126,20 @@ class IntegrationRepositoryImpl @AssistedInject constructor(
var causeException: Exception? = null
for (it in server.connection.getApiUrls()) {
try {
if (integrationService.callWebhook(it.toHttpUrlOrNull()!!, request).isSuccessful) {
persistDeviceRegistration(deviceRegistration)
return
val response = integrationService.callWebhook(it.toHttpUrlOrNull()!!, request)
// The server should return a body with the registration, but might return:
// 200 with empty body for broken direct webhook
// 404 for broken cloudhook
// 410 for missing config entry
if (response.isSuccessful) {
if (response.code() == 200 && (response.body()?.contentLength() ?: 0) == 0L) {
throw IllegalStateException("update_registration returned empty body")
} else {
persistDeviceRegistration(deviceRegistration)
return
}
} else if (response.code() == 404 || response.code() == 410) {
throw IllegalStateException("update_registration returned code ${response.code()}")
}
} catch (e: Exception) {
if (causeException == null) causeException = e
@ -137,7 +148,16 @@ class IntegrationRepositoryImpl @AssistedInject constructor(
}
if (causeException != null) {
throw IntegrationException(causeException)
if (allowReregistration && (causeException is IllegalStateException)) {
Log.w(TAG, "Device registration broken, reregistering", causeException)
try {
registerDevice(deviceRegistration)
} catch (e: Exception) {
throw IntegrationException(e)
}
} else {
throw IntegrationException(causeException)
}
} else {
throw IntegrationException("Error calling integration request update_registration")
}

View file

@ -49,10 +49,11 @@ class FirebaseCloudMessagingService : FirebaseMessagingService() {
launch {
try {
serverManager.integrationRepository(it.id).updateRegistration(
DeviceRegistration(
deviceRegistration = DeviceRegistration(
pushToken = token,
pushWebsocket = false
)
),
allowReregistration = false
)
} catch (e: Exception) {
Log.e(TAG, "Issue updating token", e)