Skip to content

Commit 5becfc8

Browse files
committed
feat(sliding-sync): prune inactive room timelines to reduce memory usage
When a room subscription is removed (user navigates away), reset its live timeline if it has accumulated more than 150 events. This frees the in-memory event chain for rooms the user is no longer actively viewing. The full event history remains on disk (IndexedDBStore) and will be re-fetched from the server subscription on next open, so this is transparent to the user.
1 parent 9db324f commit 5becfc8

1 file changed

Lines changed: 22 additions & 0 deletions

File tree

src/client/slidingSync.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ const UNENCRYPTED_SUBSCRIPTION_KEY = 'unencrypted';
5151
// Timeline limit for the active-room subscription (full history load).
5252
// List entries always use LIST_TIMELINE_LIMIT=1 for lightweight previews.
5353
const ACTIVE_ROOM_TIMELINE_LIMIT = 50;
54+
// Rooms with more than this many events in memory are pruned when they go inactive.
55+
// The full history remains on disk (IndexedDBStore); it is re-loaded on next open.
56+
const PRUNE_TIMELINE_THRESHOLD = 150;
5457

5558
export type PartialSlidingSyncRequest = {
5659
filters?: MSC3575List['filters'];
@@ -540,6 +543,24 @@ export class SlidingSyncManager {
540543
this.presenceExtension.setEnabled(enabled);
541544
}
542545

546+
/**
547+
* Reset the live timeline for a room that is no longer actively viewed,
548+
* freeing its in-memory event chain. Only fires when the room has accumulated
549+
* more than PRUNE_TIMELINE_THRESHOLD events. The full history remains on disk
550+
* (IndexedDBStore) and is re-loaded from the server subscription on next open.
551+
*/
552+
private pruneRoomTimeline(roomId: string): void {
553+
const room = this.mx.getRoom(roomId);
554+
if (!room) return;
555+
const tl = room.getUnfilteredTimelineSet().getLiveTimeline();
556+
if (tl.getEvents().length <= PRUNE_TIMELINE_THRESHOLD) return;
557+
room.getUnfilteredTimelineSet().resetLiveTimeline();
558+
debugLog.info('timeline', 'Pruned room timeline from memory', {
559+
roomId,
560+
threshold: PRUNE_TIMELINE_THRESHOLD,
561+
});
562+
}
563+
543564
public getDiagnostics(): SlidingSyncDiagnostics {
544565
return {
545566
proxyBaseUrl: this.proxyBaseUrl,
@@ -946,6 +967,7 @@ export class SlidingSyncManager {
946967
remainingSubscriptions: this.activeRoomSubscriptions.size,
947968
syncCycle: this.syncCount,
948969
});
970+
this.pruneRoomTimeline(roomId);
949971
}
950972

951973
public static async probe(

0 commit comments

Comments
 (0)