Fix list item refresh issue (#202194)

## Fix refresh issue for serverless

If use only have `write` and `read` privileges `refresh=true` don't
work, because it require at least `maintenance`

For creation it's easy to change to `wait_for` and it will work.

For delete endpoint I implement the same technique as is used in
deleting lists.

---------

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
Co-authored-by: Ryland Herrick <ryalnd@gmail.com>
This commit is contained in:
Khristinin Nikita 2024-12-10 16:02:19 +01:00 committed by GitHub
parent ebcbb0b26e
commit 36a36b44e0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 32 additions and 5 deletions

View file

@ -28,7 +28,7 @@ export const useCreateListItemMutation = (
const invalidateListItemQuery = useInvalidateListItemQuery();
return useMutation<ListItemSchema, IHttpFetchError<Error>, CreateListMutationParams>(
({ listId, value, http }) =>
createListItemWithOptionalSignal({ listId, value, http, refresh: 'true' }),
createListItemWithOptionalSignal({ listId, value, http, refresh: 'wait_for' }),
{
...options,
mutationKey: CREATE_LIST_ITEM_MUTATION_KEY,

View file

@ -26,7 +26,7 @@ export const useDeleteListItemMutation = (
) => {
const invalidateListItemQuery = useInvalidateListItemQuery();
return useMutation<ListItemSchema, IHttpFetchError<Error>, DeleteListMutationParams>(
({ id, http }) => deleteListItemWithOptionalSignal({ id, http, refresh: 'true' }),
({ id, http }) => deleteListItemWithOptionalSignal({ id, http }),
{
...options,
mutationKey: DELETE_LIST_ITEM_MUTATION_KEY,

View file

@ -34,16 +34,26 @@ describe('delete_list_item', () => {
test('Delete returns the same list item if a list item is returned from "getListItem"', async () => {
const listItem = getListItemResponseMock();
(getListItem as unknown as jest.Mock).mockResolvedValueOnce(listItem);
(getListItem as unknown as jest.Mock)
.mockResolvedValueOnce(listItem)
.mockResolvedValueOnce(null);
const options = getDeleteListItemOptionsMock();
(options.esClient.deleteByQuery as unknown as jest.Mock).mockResolvedValueOnce({
deleted: true,
});
const deletedListItem = await deleteListItem(options);
expect(deletedListItem).toEqual(listItem);
});
test('Delete calls "deleteByQuery" if a list item is returned from "getListItem"', async () => {
const listItem = getListItemResponseMock();
(getListItem as unknown as jest.Mock).mockResolvedValueOnce(listItem);
(getListItem as unknown as jest.Mock)
.mockResolvedValueOnce(listItem)
.mockResolvedValueOnce(null);
const options = getDeleteListItemOptionsMock();
(options.esClient.deleteByQuery as unknown as jest.Mock).mockResolvedValueOnce({
deleted: true,
});
await deleteListItem(options);
const deleteByQuery = {
index: LIST_ITEM_INDEX,

View file

@ -8,6 +8,8 @@
import { ElasticsearchClient } from '@kbn/core/server';
import type { Id, ListItemSchema } from '@kbn/securitysolution-io-ts-list-types';
import { waitUntilDocumentIndexed } from '../utils';
import { getListItem } from '.';
export interface DeleteListItemOptions {
@ -27,7 +29,7 @@ export const deleteListItem = async ({
if (listItem == null) {
return null;
} else {
await esClient.deleteByQuery({
const response = await esClient.deleteByQuery({
index: listItemIndex,
query: {
ids: {
@ -36,6 +38,21 @@ export const deleteListItem = async ({
},
refresh,
});
if (response.deleted) {
const checkIfListItemDeleted = async (): Promise<void> => {
const deletedListItem = await getListItem({ esClient, id, listItemIndex });
if (deletedListItem !== null) {
throw Error(
'List item was deleted, but the change was not propagated in the expected time interval.'
);
}
};
await waitUntilDocumentIndexed(checkIfListItemDeleted);
} else {
throw Error('Deletion of List Item [item_id] from [item_index] was not successful');
}
}
return listItem;
};