Projekt-Cache

Die Project Cache API verwaltet das projektbezogene Laden im Arbeitsspeicher für API-Operationen. Zu verstehen, wann Projekte geladen werden müssen, ist entscheidend für eine effiziente API-Nutzung.

Grundkonzepte

Einheitliche Cache-Architektur

API und UI teilen denselben In-Memory-Cache. Wenn Sie ein Projekt über die API laden, ist es derselbe Cache, den die UI verwendet. Das bedeutet:

  • Gemeinsamer Zustand: API-Operationen sehen dieselben Daten wie UI-Nutzer
  • Gemeinsame Ergebnisse: Ausführungsergebnisse sind sowohl API als auch UI sichtbar
  • Keine Divergenz: API und UI können keine unterschiedlichen Ansichten eines Projekts haben

Betriebskategorien

API-Operationen fallen in drei Kategorien mit unterschiedlichen Caching-Anforderungen:

Kategorie Beschreibung Projektladen erforderlich? Beispiele
Direkte DB Nur-Lese-Operationen Nein GET-Endpunkte, Mandanten-/Nutzerverwaltung
Auto-Load Änderungsoperationen Nein (wird automatisch geladen) POST/PUT/DELETE an Investigations, Notebooks, Blocks
Benötigt Laden Ausführungsoperationen Ja Notebook ausführen, Ausführungsergebnisse abrufen

Auto-Load-Muster (vereinfachter Workflow)

Für die meisten CRUD-Operationen müssen Sie das Projekt nicht explizit laden. Die API lädt das Projekt bei Bedarf automatisch:

# ALTER Workflow (nicht mehr für CRUD benötigt):
# manager.load_project(project_id)  # Nicht erforderlich!

# NEUER Workflow - Operation direkt aufrufen:
response = requests.put(
    f"{BASE_URL}/api/{TENANT_ID}/{PROJECT_ID}/notebook/{notebook_id}",
    json={"Name": "Aktualisierter Name"},
    headers=headers
)
# Projekt wird bei Bedarf automatisch geladen

Wann ein explizites Laden ERFORDERLICH ist

Das explizite Laden eines Projekts ist weiterhin bei Ausführungsoperationen erforderlich:

  • POST /execution/notebook/{notebookId} - Notebook ausführen
  • GET /execution/notebook/{notebookId}/results - Ausführungsergebnisse abrufen
  • GET /execution/status/{notebookId} - Ausführungsstatus prüfen

Projekt in den Cache laden

GET /api/{tenantId}/project/{projectId}/load

Lädt ein Projekt in den gemeinsamen Cache. Verwenden Sie dies vor der Ausführung von Notebooks.

Pfadparameter

Parameter Typ Erforderlich Beschreibung
tenantId GUID Ja Mandantenkennung
projectId GUID Ja Projektkennung

Antwort (200 OK)

{
  "projectId": "87654321-4321-4321-4321-210987654321",
  "projectName": "Purchase Order Analysis",
  "tenantName": "acme-corp",
  "investigationCount": 5,
  "notebookCount": 12,
  "datasetCount": 3,
  "loadedFromCache": false,
  "message": "Project loaded from database"
}

Antwortfelder

Feld Typ Beschreibung
projectId GUID Projektkennung
projectName string Name des Projekts
tenantName string Name des Mandanten
investigationCount integer Anzahl der Investigations
notebookCount integer Anzahl der Notebooks
datasetCount integer Anzahl der Datensätze
loadedFromCache boolean Wahr, wenn bereits im Cache; falsch bei DB-Ladung
message string Menschlich lesbare Statusmeldung

Cache-Verhalten

Szenario Antwort Performance
Erster Aufruf (Cache Miss) loadedFromCache: false ~1000ms (Datenbankabfrage)
Folgende Aufrufe (Cache Hit) loadedFromCache: true ~75ms (13x schneller)
Nach 30 Min Inaktivität Cache läuft ab Nächster Aufruf lädt neu

Cache-Eigenschaften

  • Dauer: 30 Minuten nach letztem Zugriff
  • Auto-Refresh: Jeder API-Aufruf für das Projekt setzt den 30-Minuten-Timer zurück
  • Gemeinsam genutzt: Gleiches Cache von UI und API verwendet
  • Speicherverwaltung: Automatische Bereinigung bei 90 % Speicherauslastung

Projekt aus dem Cache entladen

DELETE /api/{tenantId}/project/{projectId}/unload

Entfernt ein Projekt aus dem Cache und gibt Speicher frei.

Pfadparameter

Parameter Typ Erforderlich Beschreibung
tenantId GUID Ja Mandantenkennung
projectId GUID Ja Projektkennung

Antwort (200 OK)

{
  "projectId": "87654321-4321-4321-4321-210987654321",
  "wasInCache": true,
  "message": "Project unloaded from cache successfully"
}

Workflow-Beispiele

Workflow A: CRUD-Operationen (Auto-Load)

Für das Erstellen, Aktualisieren oder Löschen von Investigations, Notebooks oder Blocks:

import requests

headers = {"Authorization": f"Bearer {API_KEY}"}

# Operation direkt aufrufen - Laden nicht erforderlich!
response = requests.post(
    f"{BASE_URL}/api/{TENANT_ID}/{PROJECT_ID}/investigation",
    json={"name": "Neue Investigation", "description": "Über API erstellt"},
    headers=headers
)
# Projekt wird bei Bedarf automatisch geladen

Workflow B: Notebook-Ausführung (Benötigt Laden)

Für die Ausführung von Notebooks und das Abrufen der Ergebnisse:

import requests
import time

headers = {"Authorization": f"Bearer {API_KEY}"}

