AbortSignal / Timeouts

Overview

BAML provides cancellation support for in-flight function calls across all language clients. In TypeScript, this uses the modern AbortSignal API, while other languages use their native patterns.

Language Support

LanguageImplementationImport
TypeScriptAbortSignal APIBuilt-in (Node.js 15+)
PythonCustom AbortControllerfrom baml_py import AbortController
Gocontext.ContextBuilt-in
RubyNot supported-

API Reference

TypeScript

1// Manual cancellation
2const controller = new AbortController()
3const result = await b.FunctionName(input, {
4 signal: controller.signal
5})
6
7// Cancel operation
8controller.abort()
9
10// Automatic timeout using AbortSignal.timeout()
11const result2 = await b.FunctionName(input, {
12 signal: AbortSignal.timeout(5000) // 5 second timeout
13})
14
15// Check if aborted
16if (controller.signal.aborted) {
17 // Handle aborted state
18}

AbortController Properties

  • signal: AbortSignal - Read-only signal that indicates if the controller has been aborted

AbortController Methods

  • abort(reason?: any): void - Cancels the associated operation(s) with an optional reason

AbortSignal Static Methods

  • AbortSignal.timeout(delay: number): AbortSignal - Creates a signal that automatically aborts after the specified delay in milliseconds

Integration with Streaming

Abort controllers work seamlessly with streaming responses:

1const controller = new AbortController()
2const stream = b.stream.FunctionName(input, {
3 signal: controller.signal
4})
5
6try {
7 for await (const chunk of stream) {
8 // Process chunk
9 if (someCondition) {
10 controller.abort() // Stops the stream
11 break
12 }
13 }
14} catch (error) {
15 if (error instanceof BamlAbortError) {
16 console.log('Stream was aborted:', error.reason)
17 }
18}

Error Types

When an operation is aborted, language-specific errors are thrown:

  • TypeScript: BamlAbortError
  • Python: BamlAbortError
  • Go: context.Canceled or context.DeadlineExceeded
  • Ruby: Not supported

See BamlAbortError for detailed error handling information.

Thread Safety

Abort controllers are thread-safe and can be safely shared across multiple operations or threads.

The Node.js AbortController is thread-safe by design.

Examples

Basic Timeout Implementation

1// Modern approach using AbortSignal.timeout()
2const result = await b.ExtractData(input, {
3 signal: AbortSignal.timeout(5000) // 5 second timeout
4})
5
6// Manual timeout implementation
7function withTimeout<T>(
8 operation: (signal: AbortSignal) => Promise<T>,
9 timeoutMs: number
10): Promise<T> {
11 const controller = new AbortController()
12 const timeoutId = setTimeout(() => controller.abort(), timeoutMs)
13
14 return operation(controller.signal).finally(() => {
15 clearTimeout(timeoutId)
16 })
17}
18
19// Usage
20const result2 = await withTimeout(
21 (signal) => b.ExtractData(input, { signal }),
22 5000 // 5 second timeout
23)

Cancelling Multiple Operations

1const controller = new AbortController()
2
3const operations = [
4 b.Operation1(input1, { signal: controller.signal }),
5 b.Operation2(input2, { signal: controller.signal }),
6 b.Operation3(input3, { signal: controller.signal })
7]
8
9// Cancel all if any fails
10try {
11 const results = await Promise.all(operations)
12} catch (error) {
13 controller.abort() // Cancel remaining operations
14 throw error
15}