Avoid concurrent (un)registration

With synchronized MutableLists
This commit is contained in:
sim 2023-09-05 21:50:17 +02:00
parent 08aca7b5bd
commit 006ecb894c
1 changed files with 57 additions and 34 deletions

View File

@ -27,9 +27,6 @@ import kotlin.concurrent.schedule
* THIS SERVICE IS USED BY OTHER APPS TO REGISTER * THIS SERVICE IS USED BY OTHER APPS TO REGISTER
*/ */
private val createQueue = emptyList<String>().toMutableList()
private val delQueue = emptyList<String>().toMutableList()
private const val WAKE_LOCK_TAG = "NextPush:RegisterBroadcastReceiver:lock" private const val WAKE_LOCK_TAG = "NextPush:RegisterBroadcastReceiver:lock"
class RegisterBroadcastReceiver : BroadcastReceiver() { class RegisterBroadcastReceiver : BroadcastReceiver() {
@ -51,49 +48,53 @@ class RegisterBroadcastReceiver : BroadcastReceiver() {
Log.w(TAG, "Trying to register an app without packageName") Log.w(TAG, "Trying to register an app without packageName")
return return
} }
when (checkToken(context, connectorToken, application)) { if (!createQueue.containsTokenElseAdd(connectorToken)) {
TOKEN_REGISTERED_OK -> sendEndpoint(context, connectorToken) when (checkToken(context, connectorToken, application)) {
TOKEN_NOK -> sendRegistrationFailed( TOKEN_REGISTERED_OK -> {
context, sendEndpoint(context, connectorToken)
application, createQueue.removeToken(connectorToken)
connectorToken }
) TOKEN_NOK -> {
TOKEN_NEW -> {
val appName = context.getApplicationName(application) ?: application
if (!isConnected(context)) {
sendRegistrationFailed( sendRegistrationFailed(
context, context,
application, application,
connectorToken, connectorToken
message = "NextPush is not connected"
) )
Toast.makeText( createQueue.removeToken(connectorToken)
context,
"Cannot register $appName, NextPush is not connected.",
Toast.LENGTH_SHORT
).show()
return
} }
if (connectorToken !in createQueue) { TOKEN_NEW -> {
createQueue.add(connectorToken) val appName = context.getApplicationName(application) ?: application
delayRemove(createQueue, connectorToken) if (!isConnected(context)) {
sendRegistrationFailed(
context,
application,
connectorToken,
message = "NextPush is not connected"
)
Toast.makeText(
context,
"Cannot register $appName, NextPush is not connected.",
Toast.LENGTH_SHORT
).show()
return
}
createApp( createApp(
context, context,
application, application,
connectorToken connectorToken
) { ) {
sendEndpoint(context, connectorToken) sendEndpoint(context, connectorToken)
createQueue.remove(connectorToken) createQueue.removeToken(connectorToken)
Toast.makeText( Toast.makeText(
context, context,
"$appName registered.", "$appName registered.",
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
} }
} else {
Log.d(TAG, "Already registering this token")
} }
} }
} else {
Log.d(TAG, "Already registering this token")
} }
} }
ACTION_UNREGISTER -> { ACTION_UNREGISTER -> {
@ -101,13 +102,11 @@ class RegisterBroadcastReceiver : BroadcastReceiver() {
val connectorToken = intent.getStringExtra(EXTRA_TOKEN) ?: "" val connectorToken = intent.getStringExtra(EXTRA_TOKEN) ?: ""
getDb(context).getPackageName(connectorToken) ?: return getDb(context).getPackageName(connectorToken) ?: return
if (connectorToken !in delQueue) { if (!delQueue.containsTokenElseAdd(connectorToken)) {
delQueue.add(connectorToken)
delayRemove(delQueue, connectorToken)
try { try {
deleteApp(context, connectorToken) { deleteApp(context, connectorToken) {
Log.d(TAG, "Unregistration is finished") Log.d(TAG, "Unregistration is finished")
delQueue.remove(connectorToken) delQueue.removeToken(connectorToken)
} }
} catch (e: Exception) { } catch (e: Exception) {
Log.d(TAG, "Could not delete app") Log.d(TAG, "Could not delete app")
@ -124,9 +123,33 @@ class RegisterBroadcastReceiver : BroadcastReceiver() {
} }
} }
private fun delayRemove(list: MutableList<String>, token: String) { private fun MutableList<String>.containsTokenElseAdd(connectorToken: String): Boolean {
Timer().schedule(1_000L /* 1sec */) { return synchronized(this) {
list.remove(token) if (connectorToken !in this) {
Log.d(TAG, "Token: $this")
this.add(connectorToken)
delayRemove(this, connectorToken)
false
} else {
true
}
} }
} }
private fun MutableList<String>.removeToken(connectorToken: String) {
synchronized(this) {
this.remove(connectorToken)
}
}
private fun delayRemove(list: MutableList<String>, token: String) {
Timer().schedule(1_000L /* 1sec */) {
list.removeToken(token)
}
}
companion object {
private val createQueue = emptyList<String>().toMutableList()
private val delQueue = emptyList<String>().toMutableList()
}
} }