From 4144b0b2813d07fc28bd483f50e70c33fd1c15f5 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 19 Aug 2020 16:44:09 +0200 Subject: [PATCH] move memberlist load code out of Room --- src/matrix/room/Room.js | 61 ++++--------------------- src/matrix/room/members/load.js | 79 +++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 52 deletions(-) create mode 100644 src/matrix/room/members/load.js diff --git a/src/matrix/room/Room.js b/src/matrix/room/Room.js index e2937b65..8695db97 100644 --- a/src/matrix/room/Room.js +++ b/src/matrix/room/Room.js @@ -22,7 +22,7 @@ import {Timeline} from "./timeline/Timeline.js"; import {FragmentIdComparer} from "./timeline/FragmentIdComparer.js"; import {SendQueue} from "./sending/SendQueue.js"; import {WrappedError} from "../error.js" -import {RoomMember} from "./members/RoomMember.js"; +import {fetchOrloadMembers} from "./members/load.js"; import {MemberList} from "./members/MemberList.js"; export class Room extends EventEmitter { @@ -98,57 +98,14 @@ export class Room extends EventEmitter { this._memberList.retain(); return this._memberList; } else { - let members; - if (!this._summary.hasFetchedMembers) { - const paginationToken = this._summary.lastPaginationToken; - // TODO: move all of this out of Room - - // if any members are changed by sync while we're fetching members, - // they will end up here, so we check not to override them - this._changedMembersDuringSync = new Map(); - - const memberResponse = await this._hsApi.members(this._roomId, {at: paginationToken}).response; - - const txn = await this._storage.readWriteTxn([ - this._storage.storeNames.roomSummary, - this._storage.storeNames.roomMembers, - ]); - const summaryChanges = this._summary.writeHasFetchedMembers(true, txn); - const {roomMembers} = txn; - const memberEvents = memberResponse.chunk; - if (!Array.isArray(memberEvents)) { - throw new Error("malformed"); - } - members = await Promise.all(memberEvents.map(async memberEvent => { - const userId = memberEvent?.state_key; - if (!userId) { - throw new Error("malformed"); - } - // this member was changed during a sync that happened while calling /members - // and thus is more recent. Fetch it instead of overwriting. - if (this._changedMembersDuringSync.has(userId)) { - const memberData = await roomMembers.get(this._roomId, userId); - if (memberData) { - return new RoomMember(memberData); - } - } else { - const member = RoomMember.fromMemberEvent(this._roomId, memberEvent); - if (member) { - roomMembers.set(member.serialize()); - } - return member; - } - })); - this._changedMembersDuringSync = null; - await txn.complete(); - this._summary.applyChanges(summaryChanges); - } else { - const txn = await this._storage.readTxn([ - this._storage.storeNames.roomMembers, - ]); - const memberDatas = await txn.roomMembers.getAll(this._roomId); - members = memberDatas.map(d => new RoomMember(d)); - } + const members = await fetchOrloadMembers({ + summary: this._summary, + roomId: this._roomId, + hsApi: this._hsApi, + storage: this._storage, + // to handle race between /members and /sync + setChangedMembersMap: map => this._changedMembersDuringSync = map, + }); this._memberList = new MemberList({ members, closeCallback: () => { this._memberList = null; } diff --git a/src/matrix/room/members/load.js b/src/matrix/room/members/load.js new file mode 100644 index 00000000..083eb13a --- /dev/null +++ b/src/matrix/room/members/load.js @@ -0,0 +1,79 @@ +/* +Copyright 2020 Bruno Windels +Copyright 2020 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import {RoomMember} from "./RoomMember.js"; + +async function loadMembers({roomId, storage}) { + const txn = await storage.readTxn([ + storage.storeNames.roomMembers, + ]); + const memberDatas = await txn.roomMembers.getAll(roomId); + return memberDatas.map(d => new RoomMember(d)); +} + +async function fetchMembers({summary, roomId, hsApi, storage, setChangedMembersMap}) { + // if any members are changed by sync while we're fetching members, + // they will end up here, so we check not to override them + const changedMembersDuringSync = new Map(); + setChangedMembersMap(changedMembersDuringSync); + + const memberResponse = await hsApi.members(roomId, {at: summary.lastPaginationToken}).response; + + const txn = await storage.readWriteTxn([ + storage.storeNames.roomSummary, + storage.storeNames.roomMembers, + ]); + const summaryChanges = summary.writeHasFetchedMembers(true, txn); + const {roomMembers} = txn; + const memberEvents = memberResponse.chunk; + if (!Array.isArray(memberEvents)) { + throw new Error("malformed"); + } + const members = await Promise.all(memberEvents.map(async memberEvent => { + const userId = memberEvent?.state_key; + if (!userId) { + throw new Error("malformed"); + } + // this member was changed during a sync that happened while calling /members + // and thus is more recent, so don't overwrite + if (changedMembersDuringSync.has(userId)) { + const memberData = await roomMembers.get(roomId, userId); + if (memberData) { + return new RoomMember(memberData); + } + } else { + const member = RoomMember.fromMemberEvent(roomId, memberEvent); + if (member) { + roomMembers.set(member.serialize()); + } + return member; + } + })); + setChangedMembersMap(null); + await txn.complete(); + summary.applyChanges(summaryChanges); + return members; +} + +export async function fetchOrLoadMembers(options) { + const {summary} = options; + if (!summary.hasFetchedMembers) { + return fetchMembers(options); + } else { + return loadMembers(options); + } +}