Communitygithub.com

コンテンツハッシュキャッシュパターン

SHA-256 コンテンツハッシュを使用して、高コストなファイル処理結果(PDF解析、テキスト抽出、画像分析など)をキャッシュします。パスに依存せず、コンテンツの変更時に自動的に無効化され、サービス層の分離を実現します。

コンテンツハッシュキャッシュパターン とは?

このスキルは、SHA-256 コンテンツハッシュをキャッシュキーとして使用することで、高コストなファイル処理結果(PDF解析、テキスト抽出、画像分析など)を効率的にキャッシュするパターンを提供します。パスベースのキャッシュとは異なり、ファイルの移動や名前変更後もキャッシュが有効であり、ファイル内容が変更されると自動的に無効化されます。サービス層(`extract_with_cache` 関数)がキャッシュのチェックと書き込みを担当し、本来の処理関数(`extract_text`)は純粋関数のまま変更されません。このアプローチにより、既存の処理関数を修正することなく、キャッシュ機能を追加できます。主にファイル処理パイプライン、CLI ツール、バッチ処理で活用でき、`--cache/--no-cache` オプションと組み合わせることで、開発の生産性と実行効率を大幅に向上させます。

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/everything-claude-code/tree/main/skills/content-hash-cache-pattern

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

コンテンツハッシュファイルキャッシュパターン

SHA-256 コンテンツハッシュをキャッシュキーとして使用し、高コストなファイル処理結果(PDF解析、テキスト抽出、画像分析など)をキャッシュします。パスベースのキャッシュとは異なり、このアプローチではファイルの移動や名前変更後もキャッシュが有効であり、コンテンツが変更されると自動的に無効化されます。

アクティベーションのタイミング

  • ファイル処理パイプラインの構築(PDF、画像、テキスト抽出)
  • 処理コストが高く、同じファイルが繰り返し処理される場合
  • --cache/--no-cache CLI オプションが必要な場合
  • 既存の純粋関数を修正せずにキャッシュを追加したい場合

コアパターン

1. コンテンツハッシュベースのキャッシュキー

ファイルパスではなく、ファイル内容をキャッシュキーとして使用します。

import hashlib
from pathlib import Path

_HASH_CHUNK_SIZE = 65536  # 大きなファイル用の64KBチャンク

def compute_file_hash(path: Path) -> str:
    """ファイル内容のSHA-256ハッシュ(大きなファイルはチャンク読み込み)。"""
    if not path.is_file():
        raise FileNotFoundError(f"ファイルが見つかりません: {path}")
    sha256 = hashlib.sha256()
    with open(path, "rb") as f:
        while True:
            chunk = f.read(_HASH_CHUNK_SIZE)
            if not chunk:
                break
            sha256.update(chunk)
    return sha256.hexdigest()

なぜコンテンツハッシュなのか? ファイルの名前変更・移動 = キャッシュヒット。コンテンツ変更 = 自動無効化。インデックスファイルは不要。

2. 不変データクラスによるキャッシュエントリ

from dataclasses import dataclass

@dataclass(frozen=True, slots=True)
class CacheEntry:
    file_hash: str
    source_path: str
    document: ExtractedDocument  # キャッシュされた結果

3. ファイルベースのキャッシュストレージ

各キャッシュエントリは {hash}.json として保存されます。ハッシュによる O(1) ルックアップを実現し、インデックスファイルは不要です。

import json
from typing import Any

def write_cache(cache_dir: Path, entry: CacheEntry) -> None:
    cache_dir.mkdir(parents=True, exist_ok=True)
    cache_file = cache_dir / f"{entry.file_hash}.json"
    data = serialize_entry(entry)
    cache_file.write_text(json.dumps(data, ensure_ascii=False), encoding="utf-8")

def read_cache(cache_dir: Path, file_hash: str) -> CacheEntry | None:
    cache_file = cache_dir / f"{file_hash}.json"
    if not cache_file.is_file():
        return None
    try:
        raw = cache_file.read_text(encoding="utf-8")
        data = json.loads(raw)
        return deserialize_entry(data)
    except (json.JSONDecodeError, ValueError, KeyError):
        return None  # 破損はキャッシュミスとして扱う

4. サービス層ラッパー(SRP)

処理関数は純粋なまま保ち、キャッシュは別のサービス層として追加します。

