> ## 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.

# Find Events

> Query history and optionally wait for matching future events.

`find(...)` is the unified lookup API: search history, wait for future events, or combine both.

## Interface

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    await bus.find(
        event_type,                            # Event class, event type string, or '*'
        where: Callable[[BaseEvent], bool] | None = None,
        child_of: BaseEvent | None = None,
        past: bool | float | timedelta = True,
        future: bool | float = False,
        **event_fields,                        # equality filters (event_status='completed', request_id='abc', ...)
    )
    ```
  </Tab>

  <Tab title="TypeScript">
    ```ts theme={null}
    await bus.find(event_pattern, options?)
    await bus.find(event_pattern, where, options?)

    // options:
    {
      past?: boolean | number         // seconds when number
      future?: boolean | number       // seconds when number
      child_of?: BaseEvent | null
      [event_field: string]: unknown  // equality filters, e.g. event_status: 'completed'
    }
    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    bus.FindEventName(
    	"ResponseEvent",                         // event type string or "*"
    	func(event *abxbus.BaseEvent) bool {      // optional predicate
    		return true
    	},
    	&abxbus.FindOptions{
    		Past: true,                           // bool or seconds as float64/int
    		Future: false,                        // bool or seconds as float64/int
    		ChildOf: parentEvent,                 // optional lineage filter
    		Equals: map[string]any{               // event metadata or payload equality filters
    			"event_status": "completed",
    			"request_id": "abc",
    		},
    	},
    )
    ```
  </Tab>

  <Tab title="Rust">
    ```rust theme={null}
    use abxbus::event_bus::FindOptions;
    use futures::executor::block_on;
    use serde_json::json;
    use std::{collections::HashMap, sync::Arc};

    block_on(bus.find(
        "ResponseEvent",        // event type string or "*"
        true,                   // past history lookup
        Some(5.0),              // future wait timeout in seconds
        None,                   // child_of parent event
    ));

    block_on(bus.find_with_options(
        "ResponseEvent",
        FindOptions {
            past: false,
            future: Some(5.0),
            child_of: Some(parent_event.clone()),
            where_filter: Some(HashMap::from([
                ("event_status".to_string(), json!("completed")),
                ("request_id".to_string(), json!("abc")),
            ])),
            ..FindOptions::default()
        },
    ));
    ```
  </Tab>
</Tabs>

## Option semantics

* `past`
  * `true`: search all history (default)
  * `false`: skip history
  * `number` (or `timedelta` in Python): search recent history window
* `future`
  * `false`: do not wait (default)
  * `true`: wait indefinitely
  * `number`: wait up to N seconds
* `where`: predicate filter
* `child_of`: match only descendants of the given parent event
* `event_fields`: strict equality filters on event fields/metadata

Default behavior when omitted is history-only lookup (`past=True`, `future=False`).

## Common use cases

### 1) History lookup only (non-blocking)

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    existing = await bus.find(ResponseEvent)
    ```
  </Tab>

  <Tab title="TypeScript">
    ```ts theme={null}
    const existing = await bus.find(ResponseEvent)
    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    existing, err := bus.FindEventName("ResponseEvent", nil, nil)
    ```
  </Tab>

  <Tab title="Rust">
    ```rust theme={null}
    let existing = block_on(bus.find("ResponseEvent", true, None, None));
    ```
  </Tab>
</Tabs>

### 2) Wait only for future events

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    future = await bus.find(ResponseEvent, past=False, future=5)
    ```
  </Tab>

  <Tab title="TypeScript">
    ```ts theme={null}
    const future = await bus.find(ResponseEvent, { past: false, future: 5 })
    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    future, err := bus.FindEventName("ResponseEvent", nil, &abxbus.FindOptions{
    	Past: false,
    	Future: 5.0,
    })
    ```
  </Tab>

  <Tab title="Rust">
    ```rust theme={null}
    let future = block_on(bus.find("ResponseEvent", false, Some(5.0), None));
    ```
  </Tab>
</Tabs>

### 3) Check recent history, then keep waiting briefly

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    match = await bus.find(ResponseEvent, past=5, future=5)
    ```
  </Tab>

  <Tab title="TypeScript">
    ```ts theme={null}
    const match = await bus.find(ResponseEvent, { past: 5, future: 5 })
    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    match, err := bus.FindEventName("ResponseEvent", nil, &abxbus.FindOptions{
    	Past: 5.0,
    	Future: 5.0,
    })
    ```
  </Tab>

  <Tab title="Rust">
    ```rust theme={null}
    let match_event = block_on(bus.find_with_options(
        "ResponseEvent",
        FindOptions {
            past_window: Some(5.0),
            future: Some(5.0),
            ..FindOptions::default()
        },
    ));
    ```
  </Tab>
</Tabs>

### 4) Filter by fields + predicate

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    match = await bus.find(
        ResponseEvent,
        where=lambda e: e.request_id == my_id,
        event_status='completed',
        future=5,
    )
    ```
  </Tab>

  <Tab title="TypeScript">
    ```ts theme={null}
    const match = await bus.find(
      ResponseEvent,
      (event) => event.request_id === myId,
      { event_status: 'completed', future: 5 }
    )
    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    match, err := bus.FindEventName(
    	"ResponseEvent",
    	func(event *abxbus.BaseEvent) bool {
    		return event.Payload["request_id"] == myID
    	},
    	&abxbus.FindOptions{
    		Future: 5.0,
    		Equals: map[string]any{"event_status": "completed"},
    	},
    )
    ```
  </Tab>

  <Tab title="Rust">
    ```rust theme={null}
    let match_event = block_on(bus.find_with_options(
        "ResponseEvent",
        FindOptions {
            future: Some(5.0),
            where_filter: Some(HashMap::from([(
                "request_id".to_string(),
                json!(my_id),
            )])),
            ..FindOptions::default()
        },
    ));
    ```
  </Tab>
</Tabs>

### 5) Wildcard lookup across all event types

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    any_completed = await bus.find(
        '*',
        where=lambda e: e.event_type.endswith('ResultEvent'),
        event_status='completed',
        future=5,
    )
    ```
  </Tab>

  <Tab title="TypeScript">
    ```ts theme={null}
    const anyCompleted = await bus.find(
      '*',
      (event) => event.event_type.endsWith('ResultEvent'),
      { event_status: 'completed', future: 5 }
    )
    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    anyCompleted, err := bus.FindEventName(
    	"*",
    	func(event *abxbus.BaseEvent) bool {
    		return strings.HasSuffix(event.EventType, "ResultEvent")
    	},
    	&abxbus.FindOptions{
    		Future: 5.0,
    		Equals: map[string]any{"event_status": "completed"},
    	},
    )
    ```
  </Tab>

  <Tab title="Rust">
    ```rust theme={null}
    let any_completed = block_on(bus.find_with_options(
        "*",
        FindOptions {
            future: Some(5.0),
            where_filter: Some(HashMap::from([(
                "event_status".to_string(),
                json!("completed"),
            )])),
            where_predicate: Some(Arc::new(|event| {
                event
                    .to_json_value()
                    .get("event_type")
                    .and_then(|value| value.as_str())
                    .is_some_and(|event_type| event_type.ends_with("ResultEvent"))
            })),
            ..FindOptions::default()
        },
    ));
    ```
  </Tab>
</Tabs>

### 6) Find descendants of a specific parent event

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    parent_event = await bus.emit(NavigateToUrlEvent(url='https://example.com')).now()
    child = await bus.find(TabCreatedEvent, child_of=parent_event, past=5)
    ```
  </Tab>

  <Tab title="TypeScript">
    ```ts theme={null}
    const parentEvent = await bus.emit(NavigateToUrlEvent({ url: 'https://example.com' })).now()
    const child = await bus.find(TabCreatedEvent, { child_of: parentEvent, past: 5 })
    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    parentEvent := bus.Emit(abxbus.NewBaseEvent("NavigateToUrlEvent", map[string]any{
    	"url": "https://example.com",
    }))
    if _, err := parentEvent.Now(); err != nil {
    	panic(err)
    }
    child, err := bus.FindEventName("TabCreatedEvent", nil, &abxbus.FindOptions{
    	ChildOf: parentEvent,
    	Past: 5.0,
    })
    ```
  </Tab>

  <Tab title="Rust">
    ```rust theme={null}
    event! {
        struct NavigateToUrlEvent {
            url: String,
            event_result_type: (),
        }
    }

    event! {
        struct TabCreatedEvent {
            event_result_type: (),
        }
    }

    let parent_event = bus.emit(NavigateToUrlEvent {
        url: "https://example.com".to_string(),
        ..Default::default()
    });
    block_on(parent_event.now())?;

    let parent_ref = block_on(bus.find("NavigateToUrlEvent", true, None, None))
        .expect("parent event should be in history");
    let child = block_on(bus.find_with_options(
        "TabCreatedEvent",
        FindOptions {
            past_window: Some(5.0),
            child_of: Some(parent_ref),
            ..FindOptions::default()
        },
    ));
    ```
  </Tab>
</Tabs>

### 7) Debounce expensive work

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    event = (
        await bus.find(ScreenshotEvent, past=10, future=False)
        or await bus.find(ScreenshotEvent, past=False, future=5)
        or bus.emit(ScreenshotEvent())
    )
    await event.now()
    ```
  </Tab>

  <Tab title="TypeScript">
    ```ts theme={null}
    const event =
      (await bus.find(ScreenshotEvent, { past: 10, future: false })) ??
      (await bus.find(ScreenshotEvent, { past: false, future: 5 })) ??
      bus.emit(ScreenshotEvent({}))
    await event.now()
    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    event, err := bus.FindEventName("ScreenshotEvent", nil, &abxbus.FindOptions{Past: 10.0, Future: false})
    if err != nil {
    	panic(err)
    }
    if event == nil {
    	event, err = bus.FindEventName("ScreenshotEvent", nil, &abxbus.FindOptions{Past: false, Future: 5.0})
    	if err != nil {
    		panic(err)
    	}
    }
    if event == nil {
    	event = bus.Emit(abxbus.NewBaseEvent("ScreenshotEvent", nil))
    }
    if _, err := event.Now(); err != nil {
    	panic(err)
    }
    ```
  </Tab>

  <Tab title="Rust">
    ```rust theme={null}
    event! {
        struct ScreenshotEvent {
            event_result_type: Vec<u8>,
        }
    }

    let event = match block_on(bus.find_with_options(
        "ScreenshotEvent",
        FindOptions {
            past_window: Some(10.0),
            future: None,
            ..FindOptions::default()
        },
    )) {
        Some(raw) => serde_json::from_value::<ScreenshotEvent>(raw.to_json_value())?,
        None => match block_on(bus.find_with_options(
            "ScreenshotEvent",
            FindOptions {
                past: false,
                future: Some(5.0),
                ..FindOptions::default()
            },
        )) {
            Some(raw) => serde_json::from_value::<ScreenshotEvent>(raw.to_json_value())?,
            None => bus.emit(ScreenshotEvent { ..Default::default() }),
        },
    };

    block_on(event.now())?;
    ```
  </Tab>
</Tabs>

## Important behavior

* `find()` resolves when an event is emitted, not when handlers finish.
* To wait for handler completion, call `await event.now()` in Python/TypeScript, `event.Now()` in Go, or `event.now().await` in Rust.
* If no match is found (or `future` times out), `find()` returns `None` / `null`.
* If both `past` and `future` are `false`, it returns immediately with no match.

## Returning multiple matches: `filter()`

`filter()` takes the same arguments as `find()` but returns the list of all matching events
(ordered newest to oldest), plus an optional `limit` argument to cap the number of results.
`find()` is equivalent to `filter(..., limit=1)` returning the first match (or `None` / `null`).

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    recent = await bus.filter(ResponseEvent, past=10, future=False, limit=5)
    ```
  </Tab>

  <Tab title="TypeScript">
    ```ts theme={null}
    const recent = await bus.filter(ResponseEvent, { past: 10, future: false, limit: 5 })
    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    limit := 5
    recent, err := bus.FilterEventName("ResponseEvent", nil, &abxbus.FilterOptions{
    	Past:   10.0,
    	Future: false,
    	Limit:  &limit,
    })
    ```
  </Tab>

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

    let recent = block_on(bus.filter_with_options(
        "ResponseEvent",
        FilterOptions {
            past_window: Some(10.0),
            future: None,
            limit: Some(5),
            ..FilterOptions::default()
        },
    ));
    ```
  </Tab>
</Tabs>
