mcpField
L
litestar-stores

litestar-stores

github.com/alti3開発737 回インストール33 週間前に更新
リポジトリ

litestar-stores について

一時的または共有のアプリケーション状態を扱うLitestar開発者向けに、交換可能なキーバリューストアの選択と運用を解説します。バックエンド、TTL、名前空間、レジストリ接続、ライフサイクルを扱います。

主な機能

  1. 01メモリ、ファイル、Redis、Valkeyの選択
  2. 02有効期限と読み取り時の延長設定
  3. 03名前空間によるキーの分離
  4. 04StoreRegistryによるストア解決
  5. 05クリーンアップとクライアント寿命の計画

活用シーン

  1. 01セッションやレート制限用のストア選定
  2. 02アプリケーションワーカー間での状態共有
  3. 03キャッシュ値の有効期限設定
  4. 04共有バックエンド内の連携データ分離

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/alti3/litestar-skills --skill litestar-stores

インストール後、Claude Code で/litestar-storesを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

agents/
openai.yaml
references/
backend-selection-and-lifecycle.md
registry-and-namespacing.md
store-operations-and-data.md

詳細

ストア

このスキルは、リレーショナルデータモデリングではなく、Litestar の交換可能なキーバリューストアレイヤーに関する問題で使用します。

実行ワークフロー

  1. その機能が本当に Litestar のストアに適しているか判断します。キャッシュ、セッション、レート制限、その他の一時的または共有されたキーバリュー状態が対象です。
  2. プロセスモデル、永続性、レイテンシ、クリーンアップの要件に基づいてバックエンドを選択します。
  3. ストアを名前で明示的に接続するか、StoreRegistry を通じて遅延作成するか、名前空間付きのデフォルトファクトリーから派生させるかを決定します。
  4. キーの命名、名前空間の境界、TTL ポリシー、読み取り時の更新動作を定義します。
  5. レスポンスキャッシュ、セッション、レート制限などの統合機能を、意図した名前付きストアに接続します。
  6. クリーンアップとシャットダウンの動作を計画します。特に、FileStore の期限切れデータのクリーンアップと Redis クライアントの所有権を考慮します。
  7. 本番環境でストアに依存する前に、有効期限、分離、マルチワーカーでの動作を検証します。

基本ルール

  • ストアは、その場しのぎのオブジェクト永続化ではなく、交換可能なキーバリューインフラストラクチャとして扱います。
  • ストアの契約に沿って設計します。バックエンドに便利な追加機能があっても、値はバイトを前提とします。
  • delete_all() などの一括操作を使う前に、名前空間とストア名を意図的に設計します。
  • 機能に合わせて TTL ポリシーを設定します。絶対有効期限、アクセス時の更新、または有効期限なしを選びます。
  • すべてのバックエンドが期限切れデータを同じ方法でクリーンアップするとは限りません。
  • 無関係な機能で共有する単一のフラットなキースペースより、名前付きストアまたは名前空間付きストアを優先します。
  • ワーカー間またはインスタンス間で維持する必要がある状態には、分散バックエンドを使用します。
  • 外部クライアントやファイルシステムパスでライフサイクル管理が必要な場合は、ストアの所有権を明確にします。

選択ガイド

  • オーバーヘッドを最小限に抑えた、単純な単一プロセスのキャッシュや重要度の低い一時状態には、MemoryStore を使用します。
  • 特にデータが大きい、または長期間保持される場合など、速度よりディスク上の永続性が重要なときは、FileStore を使用します。
  • 一般的な本番環境向けの共有状態、マルチワーカー間の通信、名前空間付きの一括操作には、RedisStore を使用します。
  • Valkey 上で Redis 形式の動作を利用したい場合は、ValkeyStore を使用します。Litestar のドキュメントでは、これらのストアに関する用途では実質的に Redis と同等とされています。
  • 統合機能が既知のストア名を解決する必要がある場合は、明示的な stores={...} マッピングを使用します。
  • 未定義のストア名を 1 つのポリシーから遅延作成する場合は、StoreRegistry(default_factory=...) を使用します。
  • 1 つのバックエンドを安全に複数の分離された論理ストアで共有する場合は、with_namespace() を使用します。
  • 主な設計課題がレスポンスキャッシュの TTL、キャッシュキー、キャッシュフィルタリングである場合は、このスキルと併せて litestar-caching を使用します。

参考ファイル

必要なセクションのみを読みます。

ストアの基本

Litestar のストア操作は、次の小規模な非同期 API を中心に構成されています。

  • set(key, value, expires_in=...)
  • get(key, renew_for=...)
  • delete(key)
  • delete_all()
  • exists(key)
  • expires_in(key)

