delete unused disco info on bind

This commit is contained in:
Daniel Gultsch 2023-03-08 16:04:18 +01:00
parent 9a0c2226c1
commit b2c348a1df
No known key found for this signature in database
GPG key ID: F43D18AD2A0982C2
5 changed files with 40 additions and 7 deletions

View file

@ -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')"
]
}
}

View file

@ -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);

View file

@ -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;
}
}

View file

@ -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());

View file

@ -37,6 +37,7 @@ public class BindProcessor extends XmppConnection.Delegate implements Consumer<J
() -> {
database.chatDao().resetMucStates();
database.presenceDao().deletePresences(account.id);
database.discoDao().deleteUnused(account.id);
});
getManager(RosterManager.class).fetch();