Selegic CRM Docs
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 before hooks: before hooks are run one after another, as they are allowed to modify the input parameters for the next hook and the final operation.
  • Concurrent afterSuccess hooks: 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:

  1. Define a Registry: Create an object that can return a list of hooks for a given model or entity.
  2. Initialize Executor:
const executor = createHookExecutor({
  registry: myRegistry,
  errorFactory: (subject, op, stage, error) => new FeatureError({ ... }),
  subjectKey: "entity" // or "model"
});
  1. Incorporate into Pipeline: Call executor.runBeforeHooks in the prepare phase and executor.runAfterSuccessHooks in the after phase.

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: (For afterSuccess only) The result of the operation.
  • context: The HandlerContext (requestId, user ID, etc.).

Best practices

  • Idempotency: Post-operation hooks should be idempotent in case of retries.
  • Non-blocking: Although afterSuccess hooks are monitored, they should avoid performing extremely heavy computations that could be better handled by Pub-Sub.

On this page