minimizes race condition when pausing and restarting relay connections

This commit is contained in:
Vitor Pamplona
2023-11-07 17:38:59 -05:00
parent b25f346370
commit 853dcb2127
4 changed files with 47 additions and 48 deletions
@@ -49,8 +49,7 @@ object ServiceManager {
start() start()
} }
@Synchronized private fun start() {
fun start() {
Log.d("ServiceManager", "Pre Starting Relay Services $isStarted $account") Log.d("ServiceManager", "Pre Starting Relay Services $isStarted $account")
if (isStarted && account != null) { if (isStarted && account != null) {
return return
@@ -105,7 +104,7 @@ object ServiceManager {
} }
} }
fun pause() { private fun pause() {
Log.d("ServiceManager", "Pausing Relay Services") Log.d("ServiceManager", "Pausing Relay Services")
NostrAccountDataSource.stop() NostrAccountDataSource.stop()
@@ -153,19 +152,42 @@ object ServiceManager {
} }
} }
// This method keeps the pause/start in a Syncronized block to
// avoid concurrent pauses and starts.
@Synchronized
fun forceRestart(account: Account? = null, start: Boolean = true, pause: Boolean = true) {
if (pause) {
pause()
}
if (start) {
if (account != null) {
start(account)
} else {
start()
}
}
}
fun restartIfDifferentAccount(account: Account) { fun restartIfDifferentAccount(account: Account) {
if (this.account != account) { if (this.account != account) {
pause() forceRestart(account, true, true)
start(account)
} }
} }
fun forceRestartIfItShould() { fun forceRestartIfItShould() {
if (shouldPauseService) { if (shouldPauseService) {
pause() forceRestart(null, true, true)
start()
} }
} }
fun justStart() {
forceRestart(null, true, false)
}
fun pauseForGood() {
forceRestart(null, false, true)
}
} }
object SingletonDiskCache { object SingletonDiskCache {
@@ -1278,7 +1278,7 @@ object LocalCache {
childrenToBeRemoved.addAll(it.removeAllChildNotes()) childrenToBeRemoved.addAll(it.removeAllChildNotes())
} }
removeChildrenOf(childrenToBeRemoved) removeFromCache(childrenToBeRemoved)
if (toBeRemoved.size > 100 || it.value.notes.size > 100) { if (toBeRemoved.size > 100 || it.value.notes.size > 100) {
println("PRUNE: ${toBeRemoved.size} messages removed from ${it.value.toBestDisplayName()}. ${it.value.notes.size} kept") println("PRUNE: ${toBeRemoved.size} messages removed from ${it.value.toBestDisplayName()}. ${it.value.notes.size} kept")
@@ -1297,7 +1297,7 @@ object LocalCache {
childrenToBeRemoved.addAll(it.removeAllChildNotes()) childrenToBeRemoved.addAll(it.removeAllChildNotes())
} }
removeChildrenOf(childrenToBeRemoved) removeFromCache(childrenToBeRemoved)
if (toBeRemoved.size > 1) { if (toBeRemoved.size > 1) {
println("PRUNE: ${toBeRemoved.size} private messages with ${userPair.value.toBestDisplayName()} removed. ${it.roomMessages.size} kept") println("PRUNE: ${toBeRemoved.size} private messages with ${userPair.value.toBestDisplayName()} removed. ${it.roomMessages.size} kept")
@@ -1328,7 +1328,7 @@ object LocalCache {
childrenToBeRemoved.addAll(it.removeAllChildNotes()) childrenToBeRemoved.addAll(it.removeAllChildNotes())
} }
removeChildrenOf(childrenToBeRemoved) removeFromCache(childrenToBeRemoved)
if (toBeRemoved.size > 1) { if (toBeRemoved.size > 1) {
println("PRUNE: ${toBeRemoved.size} old version of addressables removed.") println("PRUNE: ${toBeRemoved.size} old version of addressables removed.")
@@ -1357,7 +1357,7 @@ object LocalCache {
childrenToBeRemoved.addAll(it.removeAllChildNotes()) childrenToBeRemoved.addAll(it.removeAllChildNotes())
} }
removeChildrenOf(childrenToBeRemoved) removeFromCache(childrenToBeRemoved)
toBeRemoved.forEach { toBeRemoved.forEach {
it.replyTo?.forEach { masterNote -> it.replyTo?.forEach { masterNote ->
@@ -1380,22 +1380,24 @@ object LocalCache {
masterNote.clearEOSE() // allows reloading of these events if needed masterNote.clearEOSE() // allows reloading of these events if needed
} }
if (note.event is LnZapEvent) { val noteEvent = note.event
(note.event as LnZapEvent).zappedAuthor().mapNotNull {
if (noteEvent is LnZapEvent) {
noteEvent.zappedAuthor().forEach {
val author = getUserIfExists(it) val author = getUserIfExists(it)
author?.removeZap(note) author?.removeZap(note)
author?.clearEOSE() author?.clearEOSE()
} }
} }
if (note.event is LnZapRequestEvent) { if (noteEvent is LnZapRequestEvent) {
(note.event as LnZapRequestEvent).zappedAuthor().mapNotNull { noteEvent.zappedAuthor().mapNotNull {
val author = getUserIfExists(it) val author = getUserIfExists(it)
author?.removeZap(note) author?.removeZap(note)
author?.clearEOSE() author?.clearEOSE()
} }
} }
if (note.event is ReportEvent) { if (noteEvent is ReportEvent) {
(note.event as ReportEvent).reportedAuthor().mapNotNull { noteEvent.reportedAuthor().mapNotNull {
val author = getUserIfExists(it.key) val author = getUserIfExists(it.key)
author?.removeReport(note) author?.removeReport(note)
author?.clearEOSE() author?.clearEOSE()
@@ -1405,31 +1407,7 @@ object LocalCache {
notes.remove(note.idHex) notes.remove(note.idHex)
} }
fun removeAuthorLinkTo(note: Note) { fun removeFromCache(nextToBeRemoved: List<Note>) {
if (note.event is LnZapEvent) {
(note.event as LnZapEvent).zappedAuthor().mapNotNull {
val author = getUserIfExists(it)
author?.removeZap(note)
author?.clearEOSE()
}
}
if (note.event is LnZapRequestEvent) {
(note.event as LnZapRequestEvent).zappedAuthor().mapNotNull {
val author = getUserIfExists(it)
author?.removeZap(note)
author?.clearEOSE()
}
}
if (note.event is ReportEvent) {
(note.event as ReportEvent).reportedAuthor().mapNotNull {
val author = getUserIfExists(it.key)
author?.removeReport(note)
author?.clearEOSE()
}
}
}
fun removeChildrenOf(nextToBeRemoved: List<Note>) {
nextToBeRemoved.forEach { note -> nextToBeRemoved.forEach { note ->
removeFromCache(note) removeFromCache(note)
} }
@@ -1449,7 +1427,7 @@ object LocalCache {
childrenToBeRemoved.addAll(it.removeAllChildNotes()) childrenToBeRemoved.addAll(it.removeAllChildNotes())
} }
removeChildrenOf(childrenToBeRemoved) removeFromCache(childrenToBeRemoved)
if (toBeRemoved.size > 1) { if (toBeRemoved.size > 1) {
println("PRUNE: ${toBeRemoved.size} thread replies removed.") println("PRUNE: ${toBeRemoved.size} thread replies removed.")
@@ -1476,7 +1454,7 @@ object LocalCache {
childrenToBeRemoved.addAll(it.removeAllChildNotes()) childrenToBeRemoved.addAll(it.removeAllChildNotes())
} }
removeChildrenOf(childrenToBeRemoved) removeFromCache(childrenToBeRemoved)
println("PRUNE: ${toBeRemoved.size} messages removed because they were Hidden") println("PRUNE: ${toBeRemoved.size} messages removed because they were Hidden")
} }
@@ -104,7 +104,7 @@ class MainActivity : AppCompatActivity() {
// Only starts after login // Only starts after login
if (ServiceManager.shouldPauseService) { if (ServiceManager.shouldPauseService) {
GlobalScope.launch(Dispatchers.IO) { GlobalScope.launch(Dispatchers.IO) {
ServiceManager.start() ServiceManager.justStart()
} }
} }
@@ -127,7 +127,7 @@ class MainActivity : AppCompatActivity() {
if (ServiceManager.shouldPauseService) { if (ServiceManager.shouldPauseService) {
GlobalScope.launch(Dispatchers.IO) { GlobalScope.launch(Dispatchers.IO) {
ServiceManager.pause() ServiceManager.pauseForGood()
} }
} }
@@ -627,8 +627,7 @@ private suspend fun enableTor(
account.proxyPort = portNumber.value.toInt() account.proxyPort = portNumber.value.toInt()
account.proxy = HttpClient.initProxy(checked, "127.0.0.1", account.proxyPort) account.proxy = HttpClient.initProxy(checked, "127.0.0.1", account.proxyPort)
LocalPreferences.saveToEncryptedStorage(account) LocalPreferences.saveToEncryptedStorage(account)
ServiceManager.pause() ServiceManager.forceRestart()
ServiceManager.start()
} }
@Composable @Composable