Files
grafana/public/app/api/clients/provisioning/utils/createOnCacheEntryAdded.ts
T
Ashley HarrisonandAlex Khomenko dd07d3dbbe API client generation: centralise api clients (#102186)
* centralise iam api

* centralise folder api client

* rename to baseAPI

* centralise provisioning api

* remove iam feature folder from CODEOWNERS

* fix type name

* Update public/app/features/provisioning/utils/selectors.ts

Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>

---------

Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
2025-03-14 14:34:36 +00:00

73 lines
2.5 KiB
TypeScript

import { Subscription } from 'rxjs';
import { ScopedResourceClient } from '../../../../features/apiserver/client';
import { ListOptions } from '../../../../features/apiserver/types';
import { ListMeta, ObjectMeta } from '../endpoints.gen';
/**
* Creates a cache entry handler for RTK Query that watches for changes to a resource
* and updates the cache accordingly.
*/
export function createOnCacheEntryAdded<
Spec,
Status,
T extends { spec?: Spec; status?: Status; metadata?: ObjectMeta },
List extends { items?: T[]; metadata?: ListMeta },
>(resourceName: string) {
return async function onCacheEntryAdded(
arg: ListOptions | undefined,
{
updateCachedData,
cacheDataLoaded,
cacheEntryRemoved,
}: {
updateCachedData: (fn: (draft: List) => void) => void;
cacheDataLoaded: Promise<{ data: List }>;
cacheEntryRemoved: Promise<void>;
}
) {
if (!arg?.watch) {
return;
}
const client = new ScopedResourceClient<Spec, Status>({
group: 'provisioning.grafana.app',
version: 'v0alpha1',
resource: resourceName,
});
let subscription: Subscription | null = null;
try {
// Wait for the initial query to resolve before proceeding
const response = await cacheDataLoaded;
const resourceVersion = response.data.metadata?.resourceVersion;
subscription = client.watch({ resourceVersion }).subscribe((event) => {
updateCachedData((draft) => {
if (!draft.items) {
draft.items = [];
}
const existingIndex = draft.items.findIndex((item) => item.metadata?.name === event.object.metadata.name);
if (event.type === 'ADDED') {
// Add the new item
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
draft.items.push(event.object as unknown as T);
} else if (event.type === 'MODIFIED' && existingIndex !== -1) {
// Update the existing item if it exists
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
draft.items[existingIndex] = event.object as unknown as T;
} else if (event.type === 'DELETED' && existingIndex !== -1) {
// Remove the item if it exists
draft.items.splice(existingIndex, 1);
}
});
});
} catch (error) {
console.error('Error in onCacheEntryAdded:', error);
}
await cacheEntryRemoved;
subscription?.unsubscribe();
};
}