mirror of
https://github.com/shawnkim1997/All-in-one-Financial-Analysis.git
synced 2026-08-25 16:28:04 +00:00
feat: major codebase audit — 21 routers, 37 services, 12 pages fully documented
- Add missing numpy, scipy, dbnomics to requirements.txt (fixes ImportError on fresh install) - Sync claude.md with actual codebase: §3 file structure (37 services, 21 routers), §5 API endpoints (92 routes), §6 frontend pages (12), §13 TODO status - Update README.md with current architecture (92 API routes, 21 routers, 37 services), multi-asset overview, research grid, macro dashboard, screener+backtest, multi-jurisdiction filings, and 2026-03-26 changelog entry - Add new routers: dart, edinet, fmp, macro, research - Add new services: cache, dart_fetcher, dart_filing_service, economic_calendar, ecos_fetcher, edinet_filing_service, fmp_client, global_macro_quadrant, kpi_history_service, macro_cycle, macro_fetcher, oecd_cycle, peer_comparison_service, research_dashboard, smart_money_service, yield_fx_service - Add new frontend: macro page, screener+backtest, research grid components, overview (Equity/ETF/Commodity), filings (SEC/DART/EDINET), error boundaries - Remove 6 unused services: copilot_context, crypto_fetcher, fx_fetcher, gemini_analysis, market_data, technical_analysis - Remove obsolete docs: .agent/, AGENT.md, ATLAS_EVALUATION.md, docs/ Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
38c56a5a43
commit
51cbaf7f8d
@@ -0,0 +1,40 @@
|
||||
"""Simple in-memory TTL cache for expensive macro data fetches."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import time
|
||||
import threading
|
||||
from typing import Any, Callable, TypeVar
|
||||
|
||||
_lock = threading.Lock()
|
||||
_store: dict[str, tuple[float, Any]] = {}
|
||||
|
||||
F = TypeVar("F", bound=Callable)
|
||||
|
||||
|
||||
def cached(key: str, ttl_seconds: int = 3600):
|
||||
"""Decorator that caches a function result for *ttl_seconds*."""
|
||||
def decorator(fn: Callable) -> Callable:
|
||||
def wrapper(*args: Any, **kwargs: Any) -> Any:
|
||||
now = time.time()
|
||||
with _lock:
|
||||
if key in _store:
|
||||
ts, val = _store[key]
|
||||
if now - ts < ttl_seconds:
|
||||
return val
|
||||
result = fn(*args, **kwargs)
|
||||
with _lock:
|
||||
_store[key] = (now, result)
|
||||
return result
|
||||
return wrapper
|
||||
return decorator
|
||||
|
||||
|
||||
def invalidate(key: str) -> None:
|
||||
with _lock:
|
||||
_store.pop(key, None)
|
||||
|
||||
|
||||
def invalidate_all() -> None:
|
||||
with _lock:
|
||||
_store.clear()
|
||||
Reference in New Issue
Block a user