Fix storage sync issues

This commit is contained in:
AsamK 2024-01-28 11:46:34 +01:00
parent f92466f6be
commit 90df256e85
8 changed files with 67 additions and 51 deletions

View file

@ -155,7 +155,7 @@ public class StorageHelper {
if (updated > 0) {
logger.warn(
"Found {} records that were deleted remotely but only marked unregistered locally. Removed those from local store. Recalculating diff.",
"Found {} records that were deleted remotely but only marked unregistered locally. Removed those from local store.",
updated);
}
}
@ -502,7 +502,7 @@ public class StorageHelper {
final var remote = remoteByRawId.get(rawId);
final var local = localByRawId.get(rawId);
if (remote.getType() != local.getType()) {
if (remote.getType() != local.getType() && local.getType() != 0) {
remoteOnlyRawIds.remove(rawId);
localOnlyRawIds.remove(rawId);
hasTypeMismatch = true;

View file

@ -324,7 +324,12 @@ public class SyncHelper {
final var recipientId = account.getRecipientTrustedResolver().resolveRecipientTrusted(c.getAddress());
var contact = account.getContactStore().getContact(recipientId);
final var builder = contact == null ? Contact.newBuilder() : Contact.newBuilder(contact);
if (c.getName().isPresent()) {
if (c.getName().isPresent() && (
contact == null || (
contact.givenName() == null
&& contact.familyName() == null
)
)) {
builder.withGivenName(c.getName().get());
builder.withFamilyName(null);
}

View file

@ -1355,8 +1355,8 @@ public class ManagerImpl implements Manager {
if (thread != null) {
stopReceiveThread(thread);
}
executor.close();
context.close();
executor.close();
dependencies.getSignalWebSocket().disconnect();
dependencies.getPushServiceSocket().close();

View file

@ -362,7 +362,7 @@ public class SignalAccount implements Closeable {
}
private void init() {
this.selfRecipientId = getRecipientResolver().resolveRecipient(getSelfRecipientAddress());
this.selfRecipientId = getRecipientTrustedResolver().resolveSelfRecipientTrusted(getSelfRecipientAddress());
}
private void migrateLegacyConfigs() {

View file

@ -122,13 +122,25 @@ public class GroupStore {
public void storeStorageRecord(
final Connection connection, final GroupId groupId, final StorageId storageId, final byte[] storageRecord
) throws SQLException {
final var groupTable = groupId instanceof GroupIdV1 ? TABLE_GROUP_V1 : TABLE_GROUP_V2;
final var deleteSql = (
"""
UPDATE %s
SET storage_id = NULL
WHERE storage_id = ?
"""
).formatted(groupTable);
try (final var statement = connection.prepareStatement(deleteSql)) {
statement.setBytes(1, storageId.getRaw());
statement.executeUpdate();
}
final var sql = (
"""
UPDATE %s
SET storage_id = ?, storage_record = ?
WHERE group_id = ?
"""
).formatted(groupId instanceof GroupIdV1 ? TABLE_GROUP_V1 : TABLE_GROUP_V2);
).formatted(groupTable);
try (final var statement = connection.prepareStatement(sql)) {
statement.setBytes(1, storageId.getRaw());
if (storageRecord == null) {

View file

@ -37,8 +37,6 @@ import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import static org.asamk.signal.manager.config.ServiceConfig.UNREGISTERED_LIFESPAN;
public class RecipientStore implements RecipientIdCreator, RecipientResolver, RecipientTrustedResolver, ContactsStore, ProfileStore {
private static final Logger logger = LoggerFactory.getLogger(RecipientStore.class);
@ -524,7 +522,7 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
"""
SELECT r._id
FROM %s r
WHERE r.storage_id IS NULL AND (r.unregistered_timestamp IS NULL OR r.unregistered_timestamp > ?)
WHERE r.storage_id IS NULL AND r.unregistered_timestamp IS NULL
"""
).formatted(TABLE_RECIPIENT);
final var updateSql = (
@ -537,7 +535,6 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
try (final var connection = database.getConnection()) {
connection.setAutoCommit(false);
try (final var selectStmt = connection.prepareStatement(selectSql)) {
selectStmt.setLong(1, System.currentTimeMillis() - UNREGISTERED_LIFESPAN);
final var recipientIds = Utils.executeQueryForStream(selectStmt, this::getRecipientIdFromResultSet)
.toList();
try (final var updateStmt = connection.prepareStatement(updateSql)) {
@ -735,14 +732,25 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
final StorageId storageId,
final byte[] storageRecord
) throws SQLException {
final var sql = (
final var deleteSql = (
"""
UPDATE %s
SET storage_id = NULL
WHERE storage_id = ?
"""
).formatted(TABLE_RECIPIENT);
try (final var statement = connection.prepareStatement(deleteSql)) {
statement.setBytes(1, storageId.getRaw());
statement.executeUpdate();
}
final var insertSql = (
"""
UPDATE %s
SET storage_id = ?, storage_record = ?
WHERE _id = ?
"""
).formatted(TABLE_RECIPIENT);
try (final var statement = connection.prepareStatement(sql)) {
try (final var statement = connection.prepareStatement(insertSql)) {
statement.setBytes(1, storageId.getRaw());
if (storageRecord == null) {
statement.setNull(2, Types.BLOB);
@ -846,7 +854,7 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
"""
UPDATE %s
SET storage_id = NULL
WHERE storage_id = ? AND storage_id IS NOT NULL AND unregistered_timestamp IS NOT NULL
WHERE storage_id = ? AND unregistered_timestamp IS NOT NULL
"""
).formatted(TABLE_RECIPIENT);
var count = 0;
@ -1002,6 +1010,7 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
}
if (!pair.second().isEmpty()) {
logger.debug("Resolved address {}, merging {} other recipients", address, pair.second().size());
try (final var connection = database.getConnection()) {
connection.setAutoCommit(false);
mergeRecipients(connection, pair.first(), pair.second());

View file

@ -105,8 +105,12 @@ public class ContactRecordProcessor extends DefaultStorageRecordProcessor<Signal
IdentityState identityState;
byte[] identityKey;
if ((remote.getIdentityState() != local.getIdentityState() && remote.getIdentityKey().isPresent())
|| (remote.getIdentityKey().isPresent() && local.getIdentityKey().isEmpty())) {
if (remote.getIdentityKey().isPresent() && (
remote.getIdentityState() != local.getIdentityState()
|| local.getIdentityKey().isEmpty()
|| !account.isPrimaryDevice()
)) {
identityState = remote.getIdentityState();
identityKey = remote.getIdentityKey().get();
} else {
@ -114,9 +118,10 @@ public class ContactRecordProcessor extends DefaultStorageRecordProcessor<Signal
identityKey = local.getIdentityKey().orElse(null);
}
if (local.getAci().isPresent() && identityKey != null && remote.getIdentityKey().isPresent() && !Arrays.equals(
identityKey,
remote.getIdentityKey().get())) {
if (local.getAci().isPresent()
&& local.getIdentityKey().isPresent()
&& remote.getIdentityKey().isPresent()
&& !Arrays.equals(local.getIdentityKey().get(), remote.getIdentityKey().get())) {
logger.debug("The local and remote identity keys do not match for {}. Enqueueing a profile fetch.",
local.getAci().orElse(null));
final var address = getRecipientAddress(local);
@ -141,13 +146,12 @@ public class ContactRecordProcessor extends DefaultStorageRecordProcessor<Signal
PNI pni;
String e164;
if (!account.isPrimaryDevice() && (e164sMatchButPnisDont || pnisMatchButE164sDont)) {
if (e164sMatchButPnisDont) {
logger.debug("Matching E164s, but the PNIs differ! Trusting our local pair.");
// TODO [pnp] Schedule CDS fetch?
pni = local.getPni().get();
e164 = local.getNumber().get();
} else if (pnisMatchButE164sDont) {
logger.debug("Matching PNIs, but the E164s differ! Trusting our local pair.");
}
// TODO [pnp] Schedule CDS fetch?
pni = local.getPni().get();
e164 = local.getNumber().get();
@ -235,41 +239,25 @@ public class ContactRecordProcessor extends DefaultStorageRecordProcessor<Signal
|| profileShared != contactRecord.isProfileSharingEnabled()
|| archived != contactRecord.isArchived()
|| hidden != contactRecord.isHidden()
|| (
contactRecord.getSystemGivenName().isPresent() && !contactRecord.getSystemGivenName()
.get()
.equals(contactGivenName)
)
|| (
contactRecord.getSystemFamilyName().isPresent() && !contactRecord.getSystemFamilyName()
.get()
.equals(contactFamilyName)
)) {
|| !Objects.equals(contactRecord.getSystemGivenName().orElse(null), contactGivenName)
|| !Objects.equals(contactRecord.getSystemFamilyName().orElse(null), contactFamilyName)) {
logger.debug("Storing new or updated contact {}", recipientId);
final var contactBuilder = contact == null ? Contact.newBuilder() : Contact.newBuilder(contact);
final var newContact = contactBuilder.withIsBlocked(contactRecord.isBlocked())
.withIsProfileSharingEnabled(contactRecord.isProfileSharingEnabled())
.withIsArchived(contactRecord.isArchived())
.withIsHidden(contactRecord.isHidden());
if (contactRecord.getSystemGivenName().isPresent() || contactRecord.getSystemFamilyName().isPresent()) {
newContact.withGivenName(contactRecord.getSystemGivenName().orElse(null))
.withIsHidden(contactRecord.isHidden())
.withGivenName(contactRecord.getSystemGivenName().orElse(null))
.withFamilyName(contactRecord.getSystemFamilyName().orElse(null));
}
account.getRecipientStore().storeContact(connection, recipientId, newContact.build());
}
final var profile = recipient.getProfile();
final var profileGivenName = profile == null ? null : profile.getGivenName();
final var profileFamilyName = profile == null ? null : profile.getFamilyName();
if ((
contactRecord.getProfileGivenName().isPresent() && !contactRecord.getProfileGivenName()
.get()
.equals(profileGivenName)
) || (
contactRecord.getProfileFamilyName().isPresent() && !contactRecord.getProfileFamilyName()
.get()
.equals(profileFamilyName)
)) {
if (!Objects.equals(contactRecord.getProfileGivenName().orElse(null), profileGivenName) || !Objects.equals(
contactRecord.getProfileFamilyName().orElse(null),
profileFamilyName)) {
final var profileBuilder = profile == null ? Profile.newBuilder() : Profile.newBuilder(profile);
final var newProfile = profileBuilder.withGivenName(contactRecord.getProfileGivenName().orElse(null))
.withFamilyName(contactRecord.getProfileFamilyName().orElse(null))
@ -285,7 +273,7 @@ public class ContactRecordProcessor extends DefaultStorageRecordProcessor<Signal
logger.warn("Received invalid contact profile key from storage");
}
}
if (contactRecord.getIdentityKey().isPresent() && contactRecord.getAci().orElse(null) != null) {
if (contactRecord.getIdentityKey().isPresent() && contactRecord.getAci().isPresent()) {
try {
logger.trace("Storing identity key {}", recipientId);
final var identityKey = new IdentityKey(contactRecord.getIdentityKey().get());

View file

@ -55,7 +55,9 @@ abstract class DefaultStorageRecordProcessor<E extends SignalRecord> implements
}
if (matchedRecords.contains(local.get())) {
debug(remote.getId(), remote, "Multiple remote records map to the same local record! Ignoring this one.");
debug(remote.getId(),
remote,
"Multiple remote records map to the same local record " + local.get() + "! Ignoring this one.");
return;
}