ServerShared
Hook Executor
Generic hook execution engine with concurrency and timeout controls.
The createHookExecutor factory (found in features/shared/hook-executor.ts) allows any feature to implement a robust hook system.
Key features
- Sequential
beforehooks:beforehooks are run one after another, as they are allowed to modify the input parameters for the next hook and the final operation. - Concurrent
afterSuccesshooks: Post-operation hooks run in parallel (default concurrency: 3) to improve performance. - Timeouts: The executor enforces a 10s timeout on post-operation hooks to prevent slow external integrations (like Webhooks) from hanging the request.
Implementation pattern
To add hooks to a feature, you typically:
- Define a Registry: Create an object that can return a list of hooks for a given model or entity.
- Initialize Executor:
const executor = createHookExecutor({
registry: myRegistry,
errorFactory: (subject, op, stage, error) => new FeatureError({ ... }),
subjectKey: "entity" // or "model"
});- Incorporate into Pipeline: Call
executor.runBeforeHooksin thepreparephase andexecutor.runAfterSuccessHooksin theafterphase.
Hook signature
A hook handler receives the following context:
subject: The name of the entity/model.op: The operation (create/update/delete).params: The incoming parameters.result: (ForafterSuccessonly) The result of the operation.context: TheHandlerContext(requestId, user ID, etc.).
Best practices
- Idempotency: Post-operation hooks should be idempotent in case of retries.
- Non-blocking: Although
afterSuccesshooks are monitored, they should avoid performing extremely heavy computations that could be better handled by Pub-Sub.