Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions src/channel_state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,15 @@ export class ChannelState {
);
}

pruneOldest(maxMessages: number) {
const currentIndex = this.messageSets.findIndex((s) => s.isCurrent);
if (this.messageSets[currentIndex].isLatest) {
const newMessages = this.messageSets[currentIndex].messages;
this.messageSets[currentIndex].messages = newMessages.slice(-maxMessages);
this.messageSets[currentIndex].pagination.hasPrev = true;
}
}

/**
* addMessageSorted - Add a message to the state
*
Expand Down Expand Up @@ -821,7 +830,7 @@ export class ChannelState {
messages: [],
isLatest: true,
isCurrent: true,
pagination: DEFAULT_MESSAGE_SET_PAGINATION,
pagination: { ...DEFAULT_MESSAGE_SET_PAGINATION },
},
];
}
Expand Down Expand Up @@ -1017,7 +1026,7 @@ export class ChannelState {
messages: [],
isCurrent: false,
isLatest: false,
pagination: DEFAULT_MESSAGE_SET_PAGINATION,
pagination: { ...DEFAULT_MESSAGE_SET_PAGINATION },
});
targetMessageSetIndex = this.messageSets.length - 1;
} else {
Expand All @@ -1026,7 +1035,7 @@ export class ChannelState {
messages: [],
isCurrent: false,
isLatest,
pagination: DEFAULT_MESSAGE_SET_PAGINATION, // fixme: it is problematic decide about pagination without having data
pagination: { ...DEFAULT_MESSAGE_SET_PAGINATION }, // fixme: it is problematic decide about pagination without having data
});
if (isLatest) {
this.messageSets.slice(1).forEach((set) => {
Expand Down
11 changes: 7 additions & 4 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
export const DEFAULT_QUERY_CHANNELS_MESSAGE_LIST_PAGE_SIZE = 25;
export const DEFAULT_QUERY_CHANNEL_MESSAGE_LIST_PAGE_SIZE = 100;
export const DEFAULT_MESSAGE_SET_PAGINATION = { hasNext: false, hasPrev: false };
export const DEFAULT_MESSAGE_SET_PAGINATION = Object.freeze({
hasNext: false,
hasPrev: false,
});
export const DEFAULT_UPLOAD_SIZE_LIMIT_BYTES = 100 * 1024 * 1024; // 100 MB
export const API_MAX_FILES_ALLOWED_PER_MESSAGE = 10;
export const MAX_CHANNEL_MEMBER_COUNT_IN_CHANNEL_QUERY = 100;
export const RESERVED_UPDATED_MESSAGE_FIELDS = {
export const RESERVED_UPDATED_MESSAGE_FIELDS = Object.freeze({
// Dates should not be converted back to ISO strings as JS looses precision on them (milliseconds)
created_at: true,
deleted_at: true,
Expand All @@ -25,7 +28,7 @@ export const RESERVED_UPDATED_MESSAGE_FIELDS = {
html: true,
__html: true,
user: true,
} as const;
export const LOCAL_MESSAGE_FIELDS = { error: true } as const;
});
export const LOCAL_MESSAGE_FIELDS = Object.freeze({ error: true });
export const DEFAULT_QUERY_CHANNELS_RETRY_COUNT = 3;
export const DEFAULT_QUERY_CHANNELS_MS_BETWEEN_RETRIES = 1000; // 1 second
81 changes: 81 additions & 0 deletions test/unit/channel_state.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -910,6 +910,87 @@ describe('ChannelState addMessagesSorted', function () {
});
});

describe('ChannelState message pruning', () => {
let channelState;
let initialMessages = [];

beforeEach(() => {
channelState = new ChannelState();
initialMessages = Array.from({ length: 10 }, () =>
generateMsg({ date: toISOString(100) }),
);
channelState.addMessagesSorted(initialMessages);
});

it('should prune messages from the end when we are in the latest set', () => {
expect(channelState.messageSets.length).to.be.equal(1);
expect(channelState.messageSets[0].isLatest).to.be.equal(true);
expect(channelState.messageSets[0].isCurrent).to.be.equal(true);
expect(channelState.messages.length).to.be.equal(10);
expect(channelState.messagePagination.hasPrev).to.be.equal(false);

const previousHasNext = channelState.messagePagination.hasNext;

channelState.pruneOldest(5);

expect(channelState.messageSets.length).to.be.equal(1);
expect(channelState.messages.length).to.be.equal(5);
expect(channelState.messagePagination.hasPrev).to.be.equal(true);
expect(channelState.messagePagination.hasNext).to.be.equal(previousHasNext);
});

it('should do nothing if the current message set is not also the latest', () => {
expect(channelState.messageSets.length).to.be.equal(1);

channelState.messageSets[0].isLatest = false;

expect(channelState.messages.length).to.be.equal(10);
expect(channelState.messagePagination.hasPrev).to.be.equal(false);

channelState.pruneOldest(5);

expect(channelState.messages.length).to.be.equal(10);
expect(channelState.messagePagination.hasPrev).to.be.equal(false);
});

it('should prune the correct messageSet', () => {
channelState.addMessagesSorted(
Array.from({ length: 10 }, () => generateMsg({ date: toISOString(50) })),
false,
true,
true,
'new',
);

expect(channelState.messageSets.length).to.be.equal(2);

channelState.pruneOldest(5);

const currentMessageSet = channelState.messageSets.find((ms) => ms.isCurrent);
const otherMessageSet = channelState.messageSets.find((ms) => !ms.isCurrent);

expect(currentMessageSet.messages.length).to.be.equal(5);
expect(currentMessageSet.pagination.hasPrev).to.be.equal(true);
expect(channelState.messages).to.be.equal(currentMessageSet.messages);

expect(otherMessageSet.messages.length).to.be.equal(10);
expect(otherMessageSet.pagination.hasPrev).to.be.equal(false);
});

it('should correctly apply pruning', () => {
channelState.pruneOldest(5);

expect(channelState.messages.length).to.be.equal(5);
for (const message of initialMessages.slice(-5)) {
expect(channelState.messages.some((m) => m.id === message.id)).to.be.equal(true);
}

for (const message of initialMessages.slice(0, 5)) {
expect(channelState.messages.some((m) => m.id === message.id)).to.be.equal(false);
}
});
});

describe('ChannelState reactions', () => {
const message = generateMsg();
let state;
Expand Down