From 85ed92357f5653bfefeae7edf2fe5b613da53231 Mon Sep 17 00:00:00 2001 From: S1m Date: Wed, 24 Nov 2021 00:04:57 +0100 Subject: [PATCH] Fix concurrent (un)registration Using registerQueue and delQueue, lists of connectorTokens --- .../distributor/nextpush/api/ApiUtils.kt | 19 ++++++++++-- .../receivers/RegisterBroadcastReceiver.kt | 31 ++++++++++++++----- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/org/unifiedpush/distributor/nextpush/api/ApiUtils.kt b/app/src/main/java/org/unifiedpush/distributor/nextpush/api/ApiUtils.kt index 5d48a65..63764b3 100644 --- a/app/src/main/java/org/unifiedpush/distributor/nextpush/api/ApiUtils.kt +++ b/app/src/main/java/org/unifiedpush/distributor/nextpush/api/ApiUtils.kt @@ -22,6 +22,9 @@ import java.util.concurrent.TimeUnit private const val TAG = "ApiUtils" +val createQueue = emptyList().toMutableList() +val delQueue = emptyList().toMutableList() + class ApiUtils { private lateinit var mApi: ProviderApi private lateinit var nextcloudAPI: NextcloudAPI @@ -187,6 +190,11 @@ class ApiUtils { override fun onNext(response: ApiResponse) { if (response.success) { Log.d(TAG, "App successfully created.") + /** + * Ignore printed error for SQLiteContstraintException. + * It is printed and not thrown by SQLiteDatabase.java + * So we can't catch it + */ db.registerApp(appName, connectorToken, response.token) } else { Log.d(TAG, "An error occurred while creating the application.") @@ -194,24 +202,27 @@ class ApiUtils { } override fun onError(e: Throwable) { + createQueue.remove(connectorToken) e.printStackTrace() } override fun onComplete() { + createQueue.remove(connectorToken) callback() } }) } - fun deleteApp(context: Context, appToken: String, callback: ()->Unit) { + fun deleteApp(context: Context, connectorToken: String, callback: ()->Unit) { cApi(context) { - cDeleteApp(appToken) { + cDeleteApp(context, connectorToken) { callback() } } } - private fun cDeleteApp(appToken: String, callback: ()->Unit) { + private fun cDeleteApp(context: Context, connectorToken: String, callback: ()->Unit) { + val appToken = getDb(context).getAppToken(connectorToken) mApi.deleteApp(appToken) ?.subscribeOn(Schedulers.newThread()) ?.observeOn(Schedulers.newThread()) @@ -229,10 +240,12 @@ class ApiUtils { } override fun onError(e: Throwable) { + delQueue.remove(connectorToken) e.printStackTrace() } override fun onComplete() { + delQueue.remove(connectorToken) callback() } }) diff --git a/app/src/main/java/org/unifiedpush/distributor/nextpush/receivers/RegisterBroadcastReceiver.kt b/app/src/main/java/org/unifiedpush/distributor/nextpush/receivers/RegisterBroadcastReceiver.kt index 4d15b94..46c568a 100644 --- a/app/src/main/java/org/unifiedpush/distributor/nextpush/receivers/RegisterBroadcastReceiver.kt +++ b/app/src/main/java/org/unifiedpush/distributor/nextpush/receivers/RegisterBroadcastReceiver.kt @@ -6,6 +6,8 @@ import android.content.Intent import android.util.Log import org.unifiedpush.distributor.nextpush.distributor.* import org.unifiedpush.distributor.nextpush.api.ApiUtils +import org.unifiedpush.distributor.nextpush.api.createQueue +import org.unifiedpush.distributor.nextpush.api.delQueue /** * THIS SERVICE IS USED BY OTHER APPS TO REGISTER @@ -25,8 +27,17 @@ class RegisterBroadcastReceiver : BroadcastReceiver() { Log.w(TAG,"Trying to register an app without packageName") return } - ApiUtils().createApp(context!!.applicationContext, application, connectorToken) { - sendEndpoint(context.applicationContext, connectorToken) + if (connectorToken !in createQueue) { + createQueue.add(connectorToken) + ApiUtils().createApp( + context!!.applicationContext, + application, + connectorToken + ) { + sendEndpoint(context.applicationContext, connectorToken) + } + } else { + Log.d(TAG, "Already registering $connectorToken") } } ACTION_UNREGISTER ->{ @@ -36,12 +47,16 @@ class RegisterBroadcastReceiver : BroadcastReceiver() { if (application.isBlank()) { return } - sendUnregistered(context!!.applicationContext, connectorToken) - val db = getDb(context.applicationContext) - val appToken = db.getAppToken(connectorToken) - db.unregisterApp(connectorToken) - ApiUtils().deleteApp(context.applicationContext, appToken) { - Log.d(TAG,"Unregistration is finished") + if (connectorToken !in delQueue) { + delQueue.add(connectorToken) + sendUnregistered(context!!.applicationContext, connectorToken) + ApiUtils().deleteApp(context.applicationContext, connectorToken) { + val db = getDb(context.applicationContext) + db.unregisterApp(connectorToken) + Log.d(TAG, "Unregistration is finished") + } + } else { + Log.d(TAG, "Already deleting $connectorToken") } } }