Remove groups table, conversation is single source of truth

This commit is contained in:
Scott Nonnenberg 2019-02-11 15:59:21 -08:00
parent b69eea543c
commit 5b54c9554e
16 changed files with 214 additions and 912 deletions

View file

@ -109,9 +109,9 @@ function createOutputStream(writer) {
};
}
async function exportContactAndGroupsToFile(parent) {
async function exportConversationListToFile(parent) {
const writer = await createFileAndWriter(parent, 'db.json');
return exportContactsAndGroups(writer);
return exportConversationList(writer);
}
function writeArray(stream, array) {
@ -137,7 +137,7 @@ function getPlainJS(collection) {
return collection.map(model => model.attributes);
}
async function exportContactsAndGroups(fileWriter) {
async function exportConversationList(fileWriter) {
const stream = createOutputStream(fileWriter);
stream.write('{');
@ -149,13 +149,6 @@ async function exportContactsAndGroups(fileWriter) {
window.log.info(`Exporting ${conversations.length} conversations`);
writeArray(stream, getPlainJS(conversations));
stream.write(',');
stream.write('"groups": ');
const groups = await window.Signal.Data.getAllGroups();
window.log.info(`Exporting ${groups.length} groups`);
writeArray(stream, groups);
stream.write('}');
await stream.close();
}
@ -167,7 +160,7 @@ async function importNonMessages(parent, options) {
}
function eliminateClientConfigInBackup(data, targetPath) {
const cleaned = _.pick(data, 'conversations', 'groups');
const cleaned = _.pick(data, 'conversations');
window.log.info('Writing configuration-free backup file back to disk');
try {
fs.writeFileSync(targetPath, JSON.stringify(cleaned));
@ -223,10 +216,8 @@ async function importFromJsonString(jsonString, targetPath, options) {
_.defaults(options, {
forceLightImport: false,
conversationLookup: {},
groupLookup: {},
});
const { groupLookup } = options;
const result = {
fullImport: true,
};
@ -251,7 +242,7 @@ async function importFromJsonString(jsonString, targetPath, options) {
// We mutate the on-disk backup to prevent the user from importing client
// configuration more than once - that causes lots of encryption errors.
// This of course preserves the true data: conversations and groups.
// This of course preserves the true data: conversations.
eliminateClientConfigInBackup(importObject, targetPath);
const storeNames = _.keys(importObject);
@ -262,12 +253,12 @@ async function importFromJsonString(jsonString, targetPath, options) {
const remainingStoreNames = _.without(
storeNames,
'conversations',
'unprocessed'
'unprocessed',
'groups' // in old data sets, but no longer included in database schema
);
await importConversationsFromJSON(conversations, options);
const SAVE_FUNCTIONS = {
groups: window.Signal.Data.createOrUpdateGroup,
identityKeys: window.Signal.Data.createOrUpdateIdentityKey,
items: window.Signal.Data.createOrUpdateItem,
preKeys: window.Signal.Data.createOrUpdatePreKey,
@ -292,29 +283,17 @@ async function importFromJsonString(jsonString, targetPath, options) {
return;
}
let skipCount = 0;
for (let i = 0, max = toImport.length; i < max; i += 1) {
const toAdd = unstringify(toImport[i]);
const haveGroupAlready =
storeName === 'groups' && groupLookup[getGroupKey(toAdd)];
if (haveGroupAlready) {
skipCount += 1;
} else {
// eslint-disable-next-line no-await-in-loop
await save(toAdd);
}
// eslint-disable-next-line no-await-in-loop
await save(toAdd);
}
window.log.info(
'Done importing to store',
storeName,
'Total count:',
toImport.length,
'Skipped:',
skipCount
toImport.length
);
})
);
@ -1160,14 +1139,6 @@ async function loadConversationLookup() {
return fromPairs(map(array, item => [getConversationKey(item), true]));
}
function getGroupKey(group) {
return group.id;
}
async function loadGroupsLookup() {
const array = await window.Signal.Data.getAllGroupIds();
return fromPairs(map(array, item => [getGroupKey(item), true]));
}
function getDirectoryForExport() {
return getDirectory();
}
@ -1254,7 +1225,7 @@ async function exportToDirectory(directory, options) {
const attachmentsDir = await createDirectory(directory, 'attachments');
await exportContactAndGroupsToFile(stagingDir);
await exportConversationListToFile(stagingDir);
await exportConversations(
Object.assign({}, options, {
messagesDir: stagingDir,
@ -1298,13 +1269,11 @@ async function importFromDirectory(directory, options) {
const lookups = await Promise.all([
loadMessagesLookup(),
loadConversationLookup(),
loadGroupsLookup(),
]);
const [messageLookup, conversationLookup, groupLookup] = lookups;
const [messageLookup, conversationLookup] = lookups;
options = Object.assign({}, options, {
messageLookup,
conversationLookup,
groupLookup,
});
const archivePath = path.join(directory, ARCHIVE_NAME);

View file

@ -47,14 +47,6 @@ module.exports = {
removeDB,
removeIndexedDBFiles,
createOrUpdateGroup,
getGroupById,
getAllGroupIds,
getAllGroups,
bulkAddGroups,
removeGroupById,
removeAllGroups,
createOrUpdateIdentityKey,
getIdentityKeyById,
bulkAddIdentityKeys,
@ -395,33 +387,6 @@ async function removeIndexedDBFiles() {
await channels.removeIndexedDBFiles();
}
// Groups
async function createOrUpdateGroup(data) {
await channels.createOrUpdateGroup(data);
}
async function getGroupById(id) {
const group = await channels.getGroupById(id);
return group;
}
async function getAllGroupIds() {
const ids = await channels.getAllGroupIds();
return ids;
}
async function getAllGroups() {
const groups = await channels.getAllGroups();
return groups;
}
async function bulkAddGroups(array) {
await channels.bulkAddGroups(array);
}
async function removeGroupById(id) {
await channels.removeGroupById(id);
}
async function removeAllGroups() {
await channels.removeAllGroups();
}
// Identity Keys
const IDENTITY_KEY_KEYS = ['publicKey'];

View file

@ -2,14 +2,12 @@
const { includes, isFunction, isString, last, map } = require('lodash');
const {
bulkAddGroups,
bulkAddSessions,
bulkAddIdentityKeys,
bulkAddPreKeys,
bulkAddSignedPreKeys,
bulkAddItems,
removeGroupById,
removeSessionById,
removeIdentityKeyById,
removePreKeyById,
@ -184,31 +182,6 @@ async function migrateToSQL({
complete = false;
lastIndex = null;
while (!complete) {
// eslint-disable-next-line no-await-in-loop
const status = await migrateStoreToSQLite({
db,
// eslint-disable-next-line no-loop-func
save: bulkAddGroups,
remove: removeGroupById,
storeName: 'groups',
handleDOMException,
lastIndex,
batchSize: 10,
});
({ complete, lastIndex } = status);
}
window.log.info('migrateToSQL: migrate of groups complete');
try {
await clearStores(['groups']);
} catch (error) {
window.log.warn('Failed to clear groups store');
}
complete = false;
lastIndex = null;
while (!complete) {
// eslint-disable-next-line no-await-in-loop
const status = await migrateStoreToSQLite({