mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[8.6] [Security Solution] Update cache invalidation logic to handle error responses (#146271) (#146380)
# Backport This will backport the following commits from `main` to `8.6`: - [[Security Solution] Update cache invalidation logic to handle error responses (#146271)](https://github.com/elastic/kibana/pull/146271) <!--- Backport version: 8.9.7 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Dmitrii Shevchenko","email":"dmitrii.shevchenko@elastic.co"},"sourceCommit":{"committedDate":"2022-11-28T11:50:40Z","message":"[Security Solution] Update cache invalidation logic to handle error responses (#146271)\n\n**Resolves: https://github.com/elastic/kibana/issues/146277**\r\n\r\n## Summary\r\n\r\nPreviously, we invalidated the rules table cache only after successful\r\nserver-side state mutations. So when an action like bulk edit was\r\nsuccessfully updating some rules and failing for others, the table\r\ncontinued showing outdated results.\r\n\r\nThis PR moves the cache invalidation from the `onSuccess` handlers to\r\nthe `onSettled` handlers to prevent showing partially stale data after\r\nfailed updates.","sha":"e9bc60355858c82fe39676622004f8e9cdfa61a2","branchLabelMapping":{"^v8.7.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["bug","release_note:fix","impact:low","Team:Detections and Resp","Team: SecuritySolution","auto-backport","Feature:Rule Management","Team:Detection Rules","v8.6.0","v8.7.0"],"number":146271,"url":"https://github.com/elastic/kibana/pull/146271","mergeCommit":{"message":"[Security Solution] Update cache invalidation logic to handle error responses (#146271)\n\n**Resolves: https://github.com/elastic/kibana/issues/146277**\r\n\r\n## Summary\r\n\r\nPreviously, we invalidated the rules table cache only after successful\r\nserver-side state mutations. So when an action like bulk edit was\r\nsuccessfully updating some rules and failing for others, the table\r\ncontinued showing outdated results.\r\n\r\nThis PR moves the cache invalidation from the `onSuccess` handlers to\r\nthe `onSettled` handlers to prevent showing partially stale data after\r\nfailed updates.","sha":"e9bc60355858c82fe39676622004f8e9cdfa61a2"}},"sourceBranch":"main","suggestedTargetBranches":["8.6"],"targetPullRequestStates":[{"branch":"8.6","label":"v8.6.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.7.0","labelRegex":"^v8.7.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/146271","number":146271,"mergeCommit":{"message":"[Security Solution] Update cache invalidation logic to handle error responses (#146271)\n\n**Resolves: https://github.com/elastic/kibana/issues/146277**\r\n\r\n## Summary\r\n\r\nPreviously, we invalidated the rules table cache only after successful\r\nserver-side state mutations. So when an action like bulk edit was\r\nsuccessfully updating some rules and failing for others, the table\r\ncontinued showing outdated results.\r\n\r\nThis PR moves the cache invalidation from the `onSuccess` handlers to\r\nthe `onSettled` handlers to prevent showing partially stale data after\r\nfailed updates.","sha":"e9bc60355858c82fe39676622004f8e9cdfa61a2"}}]}] BACKPORT--> Co-authored-by: Dmitrii Shevchenko <dmitrii.shevchenko@elastic.co>
This commit is contained in:
parent
2499d5589a
commit
8320b80002
5 changed files with 87 additions and 57 deletions
|
@ -206,14 +206,22 @@ export interface BulkActionAggregatedError {
|
|||
rules: Array<{ id: string; name?: string }>;
|
||||
}
|
||||
|
||||
export interface BulkActionAttributes {
|
||||
summary: BulkActionSummary;
|
||||
results: BulkActionResult;
|
||||
errors?: BulkActionAggregatedError[];
|
||||
}
|
||||
|
||||
export interface BulkActionResponse {
|
||||
success?: boolean;
|
||||
rules_count?: number;
|
||||
attributes: {
|
||||
summary: BulkActionSummary;
|
||||
results: BulkActionResult;
|
||||
errors?: BulkActionAggregatedError[];
|
||||
};
|
||||
attributes: BulkActionAttributes;
|
||||
}
|
||||
|
||||
export interface BulkActionErrorResponse {
|
||||
message: string;
|
||||
status_code: number;
|
||||
attributes?: BulkActionAttributes;
|
||||
}
|
||||
|
||||
export type QueryOrIds = { query: string; ids?: undefined } | { query?: undefined; ids: string[] };
|
||||
|
|
|
@ -6,8 +6,9 @@
|
|||
*/
|
||||
import type { UseMutationOptions } from '@tanstack/react-query';
|
||||
import { useMutation } from '@tanstack/react-query';
|
||||
import type { IHttpFetchError } from '@kbn/core/public';
|
||||
import { BulkActionType } from '../../../../../common/detection_engine/rule_management/api/rules/bulk_actions/request_schema';
|
||||
import type { BulkActionResponse, PerformBulkActionProps } from '../api';
|
||||
import type { BulkActionErrorResponse, BulkActionResponse, PerformBulkActionProps } from '../api';
|
||||
import { performBulkAction } from '../api';
|
||||
import { useInvalidateFetchPrebuiltRulesStatusQuery } from './use_fetch_prebuilt_rules_status_query';
|
||||
import { useInvalidateFindRulesQuery, useUpdateRulesCache } from './use_find_rules_query';
|
||||
|
@ -18,7 +19,11 @@ import { DETECTION_ENGINE_RULES_BULK_ACTION } from '../../../../../common/consta
|
|||
export const BULK_ACTION_MUTATION_KEY = ['POST', DETECTION_ENGINE_RULES_BULK_ACTION];
|
||||
|
||||
export const useBulkActionMutation = (
|
||||
options?: UseMutationOptions<BulkActionResponse, Error, PerformBulkActionProps>
|
||||
options?: UseMutationOptions<
|
||||
BulkActionResponse,
|
||||
IHttpFetchError<BulkActionErrorResponse>,
|
||||
PerformBulkActionProps
|
||||
>
|
||||
) => {
|
||||
const invalidateFindRulesQuery = useInvalidateFindRulesQuery();
|
||||
const invalidateFetchRuleByIdQuery = useInvalidateFetchRuleByIdQuery();
|
||||
|
@ -26,47 +31,64 @@ export const useBulkActionMutation = (
|
|||
const invalidateFetchPrebuiltRulesStatusQuery = useInvalidateFetchPrebuiltRulesStatusQuery();
|
||||
const updateRulesCache = useUpdateRulesCache();
|
||||
|
||||
return useMutation<BulkActionResponse, Error, PerformBulkActionProps>(
|
||||
(bulkActionProps: PerformBulkActionProps) => performBulkAction(bulkActionProps),
|
||||
{
|
||||
...options,
|
||||
mutationKey: BULK_ACTION_MUTATION_KEY,
|
||||
onSuccess: (...args) => {
|
||||
const [
|
||||
res,
|
||||
{
|
||||
bulkAction: { type: actionType },
|
||||
},
|
||||
] = args;
|
||||
switch (actionType) {
|
||||
case BulkActionType.enable:
|
||||
case BulkActionType.disable: {
|
||||
invalidateFetchRuleByIdQuery();
|
||||
// This action doesn't affect rule content, no need for invalidation
|
||||
updateRulesCache(res?.attributes?.results?.updated ?? []);
|
||||
break;
|
||||
}
|
||||
case BulkActionType.delete:
|
||||
invalidateFindRulesQuery();
|
||||
invalidateFetchRuleByIdQuery();
|
||||
invalidateFetchTagsQuery();
|
||||
invalidateFetchPrebuiltRulesStatusQuery();
|
||||
break;
|
||||
case BulkActionType.duplicate:
|
||||
invalidateFindRulesQuery();
|
||||
invalidateFetchPrebuiltRulesStatusQuery();
|
||||
break;
|
||||
case BulkActionType.edit:
|
||||
updateRulesCache(res?.attributes?.results?.updated ?? []);
|
||||
invalidateFetchRuleByIdQuery();
|
||||
invalidateFetchTagsQuery();
|
||||
break;
|
||||
}
|
||||
return useMutation<
|
||||
BulkActionResponse,
|
||||
IHttpFetchError<BulkActionErrorResponse>,
|
||||
PerformBulkActionProps
|
||||
>((bulkActionProps: PerformBulkActionProps) => performBulkAction(bulkActionProps), {
|
||||
...options,
|
||||
mutationKey: BULK_ACTION_MUTATION_KEY,
|
||||
onSettled: (...args) => {
|
||||
const [
|
||||
response,
|
||||
error,
|
||||
{
|
||||
bulkAction: { type: actionType },
|
||||
},
|
||||
] = args;
|
||||
|
||||
if (options?.onSuccess) {
|
||||
options.onSuccess(...args);
|
||||
const updatedRules =
|
||||
response?.attributes?.results?.updated ?? error?.body?.attributes?.results?.updated;
|
||||
|
||||
switch (actionType) {
|
||||
case BulkActionType.enable:
|
||||
case BulkActionType.disable: {
|
||||
invalidateFetchRuleByIdQuery();
|
||||
if (updatedRules) {
|
||||
// We have a list of updated rules, no need to invalidate all
|
||||
updateRulesCache(updatedRules);
|
||||
} else {
|
||||
// We failed to receive the list of update rules, invalidate all
|
||||
invalidateFindRulesQuery();
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
case BulkActionType.delete:
|
||||
invalidateFindRulesQuery();
|
||||
invalidateFetchRuleByIdQuery();
|
||||
invalidateFetchTagsQuery();
|
||||
invalidateFetchPrebuiltRulesStatusQuery();
|
||||
break;
|
||||
case BulkActionType.duplicate:
|
||||
invalidateFindRulesQuery();
|
||||
invalidateFetchPrebuiltRulesStatusQuery();
|
||||
break;
|
||||
case BulkActionType.edit:
|
||||
if (updatedRules) {
|
||||
// We have a list of updated rules, no need to invalidate all
|
||||
updateRulesCache(updatedRules);
|
||||
} else {
|
||||
// We failed to receive the list of update rules, invalidate all
|
||||
invalidateFindRulesQuery();
|
||||
}
|
||||
invalidateFetchRuleByIdQuery();
|
||||
invalidateFetchTagsQuery();
|
||||
break;
|
||||
}
|
||||
|
||||
if (options?.onSettled) {
|
||||
options.onSettled(...args);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
|
@ -25,15 +25,15 @@ export const useCreatePrebuiltRulesMutation = (
|
|||
return useMutation(() => createPrepackagedRules(), {
|
||||
...options,
|
||||
mutationKey: CREATE_PREBUILT_RULES_MUTATION_KEY,
|
||||
onSuccess: (...args) => {
|
||||
onSettled: (...args) => {
|
||||
// Always invalidate all rules and the prepackaged rules status cache as
|
||||
// the number of rules might change after the installation
|
||||
invalidatePrePackagedRulesStatus();
|
||||
invalidateFindRulesQuery();
|
||||
invalidateFetchTagsQuery();
|
||||
|
||||
if (options?.onSuccess) {
|
||||
options.onSuccess(...args);
|
||||
if (options?.onSettled) {
|
||||
options.onSettled(...args);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -31,13 +31,13 @@ export const useCreateRuleMutation = (
|
|||
{
|
||||
...options,
|
||||
mutationKey: CREATE_RULE_MUTATION_KEY,
|
||||
onSuccess: (...args) => {
|
||||
onSettled: (...args) => {
|
||||
invalidateFetchPrePackagedRulesStatusQuery();
|
||||
invalidateFindRulesQuery();
|
||||
invalidateFetchTagsQuery();
|
||||
|
||||
if (options?.onSuccess) {
|
||||
options.onSuccess(...args);
|
||||
if (options?.onSettled) {
|
||||
options.onSettled(...args);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
|
@ -31,13 +31,13 @@ export const useUpdateRuleMutation = (
|
|||
{
|
||||
...options,
|
||||
mutationKey: UPDATE_RULE_MUTATION_KEY,
|
||||
onSuccess: (...args) => {
|
||||
onSettled: (...args) => {
|
||||
invalidateFindRulesQuery();
|
||||
invalidateFetchRuleByIdQuery();
|
||||
invalidateFetchTagsQuery();
|
||||
|
||||
if (options?.onSuccess) {
|
||||
options.onSuccess(...args);
|
||||
if (options?.onSettled) {
|
||||
options.onSettled(...args);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue