refactor: generalize ActionCable cache invalidation over the model registry

Replaces the three hardcoded dispatches in actionCable.onCacheInvalidate and
ReconnectService.revalidateCaches with a loop over cacheableModels. Adding a
new cached model no longer requires editing these two handlers — they pick
it up automatically from the registry.

Also guards against partial server payloads: dispatches are skipped for
models whose key is undefined, so a client running ahead of a server
deploy keeps working without spurious dispatches.
This commit is contained in:
Shivam Mishra
2026-05-21 17:21:42 +05:30
parent 0ae3a82339
commit 1a61e8102e
3 changed files with 43 additions and 12 deletions
@@ -254,11 +254,13 @@ describe('ReconnectService', () => {
});
describe('revalidateCaches', () => {
it('should dispatch revalidate actions for labels, inboxes, and teams', async () => {
it('should dispatch revalidate actions for every cacheable model returned by the server', async () => {
storeMock.dispatch.mockResolvedValueOnce({
label: 'labelKey',
inbox: 'inboxKey',
team: 'teamKey',
canned_response: 'cannedKey',
account_user: 'accountUserKey',
});
await reconnectService.revalidateCaches();
expect(storeMock.dispatch).toHaveBeenCalledWith('accounts/getCacheKeys');
@@ -271,6 +273,31 @@ describe('ReconnectService', () => {
expect(storeMock.dispatch).toHaveBeenCalledWith('teams/revalidate', {
newKey: 'teamKey',
});
expect(storeMock.dispatch).toHaveBeenCalledWith(
'revalidateCannedResponses',
{ newKey: 'cannedKey' }
);
expect(storeMock.dispatch).toHaveBeenCalledWith('agents/revalidate', {
newKey: 'accountUserKey',
});
});
it('should skip dispatches for models the server does not yet emit', async () => {
storeMock.dispatch.mockResolvedValueOnce({
label: 'labelKey',
inbox: 'inboxKey',
team: 'teamKey',
// canned_response / account_user omitted (older server)
});
await reconnectService.revalidateCaches();
expect(storeMock.dispatch).not.toHaveBeenCalledWith(
'revalidateCannedResponses',
expect.anything()
);
expect(storeMock.dispatch).not.toHaveBeenCalledWith(
'agents/revalidate',
expect.anything()
);
});
});