Implements feed caching layer with LRU eviction, TTL expiration, and ETag support. Phase 3.1: Feed Caching (Complete) - LRU cache with configurable max_size (default: 50 feeds) - TTL-based expiration (default: 300 seconds = 5 minutes) - SHA-256 checksums for cache keys and ETags - Weak ETag generation (W/"checksum") - If-None-Match header support for 304 Not Modified responses - Cache invalidation (全体 or per-format) - Hit/miss/eviction statistics tracking - Content-based cache keys (changes when notes are modified) Implementation: - Created starpunk/feeds/cache.py with FeedCache class - Integrated caching into feed routes (RSS, ATOM, JSON Feed) - Added ETag headers to all feed responses - 304 Not Modified responses for conditional requests - Configuration: FEED_CACHE_ENABLED, FEED_CACHE_MAX_SIZE - Global cache instance with singleton pattern Architecture: - Two-level caching: 1. Note list cache (simple dict, existing) 2. Feed content cache (LRU with TTL, new) - Cache keys include format + notes checksum - Checksums based on note IDs + updated timestamps - Non-streaming generators used for cacheable content Testing: - 25 comprehensive cache tests (100% passing) - Tests for LRU eviction, TTL expiration, statistics - Tests for checksum generation and consistency - Tests for ETag generation and uniqueness - All 114 feed tests passing (no regressions) Quality Metrics: - 114/114 tests passing (100%) - Zero breaking changes - Full backward compatibility - Cache disabled mode supported (FEED_CACHE_ENABLED=false) Performance Benefits: - Database queries reduced (note list cached) - Feed generation reduced (content cached) - Bandwidth saved (304 responses) - Memory efficient (LRU eviction) Note: Phase 3 is partially complete. Still pending: - Feed statistics dashboard - OPML 2.0 export endpoint 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
71 lines
1.6 KiB
Python
71 lines
1.6 KiB
Python
"""
|
|
Feed generation module for StarPunk
|
|
|
|
This module provides feed generation in multiple formats (RSS, ATOM, JSON Feed)
|
|
with content negotiation and caching support.
|
|
|
|
Exports:
|
|
generate_rss: Generate RSS 2.0 feed
|
|
generate_rss_streaming: Generate RSS 2.0 feed with streaming
|
|
generate_atom: Generate ATOM 1.0 feed
|
|
generate_atom_streaming: Generate ATOM 1.0 feed with streaming
|
|
generate_json_feed: Generate JSON Feed 1.1
|
|
generate_json_feed_streaming: Generate JSON Feed 1.1 with streaming
|
|
negotiate_feed_format: Content negotiation for feed formats
|
|
get_mime_type: Get MIME type for a format name
|
|
get_cache: Get global feed cache instance
|
|
configure_cache: Configure global feed cache
|
|
FeedCache: Feed caching class
|
|
"""
|
|
|
|
from .rss import (
|
|
generate_rss,
|
|
generate_rss_streaming,
|
|
format_rfc822_date,
|
|
get_note_title,
|
|
clean_html_for_rss,
|
|
)
|
|
|
|
from .atom import (
|
|
generate_atom,
|
|
generate_atom_streaming,
|
|
)
|
|
|
|
from .json_feed import (
|
|
generate_json_feed,
|
|
generate_json_feed_streaming,
|
|
)
|
|
|
|
from .negotiation import (
|
|
negotiate_feed_format,
|
|
get_mime_type,
|
|
)
|
|
|
|
from .cache import (
|
|
FeedCache,
|
|
get_cache,
|
|
configure_cache,
|
|
)
|
|
|
|
__all__ = [
|
|
# RSS functions
|
|
"generate_rss",
|
|
"generate_rss_streaming",
|
|
"format_rfc822_date",
|
|
"get_note_title",
|
|
"clean_html_for_rss",
|
|
# ATOM functions
|
|
"generate_atom",
|
|
"generate_atom_streaming",
|
|
# JSON Feed functions
|
|
"generate_json_feed",
|
|
"generate_json_feed_streaming",
|
|
# Content negotiation
|
|
"negotiate_feed_format",
|
|
"get_mime_type",
|
|
# Caching
|
|
"FeedCache",
|
|
"get_cache",
|
|
"configure_cache",
|
|
]
|