From 1738a775efd39b59ed4bcb8bed5da15f3dadc99a Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Fri, 5 Apr 2024 14:05:04 -0400 Subject: [PATCH] Fixes the lack of the Comparator interface for the Deletion Index. --- .../amethyst/model/LocalCache.kt | 80 +++++++++---------- .../amethyst/commons/data/DeletionIndex.kt | 27 ++++++- .../quartz/events/DeletionEvent.kt | 2 + .../vitorpamplona/quartz/events/DraftEvent.kt | 2 +- 4 files changed, 66 insertions(+), 45 deletions(-) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt index 5f4022d5a..e8e17b45a 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt @@ -959,53 +959,53 @@ object LocalCache { } fun consume(event: DeletionEvent) { - deletionIndex.add(event) + if (deletionIndex.add(event)) { + var deletedAtLeastOne = false - var deletedAtLeastOne = false + event.deleteEvents() + .mapNotNull { getNoteIfExists(it) } + .forEach { deleteNote -> + // must be the same author + if (deleteNote.author?.pubkeyHex == event.pubKey) { + // reverts the add + deleteNote(deleteNote) - event.deleteEvents() - .mapNotNull { getNoteIfExists(it) } - .forEach { deleteNote -> - // must be the same author - if (deleteNote.author?.pubkeyHex == event.pubKey) { - // reverts the add - deleteNote(deleteNote) + deletedAtLeastOne = true + } + } - deletedAtLeastOne = true + val addressList = event.deleteAddressTags() + val addressSet = addressList.toSet() + + addressList + .mapNotNull { getAddressableNoteIfExists(it) } + .forEach { deleteNote -> + // must be the same author + if (deleteNote.author?.pubkeyHex == event.pubKey && (deleteNote.createdAt() ?: 0) <= event.createdAt) { + // Counts the replies + deleteNote(deleteNote) + + addressables.remove(deleteNote.idHex) + + deletedAtLeastOne = true + } + } + + notes.forEach { key, note -> + val noteEvent = note.event + if (noteEvent is AddressableEvent && noteEvent.addressTag() in addressSet) { + if (noteEvent.pubKey() == event.pubKey && noteEvent.createdAt() <= event.createdAt) { + deleteNote(note) + deletedAtLeastOne = true + } } } - val addressList = event.deleteAddresses() - val addressSet = addressList.toSet() - - addressList - .mapNotNull { getAddressableNoteIfExists(it.toTag()) } - .forEach { deleteNote -> - // must be the same author - if (deleteNote.author?.pubkeyHex == event.pubKey && (deleteNote.createdAt() ?: 0) < event.createdAt) { - // Counts the replies - deleteNote(deleteNote) - - addressables.remove(deleteNote.idHex) - - deletedAtLeastOne = true - } + if (deletedAtLeastOne) { + val note = Note(event.id) + note.loadEvent(event, getOrCreateUser(event.pubKey), emptyList()) + refreshObservers(note) } - - notes.forEach { key, note -> - val noteEvent = note.event - if (noteEvent is AddressableEvent && noteEvent.address() in addressSet) { - if (noteEvent.pubKey() == event.pubKey && noteEvent.createdAt() <= event.createdAt) { - deleteNote(note) - deletedAtLeastOne = true - } - } - } - - if (deletedAtLeastOne) { - val note = Note(event.id) - note.loadEvent(event, getOrCreateUser(event.pubKey), emptyList()) - refreshObservers(note) } } diff --git a/commons/src/main/java/com/vitorpamplona/amethyst/commons/data/DeletionIndex.kt b/commons/src/main/java/com/vitorpamplona/amethyst/commons/data/DeletionIndex.kt index da4d049b8..642d6f577 100644 --- a/commons/src/main/java/com/vitorpamplona/amethyst/commons/data/DeletionIndex.kt +++ b/commons/src/main/java/com/vitorpamplona/amethyst/commons/data/DeletionIndex.kt @@ -26,30 +26,49 @@ import com.vitorpamplona.quartz.events.DeletionEvent import com.vitorpamplona.quartz.events.Event class DeletionIndex { - data class DeletionRequest(val reference: String, val publicKey: HexKey) + data class DeletionRequest(val reference: String, val publicKey: HexKey) : Comparable { + override fun compareTo(other: DeletionRequest): Int { + val compared = reference.compareTo(other.reference) + + return if (compared == 0) { + publicKey.compareTo(publicKey) + } else { + compared + } + } + } // stores a set of id OR atags (kind:pubkey:dtag) by pubkey with the created at of the deletion event. // Anything newer than the date should not be deleted. private val deletedReferencesBefore = LargeCache() - fun add(event: DeletionEvent) { + fun add(event: DeletionEvent): Boolean { + var atLeastOne = false + event.tags.forEach { if (it.size > 1 && (it[0] == "a" || it[0] == "e")) { - add(it[1], event.pubKey, event.createdAt) + if (add(it[1], event.pubKey, event.createdAt)) { + atLeastOne = true + } } } + + return atLeastOne } private fun add( ref: String, byPubKey: HexKey, createdAt: Long, - ) { + ): Boolean { val key = DeletionRequest(ref, byPubKey) val previousDeletionTime = deletedReferencesBefore.get(key) + if (previousDeletionTime == null || createdAt > previousDeletionTime) { deletedReferencesBefore.put(key, createdAt) + return true } + return false } fun hasBeenDeleted(event: Event): Boolean { diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/DeletionEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/DeletionEvent.kt index f3b1cd7f4..e93dd4548 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/DeletionEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/events/DeletionEvent.kt @@ -38,6 +38,8 @@ class DeletionEvent( fun deleteAddresses() = taggedAddresses() + fun deleteAddressTags() = tags.mapNotNull { if (it.size > 1 && it[0] == "a") it[1] else null } + companion object { const val KIND = 5 const val ALT = "Deletion event" diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/DraftEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/DraftEvent.kt index dfc50de4f..30b762fb6 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/DraftEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/events/DraftEvent.kt @@ -115,7 +115,7 @@ class DraftEvent( pubKey: HexKey, dTag: String, ): String { - return ATag(KIND, pubKey, dTag, null).toTag() + return ATag.assembleATag(KIND, pubKey, dTag) } fun create(