refactor: sliding sync: convert to lists-as-keys rather than indexes

Sister PR to https://github.com/matrix-org/matrix-js-sdk/pull/3076
pull/28217/head
Kegan Dougal 2023-01-18 17:19:12 +00:00
parent 4d2b27a96d
commit 21f0825703
4 changed files with 24 additions and 56 deletions

View File

@ -137,10 +137,10 @@ export class SlidingSyncManager {
this.listIdToIndex = {};
// by default use the encrypted subscription as that gets everything, which is a safer
// default than potentially missing member events.
this.slidingSync = new SlidingSync(proxyUrl, [], ENCRYPTED_SUBSCRIPTION, client, SLIDING_SYNC_TIMEOUT_MS);
this.slidingSync = new SlidingSync(proxyUrl, new Map(), ENCRYPTED_SUBSCRIPTION, client, SLIDING_SYNC_TIMEOUT_MS);
this.slidingSync.addCustomSubscription(UNENCRYPTED_SUBSCRIPTION_NAME, UNENCRYPTED_SUBSCRIPTION);
// set the space list
this.slidingSync.setList(this.getOrAllocateListIndex(SlidingSyncManager.ListSpaces), {
this.slidingSync.setList(SlidingSyncManager.ListSpaces, {
ranges: [[0, 20]],
sort: ["by_name"],
slow_get_all_rooms: true,
@ -182,38 +182,16 @@ export class SlidingSyncManager {
return null;
}
/**
* Allocate or retrieve the list index for an arbitrary list ID. For example SlidingSyncManager.ListSpaces
* @param listId A string which represents the list.
* @returns The index to use when registering lists or listening for callbacks.
*/
public getOrAllocateListIndex(listId: string): number {
let index = this.listIdToIndex[listId];
if (index === undefined) {
// assign next highest index
index = -1;
for (const id in this.listIdToIndex) {
const listIndex = this.listIdToIndex[id];
if (listIndex > index) {
index = listIndex;
}
}
index++;
this.listIdToIndex[listId] = index;
}
return index;
}
/**
* Ensure that this list is registered.
* @param listIndex The list index to register
* @param listKey The list key to register
* @param updateArgs The fields to update on the list.
* @returns The complete list request params
*/
public async ensureListRegistered(listIndex: number, updateArgs: PartialSlidingSyncRequest): Promise<MSC3575List> {
logger.debug("ensureListRegistered:::", listIndex, updateArgs);
public async ensureListRegistered(listKey: string, updateArgs: PartialSlidingSyncRequest): Promise<MSC3575List> {
logger.debug("ensureListRegistered:::", listKey, updateArgs);
await this.configureDefer.promise;
let list = this.slidingSync.getList(listIndex);
let list = this.slidingSync.getListParams(listKey);
if (!list) {
list = {
ranges: [[0, 20]],
@ -252,14 +230,14 @@ export class SlidingSyncManager {
try {
// if we only have range changes then call a different function so we don't nuke the list from before
if (updateArgs.ranges && Object.keys(updateArgs).length === 1) {
await this.slidingSync.setListRanges(listIndex, updateArgs.ranges);
await this.slidingSync.setListRanges(listKey, updateArgs.ranges);
} else {
await this.slidingSync.setList(listIndex, list);
await this.slidingSync.setList(listKey, list);
}
} catch (err) {
logger.debug("ensureListRegistered: update failed txn_id=", err);
}
return this.slidingSync.getList(listIndex);
return this.slidingSync.getListParams(listKey);
}
public async setRoomVisible(roomId: string, visible: boolean): Promise<string> {
@ -304,7 +282,6 @@ export class SlidingSyncManager {
*/
public async startSpidering(batchSize: number, gapBetweenRequestsMs: number): Promise<void> {
await sleep(gapBetweenRequestsMs); // wait a bit as this is called on first render so let's let things load
const listIndex = this.getOrAllocateListIndex(SlidingSyncManager.ListSearch);
let startIndex = batchSize;
let hasMore = true;
let firstTime = true;
@ -316,7 +293,7 @@ export class SlidingSyncManager {
[startIndex, endIndex],
];
if (firstTime) {
await this.slidingSync.setList(listIndex, {
await this.slidingSync.setList(SlidingSyncManager.ListSearch, {
// e.g [0,19] [20,39] then [0,19] [40,59]. We keep [0,20] constantly to ensure
// any changes to the list whilst spidering are caught.
ranges: ranges,
@ -342,7 +319,7 @@ export class SlidingSyncManager {
},
});
} else {
await this.slidingSync.setListRanges(listIndex, ranges);
await this.slidingSync.setListRanges(SlidingSyncManager.ListSearch, ranges);
}
// gradually request more over time
await sleep(gapBetweenRequestsMs);
@ -350,7 +327,7 @@ export class SlidingSyncManager {
// do nothing, as we reject only when we get interrupted but that's fine as the next
// request will include our data
}
hasMore = endIndex + 1 < this.slidingSync.getListData(listIndex)?.joinedCount;
hasMore = endIndex + 1 < this.slidingSync.getListData(SlidingSyncManager.ListSearch)?.joinedCount;
startIndex += batchSize;
firstTime = false;
}

View File

@ -340,9 +340,8 @@ export default class RoomSublist extends React.Component<IProps, IState> {
private onShowAllClick = async (): Promise<void> => {
if (this.slidingSyncMode) {
const slidingSyncIndex = SlidingSyncManager.instance.getOrAllocateListIndex(this.props.tagId);
const count = RoomListStore.instance.getCount(this.props.tagId);
await SlidingSyncManager.instance.ensureListRegistered(slidingSyncIndex, {
await SlidingSyncManager.instance.ensureListRegistered(this.props.tagId, {
ranges: [[0, count]],
});
}
@ -566,8 +565,7 @@ export default class RoomSublist extends React.Component<IProps, IState> {
let isAlphabetical = RoomListStore.instance.getTagSorting(this.props.tagId) === SortAlgorithm.Alphabetic;
let isUnreadFirst = RoomListStore.instance.getListOrder(this.props.tagId) === ListAlgorithm.Importance;
if (this.slidingSyncMode) {
const slidingSyncIndex = SlidingSyncManager.instance.getOrAllocateListIndex(this.props.tagId);
const slidingList = SlidingSyncManager.instance.slidingSync.getList(slidingSyncIndex);
const slidingList = SlidingSyncManager.instance.slidingSync.getListParams(this.props.tagId);
isAlphabetical = slidingList.sort[0] === "by_name";
isUnreadFirst = slidingList.sort[0] === "by_notification_level";
}

View File

@ -34,7 +34,6 @@ export const useSlidingSyncRoomSearch = (): {
const [rooms, setRooms] = useState<Room[]>([]);
const [loading, setLoading] = useState(false);
const listIndex = SlidingSyncManager.instance.getOrAllocateListIndex(SlidingSyncManager.ListSearch);
const [updateQuery, updateResult] = useLatestResult<{ term: string; limit?: number }, Room[]>(setRooms);
@ -50,14 +49,14 @@ export const useSlidingSyncRoomSearch = (): {
try {
setLoading(true);
await SlidingSyncManager.instance.ensureListRegistered(listIndex, {
await SlidingSyncManager.instance.ensureListRegistered(SlidingSyncManager.ListSearch, {
ranges: [[0, limit]],
filters: {
room_name_like: term,
},
});
const rooms = [];
const { roomIndexToRoomId } = SlidingSyncManager.instance.slidingSync.getListData(listIndex);
const { roomIndexToRoomId } = SlidingSyncManager.instance.slidingSync.getListData(SlidingSyncManager.ListSearch);
let i = 0;
while (roomIndexToRoomId[i]) {
const roomId = roomIndexToRoomId[i];
@ -78,7 +77,7 @@ export const useSlidingSyncRoomSearch = (): {
// TODO: delete the list?
}
},
[updateQuery, updateResult, listIndex],
[updateQuery, updateResult, SlidingSyncManager.ListSearch],
);
return {

View File

@ -89,15 +89,14 @@ export class SlidingRoomListStoreClass extends AsyncStoreWithClient<IState> impl
public async setTagSorting(tagId: TagID, sort: SortAlgorithm): Promise<void> {
logger.info("SlidingRoomListStore.setTagSorting ", tagId, sort);
this.tagIdToSortAlgo[tagId] = sort;
const slidingSyncIndex = this.context.slidingSyncManager.getOrAllocateListIndex(tagId);
switch (sort) {
case SortAlgorithm.Alphabetic:
await this.context.slidingSyncManager.ensureListRegistered(slidingSyncIndex, {
await this.context.slidingSyncManager.ensureListRegistered(tagId, {
sort: SlidingSyncSortToFilter[SortAlgorithm.Alphabetic],
});
break;
case SortAlgorithm.Recent:
await this.context.slidingSyncManager.ensureListRegistered(slidingSyncIndex, {
await this.context.slidingSyncManager.ensureListRegistered(tagId, {
sort: SlidingSyncSortToFilter[SortAlgorithm.Recent],
});
break;
@ -164,8 +163,7 @@ export class SlidingRoomListStoreClass extends AsyncStoreWithClient<IState> impl
// check all lists for each tag we know about and see if the room is there
const tags: TagID[] = [];
for (const tagId in this.tagIdToSortAlgo) {
const index = this.context.slidingSyncManager.getOrAllocateListIndex(tagId);
const listData = this.context.slidingSyncManager.slidingSync.getListData(index);
const listData = this.context.slidingSyncManager.slidingSync.getListData(tagId);
if (!listData) {
continue;
}
@ -259,11 +257,10 @@ export class SlidingRoomListStoreClass extends AsyncStoreWithClient<IState> impl
}
private onSlidingSyncListUpdate(
listIndex: number,
tagId: string,
joinCount: number,
roomIndexToRoomId: Record<number, string>,
): void {
const tagId = this.context.slidingSyncManager.listIdForIndex(listIndex);
this.counts[tagId] = joinCount;
this.refreshOrderedLists(tagId, roomIndexToRoomId);
// let the UI update
@ -295,8 +292,7 @@ export class SlidingRoomListStoreClass extends AsyncStoreWithClient<IState> impl
if (room) {
// resort it based on the slidingSync view of the list. This may cause this old sticky
// room to cease to exist.
const index = this.context.slidingSyncManager.getOrAllocateListIndex(tagId);
const listData = this.context.slidingSyncManager.slidingSync.getListData(index);
const listData = this.context.slidingSyncManager.slidingSync.getListData(tagId);
if (!listData) {
continue;
}
@ -334,9 +330,8 @@ export class SlidingRoomListStoreClass extends AsyncStoreWithClient<IState> impl
const sort = SortAlgorithm.Recent; // default to recency sort, TODO: read from config
this.tagIdToSortAlgo[tagId] = sort;
this.emit(LISTS_LOADING_EVENT, tagId, true);
const index = this.context.slidingSyncManager.getOrAllocateListIndex(tagId);
this.context.slidingSyncManager
.ensureListRegistered(index, {
.ensureListRegistered(tagId, {
filters: filter,
sort: SlidingSyncSortToFilter[sort],
})
@ -367,9 +362,8 @@ export class SlidingRoomListStoreClass extends AsyncStoreWithClient<IState> impl
);
this.emit(LISTS_LOADING_EVENT, tagId, true);
const index = this.context.slidingSyncManager.getOrAllocateListIndex(tagId);
this.context.slidingSyncManager
.ensureListRegistered(index, {
.ensureListRegistered(tagId, {
filters: filters,
})
.then(() => {