DokuWiki Integration: Performance-Optimierung und Best Practices
- Connection Caching: Wiederverwendung von DokuWiki-Verbindungen (von 12min auf 20s für 50 Equipment) - Template Caching: Template nur einmal laden statt pro Equipment - Dokumentation: Best Practices für erweiterbare DokuWiki-Seitenstruktur (page.txt + page/ ohne start.txt) - Catlist-Syntax dokumentiert für automatische Unterseiten-Auflistung
This commit is contained in:
parent
f79e126c8c
commit
0135035a54
|
|
@ -308,3 +308,108 @@ Daten: {name}|{status_smiley}|{ows_machine_id.category_icon}|{partner_id}|{mod
|
|||
Spalten: Name|Status|Tags|Hersteller|Standort|Doku
|
||||
Daten: {name}|{status_smiley}|{tags_list}|{partner_id}|{location}|{wiki_doku_link}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Best Practices: DokuWiki Seitenstruktur
|
||||
|
||||
## Erweiterbare Dokumentation ohne Umbenennung
|
||||
|
||||
### Problem
|
||||
Benutzer möchten zu Equipment-Seiten eigene Unterseiten hinzufügen, ohne die von Odoo generierten Seiten umbenennen zu müssen.
|
||||
|
||||
### Lösung: Parallele Seite + Namespace
|
||||
|
||||
DokuWiki erlaubt **gleichzeitig** eine Seite und einen gleichnamigen Namespace:
|
||||
- Datei: `equipment.txt` (von Odoo generiert)
|
||||
- Verzeichnis: `equipment/` (für Benutzer-Unterseiten)
|
||||
|
||||
**Die Seite `equipment.txt` hat Vorrang und bleibt die Haupt-Equipment-Seite!**
|
||||
|
||||
### Empfohlene Struktur
|
||||
|
||||
```
|
||||
werkstatt/ausruestung/doku/
|
||||
├── analog-oscilloscope-hm303-6.txt # Von Odoo generiert
|
||||
├── analog-oscilloscope-hm303-6/ # Benutzer erstellt (optional)
|
||||
│ ├── kalibrierung.txt # Benutzer-Unterseite
|
||||
│ ├── messungen.txt # Benutzer-Unterseite
|
||||
│ └── bilder/ # Weitere Unter-Namespaces möglich
|
||||
│ └── oszillogramme.txt
|
||||
├── cnc-fraese-xyz.txt # Von Odoo generiert
|
||||
└── cnc-fraese-xyz/ # Benutzer-Namespace (optional)
|
||||
├── programme.txt
|
||||
└── werkzeuge.txt
|
||||
```
|
||||
|
||||
### Wichtige Regeln
|
||||
|
||||
#### ✅ DO: Unterverzeichnis OHNE start.txt
|
||||
|
||||
```
|
||||
equipment/
|
||||
├── subpage1.txt
|
||||
├── subpage2.txt
|
||||
└── weitere/
|
||||
└── details.txt
|
||||
```
|
||||
|
||||
**Vorteile:**
|
||||
- Breadcrumb zeigt: `Home » Werkstatt » Ausrüstung » Equipment » Subpage1`
|
||||
- Keine Duplikation oder Verwirrung
|
||||
- Equipment-Hauptseite bleibt `equipment.txt`
|
||||
|
||||
#### ❌ DON'T: Unterverzeichnis MIT start.txt
|
||||
|
||||
```
|
||||
equipment/
|
||||
├── start.txt # ❌ NICHT erstellen!
|
||||
├── subpage1.txt
|
||||
└── subpage2.txt
|
||||
```
|
||||
|
||||
**Probleme:**
|
||||
- Breadcrumb wird verwirrend: `Equipment` könnte auf zwei Seiten verweisen
|
||||
- `equipment` und `equipment:start` zeigen unterschiedliche Inhalte
|
||||
- Benutzer wissen nicht, welche Seite die "richtige" ist
|
||||
|
||||
### Catlist für Unterseiten-Auflistung
|
||||
|
||||
In der Odoo-generierten Hauptseite kann eine catlist-Anweisung eingefügt werden:
|
||||
|
||||
```dokuwiki
|
||||
===== Dokumentation: Analog Oscilloscope HM303-6 =====
|
||||
|
||||
... Equipment-Details ...
|
||||
|
||||
==== Weitere Dokumentation ====
|
||||
|
||||
<catlist .:analog-oscilloscope-hm303-6 -noNSInBold -sortByTitle>
|
||||
```
|
||||
|
||||
**Syntax-Erklärung:**
|
||||
- `.:namespace` → Relativer Namespace (Punkt + Doppelpunkt!)
|
||||
- `-noNSInBold` → Namespace-Präfix nicht fett darstellen
|
||||
- `-sortByTitle` → Alphabetisch sortieren
|
||||
- `-exclude:{ns1 ns2}` → Optional: Namespaces ausschließen
|
||||
|
||||
**Ergebnis:**
|
||||
- Zeigt alle Unterseiten im `equipment/` Verzeichnis
|
||||
- Automatisch aktualisiert wenn Benutzer neue Seiten erstellen
|
||||
- Kein manuelles Pflegen von Links nötig
|
||||
|
||||
### Workflow
|
||||
|
||||
1. **Odoo synchronisiert** → Erstellt/aktualisiert `equipment.txt`
|
||||
2. **Benutzer erstellt Unterseiten** → Erstellt Verzeichnis `equipment/` und fügt Seiten hinzu
|
||||
3. **Catlist zeigt automatisch** → Alle Unterseiten werden auf der Hauptseite gelistet
|
||||
4. **Keine Konflikte** → Odoo überschreibt nur `equipment.txt`, nie das `equipment/` Verzeichnis
|
||||
|
||||
### Vorteile dieser Struktur
|
||||
|
||||
- ✅ Odoo-Seiten bleiben unverändert und zentral verwaltbar
|
||||
- ✅ Benutzer können frei Unterseiten erstellen ohne Odoo-Sync zu stören
|
||||
- ✅ Keine Namenskollisionen oder Breadcrumb-Probleme
|
||||
- ✅ Automatische Verlinkung via catlist
|
||||
- ✅ Skalierbar: Beliebig viele Unterseiten und Unter-Namespaces möglich
|
||||
- ✅ Klare Trennung: Was von Odoo kommt vs. was von Benutzern kommt
|
||||
|
|
|
|||
|
|
@ -6,19 +6,42 @@ from odoo.exceptions import UserError
|
|||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
# Connection Cache (pro Request wiederverwendet)
|
||||
_connection_cache = {}
|
||||
|
||||
|
||||
class DokuWikiClient(models.AbstractModel):
|
||||
"""
|
||||
Wrapper für DokuWiki XML-RPC API Client.
|
||||
Managed die Verbindung zum DokuWiki und stellt Methoden für Seitenoperationen bereit.
|
||||
|
||||
Performance-Optimierung: Verbindungen werden gecached und wiederverwendet
|
||||
um den Overhead von XML-RPC Verbindungsaufbauten zu minimieren.
|
||||
"""
|
||||
_name = 'dokuwiki.client'
|
||||
_description = 'DokuWiki API Client'
|
||||
|
||||
@api.model
|
||||
def _get_wiki_connection(self):
|
||||
def _get_cache_key(self):
|
||||
"""
|
||||
Generiert einen Cache-Key basierend auf den Verbindungsparametern.
|
||||
|
||||
Returns:
|
||||
str: Cache-Key (URL + User)
|
||||
"""
|
||||
IrConfigParameter = self.env['ir.config_parameter'].sudo()
|
||||
wiki_url = IrConfigParameter.get_param('dokuwiki.url', '')
|
||||
wiki_user = IrConfigParameter.get_param('dokuwiki.user', '')
|
||||
return f"{wiki_url}:{wiki_user}"
|
||||
|
||||
@api.model
|
||||
def _get_wiki_connection(self, use_cache=True):
|
||||
"""
|
||||
Erstellt eine DokuWiki-Verbindung mit Credentials aus System-Parametern.
|
||||
Verbindungen werden gecached und wiederverwendet für bessere Performance.
|
||||
|
||||
Args:
|
||||
use_cache (bool): Wenn True, wird eine gecachte Verbindung wiederverwendet
|
||||
|
||||
Returns:
|
||||
DokuWiki: Verbundenes DokuWiki-Client-Objekt
|
||||
|
|
@ -46,12 +69,34 @@ class DokuWikiClient(models.AbstractModel):
|
|||
if not wiki_url.startswith(('http://', 'https://')):
|
||||
raise UserError(f"DokuWiki URL muss mit http:// oder https:// beginnen: {wiki_url}")
|
||||
|
||||
# Cache-Key generieren
|
||||
cache_key = self._get_cache_key()
|
||||
|
||||
# Gecachte Verbindung wiederverwenden wenn möglich
|
||||
if use_cache and cache_key in _connection_cache:
|
||||
try:
|
||||
# Teste ob Verbindung noch lebt
|
||||
cached_wiki = _connection_cache[cache_key]
|
||||
_ = cached_wiki.version # Test-Call
|
||||
_logger.debug(f"Wiederverwendung gecachter DokuWiki-Verbindung: {wiki_url}")
|
||||
return cached_wiki
|
||||
except Exception as e:
|
||||
_logger.warning(f"Gecachte Verbindung ungültig, erstelle neue: {e}")
|
||||
del _connection_cache[cache_key]
|
||||
|
||||
# Neue Verbindung erstellen
|
||||
try:
|
||||
_logger.info(f"Verbinde zu DokuWiki: {wiki_url} (User: {wiki_user})")
|
||||
_logger.info(f"Neue DokuWiki-Verbindung: {wiki_url} (User: {wiki_user})")
|
||||
wiki = DokuWiki(wiki_url, wiki_user, wiki_password)
|
||||
# Test-Verbindung
|
||||
version = wiki.version
|
||||
_logger.info(f"DokuWiki-Verbindung erfolgreich: Version {version}")
|
||||
|
||||
# In Cache speichern
|
||||
if use_cache:
|
||||
_connection_cache[cache_key] = wiki
|
||||
_logger.debug(f"Verbindung im Cache gespeichert: {cache_key}")
|
||||
|
||||
return wiki
|
||||
except DokuWikiError as e:
|
||||
error_details = f"URL: {wiki_url}, User: {wiki_user}, Fehler: {e}"
|
||||
|
|
@ -70,6 +115,15 @@ class DokuWikiClient(models.AbstractModel):
|
|||
except Exception as e:
|
||||
_logger.error(f"Unerwarteter Fehler bei DokuWiki-Verbindung: {e}", exc_info=True)
|
||||
raise UserError(f"Unerwarteter Fehler: {e}")
|
||||
|
||||
@api.model
|
||||
def clear_connection_cache(self):
|
||||
"""
|
||||
Löscht den Verbindungs-Cache (z.B. nach Konfigurationsänderungen).
|
||||
"""
|
||||
global _connection_cache
|
||||
_connection_cache.clear()
|
||||
_logger.info("DokuWiki Verbindungs-Cache geleert")
|
||||
|
||||
@api.model
|
||||
def create_page(self, page_id, content, summary="Erstellt von Odoo"):
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ from odoo.exceptions import UserError
|
|||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
# Cache für Wiki-Templates (wird beim Server-Neustart geleert)
|
||||
_template_cache = {}
|
||||
|
||||
class MaintenanceEquipment(models.Model):
|
||||
"""
|
||||
|
|
@ -242,17 +244,24 @@ class MaintenanceEquipment(models.Model):
|
|||
str: Gerenderter Wiki-Markup-Inhalt
|
||||
"""
|
||||
self.ensure_one()
|
||||
global _template_cache
|
||||
dokuwiki_client = self.env['dokuwiki.client']
|
||||
template_page_id = 'werkstatt:ausruestung:c_template'
|
||||
|
||||
try:
|
||||
# Template aus Wiki laden
|
||||
template_content = dokuwiki_client.get_page(template_page_id)
|
||||
if not template_content:
|
||||
_logger.warning(f"Template {template_page_id} nicht gefunden, verwende Fallback")
|
||||
return self._generate_wiki_main_page_content_fallback(view_type)
|
||||
# Template aus Cache oder Wiki laden
|
||||
if template_page_id not in _template_cache:
|
||||
template_content = dokuwiki_client.get_page(template_page_id)
|
||||
if not template_content:
|
||||
_logger.warning(f"Template {template_page_id} nicht gefunden, verwende Fallback")
|
||||
return self._generate_wiki_main_page_content_fallback(view_type)
|
||||
|
||||
_template_cache[template_page_id] = template_content
|
||||
_logger.info(f"Template geladen und gecacht: {template_page_id} ({len(template_content)} Zeichen)")
|
||||
else:
|
||||
_logger.debug(f"Template aus Cache verwendet: {template_page_id}")
|
||||
|
||||
_logger.info(f"Template geladen: {template_page_id} ({len(template_content)} Zeichen)")
|
||||
template_content = _template_cache[template_page_id]
|
||||
|
||||
# Werte-Dictionary vorbereiten
|
||||
values = self._prepare_template_values(view_type)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user