Initial import of Politrack, a self-hosted service that tracks Austrian politicians from federal to municipal level - roles, votes, money flows, statements, meetings, social media and legal proceedings - with every claim linked to its sources. - backend: FastAPI + Postgres/pgvector; adapter framework (fetch -> parse -> load -> enrich) with robots.txt/TDM-aware fetching, a raw-response archive for reparsing, and a claim/evidence model with corroboration - sources: Parliament, Wikidata, EU Parliament/Commission, Council of Ministers, Rechnungshof party reports and donations, procurement, RTR media transparency, political ad libraries, WKStA, news feeds, Wikipedia edits, Bluesky, Mastodon, public Telegram channels, YouTube and X (official API) - web: Next.js frontend in German and English with typed API client - mcp: MCP server for AI agents and RAG - docs: architecture, data model, sources, legal notes, Unraid deployment and contributor guides; Docker Compose setup for Unraid Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
32 lines
750 B
Python
32 lines
750 B
Python
import atexit
|
|
from collections.abc import Iterator
|
|
from contextlib import contextmanager
|
|
from functools import lru_cache
|
|
|
|
from psycopg import Connection
|
|
from psycopg.rows import dict_row
|
|
from psycopg_pool import ConnectionPool
|
|
|
|
from politrack.config import get_settings
|
|
|
|
|
|
@lru_cache
|
|
def get_pool() -> ConnectionPool:
|
|
pool = ConnectionPool(
|
|
get_settings().database_url,
|
|
min_size=1,
|
|
max_size=10,
|
|
kwargs={"row_factory": dict_row},
|
|
open=False,
|
|
)
|
|
pool.open()
|
|
atexit.register(pool.close)
|
|
return pool
|
|
|
|
|
|
@contextmanager
|
|
def connection() -> Iterator[Connection]:
|
|
"""A pooled connection inside a transaction (committed on success)."""
|
|
with get_pool().connection() as conn:
|
|
yield conn
|