Merge pull request #1709 from matrix-org/luke/fix-group-store-redundant-requests
Fix group store redundant requests
This commit is contained in:
commit
bd81ed6587
1 changed files with 85 additions and 69 deletions
|
@ -19,6 +19,14 @@ import { groupMemberFromApiObject, groupRoomFromApiObject } from '../groups';
|
|||
import FlairStore from './FlairStore';
|
||||
import MatrixClientPeg from '../MatrixClientPeg';
|
||||
|
||||
function parseMembersResponse(response) {
|
||||
return response.chunk.map((apiMember) => groupMemberFromApiObject(apiMember));
|
||||
}
|
||||
|
||||
function parseRoomsResponse(response) {
|
||||
return response.chunk.map((apiRoom) => groupRoomFromApiObject(apiRoom));
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the group summary for a room and provides an API to change it and
|
||||
* other useful group APIs that may have an effect on the group summary.
|
||||
|
@ -38,65 +46,68 @@ export default class GroupStore extends EventEmitter {
|
|||
throw new Error('GroupStore needs a valid groupId to be created');
|
||||
}
|
||||
this.groupId = groupId;
|
||||
this._summary = {};
|
||||
this._rooms = [];
|
||||
this._members = [];
|
||||
this._invitedMembers = [];
|
||||
this._state = {};
|
||||
this._state[GroupStore.STATE_KEY.Summary] = {};
|
||||
this._state[GroupStore.STATE_KEY.GroupRooms] = [];
|
||||
this._state[GroupStore.STATE_KEY.GroupMembers] = [];
|
||||
this._state[GroupStore.STATE_KEY.GroupInvitedMembers] = [];
|
||||
this._ready = {};
|
||||
|
||||
this._fetchResourcePromise = {};
|
||||
this._resourceFetcher = {
|
||||
[GroupStore.STATE_KEY.Summary]: () => {
|
||||
return MatrixClientPeg.get()
|
||||
.getGroupSummary(this.groupId);
|
||||
},
|
||||
[GroupStore.STATE_KEY.GroupRooms]: () => {
|
||||
return MatrixClientPeg.get()
|
||||
.getGroupRooms(this.groupId)
|
||||
.then(parseRoomsResponse);
|
||||
},
|
||||
[GroupStore.STATE_KEY.GroupMembers]: () => {
|
||||
return MatrixClientPeg.get()
|
||||
.getGroupUsers(this.groupId)
|
||||
.then(parseMembersResponse);
|
||||
},
|
||||
[GroupStore.STATE_KEY.GroupInvitedMembers]: () => {
|
||||
return MatrixClientPeg.get()
|
||||
.getGroupInvitedUsers(this.groupId)
|
||||
.then(parseMembersResponse);
|
||||
},
|
||||
};
|
||||
|
||||
this.on('error', (err) => {
|
||||
console.error(`GroupStore for ${this.groupId} encountered error`, err);
|
||||
});
|
||||
}
|
||||
|
||||
_fetchMembers() {
|
||||
MatrixClientPeg.get().getGroupUsers(this.groupId).then((result) => {
|
||||
this._members = result.chunk.map((apiMember) => {
|
||||
return groupMemberFromApiObject(apiMember);
|
||||
});
|
||||
this._ready[GroupStore.STATE_KEY.GroupMembers] = true;
|
||||
this._notifyListeners();
|
||||
}).catch((err) => {
|
||||
console.error("Failed to get group member list: " + err);
|
||||
this.emit('error', err);
|
||||
});
|
||||
_fetchResource(stateKey) {
|
||||
// Ongoing request, ignore
|
||||
if (this._fetchResourcePromise[stateKey]) return;
|
||||
|
||||
MatrixClientPeg.get().getGroupInvitedUsers(this.groupId).then((result) => {
|
||||
this._invitedMembers = result.chunk.map((apiMember) => {
|
||||
return groupMemberFromApiObject(apiMember);
|
||||
});
|
||||
this._ready[GroupStore.STATE_KEY.GroupInvitedMembers] = true;
|
||||
const clientPromise = this._resourceFetcher[stateKey]();
|
||||
|
||||
// Indicate ongoing request
|
||||
this._fetchResourcePromise[stateKey] = clientPromise;
|
||||
|
||||
clientPromise.then((result) => {
|
||||
this._state[stateKey] = result;
|
||||
this._ready[stateKey] = true;
|
||||
this._notifyListeners();
|
||||
}).catch((err) => {
|
||||
// Invited users not visible to non-members
|
||||
if (err.httpStatus === 403) {
|
||||
if (stateKey === GroupStore.STATE_KEY.GroupInvitedMembers && err.httpStatus === 403) {
|
||||
return;
|
||||
}
|
||||
console.error("Failed to get group invited member list: " + err);
|
||||
this.emit('error', err);
|
||||
});
|
||||
}
|
||||
|
||||
_fetchSummary() {
|
||||
MatrixClientPeg.get().getGroupSummary(this.groupId).then((resp) => {
|
||||
this._summary = resp;
|
||||
this._ready[GroupStore.STATE_KEY.Summary] = true;
|
||||
this._notifyListeners();
|
||||
}).catch((err) => {
|
||||
console.error("Failed to get resource " + stateKey + ":" + err);
|
||||
this.emit('error', err);
|
||||
}).finally(() => {
|
||||
// Indicate finished request, allow for future fetches
|
||||
delete this._fetchResourcePromise[stateKey];
|
||||
});
|
||||
}
|
||||
|
||||
_fetchRooms() {
|
||||
MatrixClientPeg.get().getGroupRooms(this.groupId).then((resp) => {
|
||||
this._rooms = resp.chunk.map((apiRoom) => {
|
||||
return groupRoomFromApiObject(apiRoom);
|
||||
});
|
||||
this._ready[GroupStore.STATE_KEY.GroupRooms] = true;
|
||||
this._notifyListeners();
|
||||
}).catch((err) => {
|
||||
this.emit('error', err);
|
||||
});
|
||||
return clientPromise;
|
||||
}
|
||||
|
||||
_notifyListeners() {
|
||||
|
@ -108,10 +119,9 @@ export default class GroupStore extends EventEmitter {
|
|||
* immediately triggers an update to send the current state of the
|
||||
* store (which could be the initial state).
|
||||
*
|
||||
* XXX: This also causes a fetch of all group data, which effectively
|
||||
* causes 4 separate HTTP requests. This is bad, we should at least
|
||||
* deduplicate these in order to fix:
|
||||
* https://github.com/vector-im/riot-web/issues/5901
|
||||
* This also causes a fetch of all group data, which might cause
|
||||
* 4 separate HTTP requests, but only said requests aren't already
|
||||
* ongoing.
|
||||
*
|
||||
* @param {function} fn the function to call when the store updates.
|
||||
* @return {Object} tok a registration "token" with a single
|
||||
|
@ -123,9 +133,11 @@ export default class GroupStore extends EventEmitter {
|
|||
this.on('update', fn);
|
||||
// Call to set initial state (before fetching starts)
|
||||
this.emit('update');
|
||||
this._fetchSummary();
|
||||
this._fetchRooms();
|
||||
this._fetchMembers();
|
||||
|
||||
this._fetchResource(GroupStore.STATE_KEY.Summary);
|
||||
this._fetchResource(GroupStore.STATE_KEY.GroupRooms);
|
||||
this._fetchResource(GroupStore.STATE_KEY.GroupMembers);
|
||||
this._fetchResource(GroupStore.STATE_KEY.GroupInvitedMembers);
|
||||
|
||||
// Similar to the Store of flux/utils, we return a "token" that
|
||||
// can be used to unregister the listener.
|
||||
|
@ -145,90 +157,94 @@ export default class GroupStore extends EventEmitter {
|
|||
}
|
||||
|
||||
getSummary() {
|
||||
return this._summary;
|
||||
return this._state[GroupStore.STATE_KEY.Summary];
|
||||
}
|
||||
|
||||
getGroupRooms() {
|
||||
return this._rooms;
|
||||
return this._state[GroupStore.STATE_KEY.GroupRooms];
|
||||
}
|
||||
|
||||
getGroupMembers( ) {
|
||||
return this._members;
|
||||
getGroupMembers() {
|
||||
return this._state[GroupStore.STATE_KEY.GroupMembers];
|
||||
}
|
||||
|
||||
getGroupInvitedMembers( ) {
|
||||
return this._invitedMembers;
|
||||
getGroupInvitedMembers() {
|
||||
return this._state[GroupStore.STATE_KEY.GroupInvitedMembers];
|
||||
}
|
||||
|
||||
getGroupPublicity() {
|
||||
return this._summary.user ? this._summary.user.is_publicised : null;
|
||||
return this._state[GroupStore.STATE_KEY.Summary].user ?
|
||||
this._state[GroupStore.STATE_KEY.Summary].user.is_publicised : null;
|
||||
}
|
||||
|
||||
isUserPrivileged() {
|
||||
return this._summary.user ? this._summary.user.is_privileged : null;
|
||||
return this._state[GroupStore.STATE_KEY.Summary].user ?
|
||||
this._state[GroupStore.STATE_KEY.Summary].user.is_privileged : null;
|
||||
}
|
||||
|
||||
addRoomToGroup(roomId, isPublic) {
|
||||
return MatrixClientPeg.get()
|
||||
.addRoomToGroup(this.groupId, roomId, isPublic)
|
||||
.then(this._fetchRooms.bind(this));
|
||||
.then(this._fetchResource.bind(this, GroupStore.STATE_KEY.GroupRooms));
|
||||
}
|
||||
|
||||
updateGroupRoomVisibility(roomId, isPublic) {
|
||||
return MatrixClientPeg.get()
|
||||
.updateGroupRoomVisibility(this.groupId, roomId, isPublic)
|
||||
.then(this._fetchRooms.bind(this));
|
||||
.then(this._fetchResource.bind(this, GroupStore.STATE_KEY.GroupRooms));
|
||||
}
|
||||
|
||||
removeRoomFromGroup(roomId) {
|
||||
return MatrixClientPeg.get()
|
||||
.removeRoomFromGroup(this.groupId, roomId)
|
||||
// Room might be in the summary, refresh just in case
|
||||
.then(this._fetchSummary.bind(this))
|
||||
.then(this._fetchRooms.bind(this));
|
||||
.then(this._fetchResource.bind(this, GroupStore.STATE_KEY.Summary))
|
||||
.then(this._fetchResource.bind(this, GroupStore.STATE_KEY.GroupRooms));
|
||||
}
|
||||
|
||||
inviteUserToGroup(userId) {
|
||||
return MatrixClientPeg.get().inviteUserToGroup(this.groupId, userId)
|
||||
.then(this._fetchMembers.bind(this));
|
||||
.then(this._fetchResource.bind(this, GroupStore.STATE_KEY.GroupInvitedMembers));
|
||||
}
|
||||
|
||||
acceptGroupInvite() {
|
||||
return MatrixClientPeg.get().acceptGroupInvite(this.groupId)
|
||||
// The user might be able to see more rooms now
|
||||
.then(this._fetchRooms.bind(this))
|
||||
.then(this._fetchResource.bind(this, GroupStore.STATE_KEY.GroupRooms))
|
||||
// The user should now appear as a member
|
||||
.then(this._fetchMembers.bind(this));
|
||||
.then(this._fetchResource.bind(this, GroupStore.STATE_KEY.GroupMembers))
|
||||
// The user should now not appear as an invited member
|
||||
.then(this._fetchResource.bind(this, GroupStore.STATE_KEY.GroupInvitedMembers));
|
||||
}
|
||||
|
||||
addRoomToGroupSummary(roomId, categoryId) {
|
||||
return MatrixClientPeg.get()
|
||||
.addRoomToGroupSummary(this.groupId, roomId, categoryId)
|
||||
.then(this._fetchSummary.bind(this));
|
||||
.then(this._fetchResource.bind(this, GroupStore.STATE_KEY.Summary));
|
||||
}
|
||||
|
||||
addUserToGroupSummary(userId, roleId) {
|
||||
return MatrixClientPeg.get()
|
||||
.addUserToGroupSummary(this.groupId, userId, roleId)
|
||||
.then(this._fetchSummary.bind(this));
|
||||
.then(this._fetchResource.bind(this, GroupStore.STATE_KEY.Summary));
|
||||
}
|
||||
|
||||
removeRoomFromGroupSummary(roomId) {
|
||||
return MatrixClientPeg.get()
|
||||
.removeRoomFromGroupSummary(this.groupId, roomId)
|
||||
.then(this._fetchSummary.bind(this));
|
||||
.then(this._fetchResource.bind(this, GroupStore.STATE_KEY.Summary));
|
||||
}
|
||||
|
||||
removeUserFromGroupSummary(userId) {
|
||||
return MatrixClientPeg.get()
|
||||
.removeUserFromGroupSummary(this.groupId, userId)
|
||||
.then(this._fetchSummary.bind(this));
|
||||
.then(this._fetchResource.bind(this, GroupStore.STATE_KEY.Summary));
|
||||
}
|
||||
|
||||
setGroupPublicity(isPublished) {
|
||||
return MatrixClientPeg.get()
|
||||
.setGroupPublicity(this.groupId, isPublished)
|
||||
.then(() => { FlairStore.invalidatePublicisedGroups(MatrixClientPeg.get().credentials.userId); })
|
||||
.then(this._fetchSummary.bind(this));
|
||||
.then(this._fetchResource.bind(this, GroupStore.STATE_KEY.Summary));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue