Skip to main content

ai-core-locks

LockStore, InMemoryLockStore, LocksCapability and withLocks for multi-instance coordination in TanStack AI. Ships in @tanstack/ai — NOT in @tanstack/ai-persistence. Separate from AIPersistence state stores — not a stores key, not composable. InMemoryLockStore vs a distributed (e.g. Cloudflare Durable Object) lock, lease recovery, AbortSignal in critical sections. Use when sandbox or other middleware needs cross-worker mutual exclusion — NOT for storing messages/runs (use withPersistence).

Quellinformationen

Repository
TanStack/ai
Letzte Quellaktivität
9. September 2026 um 06:08
Erkannte Sprache von SKILL.md
Englisch
Sterne
3.199
Forks
366

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
ai-core/locks
description
LockStore, InMemoryLockStore, LocksCapability and withLocks for multi-instance coordination in TanStack AI. Ships in @tanstack/ai — NOT in @tanstack/ai-persistence. Separate from AIPersistence state stores — not a stores key, not composable. InMemoryLockStore vs a distributed (e.g. Cloudflare Durable Object) lock, lease recovery, AbortSignal in critical sections. Use when sandbox or other middleware needs cross-worker mutual exclusion — NOT for storing messages/runs (use withPersistence).
type
sub-skill
library
tanstack-ai
library_version
0.42.0
sources
["TanStack/ai:docs/advanced/locks.md","TanStack/ai:packages/ai/src/activities/chat/middleware/locks.ts"]
# Locks (coordination — not persistence) > **Dependency note:** This skill builds on ai-core and ai-core/middleware. > `withLocks` is a ChatMiddleware that provides a capability. Locks are **not** > part of `AIPersistence.stores` and are **not** composed with > `composePersistence` — they ship in `@tanstack/ai`, independent of > `@tanstack/ai-persistence`. ## Why separate? State stores answer "what is durable chat data?" Locks answer "who may run this critical section right now?" `withPersistence` does **not** automatically lock a whole turn. Take a per-thread (or other) lock yourself when multi-writer races matter. ## Wire locks ```ts import { chat } from '@tanstack/ai' import { withLocks, InMemoryLockStore } from '@tanstack/ai/locks' import { openaiText } from '@tanstack/ai-openai' const messages = [{ role: 'user' as const, content: 'Hello' }] chat({ adapter: openaiText('gpt-5.6'), messages, middleware: [ withLocks(new InMemoryLockStore()), // single process ], }) ``` Alongside persistence — optional, locks do not require it: ```ts import { chat } from '@tanstack/ai' import { withLocks, InMemoryLockStore } from '@tanstack/ai/locks' import { openaiText } from '@tanstack/ai-openai' import { memoryPersistence, withPersistence } from '@tanstack/ai-persistence' const persistence = memoryPersistence() const messages = [{ role: 'user' as const, content: 'Hello' }] chat({ adapter: openaiText('gpt-5.6'), messages, middleware: [ withPersistence(persistence), withLocks(new InMemoryLockStore()), ], }) ``` `withLocks` provides `LocksCapability` for downstream middleware (e.g. sandbox). Order: usually state first, locks alongside or after depending on who consumes the capability. ## The contract ```ts interface LockStore { withLock<T>(key: string, fn: (signal: AbortSignal) => Promise<T>): Promise<T> } ``` `InMemoryLockStore` ships in **`@tanstack/ai/locks`**: a per-key promise chain, correct **within a single process only**. Multi-instance deployments need a distributed implementation — you write it. The Cloudflare Durable Object recipe is in **ai-persistence/build-cloudflare-adapter** (`@tanstack/ai-persistence`). Type your own store with `defineLock` (autocomplete, no `: LockStore` annotation), then hand it to `withLocks`. Acquire the key, run `fn`, release when `fn` settles: ```ts import { chat } from '@tanstack/ai' import { defineLock, withLocks } from '@tanstack/ai/locks' import { openaiText } from '@tanstack/ai-openai' import { acquire } from './my-lock-backend' const locks = defineLock({ async withLock(key, fn) { const { release, signal } = await acquire(key) try { return await fn(signal) } finally { release() } }, }) const messages = [{ role: 'user' as const, content: 'Hello' }] chat({ adapter: openaiText('gpt-5.6'), messages, middleware: [withLocks(locks)], }) ``` ## Lease semantics A good `LockStore`: - Serializes owners per key, - Uses **leases** (or equivalent) so a crashed owner cannot block forever, - Passes an `AbortSignal` into the critical section via `withLock`; when the lease is lost, abort so work stops starting external mutations. Callbacks must honor the signal and pass it to cancellable dependencies. `InMemoryLockStore` never aborts its signal — within one process, ownership cannot be lost. ## Capability identity The `'locks'` capability token lives in `@tanstack/ai/locks`. Capability identity is by **object reference**, so one shared token means a `withLocks` in the chain reaches `withSandbox` automatically. ## Common mistakes ### HIGH: Importing locks from `@tanstack/ai-persistence` They are not exported there. Use `@tanstack/ai`. ### HIGH: Putting `locks` on `AIPersistence.stores` Not supported. `stores` accepts only `messages`, `runs`, `interrupts`, `metadata` — never `locks`. Use `withLocks`. ### HIGH: Passing `locks` to `composePersistence` overrides Same rejection, at the override layer. Locks are not state. ### HIGH: Passing `'locks'` to the conformance testkit's `skip` `skip` accepts only chat state store keys. The suite does not cover locks at all — test lease expiry and abort separately. ### HIGH: `InMemoryLockStore` across multiple processes No mutual exclusion between machines — use a distributed lock store. ### MEDIUM: Ignoring lease abort Continuing work after losing the lease races other owners. ## Cross-references - See also: **ai-core/middleware/SKILL.md** -- the middleware chain and capability plumbing - See also: **`@tanstack/ai-persistence` skills** (`skills/ai-persistence/SKILL.md` in that package) -- `ai-persistence/server` (state middleware) and `ai-persistence/build-cloudflare-adapter` (Durable Object lock recipe)
Auf GitHub ansehen