# Schritt 1: Projekt laden (für Ausführung ERFORDERLICH)
response = requests.get(
    f"{BASE_URL}/api/{TENANT_ID}/project/{PROJECT_ID}/load",
    headers=headers
)
print(f"Projekt geladen: {response.json()['projectName']}")

# Schritt 2: Notebook ausführen
response = requests.post(
    f"{BASE_URL}/api/{TENANT_ID}/{PROJECT_ID}/execution/notebook/{NOTEBOOK_ID}",
    headers=headers
)
print(f"Ausführung in Warteschlange: {response.json()['status']}")

# Schritt 3: Auf Abschluss warten
while True:
    response = requests.get(
        f"{BASE_URL}/api/{TENANT_ID}/{PROJECT_ID}/execution/status/{NOTEBOOK_ID}",
        headers=headers
    )
    status = response.json()
    print(f"Status: {status['status']} ({status['progress']}%)")

    if status['status'] == 'Completed':
        break
    time.sleep(2)

# Schritt 4: Ergebnisse abrufen
response = requests.get(
    f"{BASE_URL}/api/{TENANT_ID}/{PROJECT_ID}/execution/notebook/{NOTEBOOK_ID}/results",
    headers=headers
)
results = response.json()

# Schritt 5: Projekt entladen (optionale Aufräumaktion)
requests.delete(
    f"{BASE_URL}/api/{TENANT_ID}/project/{PROJECT_ID}/unload",
    headers=headers
)

Implementierungsbeispiele

cURL

# Projekt in den Cache laden
curl -X GET "https://your-mindzie-instance.com/api/12345678-1234-1234-1234-123456789012/project/87654321-4321-4321-4321-210987654321/load" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Projekt aus dem Cache entladen
curl -X DELETE "https://your-mindzie-instance.com/api/12345678-1234-1234-1234-123456789012/project/87654321-4321-4321-4321-210987654321/unload" \
  -H "Authorization: Bearer YOUR_API_KEY"

Python

import requests

TENANT_ID = '12345678-1234-1234-1234-123456789012'
BASE_URL = 'https://your-mindzie-instance.com'

class ProjectCacheManager:
    def __init__(self, token):
        self.headers = {
            'Authorization': f'Bearer {token}',
            'Content-Type': 'application/json'
        }
        self.loaded_projects = set()

    def load_project(self, project_id):
        """Lädt ein Projekt in den Cache (erforderlich für Ausführungsoperationen)."""
        url = f'{BASE_URL}/api/{TENANT_ID}/project/{project_id}/load'
        response = requests.get(url, headers=self.headers)
        response.raise_for_status()

        result = response.json()
        self.loaded_projects.add(project_id)

        status = "aus dem Cache" if result['loadedFromCache'] else "aus der Datenbank"
        print(f"Projekt '{result['projectName']}' geladen {status}")

        return result

    def unload_project(self, project_id):
        """Entlädt ein Projekt aus dem Cache."""
        url = f'{BASE_URL}/api/{TENANT_ID}/project/{project_id}/unload'
        response = requests.delete(url, headers=self.headers)
        response.raise_for_status()

        self.loaded_projects.discard(project_id)
        return response.json()

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        for project_id in list(self.loaded_projects):
            self.unload_project(project_id)

# Verwendung mit Kontext-Manager
with ProjectCacheManager('your-api-key') as cache:
    result = cache.load_project('87654321-4321-4321-4321-210987654321')
    # Notebooks hier ausführen...
# Projekte werden beim Verlassen automatisch entladen

JavaScript/Node.js

const TENANT_ID = '12345678-1234-1234-1234-123456789012';
const BASE_URL = 'https://your-mindzie-instance.com';

class ProjectCacheManager {
  constructor(token) {
    this.headers = {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    };
    this.loadedProjects = new Set();
  }

  async loadProject(projectId) {
    const url = `${BASE_URL}/api/${TENANT_ID}/project/${projectId}/load`;
    const response = await fetch(url, { headers: this.headers });

    if (!response.ok) throw new Error(`Fehlgeschlagen: ${response.status}`);

    const result = await response.json();
    this.loadedProjects.add(projectId);

    console.log(`Geladen: ${result.projectName} (aus Cache: ${result.loadedFromCache})`);
    return result;
  }

  async unloadProject(projectId) {
    const url = `${BASE_URL}/api/${TENANT_ID}/project/${projectId}/unload`;
    const response = await fetch(url, {
      method: 'DELETE',
      headers: this.headers
    });

    this.loadedProjects.delete(projectId);
    return response.json();
  }

  async unloadAll() {
    await Promise.all(
      Array.from(this.loadedProjects).map(id => this.unloadProject(id))
    );
  }
}

// Nutzung
const cache = new ProjectCacheManager('your-api-key');
try {
  await cache.loadProject('87654321-4321-4321-4321-210987654321');
  // Notebooks hier ausführen...
} finally {
  await cache.unloadAll();
}

Best Practices

  1. CRUD-Operationen: Laden Sie nicht explizit – lassen Sie Auto-Load das übernehmen
  2. Ausführungsoperationen: Laden Sie immer zuerst das Projekt
  3. Langlaufende Clients: Entladen Sie Projekte nach der Nutzung, um Speicher freizugeben
  4. Kontext-Manager: Verwenden Sie with-Anweisungen (Python) oder try/finally für Aufräumaktionen
  5. Speicherbewusstsein: Der Cache bereinigt automatisch bei 90 % Speicherauslastung, aber explizites Entladen ist besser
  6. Gemeinsamer Cache: Denken Sie daran, dass UI-Nutzer denselben Projektzustand sehen wie Ihre API-Operationen