## Description The conversation sidebar counts (`GET /conversations/meta`) are polled on a debounced cadence selected from the last known conversation count (`allCount` in the `conversationStats` store). `allCount` starts at `0` and is only set after a **successful** meta response. When the meta query is slow or failing under load, `allCount` stays `0`, which selected the fastest cadence, so every client polled as aggressively as possible exactly when the endpoint was already struggling. On large accounts with many concurrent agents this multiplies into sustained load that keeps the query slow, a self-reinforcing loop. This PR makes two changes: 1. **Treat an unknown count (`0`) as a large account** and poll at the slowest cadence instead of the fastest (`getMetaDebounceKey`, extracted as a pure, testable function). This breaks the failure loop. 2. **Raise the debounce intervals across all tiers** so counts are polled less frequently under sustained activity: - fast: max 1 poll / 2s -> 1 / 5s - mid: 1 / 10s -> 1 / 20s - slow (large/unknown accounts): 1 / 20s -> 1 / 30s First-load counts still render immediately (the debounce fires on the leading edge for the very first call), so the higher intervals only affect the sustained poll rate, not initial render. ## Type of change - [x] Bug fix (non-breaking change which fixes an issue)
83 lines
1.9 KiB
JavaScript
83 lines
1.9 KiB
JavaScript
import types from '../mutation-types';
|
|
import ConversationApi from '../../api/inbox/conversation';
|
|
import { debounce } from '@chatwoot/utils';
|
|
|
|
const state = {
|
|
mineCount: 0,
|
|
unAssignedCount: 0,
|
|
allCount: 0,
|
|
};
|
|
|
|
export const getters = {
|
|
getStats: $state => $state,
|
|
};
|
|
|
|
// Create a debounced version of the actual API call function
|
|
const fetchMetaData = async (commit, params) => {
|
|
try {
|
|
const response = await ConversationApi.meta(params);
|
|
const {
|
|
data: { meta },
|
|
} = response;
|
|
commit(types.SET_CONV_TAB_META, meta);
|
|
} catch (error) {
|
|
// ignore
|
|
}
|
|
};
|
|
|
|
const debouncedFetchMetaData = debounce(fetchMetaData, 1000, false, 5000);
|
|
const longDebouncedFetchMetaData = debounce(fetchMetaData, 7500, false, 20000);
|
|
const superLongDebouncedFetchMetaData = debounce(
|
|
fetchMetaData,
|
|
15000,
|
|
false,
|
|
30000
|
|
);
|
|
|
|
const metaDebouncers = {
|
|
default: debouncedFetchMetaData,
|
|
long: longDebouncedFetchMetaData,
|
|
superLong: superLongDebouncedFetchMetaData,
|
|
};
|
|
|
|
// allCount is 0 until a meta request succeeds; under load it stays 0, so treat
|
|
// the unknown case as a large account and poll slowest instead of fastest.
|
|
export const getMetaDebounceKey = allCount => {
|
|
if (allCount > 2000 || allCount === 0) return 'superLong';
|
|
if (allCount > 100) return 'long';
|
|
return 'default';
|
|
};
|
|
|
|
export const actions = {
|
|
get: ({ commit, state: $state }, params) => {
|
|
metaDebouncers[getMetaDebounceKey($state.allCount)](commit, params);
|
|
},
|
|
set({ commit }, meta) {
|
|
commit(types.SET_CONV_TAB_META, meta);
|
|
},
|
|
};
|
|
|
|
export const mutations = {
|
|
[types.SET_CONV_TAB_META](
|
|
$state,
|
|
{
|
|
mine_count: mineCount,
|
|
unassigned_count: unAssignedCount,
|
|
all_count: allCount,
|
|
} = {}
|
|
) {
|
|
$state.mineCount = mineCount;
|
|
$state.allCount = allCount;
|
|
$state.unAssignedCount = unAssignedCount;
|
|
$state.updatedOn = new Date();
|
|
},
|
|
};
|
|
|
|
export default {
|
|
namespaced: true,
|
|
state,
|
|
getters,
|
|
actions,
|
|
mutations,
|
|
};
|