a7d6d88f6f
CI / changes (push) Has been cancelled
CI / cd libs/checkpoint (push) Has been cancelled
CI / cd libs/checkpoint-conformance (push) Has been cancelled
CI / cd libs/checkpoint-postgres (push) Has been cancelled
CI / cd libs/checkpoint-sqlite (push) Has been cancelled
CI / cd libs/cli (push) Has been cancelled
CI / cd libs/prebuilt (push) Has been cancelled
CI / cd libs/sdk-py (push) Has been cancelled
CI / cd libs/langgraph (push) Has been cancelled
CI / Check SDK methods matching (push) Has been cancelled
CI / Check CLI schema hasn't changed #3.13 (push) Has been cancelled
CI / CLI integration test (push) Has been cancelled
CI / sdk-py integration test (push) Has been cancelled
CI / CI Success (push) Has been cancelled
baseline / benchmark (push) Has been cancelled
Deploy Redirects to GitHub Pages / deploy (push) Has been cancelled
144 lines
4.6 KiB
Python
144 lines
4.6 KiB
Python
"""Key/value cache for use inside LangGraph deployments.
|
|
|
|
Thin wrapper around ``langgraph_api.cache``.
|
|
Values must be JSON-serializable (dicts, lists, strings, numbers, booleans,
|
|
``None``).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Awaitable, Callable
|
|
from datetime import timedelta
|
|
from typing import Any, Generic, Literal, TypeVar
|
|
|
|
T = TypeVar("T")
|
|
|
|
CacheStatus = Literal["miss", "fresh", "stale", "expired"]
|
|
|
|
try:
|
|
from langgraph_api.cache import ( # ty: ignore[unresolved-import]
|
|
cache_get as _cache_get,
|
|
)
|
|
from langgraph_api.cache import ( # ty: ignore[unresolved-import]
|
|
cache_set as _cache_set,
|
|
)
|
|
except ImportError:
|
|
_cache_get = None
|
|
_cache_set = None
|
|
|
|
|
|
try:
|
|
from langgraph_api.cache import SWRResult # ty: ignore[unresolved-import]
|
|
from langgraph_api.cache import swr as _api_swr # ty: ignore[unresolved-import]
|
|
|
|
except ImportError:
|
|
_api_swr = None
|
|
|
|
class SWRResult(Generic[T]):
|
|
"""Result wrapper returned by :func:`swr`."""
|
|
|
|
value: T
|
|
status: CacheStatus
|
|
|
|
async def mutate(
|
|
self,
|
|
value: T = ..., # ty: ignore[invalid-parameter-default]
|
|
) -> T: # ty: ignore[empty-body]
|
|
"""Update or revalidate the cached value."""
|
|
...
|
|
|
|
|
|
__all__ = [
|
|
"SWRResult",
|
|
"cache_get",
|
|
"cache_set",
|
|
"swr",
|
|
]
|
|
|
|
|
|
async def cache_get(key: str) -> Any | None:
|
|
"""Get a value from the cache.
|
|
|
|
Returns the deserialized value, or ``None`` if the key is missing or expired.
|
|
|
|
Requires Agent Server runtime version 0.7.29 or later.
|
|
"""
|
|
if _cache_get is None:
|
|
raise RuntimeError(
|
|
"Cache is only available server-side within the LangGraph Agent Server "
|
|
"(https://docs.langchain.com/langsmith/deployments)."
|
|
)
|
|
return await _cache_get(key)
|
|
|
|
|
|
async def cache_set(key: str, value: Any, *, ttl: timedelta | None = None) -> None:
|
|
"""Set a value in the cache.
|
|
|
|
Args:
|
|
key: The cache key.
|
|
value: The value to cache (must be JSON-serializable).
|
|
ttl: Optional time-to-live. Capped at 1 day; ``None`` or zero
|
|
defaults to 1 day.
|
|
|
|
Requires Agent Server runtime version 0.7.29 or later.
|
|
"""
|
|
if _cache_set is None:
|
|
raise RuntimeError(
|
|
"Cache is only available server-side within the LangGraph Agent Server "
|
|
"(https://docs.langchain.com/langsmith/deployments)."
|
|
)
|
|
await _cache_set(key, value, ttl)
|
|
|
|
|
|
async def swr(
|
|
key: str,
|
|
loader: Callable[[], Awaitable[T]],
|
|
*,
|
|
fresh_for: timedelta | None = None,
|
|
max_age: timedelta | None = None,
|
|
model: type[T] | None = None,
|
|
) -> SWRResult[T]:
|
|
"""Load a cached value using stale-while-revalidate semantics.
|
|
|
|
This helper is server-side only and is intended for caching internal async
|
|
dependencies such as auth or metadata lookups.
|
|
|
|
Args:
|
|
key: Cache key.
|
|
loader: Async callable that fetches the value on miss/revalidation.
|
|
fresh_for: How long a cached value is considered fresh (no revalidation).
|
|
Defaults to ``timedelta(0)`` so every access triggers a background
|
|
revalidate while still returning the cached value instantly. Values
|
|
above :data:`MAX_CACHE_TTL` are clamped to the backend maximum.
|
|
max_age: Total lifetime of a cached entry. After this, the next access
|
|
blocks on the loader. Defaults to :data:`MAX_CACHE_TTL` (24 h by
|
|
default). Values above :data:`MAX_CACHE_TTL` are clamped to the
|
|
backend maximum.
|
|
model: Optional Pydantic model class. When provided, values are
|
|
serialized via ``model_dump(mode="json")`` before storage and
|
|
deserialized via ``model.model_validate()`` on read.
|
|
|
|
Returns:
|
|
An :class:`SWRResult` with ``.value``, ``.status``, and an async
|
|
``.mutate()`` method.
|
|
|
|
Semantics:
|
|
- cache miss: await ``loader()``, store the value, return it
|
|
- fresh hit (age < fresh_for): return the cached value
|
|
- stale hit (fresh_for <= age < max_age): return the cached value
|
|
immediately and trigger a best-effort background refresh
|
|
- expired (age >= max_age): await ``loader()``, store the value, return it
|
|
"""
|
|
if _api_swr is None:
|
|
raise RuntimeError(
|
|
"Cache is only available server-side within the LangGraph Agent Server "
|
|
"(https://docs.langchain.com/langsmith/deployments)."
|
|
)
|
|
if fresh_for is None:
|
|
fresh_for = timedelta(0)
|
|
if max_age is None:
|
|
max_age = timedelta(days=1)
|
|
return await _api_swr(
|
|
key, loader, fresh_for=fresh_for, max_age=max_age, model=model
|
|
)
|