I am getting messages via stompjs and I am having issues when trying to push that message to the top of the table. Once I change the page and go back the the new instance in cache gets created and it always pushes the messages to the latest created cache entry.
interface GetMessagesBody {
messageStatus?: MessageStatus;
page: number;
size: number;
sort: BackendSortingOrderModel;
}
interface MessagesModel {
messages?: Message[];
totalElements: number;
totalPages: number;
}
const messagesAdapter = createEntityAdapter<MessagesModel>({
selectId: (message) => {
return 'test';
// Since technically I only have 1 cache entry I just added a test string to match it in cache
},
});
let messageSubs: StompSubscription[] = [];
const unsubscribeMessages = () => {
if (messageSubs.length > 0) {
messageSubs.forEach((sub) => {
try {
sub.unsubscribe();
} catch (e) {
log.error(e);
}
});
messageSubs = [];
}
};
endpoints: (builder) => ({
getMessages: builder.query<
EntityState<MessagesModel>,
GetMessagesBody
>({
query: (searchParams) => ({
url: `/messages`,
method: 'GET',
params: {
...searchParams,
sort: [`${searchParams.sort.id},${searchParams.sort.order}`],
},
}),
providesTags: ['Messages'],
transformResponse: (messages: PageMessagesEntry) => {
return messagesAdapter.addOne(messagesAdapter.getInitialState(), {
totalElements: messages.totalElements ?? 0,
totalPages: messages.totalPages ?? 0,
messages: messages.content?.map((item) => item),
});
},
async onCacheEntryAdded(
arg,
{
updateCachedData,
cacheDataLoaded,
cacheEntryRemoved,
getState,
}
) {
try {
// wait for the initial query to resolve before proceeding
await cacheDataLoaded;
if (stompClientInstance && stompClientInstance.connected) {
unsubscribeMessages ();
const topics = ['/topic/message-created', '/topic/message-updated'];
topics.forEach((topic) => {
const sub = stompClientInstance?.subscribe(topic, (message) => {
if (message.body === undefined) return;
const message = JSON.parse(message.body) as Message;
console.info('arg', arg);
// THIS "arg" that I get would always display the wrong page once the user
// goes to the next page and returns
if (!arg.messageStatus) {
updateCachedData((draft) => {
const existingMessages = draft.entities['test']?.messages;
const filteredMessages =
existingMessages ?.filter(
(item) => item.id !== message.id
) || [];
const totalPages = draft.entities['test']?.totalPages ?? 0;
const totalElements =
draft.entities['test']?.totalElements ?? 0;
messagesAdapter.updateOne(draft, {
id: 'test',
changes: {
//HERE I DO THE LOGIC FOR UPDATING THAT CACHE ITEM SINCE THE MESSAGE
// CAN GET RESOLVED AND I GET THE MESSAGE FROM UP
totalElements: !message.dateResolved
? (draft.entities['test']?.totalElements ?? 0) + 1
: draft.entities['test']?.totalElements ?? 0,
//THIS IS THE MAIN ISSUE I'M HAVING SINCE ARG.PAGE WOULD ALWAYS SHOW
//THE LATTEST PAGE INSTEAD THE ONE THAT I AM ON
totalPages: ..logicForTotalPages,
messages: [message, ...filteredMessages],
},
});
});
}
return;
});
if (sub) {
messageSubs.push(sub);
}
});
} else {
log.error(
'Stomp lost connection. Could not subscribe to messages topics.'
);
}
} catch {
// no-op in case `cacheEntryRemoved` resolves before `cacheDataLoaded`,
// in which case `cacheDataLoaded` will throw
}
await cacheEntryRemoved;
// perform cleanup steps once the `cacheEntryRemoved` promise resolves
unsubscribeMessages();
},
}),
}),
I have tried connecting stomp inside of useEffect in the component and then to dispatch(messagesApi.util.updateQueryData('getMessages'....) , the issue there was the rows per page and page number since it's dynamic for our app and again. I tried to use dispatch inside onCacheEntryAdded but I have the same issue.
When i console log the state I see those cache entries
queries:
getMessages({"page":0,"size":10,"sort":{"id":"dateCreated","order":"DESC"}})
getMessages({"page":1,"size":10,"sort":{"id":"dateCreated","order":"DESC"}})
So even if I am on the page 0, it would always push messages to page 1. What am I doing wrong? This method seems kinda wrong since for 1 entry I need to update the whole pagination logic. Any help would be appreciated , thank you