Skip to content

Commit

Permalink
fix: parallelize action callbacks execution
Browse files Browse the repository at this point in the history
  • Loading branch information
TheEdoRan committed Aug 16, 2024
1 parent b2c02f0 commit 53ddab6
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 9 deletions.
17 changes: 12 additions & 5 deletions packages/next-safe-action/src/action-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import type {
StateServerCodeFn,
} from "./index.types";
import { ActionMetadataError, DEFAULT_SERVER_ERROR_MESSAGE, isError } from "./utils";
import type { MaybePromise } from "./utils.types";
import { ActionServerValidationError, ActionValidationError, buildValidationErrors } from "./validation-errors";
import type {
BindArgsValidationErrors,
Expand Down Expand Up @@ -259,9 +260,11 @@ export function actionBuilder<
// Execute middleware chain + action function.
await executeMiddlewareStack();

const callbacksToExecute: MaybePromise<void>[] = [];

// If an internal framework error occurred, throw it, so it will be processed by Next.js.
if (frameworkError) {
await Promise.resolve(
callbacksToExecute.push(
utils?.onSuccess?.({
data: undefined,
metadata: args.metadata,
Expand All @@ -275,7 +278,7 @@ export function actionBuilder<
})
);

await Promise.resolve(
callbacksToExecute.push(
utils?.onSettled?.({
metadata: args.metadata,
ctx: currentCtx as Ctx,
Expand All @@ -287,6 +290,8 @@ export function actionBuilder<
})
);

await Promise.all(callbacksToExecute);

throw frameworkError;
}

Expand Down Expand Up @@ -323,7 +328,7 @@ export function actionBuilder<
actionResult.data = middlewareResult.data as Data;
}

await Promise.resolve(
callbacksToExecute.push(
utils?.onSuccess?.({
metadata: args.metadata,
ctx: currentCtx as Ctx,
Expand All @@ -337,7 +342,7 @@ export function actionBuilder<
})
);
} else {
await Promise.resolve(
callbacksToExecute.push(
utils?.onError?.({
metadata: args.metadata,
ctx: currentCtx as Ctx,
Expand All @@ -349,7 +354,7 @@ export function actionBuilder<
}

// onSettled, if provided, is always executed.
await Promise.resolve(
callbacksToExecute.push(
utils?.onSettled?.({
metadata: args.metadata,
ctx: currentCtx as Ctx,
Expand All @@ -361,6 +366,8 @@ export function actionBuilder<
})
);

await Promise.all(callbacksToExecute);

return actionResult;
};
},
Expand Down
8 changes: 4 additions & 4 deletions website/docs/execution/action-utils.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ const action = actionClient

Here is the list of callbacks, with their behavior explained. All of them are optional and have return type `void` or `Promise<void>` (async or non-async functions with no return):

| Name | Executed after |
| Name | Executed after |
| ------------ | ----------------------------------------------------------------------- |
| `onSuccess?` | Action succeeded
| `onError?` | Action errored with server or validation error(s)
| `onSettled?` | Action succeeded or errored (after `onSuccess` or `onError` call) |
| `onSuccess?` | Action succeeded |
| `onError?` | Action errored with server or validation error(s) |
| `onSettled?` | Action succeeded or errored |

0 comments on commit 53ddab6

Please sign in to comment.