def extract_with_cache(
    file_path: Path,
    *,
    cache_enabled: bool = True,
    cache_dir: Path = Path(".cache"),
) -> ExtractedDocument:
    """サービス層: キャッシュチェック -> 抽出 -> キャッシュ書き込み。"""
    if not cache_enabled:
        return extract_text(file_path)  # 純粋関数、キャッシュを知らない

    file_hash = compute_file_hash(file_path)

    # キャッシュをチェック
    cached = read_cache(cache_dir, file_hash)
    if cached is not None:
        logger.info("キャッシュヒット: %s (hash=%s)", file_path.name, file_hash[:12])
        return cached.document

    # キャッシュミス -> 抽出 -> 保存
    logger.info("キャッシュミス: %s (hash=%s)", file_path.name, file_hash[:12])
    doc = extract_text(file_path)
    entry = CacheEntry(file_hash=file_hash, source_path=str(file_path), document=doc)
    write_cache(cache_dir, entry)
    return doc

主要な設計上の決定

決定根拠
SHA-256 コンテンツハッシュパスに依存せず、コンテンツ変更時に自動無効化
{hash}.json ファイル命名O(1) ルックアップ、インデックスファイル不要
サービス層ラッパーSRP: 抽出は純粋関数のまま、キャッシュは別の関心事
手動 JSON シリアライズ不変データクラスのシリアライズを完全制御
破損時は None を返すグレースフルデグラデーション、次回実行時に再処理
cache_dir.mkdir(parents=True)初回書き込み時に遅延ディレクトリ作成

ベストプラクティス

  • パスではなくコンテンツをハッシュ化 — パスは変わっても、コンテンツの同一性は変わらない
  • 大きなファイルのハッシュ化はチャンク読み込み — ファイル全体をメモリに読み込まない
  • 処理関数は純粋に保つ — キャッシュについて一切知る必要がない
  • キャッシュヒット/ミスをログに記録 — デバッグのために短縮ハッシュを使用
  • 破損をグレースフルに処理 — 無効なキャッシュエントリはミスとして扱い、クラッシュさせない

避けるべきアンチパターン

# 悪い例: パスベースのキャッシュ(ファイル移動・名前変更で壊れる)
cache = {"/path/to/file.pdf": result}

# 悪い例: 処理関数内部にキャッシュロジックを追加(SRP違反)
def extract_text(path, *, cache_enabled=False, cache_dir=None):
    if cache_enabled:  # この関数に2つの責務が生じる
        ...

# 悪い例: ネストした不変データクラスに dataclasses.asdict() を使用
# (複雑なネスト型で問題を引き起こす可能性がある)
data = dataclasses.asdict(entry)  # 代わりに手動シリアライズを使用

使用すべき場合

  • ファイル処理パイプライン(PDF解析、OCR、テキスト抽出、画像分析)
  • --cache/--no-cache オプションが有用なCLIツール
  • 実行をまたいで同じファイルが現れるバッチ処理
  • 既存の純粋関数を変更せずにキャッシュを追加する場合

使用すべきでない場合

  • 常に最新データが必要な場合(リアルタイムフィード)
  • キャッシュエントリが極端に大きい場合(ストリーミングを検討)
  • ファイル内容以外のパラメータに依存する結果の場合(例:異なる抽出設定)

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/claude-api

Anthropic Claude API patterns for Python and TypeScript. Covers Messages API, streaming, tool use, vision, extended thinking, batches, prompt caching, and Claude Agent SDK. Use when building applications with the Claude API or Anthropic SDKs.

affaan-m/everything-claude-code

End-to-end marketing campaign planning and execution. Covers audience research, positioning, campaign angle definition, landing page copy, email sequences, social posts, ad copy, short-form video scripts, and content calendars. Use as the orchestration layer for multi-channel product launches. Use when planning or executing a multi-channel product launch, or producing landing page, email, social, or ad copy.

affaan-m/everything-claude-code

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/everything-claude-code-conventions

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/frontend-design

Create distinctive, production-grade frontend interfaces with high design quality. Use when the user asks to build web components, pages, or applications and the visual direction matters as much as the code quality.

affaan-m/gget

gget CLI and Python workflow for quick genomic database queries, sequence lookup, BLAST-style searches, enrichment checks, and reproducible bioinformatics evidence logs.

affaan-m/literature-review

Systematic literature-review workflow for academic, biomedical, technical, and scientific topics, including search planning, source screening, synthesis, citation checks, and evidence logging.

affaan-m/motion-ui

Production-ready UI motion system for React/Next.js. Use when implementing animations, transitions, or motion patterns.

affaan-m/project-guidelines-example

Example project-specific skill template based on a real production application.

affaan-m/pubmed-database

Direct PubMed and NCBI E-utilities search workflows for biomedical literature, MeSH queries, PMID lookup, citation retrieval, and API-backed literature monitoring.

affaan-m/scholar-evaluation

Structured scholarly-work evaluation for papers, proposals, literature reviews, methods sections, evidence quality, citation support, and research-writing feedback.

affaan-m/uspto-database

USPTO patent and trademark data workflow for official record lookup, PatentSearch queries, TSDR checks, assignment data, and reproducible IP research logs.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

関連スキル