0

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

getCoffee
  • 21
  • 2

0 Answers0