Skip to content

Commit

Permalink
[8.6] [Security Solution] Update cache invalidation logic to handle e…
Browse files Browse the repository at this point in the history
…rror 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)](#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:
#146277
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":"#146271
Solution] Update cache invalidation logic to handle error responses
(#146271)\n\n**Resolves:
#146277
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":"#146271
Solution] Update cache invalidation logic to handle error responses
(#146271)\n\n**Resolves:
#146277
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>
  • Loading branch information
kibanamachine and xcrzx committed Nov 28, 2022
1 parent 2499d55 commit 8320b80
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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[] };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -18,55 +19,76 @@ 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();
const invalidateFetchTagsQuery = useInvalidateFetchTagsQuery();
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:
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;

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();
invalidateFetchPrebuiltRulesStatusQuery();
break;
case BulkActionType.edit:
updateRulesCache(res?.attributes?.results?.updated ?? []);
invalidateFetchRuleByIdQuery();
invalidateFetchTagsQuery();
break;
}
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?.onSuccess) {
options.onSuccess(...args);
}
},
}
);
if (options?.onSettled) {
options.onSettled(...args);
}
},
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
},
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
},
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
},
}
Expand Down

0 comments on commit 8320b80

Please sign in to comment.