Skip to content

Commit 40b1928

Browse files
committed
Fix removal of local only unregistered accounts in storage sync
1 parent 2a827f1 commit 40b1928

3 files changed

Lines changed: 39 additions & 20 deletions

File tree

lib/src/main/java/org/asamk/signal/manager/helper/StorageHelper.java

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import org.asamk.signal.manager.api.GroupIdV1;
44
import org.asamk.signal.manager.api.GroupIdV2;
5+
import org.asamk.signal.manager.api.Pair;
56
import org.asamk.signal.manager.api.Profile;
67
import org.asamk.signal.manager.internal.SignalDependencies;
78
import org.asamk.signal.manager.storage.SignalAccount;
@@ -38,6 +39,7 @@
3839
import java.util.Base64;
3940
import java.util.Collection;
4041
import java.util.Collections;
42+
import java.util.HashSet;
4143
import java.util.List;
4244
import java.util.Map;
4345
import java.util.stream.Collectors;
@@ -211,20 +213,23 @@ private boolean readDataFromStorage(
211213
remoteOnlyRecords.size());
212214
}
213215

214-
// This logic is wrong, records should only be deleted if they're deleted remotely, not if the remote record is updated
215-
// if (!idDifference.localOnlyIds().isEmpty()) {
216-
// final var updated = account.getRecipientStore()
217-
// .removeStorageIdsFromLocalOnlyUnregisteredRecipients(connection,
218-
// idDifference.localOnlyIds());
219-
//
220-
// if (updated > 0) {
221-
// logger.warn(
222-
// "Found {} records that were deleted remotely but only marked unregistered locally. Removed those from local store.",
223-
// updated);
224-
// }
225-
// }
226-
//
227-
final var unknownInserts = processKnownRecords(connection, remoteOnlyRecords);
216+
final var listListPair = processKnownRecords(connection, remoteOnlyRecords);
217+
final var unknownInserts = listListPair.first();
218+
final var updatedStorageIds = listListPair.second();
219+
final var oldUnregisteredLocalOnlyIds = new HashSet<>(idDifference.localOnlyIds());
220+
updatedStorageIds.forEach(oldUnregisteredLocalOnlyIds::remove);
221+
if (!idDifference.localOnlyIds().isEmpty()) {
222+
final var updated = account.getRecipientStore()
223+
.removeStorageIdsFromLocalOnlyUnregisteredRecipients(connection,
224+
oldUnregisteredLocalOnlyIds);
225+
226+
if (updated > 0) {
227+
logger.warn(
228+
"Found {} records that were deleted remotely but only marked unregistered locally. Removed those from local store.",
229+
updated);
230+
}
231+
}
232+
228233
final var unknownDeletes = idDifference.localOnlyIds()
229234
.stream()
230235
.filter(id -> !KNOWN_TYPES.contains(id.getType()))
@@ -480,13 +485,13 @@ private Map<RecipientId, StorageId> generateContactStorageIds(List<RecipientId>
480485
private Map<GroupIdV1, StorageId> generateGroupV1StorageIds(List<GroupIdV1> groupIds) {
481486
return groupIds.stream()
482487
.collect(Collectors.toMap(recipientId -> recipientId,
483-
recipientId -> StorageId.forGroupV1(KeyUtils.createRawStorageId())));
488+
_ -> StorageId.forGroupV1(KeyUtils.createRawStorageId())));
484489
}
485490

486491
private Map<GroupIdV2, StorageId> generateGroupV2StorageIds(List<GroupIdV2> groupIds) {
487492
return groupIds.stream()
488493
.collect(Collectors.toMap(recipientId -> recipientId,
489-
recipientId -> StorageId.forGroupV2(KeyUtils.createRawStorageId())));
494+
_ -> StorageId.forGroupV2(KeyUtils.createRawStorageId())));
490495
}
491496