ドキュメントに記載された主な動作ルールは次のとおりです。

  • ストアは通常、バイトを受け取り、バイトを返します。
  • set() は利便性のため文字列も受け付けますが、get() は引き続きバイトを返します。
  • データを書き込むときに expires_in を設定できます。
  • バックエンドがそのキーの有効期限に対応している場合、get() に renew_for を渡すと、アクセス時に TTL を延長できます。
  • 存在しないキーに対して delete() を呼び出しても、何も行われません。

バックエンドの選択

MemoryStore
  • Litestar のデフォルトストアです。
  • オーバーヘッドが最も低くなります。
  • 永続化されません。
  • スレッドセーフでも、マルチプロセスセーフでもありません。
  • 複数ワーカーや複数インスタンスで共有する状態には使用しないでください。
FileStore
  • データをディスクに永続化します。
  • メモリベースの方式より低速です。
  • データ量、保存期間、バックアップのしやすさが重要な場合に適しています。
  • サブパスによる名前空間に対応しています。
  • 期限切れのエントリは自動的に削除されません。delete_expired() の呼び出しを計画してください。
RedisStore
  • 共有型またはある程度の永続性を備えたキーバリューインフラストラクチャが必要な、ほとんどすべてのアプリケーションに適しています。
  • 名前空間と、安全に名前空間内に限定された delete_all() に対応しています。
  • ネイティブの有効期限処理は Redis 自体が行います。
  • 複数ワーカーのデプロイ、セッション、レート制限、共有キャッシュ状態に適しています。
ValkeyStore
  • Litestar のドキュメントによると、実用上の指針は RedisStore と同じです。
  • 名前空間に対応しています。
  • デプロイ環境の標準が Redis ではなく Valkey の場合に使用してください。

TTL と有効期限のセマンティクス

  • 絶対的な有効期限を設定するには、set() で expires_in を使用します。
  • セッションや LRU に似た動作など、スライディング有効期限やアクセスに基づく更新には、get() で renew_for を使用します。
  • Redis/Valkey はネイティブの有効期限メカニズムを使用します。
  • FileStore は、期限切れの値がアクセスされたとき、または delete_expired() を明示的に実行したときにのみ削除します。
  • MemoryStore と FileStore では、アクセスまたはクリーンアップまで期限切れのデータが保持される場合があります。これらのバックエンドでは、TTL を即時のバックグラウンド削除と同等に扱わないでください。

名前空間

  • 名前空間は、共有バックエンドを複数の論理的な用途で安全に使うためのものです。
  • with_namespace() は、操作の影響範囲がその名前空間とその子に限定される子ストアを作成します。
  • これは delete_all() を使用する前に特に重要です。
  • RedisStore は、デフォルトの名前空間として LITESTAR を使用します。
  • namespace=None を渡すと Redis の名前空間が無効になり、delete_all() は使用できなくなります。
  • ファイルベースの名前空間では、親ストアのパスの下にサブパスが使用されます。

ストアレジストリ

  • Litestar.stores は、アプリケーションの StoreRegistry を公開します。
  • レジストリは、ストア名とストアインスタンスのマッピングから開始できます。
  • app.stores.get(name) は、登録済みストアを返すか、レジストリの default_factory を通じて作成します。
  • デフォルトのレジストリファクトリーは、未知の名前に対して新しい MemoryStore を返します。
  • カスタムの StoreRegistry を渡すことで、この動作を全体的に変更できます。
  • 動的な作成では不十分な場合に明示的に登録するには、StoreRegistry.register(name, store, allow_override=False) を使用します。

インテグレーションの接続

Litestar のインテグレーションは、レジストリを通じて名前でストアを解決します。重要な点は次のとおりです。

  • レスポンスキャッシュは、別途設定しない限り、デフォルトで response_cache というストア名を使用します。
  • セッションミドルウェアは、別途設定しない限り、デフォルトで sessions というストア名を使用します。
  • レート制限も、名前でストアを解決します。
  • これらの名前は慣例であり、特別な定数ではありません。それぞれの設定で他の名前を指定できます。
  • 1 つのレジストリでインテグレーションごとに複数のバックエンドを使用することも、1 つの名前空間付きバックエンドをデフォルトファクトリー経由で複数のインテグレーションに使用することもできます。

データ契約とシリアライズの境界

  • 移植可能なストアの契約は、バイト列ベースです。
  • 後でストアを入れ替える可能性がある場合は、バックエンド固有のオブジェクトの動作に依存しないでください。
  • MemoryStore はメモリに直接保存するため、技術的には任意の Python オブジェクトを保持できますが、Litestar のドキュメントに記載されたインターフェースでは、その移植性は保証されません。
  • バックエンド間の互換性が重要な場合は、構造化された値を保存前に明示的にシリアライズしてください。

