Document backend capacity management

This commit is contained in:
2026-07-29 21:16:49 +00:00
parent d2c4051dd0
commit e61ab700c7
10 changed files with 269 additions and 57 deletions

View File

@@ -127,7 +127,9 @@ exact normalization, precedence, error, copying, and exposure contract.
### Register A Custom Backend
Register a reusable OpenAI-compatible connection once, then select it from a
profile:
profile. This local backend limits model generation to two simultaneous calls;
because `QueueCapacity` is omitted, the engine admits up to 1024 additional
calls waiting behind them:
```go
engine, err := promptkit.NewEngine(promptkit.Config{
@@ -137,6 +139,7 @@ engine, err := promptkit.NewEngine(promptkit.Config{
ID: "local",
Endpoint: "http://localhost:8000/v1",
APIKeyEnv: "LOCAL_LLM_API_KEY",
ConcurrencyLimit: 2,
}),
promptkit.WithProfiles(promptkit.Profile{
ID: "local-summary",
@@ -148,15 +151,42 @@ engine, err := promptkit.NewEngine(promptkit.Config{
Registrations belong to one engine and custom IDs cannot replace built-ins.
The [`Backend` and `WithBackend` GoDoc](../../backends.go) defines validation,
copying, uniqueness, and request-default behavior.
copying, uniqueness, exact concurrency-field semantics, and request-default
behavior.
Both file-backed and in-memory profiles select a registration through
`backend` or `Profile.BackendID`. Profile and request endpoint overrides retain
that routing identity. `PreparedRun.SelectedBackendID`,
that routing and capacity identity. `PreparedRun.SelectedBackendID`,
`RunResult.SelectedBackendID`, and the effective `ExecutionTarget.BackendID`
expose it to consumers and injected model clients. Endpoint-only profiles
remain supported and expose an empty backend ID.
### Limit Backend Concurrency
Set `Backend.ConcurrencyLimit` when a backend needs protection from too many
simultaneous model calls. Leaving `QueueCapacity` nil, as in the local-backend
example above, selects the default waiting capacity of 1024.
To accept no waiting backlog beyond the active calls, provide an explicit
zero:
```go
noWaiting := 0
backend := promptkit.Backend{
ID: "local",
Endpoint: "http://localhost:8000/v1",
ConcurrencyLimit: 2,
QueueCapacity: &noWaiting,
}
```
The pointer distinguishes an explicit zero from omission. Keep using keyed
`Backend` literals so additive configuration fields remain source-compatible.
Capacity belongs to one engine and the selected backend ID; endpoint-only
profiles and custom backends without a configured limit remain unrestricted.
Exact validation, defaulting, ownership, and concurrency semantics belong to
the [`Backend` GoDoc](../../backends.go).
## Credentials
File-backed profiles name an environment variable; in-memory profiles can
@@ -200,6 +230,22 @@ failures. Specific request conditions may also match the broader
documented. Invalid or duplicate backend registrations match
`ErrInvalidConfig`; selecting an unknown backend matches `ErrProfileLoad`.
When a limited backend has admitted all active and waiting calls, handle
`ErrCapacityExceeded` separately from request errors and provider failures:
```go
result, err := engine.Run(ctx, request)
if errors.Is(err, promptkit.ErrCapacityExceeded) {
// Apply application policy: shed work, report overload, or retry later.
}
```
A rejected call returns no partial result and does not invoke the model
client. Promptkit does not prescribe retries or map this error to an HTTP
status; those choices remain with the consuming application. The
[`Engine.Run` and error GoDoc](../../engine.go) owns exact error and
cancellation identities.
## Application Boundary
Promptkit is an importable library. It does not own a command, inbound HTTP