492497
private void storeManifestLocally(
@@ -630,16 +635,17 @@ private static IdDifferenceResult findIdDifference(
630635
return new IdDifferenceResult(remoteOnlyKeys, localOnlyKeys, hasTypeMismatch);
631636
}
632637

633-
private List<StorageId> processKnownRecords(
638+
private Pair<List<StorageId>, List<StorageId>> processKnownRecords(
634639
final Connection connection,
635640
List<SignalStorageRecord> records
636641
) throws SQLException {
637642
final var unknownRecords = new ArrayList<StorageId>();
643+
final var processedRecords = new ArrayList<StorageId>();
638644

639645
final var accountRecordProcessor = new AccountRecordProcessor(account, connection, context.getJobExecutor());
640-
final var contactRecordProcessor = new ContactRecordProcessor(account, connection, context.getJobExecutor());
641646
final var groupV1RecordProcessor = new GroupV1RecordProcessor(account, connection);
642647
final var groupV2RecordProcessor = new GroupV2RecordProcessor(account, connection);
648+
final var contactRecordProcessor = new ContactRecordProcessor(account, connection, context.getJobExecutor());
643649

644650
for (final var record : records) {
645651
if (record.getProto().account != null) {
@@ -662,8 +668,12 @@ private List<StorageId> processKnownRecords(
662668
unknownRecords.add(record.getId());
663669
}
664670
}
671+
processedRecords.addAll(accountRecordProcessor.getUpdatedStorageIds());
672+
processedRecords.addAll(groupV1RecordProcessor.getUpdatedStorageIds());
673+
processedRecords.addAll(groupV2RecordProcessor.getUpdatedStorageIds());
674+
processedRecords.addAll(contactRecordProcessor.getUpdatedStorageIds());
665675

666-
return unknownRecords;
676+
return new Pair<>(unknownRecords, processedRecords);
667677
}
668678

669679
/**

lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -878,7 +878,7 @@ public void storeContact(
878878

879879
public int removeStorageIdsFromLocalOnlyUnregisteredRecipients(
880880
final Connection connection,
881-
final List<StorageId> storageIds
881+
final Collection<StorageId> storageIds
882882
) throws SQLException {
883883
final var sql = (
884884
"""

lib/src/main/java/org/asamk/signal/manager/syncStorage/DefaultStorageRecordProcessor.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
import org.whispersystems.signalservice.api.storage.StorageId;
77

88
import java.sql.SQLException;
9+
import java.util.Collections;
910
import java.util.Comparator;
11+
import java.util.HashSet;
1012
import java.util.Optional;
1113
import java.util.Set;
1214
import java.util.TreeSet;
@@ -24,6 +26,7 @@ abstract class DefaultStorageRecordProcessor<E extends SignalRecord<?>> implemen
2426

2527
private static final Logger logger = LoggerFactory.getLogger(DefaultStorageRecordProcessor.class);
2628
private final Set<E> matchedRecords = new TreeSet<>(this);
29+
private final Set<StorageId> updatedStorageIds = new HashSet<>();
2730

2831
/**
2932
* One type of invalid remote data this handles is two records mapping to the same local data. We
@@ -50,6 +53,7 @@ public void process(E remote) throws SQLException {
5053

5154
if (local.isEmpty()) {
5255
debug(remote.getId(), remote, "[Local Insert] No matching local record. Inserting.");
56+
updatedStorageIds.add(remote.getId());
5357
insertLocal(remote);
5458
return;
5559
}
@@ -64,6 +68,7 @@ public void process(E remote) throws SQLException {
6468
matchedRecords.add(local.get());
6569

6670
final var merged = merge(remote, local.get());
71+
updatedStorageIds.add(merged.getId());
6772
if (!merged.equals(remote)) {
6873
debug(remote.getId(), remote, "[Remote Update] " + merged.describeDiff(remote));
6974
}
@@ -75,6 +80,10 @@ public void process(E remote) throws SQLException {
7580
}
7681
}
7782

83+
public Set<StorageId> getUpdatedStorageIds() {
84+
return Collections.unmodifiableSet(updatedStorageIds);
85+
}
86+
7887
private void debug(StorageId i, E record, String message) {
7988
logger.debug("[{}][{}] {}", i, record.getClass().getSimpleName(), message);
8089
}

0 commit comments

Comments
 (0)