You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-11-29 16:43:09 +03:00
Merge pull request #711 from matrix-org/bwindels/clearidbmembersonleave
Remove lazy loaded members when leaving room
This commit is contained in:
@@ -443,6 +443,22 @@ RoomState.prototype.markOutOfBandMembersFailed = function() {
|
|||||||
this._oobMemberFlags.status = OOB_STATUS_NOTSTARTED;
|
this._oobMemberFlags.status = OOB_STATUS_NOTSTARTED;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the loaded out-of-band members
|
||||||
|
*/
|
||||||
|
RoomState.prototype.clearOutOfBandMembers = function() {
|
||||||
|
let count = 0;
|
||||||
|
Object.keys(this.members).forEach((userId) => {
|
||||||
|
const member = this.members[userId];
|
||||||
|
if (member.isOutOfBand()) {
|
||||||
|
++count;
|
||||||
|
delete this.members[userId];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log(`LL: RoomState removed ${count} members...`);
|
||||||
|
this._oobMemberFlags.status = OOB_STATUS_NOTSTARTED;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the loaded out-of-band members.
|
* Sets the loaded out-of-band members.
|
||||||
* @param {MatrixEvent[]} stateEvents array of membership state events
|
* @param {MatrixEvent[]} stateEvents array of membership state events
|
||||||
|
|||||||
@@ -456,6 +456,30 @@ Room.prototype.loadMembersIfNeeded = function() {
|
|||||||
return this._membersPromise;
|
return this._membersPromise;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the lazily loaded members from storage if needed
|
||||||
|
*/
|
||||||
|
Room.prototype.clearLoadedMembersIfNeeded = async function() {
|
||||||
|
if (this._opts.lazyLoadMembers && this._membersPromise) {
|
||||||
|
await this.loadMembersIfNeeded();
|
||||||
|
await this._client.store.clearOutOfBandMembers(this.roomId);
|
||||||
|
this.currentState.clearOutOfBandMembers();
|
||||||
|
this._membersPromise = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* called when sync receives this room in the leave section
|
||||||
|
* to do cleanup after leaving a room. Possibly called multiple times.
|
||||||
|
*/
|
||||||
|
Room.prototype.onLeft = function() {
|
||||||
|
this.clearLoadedMembersIfNeeded().catch((err) => {
|
||||||
|
console.error(`error after clearing loaded members from ` +
|
||||||
|
`room ${this.roomId} after leaving`);
|
||||||
|
console.dir(err);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset the live timeline of all timelineSets, and start new ones.
|
* Reset the live timeline of all timelineSets, and start new ones.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -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,44 @@ 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 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],
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(`LL: Deleting all users + marker in storage 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 +438,7 @@ LocalIndexedDBStoreBackend.prototype = {
|
|||||||
roomsData: roomsData,
|
roomsData: roomsData,
|
||||||
groupsData: groupsData,
|
groupsData: groupsData,
|
||||||
}); // put == UPSERT
|
}); // put == UPSERT
|
||||||
return promiseifyTxn(txn);
|
return txnAsPromise(txn);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -406,7 +455,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 +477,7 @@ LocalIndexedDBStoreBackend.prototype = {
|
|||||||
event: tuple[1],
|
event: tuple[1],
|
||||||
}); // put == UPSERT
|
}); // put == UPSERT
|
||||||
}
|
}
|
||||||
return promiseifyTxn(txn);
|
return txnAsPromise(txn);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -272,6 +272,10 @@ StubStore.prototype = {
|
|||||||
setOutOfBandMembers: function() {
|
setOutOfBandMembers: function() {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
clearOutOfBandMembers: function() {
|
||||||
|
return Promise.resolve();
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Stub Store class. */
|
/** Stub Store class. */
|
||||||
|
|||||||
@@ -1141,6 +1141,8 @@ SyncApi.prototype._processSyncResponse = async function(
|
|||||||
accountDataEvents.forEach(function(e) {
|
accountDataEvents.forEach(function(e) {
|
||||||
client.emit("event", e);
|
client.emit("event", e);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
room.onLeft();
|
||||||
});
|
});
|
||||||
|
|
||||||
// update the notification timeline, if appropriate.
|
// update the notification timeline, if appropriate.
|
||||||
|
|||||||
Reference in New Issue
Block a user