> ## Documentation Index
> Fetch the complete documentation index at: https://abxbus.archivebox.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Timeout Enforcement

> Configure execution deadlines and slow-warning thresholds at bus, event, and handler levels.

Timeout controls operate at three levels:

* Bus defaults (resolved on each bus at processing time when event-level values are unset)
* Per-event overrides (applies to one emitted event instance)
* Per-handler overrides (applies to one handler registration)

Repository example files:

* [`examples/concurrency_options.py`](https://github.com/ArchiveBox/abxbus/blob/main/examples/concurrency_options.py)
* [`abxbus-ts/examples/concurrency_options.ts`](https://github.com/ArchiveBox/abxbus/blob/main/abxbus-ts/examples/concurrency_options.ts)
* [`abxbus-rust/tests/test_eventbus_timeout.rs`](https://github.com/ArchiveBox/abxbus/blob/main/abxbus-rust/tests/test_eventbus_timeout.rs)
* [`examples/log_tree_demo.py`](https://github.com/ArchiveBox/abxbus/blob/main/examples/log_tree_demo.py)
* [`abxbus-ts/examples/log_tree_demo.ts`](https://github.com/ArchiveBox/abxbus/blob/main/abxbus-ts/examples/log_tree_demo.ts)

## Timeout types

### 1) Event timeout (`event_timeout`)

The outer execution budget for an event. This also acts as an upper cap for each handler run for that event.

### 2) Handler timeout (`event_handler_timeout` / `handler_timeout`)

A handler-specific timeout budget. The effective handler timeout is resolved from handler -> event -> bus, then capped by `event_timeout` when both are set.

### 3) Slow-warning thresholds (`event_slow_timeout`, `event_handler_slow_timeout`, `handler_slow_timeout`)

These emit warnings when work is taking longer than expected:

* `event_slow_timeout`: warns when event processing is still running past the threshold.
* `event_handler_slow_timeout` / `handler_slow_timeout`: warns when a handler run is still running past the threshold.

Slow thresholds are warnings, not forced cancellation.
For event and handler timeout fields, unset (`None` / `null` / `nil`) means inherit the processing bus default at execution time. Set `0` to explicitly disable that timeout or slow warning.

## Where to set each value

| Level   | Execution timeout fields                 | Slow-warning fields                                |
| ------- | ---------------------------------------- | -------------------------------------------------- |
| Bus     | `event_timeout`                          | `event_slow_timeout`, `event_handler_slow_timeout` |
| Event   | `event_timeout`, `event_handler_timeout` | `event_slow_timeout`, `event_handler_slow_timeout` |
| Handler | `handler_timeout`                        | `handler_slow_timeout`                             |

## Bus-level defaults

Set default budgets and warning thresholds once when creating a bus.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from abxbus import EventBus

    bus = EventBus(
        'TimeoutBus',
        event_timeout=30.0,
        event_slow_timeout=10.0,
        event_handler_slow_timeout=3.0,
    )
    ```
  </Tab>

  <Tab title="TypeScript">
    ```ts theme={null}
    import { EventBus } from 'abxbus'

    const bus = new EventBus('TimeoutBus', {
      event_timeout: 30,
      event_slow_timeout: 10,
      event_handler_slow_timeout: 3,
    })
    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    eventTimeout := 30.0
    eventSlowTimeout := 10.0
    handlerSlowTimeout := 3.0

    bus := abxbus.NewEventBus("TimeoutBus", &abxbus.EventBusOptions{
    	EventTimeout:            &eventTimeout,
    	EventSlowTimeout:        &eventSlowTimeout,
    	EventHandlerSlowTimeout: &handlerSlowTimeout,
    })
    ```
  </Tab>

  <Tab title="Rust">
    ```rust theme={null}
    use abxbus::event_bus::{EventBus, EventBusOptions};

    let bus = EventBus::new_with_options(
        Some("TimeoutBus".to_string()),
        EventBusOptions {
            event_timeout: Some(30.0),
            event_slow_timeout: Some(10.0),
            event_handler_slow_timeout: Some(3.0),
            ..EventBusOptions::default()
        },
    );
    ```
  </Tab>
</Tabs>

## Event-level overrides

Set per-event values when emitting an event instance.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from abxbus import BaseEvent

    class WorkEvent(BaseEvent):
        pass

    event = bus.emit(
        WorkEvent(
            event_timeout=8.0,
            event_handler_timeout=2.0,
            event_slow_timeout=4.0,
            event_handler_slow_timeout=1.0,
        )
    )
    ```
  </Tab>

  <Tab title="TypeScript">
    ```ts theme={null}
    import { BaseEvent } from 'abxbus'

    const WorkEvent = BaseEvent.extend('WorkEvent', {})

    const event = bus.emit(
      WorkEvent({
        event_timeout: 8,
        event_handler_timeout: 2,
        event_slow_timeout: 4,
        event_handler_slow_timeout: 1,
      })
    )
    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    eventTimeout := 8.0
    eventHandlerTimeout := 2.0
    eventSlowTimeout := 4.0
    eventHandlerSlowTimeout := 1.0

    event := abxbus.NewBaseEvent("WorkEvent", nil)
    event.EventTimeout = &eventTimeout
    event.EventHandlerTimeout = &eventHandlerTimeout
    event.EventSlowTimeout = &eventSlowTimeout
    event.EventHandlerSlowTimeout = &eventHandlerSlowTimeout

    event = bus.Emit(event)
    ```
  </Tab>

  <Tab title="Rust">
    ```rust theme={null}
    let event = WorkEvent {
        event_timeout: Some(8.0),
        event_handler_timeout: Some(2.0),
        event_slow_timeout: Some(4.0),
        event_handler_slow_timeout: Some(1.0),
        ..Default::default()
    };
    let event = bus.emit(event);
    ```
  </Tab>
</Tabs>

## Handler-level overrides

Set per-handler timeout and slow-warning overrides at registration time (or by updating the returned handler metadata).

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    entry = bus.on(WorkEvent, slow_handler)
    entry.handler_timeout = 1.5
    entry.handler_slow_timeout = 0.5
    ```
  </Tab>

  <Tab title="TypeScript">
    ```ts theme={null}
    bus.on(WorkEvent, slowHandler, {
      handler_timeout: 1.5,
      handler_slow_timeout: 0.5,
    })
    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    entry := bus.On("WorkEvent", "slow_handler", slowHandler, nil)
    handlerTimeout := 1.5
    handlerSlowTimeout := 0.5
    entry.HandlerTimeout = &handlerTimeout
    entry.HandlerSlowTimeout = &handlerSlowTimeout
    ```
  </Tab>

  <Tab title="Rust">
    ```rust theme={null}
    use abxbus::event_handler::EventHandlerOptions;

    let entry = bus.on_with_options(
        WorkEvent,
        "slow_handler",
        EventHandlerOptions {
            handler_timeout: Some(1.5),
            handler_slow_timeout: Some(0.5),
            ..EventHandlerOptions::default()
        },
        |_event: WorkEvent| async move { Ok(()) },
    );
    ```
  </Tab>
</Tabs>

## Precedence rules

### Effective handler timeout

1. Resolve handler timeout source:
   * `handler_timeout` (handler level)
   * else `event_handler_timeout` (event level)
   * else bus `event_timeout`
2. Apply event cap:
   * effective timeout is `min(resolved_handler_timeout, event_timeout)` when both are set
   * if one is unset, the other value is used
   * if both are unset, no timeout is enforced

Resolution happens at processing time on each bus.
For forwarded events, an unset timeout/concurrency field uses the target bus defaults.

### Effective handler slow-warning threshold

Resolved in this order:

1. `handler_slow_timeout`
2. `event_handler_slow_timeout`
3. bus `event_handler_slow_timeout`

### Effective event slow-warning threshold

Resolved in this order:

1. `event_slow_timeout`
2. bus `event_slow_timeout`

## Execution behavior

Timeout and slow-warning behavior is part of the public event lifecycle:

* Event-level timeouts bound the whole event.
* Handler-level timeouts bound each handler and are capped by the remaining event-level budget when both are set.
* Slow-warning settings only log warnings; they do not cancel work.
* Hard timeouts mark unfinished handler results as cancelled, aborted, or timed out and prevent late handler results or late child emits from being accepted.

Event-level timeout finalization keeps cancellation semantics explicit:

* pending handlers -> cancelled
* started handlers -> aborted

## Note on retry

Bus/event timeouts are outer budgets. If you need per-attempt limits for retried handlers, use the `retry` decorator's `timeout` option.

Go does not include the retry decorator yet; for now, wrap retry behavior around your handler body explicitly and keep the bus/event timeout as the outer budget.
