AbortSignal / Timeouts
BAML provides cancellation support for in-flight function calls across all language clients.
Language Support
| Language | Implementation | Import |
|---|---|---|
| TypeScript | AbortSignal API | Built-in (Node.js 15+) |
| Python | Custom AbortController | from baml_py import AbortController |
| Go | context.Context | Built-in |
| Ruby | Not supported | - |
Basic Usage
- TypeScript
- Python
- Go
- Ruby
// Manual cancellation
const controller = new AbortController()
const result = await b.FunctionName(input, {
signal: controller.signal
})
// Cancel operation
controller.abort()
// Automatic timeout
const result2 = await b.FunctionName(input, {
signal: AbortSignal.timeout(5000) // 5 second timeout
})
// Check if aborted
if (controller.signal.aborted) {
// Handle aborted state
}
AbortController Properties
signal: AbortSignal- Read-only signal indicating if aborted
AbortController Methods
abort(reason?: any): void- Cancels operation with optional reason
AbortSignal Static Methods
AbortSignal.timeout(delay: number): AbortSignal- Auto-aborts after delay (ms)
from baml_py import AbortController
# Create controller
controller = AbortController()
# Or with timeout
controller_with_timeout = AbortController(timeout_ms=5000)
# Pass to function call
result = await b.FunctionName(
input,
baml_options={"abort_controller": controller}
)
# Cancel operation
controller.abort()
# Check if aborted
if controller.aborted:
# Handle aborted state
Properties
aborted: bool- ReturnsTrueif aborted
Methods
__init__(timeout_ms: Optional[int] = None)- Create controller with optional timeoutabort(reason: Any = None) -> None- Cancel operation
import "context"
// Create cancellable context
ctx, cancel := context.WithCancel(context.Background())
// Pass context to function call
result, err := b.FunctionName(ctx, input)
// Cancel operation
cancel()
// Check if cancelled
select {
case <-ctx.Done():
// Context was cancelled
default:
// Still active
}
Context Functions
context.WithCancel(parent Context)- Creates cancellable contextcontext.WithTimeout(parent Context, timeout Duration)- Context with timeoutcontext.WithDeadline(parent Context, deadline Time)- Context with deadline
AbortController is not currently supported in the Ruby client.
Integration with Streaming
- TypeScript
- Python
- Go
const controller = new AbortController()
const stream = b.stream.FunctionName(input, {
signal: controller.signal
})
try {
for await (const chunk of stream) {
if (someCondition) {
controller.abort()
break
}
}
} catch (error) {
if (error instanceof BamlAbortError) {
console.log('Stream was aborted:', error.reason)
}
}
controller = AbortController()
stream = b.stream.FunctionName(
input,
baml_options={"abort_controller": controller}
)
async for chunk in stream:
if some_condition:
controller.abort()
break
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
stream := b.StreamFunctionName(ctx, input)
for chunk := range stream {
if someCondition {
cancel()
break
}
}
Error Types
When an operation is aborted:
- TypeScript:
BamlAbortError - Python:
BamlAbortError - Go:
context.Canceledorcontext.DeadlineExceeded
Thread Safety
note
Abort controllers are thread-safe and can be safely shared across multiple operations or threads.
Examples
Basic Timeout
- TypeScript
- Python
// Modern approach
const result = await b.ExtractData(input, {
signal: AbortSignal.timeout(5000)
})
// Manual timeout
function withTimeout<T>(
operation: (signal: AbortSignal) => Promise<T>,
timeoutMs: number
): Promise<T> {
const controller = new AbortController()
const timeoutId = setTimeout(() => controller.abort(), timeoutMs)
return operation(controller.signal).finally(() => {
clearTimeout(timeoutId)
})
}
const result2 = await withTimeout(
(signal) => b.ExtractData(input, { signal }),
5000
)
controller = AbortController(timeout_ms=5000)
await b.ExtractData(input, baml_options={"abort_controller": controller})
Cancelling Multiple Operations
- TypeScript
- Python
- Go
const controller = new AbortController()
const operations = [
b.Operation1(input1, { signal: controller.signal }),
b.Operation2(input2, { signal: controller.signal }),
b.Operation3(input3, { signal: controller.signal })
]
try {
const results = await Promise.all(operations)
} catch (error) {
controller.abort() // Cancel remaining operations
throw error
}
controller = AbortController()
operations = [
b.Operation1(input1, baml_options={"abort_controller": controller}),
b.Operation2(input2, baml_options={"abort_controller": controller}),
b.Operation3(input3, baml_options={"abort_controller": controller})
]
try:
results = await asyncio.gather(*operations)
except Exception as e:
controller.abort()
raise
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
errChan := make(chan error, 3)
for i := 0; i < 3; i++ {
go func(idx int) {
_, err := b.Operation1(ctx, input)
errChan <- err
}(i)
}
// Cancel all after 100ms
time.Sleep(100 * time.Millisecond)
cancel()
See Also
- with_options - Set default abort controllers
- Errors - Error handling