Files
grafana/public/app/api/clients/provisioning/utils/createOnCacheEntryAdded.ts
Alex Khomenko 15c903fa5c Provisioning: Refactor createOnCacheEntryAdded (#105228)
* Provisioning: Refactor createOnCacheEntryAdded

* Use custom list resource type

* add generated types and transformers

* Switch to type guards

* Do not create new array
2025-05-19 13:23:23 +03:00

67 lines
2.2 KiB
TypeScript

import { Subscription } from 'rxjs';
import { ScopedResourceClient } from 'app/features/apiserver/client';
import { ListOptions, GeneratedResourceList as ResourceList } from 'app/features/apiserver/types';
/**
* 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>(resourceName: string) {
return async function onCacheEntryAdded<List extends ResourceList<Spec, Status>>(
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 = [];
}
// Find the item with the matching name
const existingIndex = draft.items.findIndex((item) => item.metadata?.name === event.object.metadata.name);
if (event.type === 'ADDED' && existingIndex === -1) {
draft.items.push(event.object);
} else if (event.type === 'DELETED' && existingIndex !== -1) {
// Remove the item if it exists
draft.items.splice(existingIndex, 1);
} else if (existingIndex !== -1) {
// Could be ADDED or MODIFIED
// Update the existing item if it exists
draft.items[existingIndex] = event.object;
}
});
});
} catch (error) {
console.error('Error in onCacheEntryAdded:', error);
}
await cacheEntryRemoved;
subscription?.unsubscribe();
};
}