Convert GroupV1RecordProcessor to kotlin.

This commit is contained in:
Greyson Parrelli 2024-11-07 13:10:47 -05:00
parent 0f8580c398
commit d5f68130fe
3 changed files with 118 additions and 138 deletions

View file

@ -368,7 +368,7 @@ class StorageSyncJob private constructor(parameters: Parameters) : BaseJob(param
@Throws(IOException::class)
private fun processKnownRecords(context: Context, records: StorageRecordCollection) {
ContactRecordProcessor().process(records.contacts, StorageSyncHelper.KEY_GENERATOR)
GroupV1RecordProcessor(context).process(records.gv1, StorageSyncHelper.KEY_GENERATOR)
GroupV1RecordProcessor().process(records.gv1, StorageSyncHelper.KEY_GENERATOR)
GroupV2RecordProcessor(context).process(records.gv2, StorageSyncHelper.KEY_GENERATOR)
AccountRecordProcessor(context, freshSelf()).process(records.account, StorageSyncHelper.KEY_GENERATOR)
StoryDistributionListRecordProcessor().process(records.storyDistributionLists, StorageSyncHelper.KEY_GENERATOR)

View file

@ -1,137 +0,0 @@
package org.thoughtcrime.securesms.storage;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.database.GroupTable;
import org.thoughtcrime.securesms.database.RecipientTable;
import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.database.model.GroupRecord;
import org.thoughtcrime.securesms.groups.BadGroupIdException;
import org.thoughtcrime.securesms.groups.GroupId;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.whispersystems.signalservice.api.storage.SignalGroupV1Record;
import java.util.Arrays;
import java.util.Optional;
/**
* Handles merging remote storage updates into local group v1 state.
*/
public final class GroupV1RecordProcessor extends DefaultStorageRecordProcessor<SignalGroupV1Record> {
private static final String TAG = Log.tag(GroupV1RecordProcessor.class);
private final GroupTable groupDatabase;
private final RecipientTable recipientTable;
public GroupV1RecordProcessor(@NonNull Context context) {
this(SignalDatabase.groups(), SignalDatabase.recipients());
}
GroupV1RecordProcessor(@NonNull GroupTable groupDatabase, @NonNull RecipientTable recipientTable) {
this.groupDatabase = groupDatabase;
this.recipientTable = recipientTable;
}
/**
* We want to catch:
* - Invalid group ID's
* - GV1 ID's that map to GV2 ID's, meaning we've already migrated them.
*
* Note: This method could be written more succinctly, but the logs are useful :)
*/
@Override
public boolean isInvalid(@NonNull SignalGroupV1Record remote) {
try {
GroupId.V1 id = GroupId.v1(remote.getGroupId());
Optional<GroupRecord> v2Record = groupDatabase.getGroup(id.deriveV2MigrationGroupId());
if (v2Record.isPresent()) {
Log.w(TAG, "We already have an upgraded V2 group for this V1 group -- marking as invalid.");
return true;
} else {
return false;
}
} catch (BadGroupIdException e) {
Log.w(TAG, "Bad Group ID -- marking as invalid.");
return true;
}
}
@Override
public @NonNull Optional<SignalGroupV1Record> getMatching(@NonNull SignalGroupV1Record record, @NonNull StorageKeyGenerator keyGenerator) {
GroupId.V1 groupId = GroupId.v1orThrow(record.getGroupId());
Optional<RecipientId> recipientId = recipientTable.getByGroupId(groupId);
return recipientId.map(recipientTable::getRecordForSync)
.map(StorageSyncModels::localToRemoteRecord)
.map(r -> r.getGroupV1().get());
}
@Override
public @NonNull SignalGroupV1Record merge(@NonNull SignalGroupV1Record remote, @NonNull SignalGroupV1Record local, @NonNull StorageKeyGenerator keyGenerator) {
byte[] unknownFields = remote.serializeUnknownFields();
boolean blocked = remote.isBlocked();
boolean profileSharing = remote.isProfileSharingEnabled();
boolean archived = remote.isArchived();
boolean forcedUnread = remote.isForcedUnread();
long muteUntil = remote.getMuteUntil();
boolean matchesRemote = doParamsMatch(remote, unknownFields, blocked, profileSharing, archived, forcedUnread, muteUntil);
boolean matchesLocal = doParamsMatch(local, unknownFields, blocked, profileSharing, archived, forcedUnread, muteUntil);
if (matchesRemote) {
return remote;
} else if (matchesLocal) {
return local;
} else {
return new SignalGroupV1Record.Builder(keyGenerator.generate(), remote.getGroupId(), unknownFields)
.setBlocked(blocked)
.setProfileSharingEnabled(profileSharing)
.setArchived(archived)
.setForcedUnread(forcedUnread)
.setMuteUntil(muteUntil)
.build();
}
}
@Override
public void insertLocal(@NonNull SignalGroupV1Record record) {
recipientTable.applyStorageSyncGroupV1Insert(record);
}
@Override
public void updateLocal(@NonNull StorageRecordUpdate<SignalGroupV1Record> update) {
recipientTable.applyStorageSyncGroupV1Update(update);
}
@Override
public int compare(@NonNull SignalGroupV1Record lhs, @NonNull SignalGroupV1Record rhs) {
if (Arrays.equals(lhs.getGroupId(), rhs.getGroupId())) {
return 0;
} else {
return 1;
}
}
private boolean doParamsMatch(@NonNull SignalGroupV1Record group,
@Nullable byte[] unknownFields,
boolean blocked,
boolean profileSharing,
boolean archived,
boolean forcedUnread,
long muteUntil)
{
return Arrays.equals(unknownFields, group.serializeUnknownFields()) &&
blocked == group.isBlocked() &&
profileSharing == group.isProfileSharingEnabled() &&
archived == group.isArchived() &&
forcedUnread == group.isForcedUnread() &&
muteUntil == group.getMuteUntil();
}
}

View file

@ -0,0 +1,117 @@
package org.thoughtcrime.securesms.storage
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.database.GroupTable
import org.thoughtcrime.securesms.database.RecipientTable
import org.thoughtcrime.securesms.database.SignalDatabase
import org.thoughtcrime.securesms.database.model.RecipientRecord
import org.thoughtcrime.securesms.groups.BadGroupIdException
import org.thoughtcrime.securesms.groups.GroupId
import org.whispersystems.signalservice.api.storage.SignalGroupV1Record
import org.whispersystems.signalservice.api.storage.SignalStorageRecord
import java.util.Optional
/**
* Handles merging remote storage updates into local group v1 state.
*/
class GroupV1RecordProcessor(private val groupDatabase: GroupTable, private val recipientTable: RecipientTable) : DefaultStorageRecordProcessor<SignalGroupV1Record>() {
companion object {
private val TAG = Log.tag(GroupV1RecordProcessor::class.java)
}
constructor() : this(SignalDatabase.groups, SignalDatabase.recipients)
/**
* We want to catch:
* - Invalid group ID's
* - GV1 ID's that map to GV2 ID's, meaning we've already migrated them.
*
* Note: This method could be written more succinctly, but the logs are useful :)
*/
override fun isInvalid(remote: SignalGroupV1Record): Boolean {
try {
val id = GroupId.v1(remote.groupId)
val v2Record = groupDatabase.getGroup(id.deriveV2MigrationGroupId())
if (v2Record.isPresent) {
Log.w(TAG, "We already have an upgraded V2 group for this V1 group -- marking as invalid.")
return true
} else {
return false
}
} catch (e: BadGroupIdException) {
Log.w(TAG, "Bad Group ID -- marking as invalid.")
return true
}
}
override fun getMatching(remote: SignalGroupV1Record, keyGenerator: StorageKeyGenerator): Optional<SignalGroupV1Record> {
val groupId = GroupId.v1orThrow(remote.groupId)
val recipientId = recipientTable.getByGroupId(groupId)
return recipientId
.map { recipientTable.getRecordForSync(it)!! }
.map { settings: RecipientRecord -> StorageSyncModels.localToRemoteRecord(settings) }
.map { record: SignalStorageRecord -> record.groupV1.get() }
}
override fun merge(remote: SignalGroupV1Record, local: SignalGroupV1Record, keyGenerator: StorageKeyGenerator): SignalGroupV1Record {
val unknownFields = remote.serializeUnknownFields()
val blocked = remote.isBlocked
val profileSharing = remote.isProfileSharingEnabled
val archived = remote.isArchived
val forcedUnread = remote.isForcedUnread
val muteUntil = remote.muteUntil
val matchesRemote = doParamsMatch(group = remote, unknownFields = unknownFields, blocked = blocked, profileSharing = profileSharing, archived = archived, forcedUnread = forcedUnread, muteUntil = muteUntil)
val matchesLocal = doParamsMatch(group = local, unknownFields = unknownFields, blocked = blocked, profileSharing = profileSharing, archived = archived, forcedUnread = forcedUnread, muteUntil = muteUntil)
return if (matchesRemote) {
remote
} else if (matchesLocal) {
local
} else {
SignalGroupV1Record.Builder(keyGenerator.generate(), remote.groupId, unknownFields)
.setBlocked(blocked)
.setProfileSharingEnabled(profileSharing)
.setArchived(archived)
.setForcedUnread(forcedUnread)
.setMuteUntil(muteUntil)
.build()
}
}
override fun insertLocal(record: SignalGroupV1Record) {
recipientTable.applyStorageSyncGroupV1Insert(record)
}
override fun updateLocal(update: StorageRecordUpdate<SignalGroupV1Record>) {
recipientTable.applyStorageSyncGroupV1Update(update)
}
override fun compare(lhs: SignalGroupV1Record, rhs: SignalGroupV1Record): Int {
return if (lhs.groupId.contentEquals(rhs.groupId)) {
0
} else {
1
}
}
private fun doParamsMatch(
group: SignalGroupV1Record,
unknownFields: ByteArray?,
blocked: Boolean,
profileSharing: Boolean,
archived: Boolean,
forcedUnread: Boolean,
muteUntil: Long
): Boolean {
return unknownFields.contentEquals(group.serializeUnknownFields()) &&
blocked == group.isBlocked &&
profileSharing == group.isProfileSharingEnabled &&
archived == group.isArchived &&
forcedUnread == group.isForcedUnread &&
muteUntil == group.muteUntil
}
}