From b2c348a1df43478c56be9e767b83b83ecb839b46 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 8 Mar 2023 16:04:18 +0100 Subject: [PATCH] delete unused disco info on bind --- .../1.json | 12 +++++++++--- .../android/database/dao/DiscoDao.java | 11 +++++++++-- .../android/database/entity/DiscoEntity.java | 8 +++++++- .../android/xmpp/manager/DiscoManager.java | 15 ++++++++++++++- .../android/xmpp/processor/BindProcessor.java | 1 + 5 files changed, 40 insertions(+), 7 deletions(-) diff --git a/app/schemas/im.conversations.android.database.ConversationsDatabase/1.json b/app/schemas/im.conversations.android.database.ConversationsDatabase/1.json index 84b16426b..c4ddeb3ec 100644 --- a/app/schemas/im.conversations.android.database.ConversationsDatabase/1.json +++ b/app/schemas/im.conversations.android.database.ConversationsDatabase/1.json @@ -2,7 +2,7 @@ "formatVersion": 1, "database": { "version": 1, - "identityHash": "414be5ac9e68ecf9063dddbcc1cf993a", + "identityHash": "1780dce1d6aca78c94a2c5c497d158c5", "entities": [ { "tableName": "account", @@ -1088,7 +1088,7 @@ }, { "tableName": "disco", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `accountId` INTEGER NOT NULL, `capsHash` BLOB, `caps2HashSha256` BLOB, FOREIGN KEY(`accountId`) REFERENCES `account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `accountId` INTEGER NOT NULL, `capsHash` BLOB, `caps2HashSha256` BLOB, `cache` INTEGER NOT NULL, FOREIGN KEY(`accountId`) REFERENCES `account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", "fields": [ { "fieldPath": "id", @@ -1113,6 +1113,12 @@ "columnName": "caps2HashSha256", "affinity": "BLOB", "notNull": false + }, + { + "fieldPath": "cache", + "columnName": "cache", + "affinity": "INTEGER", + "notNull": true } ], "primaryKey": { @@ -2594,7 +2600,7 @@ "views": [], "setupQueries": [ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", - "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '414be5ac9e68ecf9063dddbcc1cf993a')" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '1780dce1d6aca78c94a2c5c497d158c5')" ] } } \ No newline at end of file diff --git a/app/src/main/java/im/conversations/android/database/dao/DiscoDao.java b/app/src/main/java/im/conversations/android/database/dao/DiscoDao.java index 8b1260a30..0dabf3fbc 100644 --- a/app/src/main/java/im/conversations/android/database/dao/DiscoDao.java +++ b/app/src/main/java/im/conversations/android/database/dao/DiscoDao.java @@ -147,14 +147,15 @@ public abstract class DiscoDao { final String node, final byte[] capsHash, final byte[] caps2HashSha256, - final InfoQuery infoQuery) { + final InfoQuery infoQuery, + final boolean cache) { final Long existingDiscoId = getDiscoId(account.id, caps2HashSha256); if (existingDiscoId != null) { updateDiscoId(account.id, entity, node, existingDiscoId); return; } - final long discoId = insert(DiscoEntity.of(account.id, capsHash, caps2HashSha256)); + final long discoId = insert(DiscoEntity.of(account.id, capsHash, caps2HashSha256, cache)); insertDiscoIdentities( Collections2.transform( @@ -177,6 +178,12 @@ public abstract class DiscoDao { updateDiscoId(account.id, entity, node, discoId); } + @Query( + "DELETE FROM disco WHERE accountId=:account AND cache=0 AND id NOT IN(SELECT discoId" + + " FROM presence WHERE discoId IS NOT NULL) AND id NOT IN(SELECT discoId FROM" + + " disco_item WHERE discoId IS NOT NULL)") + public abstract void deleteUnused(long account); + @Query("SELECT id FROM disco WHERE accountId=:accountId AND caps2HashSha256=:caps2HashSha256") protected abstract Long getDiscoId(final long accountId, final byte[] caps2HashSha256); diff --git a/app/src/main/java/im/conversations/android/database/entity/DiscoEntity.java b/app/src/main/java/im/conversations/android/database/entity/DiscoEntity.java index a4f30325e..02163782a 100644 --- a/app/src/main/java/im/conversations/android/database/entity/DiscoEntity.java +++ b/app/src/main/java/im/conversations/android/database/entity/DiscoEntity.java @@ -30,12 +30,18 @@ public class DiscoEntity { public byte[] capsHash; public byte[] caps2HashSha256; + public boolean cache; + public static DiscoEntity of( - final long accountId, final byte[] capsHash, final byte[] caps2HashSha256) { + final long accountId, + final byte[] capsHash, + final byte[] caps2HashSha256, + final boolean cache) { final var entity = new DiscoEntity(); entity.accountId = accountId; entity.capsHash = capsHash; entity.caps2HashSha256 = caps2HashSha256; + entity.cache = cache; return entity; } } diff --git a/app/src/main/java/im/conversations/android/xmpp/manager/DiscoManager.java b/app/src/main/java/im/conversations/android/xmpp/manager/DiscoManager.java index f44ab98c7..bb52d410a 100644 --- a/app/src/main/java/im/conversations/android/xmpp/manager/DiscoManager.java +++ b/app/src/main/java/im/conversations/android/xmpp/manager/DiscoManager.java @@ -173,9 +173,22 @@ public class DiscoManager extends AbstractManager { caps2, EntityCapabilities2.EntityCaps2Hash.class); } + // we want to avoid caching disco info for entities that put variable data (like + // number of occupants in a MUC) into it + final boolean cache = + Objects.nonNull(hash) + || infoQuery.hasFeature(Namespace.ENTITY_CAPABILITIES) + || infoQuery.hasFeature(Namespace.ENTITY_CAPABILITIES_2); getDatabase() .discoDao() - .set(getAccount(), entity, node, caps.hash, caps2.hash, infoQuery); + .set( + getAccount(), + entity, + node, + caps.hash, + caps2.hash, + infoQuery, + cache); return infoQuery; }, MoreExecutors.directExecutor()); diff --git a/app/src/main/java/im/conversations/android/xmpp/processor/BindProcessor.java b/app/src/main/java/im/conversations/android/xmpp/processor/BindProcessor.java index 53f4450ee..ed6aeba47 100644 --- a/app/src/main/java/im/conversations/android/xmpp/processor/BindProcessor.java +++ b/app/src/main/java/im/conversations/android/xmpp/processor/BindProcessor.java @@ -37,6 +37,7 @@ public class BindProcessor extends XmppConnection.Delegate implements Consumer { database.chatDao().resetMucStates(); database.presenceDao().deletePresences(account.id); + database.discoDao().deleteUnused(account.id); }); getManager(RosterManager.class).fetch();