{
"tool_response": [
{
"type": "text",
"text": "{\n \"success\": true,\n \"doc\": {\n \"id\": 154,\n \"parent_id\": 91,\n \"slug\": \"db-py-refactoring-plan\",\n \"path\": \"\/prozesse\/db-py-refactoring-plan\",\n \"title\": \"db.py Refactoring Plan\",\n \"description\": \"Detaillierter Plan zur Aufspaltung der 834-Zeilen db.py nach SRP\",\n \"content\": \"# db.py Refactoring Plan\\n\\n## Status\\n- **Task ID**: 505\\n- **Erstellt**: 2025-12-28\\n- **Status**: Plan erstellt\\n\\n## Ausgangslage\\n\\n**Datei**: `\/var\/www\/scripts\/pipeline\/db.py`\\n**Zeilen**: 834\\n**Klassen**: 2 (Database: 707 Zeilen, PipelineProgress: 109 Zeilen)\\n**Problem**: 14 verschiedene Verantwortlichkeiten in der Database-Klasse (SRP-Verletzung)\\n\\n## Ziele\\n\\n1. Jedes Modul unter 500 Zeilen (Code Hygiene Limit)\\n2. Strikte Einhaltung von SRP (Single Responsibility Principle)\\n3. **100% Rückwärtskompatibilität** - alle bestehenden Imports funktionieren weiterhin\\n4. DRY, KISS, SOLID Prinzipien\\n\\n## Architektur: Mixin-Pattern\\n\\nPython Mixins ermöglichen das Aufteilen einer Klasse in logische Einheiten bei gleichzeitiger Beibehaltung der Abwärtskompatibilität.\\n\\n```\\ndb_core.py ─┐\\ndb_documents.py │\\ndb_queue.py ├── Mixins ──► db.py (Database erbt von allen)\\ndb_logging.py │\\ndb_semantic.py │\\ndb_prompts.py ─┘\\n```\\n\\n## Modul-Aufteilung\\n\\n### 1. db_core.py (~100 Zeilen)\\n**Verantwortung**: Connection Management\\n\\n```python\\nclass DatabaseCore:\\n def __init__(self): ...\\n def connect(self): ...\\n def disconnect(self): ...\\n def execute(self, query, params=None): ...\\n def commit(self): ...\\n```\\n\\n### 2. db_documents.py (~150 Zeilen)\\n**Verantwortung**: Document, Page, Chunk CRUD\\n\\n```python\\nclass DocumentsMixin:\\n # Documents\\n def document_exists(self, file_path): ...\\n def document_is_done(self, file_path): ...\\n def insert_document(self, file_path, title, file_type, file_size, file_hash): ...\\n def update_document_status(self, doc_id, status, error_message=None): ...\\n \\n # Pages\\n def insert_page(self, doc_id, page_number, text_content, token_count=None): ...\\n def get_page_id(self, doc_id, page_number): ...\\n \\n # Chunks\\n def insert_chunk(self, doc_id, chunk_index, content, heading_path, ...): ...\\n def get_chunks_for_embedding(self, limit=DEFAULT_LIMIT): ...\\n def update_chunk_qdrant_id(self, chunk_id, qdrant_id): ...\\n```\\n\\n### 3. db_queue.py (~60 Zeilen)\\n**Verantwortung**: Pipeline Queue Operations\\n\\n```python\\nclass QueueMixin:\\n def add_to_queue(self, file_path, action=\\\"process\\\"): ...\\n def get_pending_queue_items(self, limit=10): ...\\n def update_queue_status(self, queue_id, status, error_message=None): ...\\n```\\n\\n### 4. db_logging.py (~180 Zeilen)\\n**Verantwortung**: Alle Logging-Operationen\\n\\n```python\\nclass LoggingMixin:\\n def log(self, level, message, context=None): ...\\n def log_to_protokoll(self, client_name, request, response=None, ...): ...\\n def log_provenance(self, artifact_type, artifact_id, source_type, ...): ...\\n```\\n\\n### 5. db_semantic.py (~250 Zeilen)\\n**Verantwortung**: Entity Types, Stopwords, Taxonomy, Synonyms\\n\\n```python\\nclass SemanticMixin:\\n # Entity Types\\n def get_entity_types(self, active_only=True): ...\\n def get_entity_type_codes(self): ...\\n def build_entity_prompt_categories(self): ...\\n \\n # Stopwords\\n def get_stopwords(self, active_only=True): ...\\n def is_stopword(self, word): ...\\n def _normalize_stopword(self, word): ...\\n \\n # Synonyms (internal, nicht extern genutzt)\\n def find_entity_by_synonym(self, synonym): ...\\n def add_synonym(self, entity_id, synonym, ...): ...\\n \\n # Chunk Taxonomy\\n def add_chunk_taxonomy(self, chunk_id, term_id, ...): ...\\n def get_chunk_taxonomies(self, chunk_id): ...\\n \\n # Entity Taxonomy\\n def add_entity_taxonomy(self, entity_id, term_id, ...): ...\\n def get_entity_taxonomies(self, entity_id): ...\\n def get_taxonomy_terms(self): ...\\n```\\n\\n### 6. db_prompts.py (~70 Zeilen)\\n**Verantwortung**: Prompt-Verwaltung\\n\\n```python\\nclass PromptsMixin:\\n def get_prompt(self, name, version=None): ...\\n def get_prompt_by_use_case(self, use_case, version=None): ...\\n```\\n\\n### 7. db.py (~100 Zeilen - Kompositions-Layer)\\n**Verantwortung**: Rückwärtskompatibilität\\n\\n```python\\nfrom db_core import DatabaseCore\\nfrom db_documents import DocumentsMixin\\nfrom db_queue import QueueMixin\\nfrom db_logging import LoggingMixin\\nfrom db_semantic import SemanticMixin\\nfrom db_prompts import PromptsMixin\\n\\nclass Database(\\n DatabaseCore,\\n DocumentsMixin,\\n QueueMixin,\\n LoggingMixin,\\n SemanticMixin,\\n PromptsMixin\\n):\\n '''Vollständige Database-Klasse mit allen Operationen.'''\\n pass\\n\\nclass PipelineProgress:\\n # ... (unverändert, eigene Klasse)\\n\\n# Globale Instanz für Rückwärtskompatibilität\\ndb = Database()\\n```\\n\\n## Zeilen-Verteilung\\n\\n| Modul | Zeilen | Verantwortlichkeiten |\\n|-------|--------|---------------------|\\n| db_core.py | ~100 | Connection |\\n| db_documents.py | ~150 | Documents, Pages, Chunks |\\n| db_queue.py | ~60 | Queue |\\n| db_logging.py | ~180 | Log, Protokoll, Provenance |\\n| db_semantic.py | ~250 | Types, Stopwords, Taxonomy |\\n| db_prompts.py | ~70 | Prompts |\\n| db.py | ~100 | Komposition + PipelineProgress |\\n| **Total** | ~910 | (verteilt auf 7 Dateien) |\\n\\n## Rückwärtskompatibilität\\n\\nAlle existierenden Imports funktionieren weiterhin:\\n\\n```python\\n# Diese Imports bleiben gültig:\\nfrom db import db\\nfrom db import Database\\nfrom db import PipelineProgress\\nfrom db import db, PipelineProgress\\n```\\n\\n## Implementierungs-Reihenfolge\\n\\n1. **db_core.py** erstellen (Basis für alle anderen)\\n2. **db_logging.py** erstellen (wird von vielen benötigt)\\n3. **db_prompts.py** erstellen (eigenständig)\\n4. **db_documents.py** erstellen (eigenständig)\\n5. **db_queue.py** erstellen (eigenständig)\\n6. **db_semantic.py** erstellen (eigenständig)\\n7. **db.py** umschreiben (Komposition)\\n8. **Tests** durchführen (alle Pipeline-Scripts testen)\\n\\n## Risiken & Mitigationen\\n\\n| Risiko | Mitigation |\\n|--------|------------|\\n| Import-Fehler nach Refactoring | Kompositions-Layer in db.py exportiert alles |\\n| Circular Imports | Jedes Modul importiert nur db_core.py |\\n| Connection-Sharing | Mixins nutzen self.connection von DatabaseCore |\\n| Tests fehlschlagen | Schrittweise Tests nach jedem Modul |\\n\\n## Cleanup-Möglichkeiten\\n\\n- **Entfernen**: `find_entity_by_synonym`, `add_synonym` (nicht extern genutzt)\\n- **Vereinfachen**: `get_page_id` könnte in `insert_page` integriert werden\\n- **Optimieren**: Redundante Cursor-Handling kann vereinheitlicht werden\\n\",\n \"status\": \"published\",\n \"sort_order\": 10,\n \"depth\": 1,\n \"created_at\": \"2025-12-28T08:53:35\",\n \"updated_at\": \"2025-12-28T13:50:09\"\n }\n}"
}
]
}