クリーンアップとライフタイム

  • 古いエントリーが蓄積する場合は、MemoryStore、特に FileStore で定期的に delete_expired() を呼び出してください。
  • ディレクトリを長期間使用する場合、FileStore.delete_expired() は起動時またはメンテナンス時に実行するのに適しています。
  • 独自の Redis クライアントを直接使用して RedisStore を作成し、ヘルパーのライフサイクル管理を使用しない場合は、そのクライアントのシャットダウンを自分で行う必要があります。
  • Litestar/ストアにクライアントのライフサイクルを管理させる場合は、RedisStore.with_client(...) または明示的な所有権フラグを使用してください。

推奨されるデフォルト設定

  • MemoryStore は、ローカル開発、単一プロセスのアプリ、または重要度の低い一時的な状態に限って使用してください。
  • 本番環境で共有キャッシュ、セッション、レート制限を扱う場合は、Redis または Valkey を優先してください。
  • バックエンドごとに異なる用途を扱う場合は、インテグレーションに明示的なストア名を使用してください。
  • 論理的な子ストアを分離しながらインフラストラクチャを共有する場合は、ルートの名前空間付き Redis/Valkey ストアを 1 つ使用してください。
  • MemoryStore のオブジェクトストレージに頼るのではなく、構造化データを意図的にバイト列または文字列にシリアライズしてください。
  • ファイルベースのストアでは、意図的なメンテナンスタスクとして有効期限切れのエントリーをクリーンアップしてください。

パターン例

from litestar import Litestar, get
from litestar.config.response_cache import ResponseCacheConfig
from litestar.middleware.rate_limit import RateLimitConfig
from litestar.middleware.session.server_side import ServerSideSessionConfig
from litestar.stores.redis import RedisStore
from litestar.stores.registry import StoreRegistry


root_store = RedisStore.with_client()


@get("/cached", cache=True, sync_to_thread=False)
def cached_handler() -> str:
    return "hello"


app = Litestar(
    [cached_handler],
    stores=StoreRegistry(default_factory=root_store.with_namespace),
    response_cache_config=ResponseCacheConfig(store="response_cache"),
    middleware=[
        ServerSideSessionConfig(store="sessions").middleware,
        RateLimitConfig(rate_limit=("second", 10), store="rate_limit").middleware,
    ],
)

アンチパターン

  • ワーカーまたはプロセス間で共有する必要がある状態に MemoryStore を使用する。
  • ストアを、リレーショナルデータやクエリ可能な永続化の代替として扱う。
  • MemoryStore がたまたま許可しているという理由で、任意の Python オブジェクトを保存する。
  • 名前空間や分離されたストア名を使わずに単一のフラットなキー空間を使用し、delete_all() を呼び出す。
  • FileStore または MemoryStore では、有効期限切れのエントリーがすぐに消えると思い込む。
  • ファイルシステムベースの有効期限切れエントリーのクリーンアップを忘れる。
  • Redis に namespace=None を渡し、その後で安全な名前空間単位の一括削除を期待する。
  • インテグレーションのストア名は設定で変更できるのではなく、固定されていると思い込む。
  • Memcached を、サポート対象のドロップインバックエンドであるかのように追加する。

検証チェックリスト

  • 選択したバックエンドが、プロセス構成と耐久性の要件に合っていることを確認します。
  • 移植性が重要な場合、値がバックエンド間で移植可能な方法でシリアライズされていることを確認します。
  • 読み取り時に有効期限が更新される場合など、TTL の動作が実際のバックエンドの仕様と一致していることを確認します。
  • 必要に応じて、ファイルベースまたはメモリベースのストアに有効期限切れエントリーを明示的にクリーンアップする方法があることを確認します。
  • 名前空間またはストア名により、機能間の衝突や危険な一括削除を防止できることを確認します。
  • app.stores.get(name) が各インテグレーションに意図したストアを返すことを確認します。
  • キャッシュ、セッション、レート制限が意図したストア名を参照していることを確認します。
  • Redis/Valkey クライアントのシャットダウンに関する所有権が明示されていることを確認します。
  • 複数ワーカーのデプロイが MemoryStore に依存していないことを確認します。

スキル間の引き継ぎ

  • レスポンスキャッシュの TTL、キー生成、キャッシュフィルターの方針には litestar-caching を使用してください。
  • セッション/認証データが主な対象の場合は、litestar-authentication または litestar-security を使用してください。
  • レート制限またはセッションのミドルウェア動作が主な対象の場合は、litestar-middleware を使用してください。
  • ストアのメンテナンスに関する起動時/シャットダウン時のクリーンアップフックには、litestar-app-setup を使用してください。
  • 有効期限、インテグレーションの接続、複数バックエンドの動作の検証には、litestar-testing を使用してください。

Litestar の参考資料

コメント