Class ArvoEventHandler<TContract>

ArvoEventHandler is the foundational component for building stateless, contract-bound services in the Arvo system.

It enforces strict contract validation, version-aware handler resolution, and safe, observable event emission — all while maintaining type safety, traceability, and support for multi-domain workflows.

  • Ensures incoming events match the contract's type and dataschema
  • Resolves the correct contract version using dataschema
  • Validates input and output data via Zod schemas
  • Executes the version-specific handler function
  • Emits one or more response events based on the handler result
  • Supports multi-domain broadcasting via domain[] on the emitted events
  • Automatically emits system error events (sys.*.error) on failure
  • Integrates deeply with OpenTelemetry for tracing and observability

ArvoEventHandler enforces a clear separation between:

  • Violations — structural, schema, or config errors that break the contract. These are thrown and must be handled explicitly by the caller.

  • System Errors — runtime exceptions during execution that are caught and emitted as standardized sys.<contract>.error events.

The handler supports multi-domain event distribution. When the handler returns an event with a domain array, it is broadcast to one or more routing contexts.

By default, system error events are broadcast into the source event’s domain, the handler’s contract domain, and the null domain. This fallback ensures errors are visible across all relevant contexts. Developers can override this behavior using the optional systemErrorDomain field to specify an explicit set of domain values, including symbolic constants from ArvoDomain.

  • A concrete domain string like 'audit.orders' or 'human.review'
  • null to emit with no domain (standard internal flow)
  • A symbolic reference from ArvoDomain
  • Each item in the domain array is resolved via resolveEventDomain
  • Duplicate domains are deduplicated before emitting
  • If domain is omitted entirely, Arvo defaults to [null]
return {
type: 'evt.user.registered',
data: { ... },
domain: ['analytics', ArvoDomain.FROM_TRIGGERING_EVENT, null]
};

This would emit at most 3 copies of the event, domained to:

  • 'analytics'
  • the domain of the incoming event
  • no domain (default)

Avoid setting contract.domain unless fully intentional. 99% emitted event should default to null (standard processing pipeline).

Contract-level domains enforce implicit routing for every emitted event in that handler, making the behavior harder to override and debug.

Prefer:

  • Explicit per-event domain values in handler output
  • Using null or symbolic constants to control domain cleanly

Use domains when handling for specialized contexts:

  • 'human.review' → for human-in-the-loop steps
  • 'analytics.workflow' → to pipe events into observability systems
  • 'external.partner.sync' → to route to external services

Type Parameters

  • TContract extends ArvoContract

Hierarchy (view full)

Constructors

  • Initializes a new ArvoEventHandler instance with the specified contract and configuration. Validates handler implementations against contract versions during initialization.

    The constructor ensures that handler implementations exist for all supported contract versions and configures OpenTelemetry span attributes for monitoring event handling.

    Type Parameters

    • TContract extends ArvoContract<string, string, Record<`${number}.${number}.${number}`, {
          accepts: ZodTypeAny;
          emits: Record<string, ZodTypeAny>;
      }>, Record<string, any>>

    Parameters

    Returns ArvoEventHandler<TContract>

    When handler implementations are missing for any contract version

Properties

contract: TContract

Contract instance that defines the event schema and validation rules

executionunits: number

Computational cost metric associated with event handling operations

Version-specific event handler implementation map

spanOptions: SpanOptions

OpenTelemetry configuration for event handling spans

systemErrorDomain?: (null | string)[] = undefined

Accessors

  • get domain(): null | string
  • The contract-defined domain for this handler, used as the default domain for emitted events. Can be overridden by individual handler implementations for cross-domain workflows. Returns null if no domain is specified, indicating standard processing context.

    Returns null | string

  • get systemErrorSchema(): ArvoContractRecord<`sys.${string}.error`, ZodObject<{
        errorMessage: ZodString;
        errorName: ZodString;
        errorStack: ZodNullable<ZodString>;
    }, "strip", ZodTypeAny, {
        errorMessage: string;
        errorName: string;
        errorStack: null | string;
    }, {
        errorMessage: string;
        errorName: string;
        errorStack: null | string;
    }>>
  • Provides access to the system error event schema configuration.

    The schema defines the structure of error events emitted during execution failures. These events are automatically generated when runtime errors occur and follow a standardized format for consistent error handling across the system.

    Error events follow the naming convention: sys.<contract-type>.error

    Returns ArvoContractRecord<`sys.${string}.error`, ZodObject<{
        errorMessage: ZodString;
        errorName: ZodString;
        errorStack: ZodNullable<ZodString>;
    }, "strip", ZodTypeAny, {
        errorMessage: string;
        errorName: string;
        errorStack: null | string;
    }, {
        errorMessage: string;
        errorName: string;
        errorStack: null | string;
    }>>

    The error event schema containing type and validation rules

    For a contract handling 'com.user.create' events, system error events
    will have the type 'sys.com.user.create.error'

Methods

  • Processes an incoming event according to the handler's contract specifications. This method handles the complete lifecycle of event processing including validation, execution, error handling, and multi-domain event broadcasting, while maintaining detailed telemetry through OpenTelemetry.

    Parameters

    • event: ArvoEvent<Record<string, any>, Record<string,
          | null
          | string
          | number
          | boolean>, string>

      The incoming event to process

    • opentelemetry: ArvoEventHandlerOpenTelemetryOptions = ...

      Configuration for OpenTelemetry context inheritance, defaults to inheriting from the event

    Returns Promise<{
        events: ArvoEvent<Record<string, any>, Record<string,
            | null
            | string
            | number
            | boolean>, string>[];
    }>

    Promise resolving to a structured result containing an array of output events

    when input or output event data violates the contract schema, or when event emission fails due to invalid data

    when event type doesn't match contract type, when the contract version expected by the event does not exist in handler configuration, or when contract URI mismatch occurs

    for explicitly handled runtime errors that should bubble up