Files
chatwoot/app/javascript/dashboard/store/modules/specs/conversationStats/actions.spec.js
Shivam Mishra 9761214860 feat: Add debounce for meta query (#11195)
This PR combines the approaches in
https://github.com/chatwoot/chatwoot/pull/11190 and
https://github.com/chatwoot/chatwoot/pull/11187 to debounce the meta
request with a max wait time of 2.5 seconds With 500 concurrent users,
the theoretical limit with this is 720K requests per minute, if all of
them continuously receive websocket events.

The max wait of 2.5 seconds is still very generous, and we can easily
make it 2 seconds for smaller accounts and 5 seconds for larger
accounts.

```js
const debouncedFetchMetaData = debounce(fetchMetaData, 500, false, 200);
const longDebouncedFetchMetaData = debounce(fetchMetaData, 500, false, 5000);

export const actions = {
  get: async ({ commit, state: $state }, params) => {
    if ($state.allCount > 100) {
      longDebouncedFetchMetaData(commit, params);
    } else {
      debouncedFetchMetaData(commit, params);
    }
  },
  set({ commit }, meta) {
    commit(types.SET_CONV_TAB_META, meta);
  },
};

```

Related Utils PR: https://github.com/chatwoot/utils/pull/49
Here's the debounce in action

<img width="934" alt="image"
src="https://github.com/user-attachments/assets/5265a108-9c64-4488-9b4c-2e0d06aadc50"
/>

---------

Co-authored-by: Pranav <pranavrajs@gmail.com>
2025-03-27 19:41:02 -07:00

65 lines
1.7 KiB
JavaScript

import axios from 'axios';
import { actions } from '../../conversationStats';
import * as types from '../../../mutation-types';
const commit = vi.fn();
global.axios = axios;
vi.mock('axios');
vi.mock('@chatwoot/utils', () => ({
debounce: vi.fn(fn => {
return fn;
}),
}));
describe('#actions', () => {
beforeEach(() => {
vi.useFakeTimers(); // Set up fake timers
commit.mockClear();
});
afterEach(() => {
vi.useRealTimers(); // Reset to real timers after each test
});
describe('#get', () => {
it('sends correct mutations if API is success', async () => {
axios.get.mockResolvedValue({ data: { meta: { mine_count: 1 } } });
actions.get(
{ commit, state: { allCount: 0 } },
{ inboxId: 1, assigneeTpe: 'me', status: 'open' }
);
await vi.runAllTimersAsync();
await vi.waitFor(() => expect(commit).toHaveBeenCalled());
expect(commit.mock.calls).toEqual([
[types.default.SET_CONV_TAB_META, { mine_count: 1 }],
]);
});
it('sends correct actions if API is error', async () => {
axios.get.mockRejectedValue({ message: 'Incorrect header' });
actions.get(
{ commit, state: { allCount: 0 } },
{ inboxId: 1, assigneeTpe: 'me', status: 'open' }
);
expect(commit.mock.calls).toEqual([]);
});
});
describe('#set', () => {
it('sends correct mutations', async () => {
actions.set(
{ commit },
{ mine_count: 1, unassigned_count: 1, all_count: 2 }
);
expect(commit.mock.calls).toEqual([
[
types.default.SET_CONV_TAB_META,
{ mine_count: 1, unassigned_count: 1, all_count: 2 },
],
]);
});
});
});