refactor: deduplicate cache revalidation actions

This commit is contained in:
Shivam Mishra
2026-06-08 18:39:40 +05:30
parent 0deb026f9d
commit 625302ac3c
8 changed files with 129 additions and 71 deletions
@@ -1,6 +1,7 @@
import * as MutationHelpers from 'shared/helpers/vuex/mutationHelpers';
import * as types from '../mutation-types';
import AgentAPI from '../../api/agents';
import { createCacheRevalidateAction } from '../utils/cacheRevalidate';
export const state = {
records: [],
@@ -51,17 +52,10 @@ export const actions = {
commit(types.default.SET_AGENT_FETCHING_STATUS, false);
}
},
revalidate: async ({ commit }, { newKey }) => {
try {
const isExistingKeyValid = await AgentAPI.validateCacheKey(newKey);
if (!isExistingKeyValid) {
const response = await AgentAPI.refetchAndCommit(newKey);
commit(types.default.SET_AGENTS, response.data);
}
} catch (error) {
// Ignore error
}
},
revalidate: createCacheRevalidateAction({
api: AgentAPI,
mutation: types.default.SET_AGENTS,
}),
create: async ({ commit }, agentInfo) => {
commit(types.default.SET_AGENT_CREATING_STATUS, true);
try {
@@ -2,6 +2,7 @@ import * as MutationHelpers from 'shared/helpers/vuex/mutationHelpers';
import types from '../mutation-types';
import AttributeAPI from '../../api/attributes';
import camelcaseKeys from 'camelcase-keys';
import { createCacheRevalidateAction } from '../utils/cacheRevalidate';
export const state = {
records: [],
@@ -54,17 +55,10 @@ export const actions = {
commit(types.SET_CUSTOM_ATTRIBUTE_UI_FLAG, { isFetching: false });
}
},
revalidate: async ({ commit }, { newKey }) => {
try {
const isExistingKeyValid = await AttributeAPI.validateCacheKey(newKey);
if (!isExistingKeyValid) {
const response = await AttributeAPI.refetchAndCommit(newKey);
commit(types.SET_CUSTOM_ATTRIBUTE, response.data);
}
} catch (error) {
// Ignore error
}
},
revalidate: createCacheRevalidateAction({
api: AttributeAPI,
mutation: types.SET_CUSTOM_ATTRIBUTE,
}),
create: async function createAttribute({ commit }, attributeObj) {
commit(types.SET_CUSTOM_ATTRIBUTE_UI_FLAG, { isCreating: true });
try {
@@ -1,4 +1,5 @@
import { throwErrorMessage } from 'dashboard/store/utils/api';
import { createCacheRevalidateAction } from 'dashboard/store/utils/cacheRevalidate';
import * as MutationHelpers from 'shared/helpers/vuex/mutationHelpers';
import * as types from '../mutation-types';
import CannedResponseAPI from '../../api/cannedResponse';
@@ -47,21 +48,10 @@ const actions = {
}
},
revalidateCannedResponses: async function revalidateCannedResponses(
{ commit },
{ newKey }
) {
try {
const isExistingKeyValid =
await CannedResponseAPI.validateCacheKey(newKey);
if (!isExistingKeyValid) {
const response = await CannedResponseAPI.refetchAndCommit(newKey);
commit(types.default.SET_CANNED, response.data);
}
} catch (error) {
// Ignore error
}
},
revalidateCannedResponses: createCacheRevalidateAction({
api: CannedResponseAPI,
mutation: types.default.SET_CANNED,
}),
createCannedResponse: async function createCannedResponse(
{ commit },
@@ -7,6 +7,7 @@ import FBChannel from '../../api/channel/fbChannel';
import TwilioChannel from '../../api/channel/twilioChannel';
import WhatsappChannel from '../../api/channel/whatsappChannel';
import { throwErrorMessage } from '../utils/api';
import { createCacheRevalidateAction } from '../utils/cacheRevalidate';
import AnalyticsHelper from '../../helper/AnalyticsHelper';
import camelcaseKeys from 'camelcase-keys';
import { ACCOUNT_EVENTS } from '../../helper/AnalyticsHelper/events';
@@ -189,17 +190,11 @@ const sendAnalyticsEvent = channelType => {
};
export const actions = {
revalidate: async ({ commit }, { newKey }) => {
try {
const isExistingKeyValid = await InboxesAPI.validateCacheKey(newKey);
if (!isExistingKeyValid) {
const response = await InboxesAPI.refetchAndCommit(newKey);
commit(types.default.SET_INBOXES, response.data.payload);
}
} catch (error) {
// Ignore error
}
},
revalidate: createCacheRevalidateAction({
api: InboxesAPI,
mutation: types.default.SET_INBOXES,
getData: response => response.data.payload,
}),
get: async ({ commit }) => {
commit(types.default.SET_INBOXES_UI_FLAG, { isFetching: true });
try {
@@ -3,6 +3,7 @@ import types from '../mutation-types';
import LabelsAPI from '../../api/labels';
import AnalyticsHelper from '../../helper/AnalyticsHelper';
import { LABEL_EVENTS } from '../../helper/AnalyticsHelper/events';
import { createCacheRevalidateAction } from '../utils/cacheRevalidate';
export const state = {
records: [],
@@ -32,17 +33,11 @@ export const getters = {
};
export const actions = {
revalidate: async function revalidate({ commit }, { newKey }) {
try {
const isExistingKeyValid = await LabelsAPI.validateCacheKey(newKey);
if (!isExistingKeyValid) {
const response = await LabelsAPI.refetchAndCommit(newKey);
commit(types.SET_LABELS, response.data.payload);
}
} catch (error) {
// Ignore error
}
},
revalidate: createCacheRevalidateAction({
api: LabelsAPI,
mutation: types.SET_LABELS,
getData: response => response.data.payload,
}),
get: async function getLabels({ commit }) {
commit(types.SET_LABEL_UI_FLAG, { isFetching: true });
@@ -7,6 +7,7 @@ import {
DELETE_TEAM,
} from './types';
import TeamsAPI from '../../../api/teams';
import { createCacheRevalidateAction } from '../../utils/cacheRevalidate';
export const actions = {
create: async ({ commit }, teamInfo) => {
@@ -22,18 +23,11 @@ export const actions = {
commit(SET_TEAM_UI_FLAG, { isCreating: false });
}
},
revalidate: async ({ commit }, { newKey }) => {
try {
const isExistingKeyValid = await TeamsAPI.validateCacheKey(newKey);
if (!isExistingKeyValid) {
const response = await TeamsAPI.refetchAndCommit(newKey);
commit(CLEAR_TEAMS);
commit(SET_TEAMS, response.data);
}
} catch (error) {
// Ignore error
}
},
revalidate: createCacheRevalidateAction({
api: TeamsAPI,
mutation: SET_TEAMS,
clearMutation: CLEAR_TEAMS,
}),
get: async ({ commit }) => {
commit(SET_TEAM_UI_FLAG, { isFetching: true });
try {
@@ -0,0 +1,14 @@
export const createCacheRevalidateAction =
({ api, mutation, clearMutation, getData = response => response.data }) =>
async ({ commit }, { newKey }) => {
try {
const isExistingKeyValid = await api.validateCacheKey(newKey);
if (isExistingKeyValid) return;
const response = await api.refetchAndCommit(newKey);
if (clearMutation) commit(clearMutation);
commit(mutation, getData(response));
} catch (error) {
// Ignore error
}
};
@@ -0,0 +1,82 @@
import { createCacheRevalidateAction } from '../cacheRevalidate';
describe('#createCacheRevalidateAction', () => {
const commit = vi.fn();
beforeEach(() => {
commit.mockReset();
});
it('refetches and commits data when the cache key is stale', async () => {
const api = {
validateCacheKey: vi.fn().mockResolvedValue(false),
refetchAndCommit: vi.fn().mockResolvedValue({ data: [{ id: 1 }] }),
};
const action = createCacheRevalidateAction({
api,
mutation: 'SET_RECORDS',
});
await action({ commit }, { newKey: 'new-key' });
expect(api.validateCacheKey).toHaveBeenCalledWith('new-key');
expect(api.refetchAndCommit).toHaveBeenCalledWith('new-key');
expect(commit).toHaveBeenCalledWith('SET_RECORDS', [{ id: 1 }]);
});
it('skips refetch when the cache key is current', async () => {
const api = {
validateCacheKey: vi.fn().mockResolvedValue(true),
refetchAndCommit: vi.fn(),
};
const action = createCacheRevalidateAction({
api,
mutation: 'SET_RECORDS',
});
await action({ commit }, { newKey: 'new-key' });
expect(api.refetchAndCommit).not.toHaveBeenCalled();
expect(commit).not.toHaveBeenCalled();
});
it('supports clear-before-set and custom response data extraction', async () => {
const api = {
validateCacheKey: vi.fn().mockResolvedValue(false),
refetchAndCommit: vi
.fn()
.mockResolvedValue({ data: { payload: [{ id: 1 }] } }),
};
const action = createCacheRevalidateAction({
api,
mutation: 'SET_RECORDS',
clearMutation: 'CLEAR_RECORDS',
getData: response => response.data.payload,
});
await action({ commit }, { newKey: 'new-key' });
expect(commit.mock.calls).toEqual([
['CLEAR_RECORDS'],
['SET_RECORDS', [{ id: 1 }]],
]);
});
it('ignores revalidation errors', async () => {
const api = {
validateCacheKey: vi.fn().mockRejectedValue(new Error('boom')),
refetchAndCommit: vi.fn(),
};
const action = createCacheRevalidateAction({
api,
mutation: 'SET_RECORDS',
});
await expect(action({ commit }, { newKey: 'new-key' })).resolves.toBe();
expect(commit).not.toHaveBeenCalled();
});
});