1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-11-29 16:43:09 +03:00

store support for removing out of band members for a room

This commit is contained in:
Bruno Windels
2018-08-31 14:40:56 +02:00
parent b8744a79ae
commit f8ea1702f8
4 changed files with 79 additions and 8 deletions

View File

@@ -71,7 +71,7 @@ function selectQuery(store, keyRange, resultMapper) {
}); });
} }
function promiseifyTxn(txn) { function txnAsPromise(txn) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
txn.oncomplete = function(event) { txn.oncomplete = function(event) {
resolve(event); resolve(event);
@@ -82,7 +82,7 @@ function promiseifyTxn(txn) {
}); });
} }
function promiseifyRequest(req) { function reqAsEventPromise(req) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
req.onsuccess = function(event) { req.onsuccess = function(event) {
resolve(event); resolve(event);
@@ -93,6 +93,17 @@ function promiseifyRequest(req) {
}); });
} }
function reqAsPromise(req) {
return new Promise((resolve, reject) => {
req.onsuccess = () => resolve(req);
req.onerror = (err) => reject(err);
});
}
function reqAsCursorPromise(req) {
return reqAsEventPromise(req).then((event) => event.target.result);
}
/** /**
* Does the actual reading from and writing to the indexeddb * Does the actual reading from and writing to the indexeddb
* *
@@ -159,7 +170,7 @@ LocalIndexedDBStoreBackend.prototype = {
console.log( console.log(
`LocalIndexedDBStoreBackend.connect: awaiting connection...`, `LocalIndexedDBStoreBackend.connect: awaiting connection...`,
); );
return promiseifyRequest(req).then((ev) => { return reqAsEventPromise(req).then((ev) => {
console.log( console.log(
`LocalIndexedDBStoreBackend.connect: connected`, `LocalIndexedDBStoreBackend.connect: connected`,
); );
@@ -265,7 +276,7 @@ LocalIndexedDBStoreBackend.prototype = {
const tx = this.db.transaction(["oob_membership_events"], "readwrite"); const tx = this.db.transaction(["oob_membership_events"], "readwrite");
const store = tx.objectStore("oob_membership_events"); const store = tx.objectStore("oob_membership_events");
const eventPuts = membershipEvents.map((e) => { const eventPuts = membershipEvents.map((e) => {
const putPromise = promiseifyRequest(store.put(e)); const putPromise = reqAsEventPromise(store.put(e));
// ignoring the result makes sure we discard the IDB success event // ignoring the result makes sure we discard the IDB success event
// ASAP, and not create a potentially big array containing them // ASAP, and not create a potentially big array containing them
// unneccesarily later on by calling Promise.all. // unneccesarily later on by calling Promise.all.
@@ -281,7 +292,7 @@ LocalIndexedDBStoreBackend.prototype = {
oob_written: true, oob_written: true,
state_key: 0, state_key: 0,
}; };
const markerPut = promiseifyRequest(store.put(markerObject)); const markerPut = reqAsEventPromise(store.put(markerObject));
const allPuts = eventPuts.concat(markerPut); const allPuts = eventPuts.concat(markerPut);
// ignore the empty array Promise.all creates // ignore the empty array Promise.all creates
// as this method should just resolve // as this method should just resolve
@@ -292,6 +303,55 @@ LocalIndexedDBStoreBackend.prototype = {
}); });
}, },
clearOutOfBandMembers: async function(roomId) {
// the approach to delete all members for a room
// is to get the min and max state key from the index
// for that room, and then delete between those
// keys in the store.
// this should be way faster than deleting every member
// individually for a large room.
const readTx = this.db.transaction(
["oob_membership_events"],
"readonly");
const store = readTx.objectStore("oob_membership_events");
const roomIndex = store.index("room");
const roomRange = IDBKeyRange.only(roomId);
const indexCount = (await reqAsPromise(roomIndex.count(roomRange))).result;
const minStateKeyProm = reqAsCursorPromise(
roomIndex.openKeyCursor(roomRange, "next"),
).then((cursor) => cursor && cursor.primaryKey[1]);
const maxStateKeyProm = reqAsCursorPromise(
roomIndex.openKeyCursor(roomRange, "prev"),
).then((cursor) => cursor && cursor.primaryKey[1]);
const [minStateKey, maxStateKey] = await Promise.all(
[minStateKeyProm, maxStateKeyProm]);
const writeTx = this.db.transaction(
["oob_membership_events"],
"readwrite");
const writeStore = writeTx.objectStore("oob_membership_events");
const membersKeyRange = IDBKeyRange.bound(
[roomId, minStateKey],
[roomId, maxStateKey],
);
const count =
(await reqAsPromise(writeStore.count(membersKeyRange))).result;
// Leaving this for now to make sure
if (count !== indexCount) {
console.error(`not deleting all members, ` +
`oob_membership_events and its index room ` +
`dont seem to have the same key order`);
}
console.log(`LL: Deleting ${count} users + marker for ` +
`room ${roomId}, with key range:`,
[roomId, minStateKey], [roomId, maxStateKey]);
await reqAsPromise(writeStore.delete(membersKeyRange));
},
/** /**
* Clear the entire database. This should be used when logging out of a client * Clear the entire database. This should be used when logging out of a client
* to prevent mixing data between accounts. * to prevent mixing data between accounts.
@@ -389,7 +449,7 @@ LocalIndexedDBStoreBackend.prototype = {
roomsData: roomsData, roomsData: roomsData,
groupsData: groupsData, groupsData: groupsData,
}); // put == UPSERT }); // put == UPSERT
return promiseifyTxn(txn); return txnAsPromise(txn);
}); });
}, },
@@ -406,7 +466,7 @@ LocalIndexedDBStoreBackend.prototype = {
for (let i = 0; i < accountData.length; i++) { for (let i = 0; i < accountData.length; i++) {
store.put(accountData[i]); // put == UPSERT store.put(accountData[i]); // put == UPSERT
} }
return promiseifyTxn(txn); return txnAsPromise(txn);
}); });
}, },
@@ -428,7 +488,7 @@ LocalIndexedDBStoreBackend.prototype = {
event: tuple[1], event: tuple[1],
}); // put == UPSERT }); // put == UPSERT
} }
return promiseifyTxn(txn); return txnAsPromise(txn);
}); });
}, },

View File

@@ -110,6 +110,10 @@ RemoteIndexedDBStoreBackend.prototype = {
return this._doCmd('setOutOfBandMembers', [roomId, membershipEvents]); return this._doCmd('setOutOfBandMembers', [roomId, membershipEvents]);
}, },
clearOutOfBandMembers: function(roomId) {
return this._doCmd('clearOutOfBandMembers', [roomId]);
},
/** /**
* Load all user presence events from the database. This is not cached. * Load all user presence events from the database. This is not cached.
* @return {Promise<Object[]>} A list of presence events in their raw form. * @return {Promise<Object[]>} A list of presence events in their raw form.

View File

@@ -95,6 +95,9 @@ class IndexedDBStoreWorker {
case 'getOutOfBandMembers': case 'getOutOfBandMembers':
prom = this.backend.getOutOfBandMembers(msg.args[0]); prom = this.backend.getOutOfBandMembers(msg.args[0]);
break; break;
case 'clearOutOfBandMembers':
prom = this.backend.clearOutOfBandMembers(msg.args[0]);
break;
case 'setOutOfBandMembers': case 'setOutOfBandMembers':
prom = this.backend.setOutOfBandMembers(msg.args[0], msg.args[1]); prom = this.backend.setOutOfBandMembers(msg.args[0], msg.args[1]);
break; break;

View File

@@ -242,4 +242,8 @@ IndexedDBStore.prototype.setOutOfBandMembers = function(roomId, membershipEvents
return this.backend.setOutOfBandMembers(roomId, membershipEvents); return this.backend.setOutOfBandMembers(roomId, membershipEvents);
}; };
IndexedDBStore.prototype.clearOutOfBandMembers = function(roomId) {
return this.backend.clearOutOfBandMembers(roomId);
};
module.exports.IndexedDBStore = IndexedDBStore; module.exports.IndexedDBStore = IndexedDBStore;