Projectcache

De Projectcache API beheert het laden van projecten in het geheugen voor API-operaties. Begrijpen wanneer projecten geladen moeten worden is essentieel voor efficiënt API-gebruik.

Belangrijke concepten

Geünificeerde cache-architectuur

De API en UI delen dezelfde cache in het geheugen. Wanneer je een project laadt via de API, is het dezelfde cache die de UI gebruikt. Dit betekent:

  • Gedeelde status: API-operaties zien dezelfde data als UI-gebruikers
  • Gedeelde resultaten: Uitvoeringsresultaten zijn zichtbaar voor zowel API als UI
  • Geen divergentie: Het is onmogelijk voor API en UI om verschillende weergaven van een project te hebben

Categorieën van operaties

API-operaties vallen in drie categorieën met verschillende cachevereisten:

Categorie Beschrijving Project laden vereist? Voorbeelden
Directe DB Alleen-lezen bewerkingen Nee GET endpoints, beheer van tenant/gebruiker
Auto-Laden Bewerking operaties Nee (automatisch laden) POST/PUT/DELETE op onderzoeken, notitieboeken, blokken
Vereist laden Uitvoeringsoperaties Ja Notitieboek uitvoeren, uitvoeringsresultaten ophalen

Auto-Laden patroon (vereenvoudigde workflow)

Voor de meeste CRUD-operaties moet je het project niet expliciet laden. De API laadt het project automatisch wanneer nodig:

# OUDE workflow (niet meer nodig voor CRUD):
# manager.load_project(project_id)  # Niet verplicht!

# NIEUWE workflow - roep de operatie direct aan:
response = requests.put(
    f"{BASE_URL}/api/{TENANT_ID}/{PROJECT_ID}/notebook/{notebook_id}",
    json={"Name": "Updated Name"},
    headers=headers
)
# Project wordt automatisch geladen indien nodig

Wanneer expliciet laden WEL vereist is

Expliciet projectladen is nog steeds vereist voor uitvoeringsoperaties:

  • POST /execution/notebook/{notebookId} - Voer notitieboek uit
  • GET /execution/notebook/{notebookId}/results - Haal uitvoeringsresultaten op
  • GET /execution/status/{notebookId} - Controleer uitvoeringsstatus

Project laden in cache

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

Laadt een project in de gedeelde cache. Gebruik dit vóór het uitvoeren van notitieboeken.

Padparameters

Parameter Type Verplicht Beschrijving
tenantId GUID Ja Identificator van de tenant
projectId GUID Ja Identificator van het project

Respons (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"
}

Responsvelden

Veld Type Beschrijving
projectId GUID Projectidentificator
projectName string Naam van het project
tenantName string Naam van de tenant
investigationCount integer Aantal onderzoeken
notebookCount integer Aantal notitieboeken
datasetCount integer Aantal datasets
loadedFromCache boolean Waar als al in cache, onwaar als geladen uit database
message string Mensvriendelijke statusmelding

Cachegedrag

Scenario Respons Prestaties
Eerste oproep (cache miss) loadedFromCache: false ~1000ms (database query)
Volgende oproepen (cache hit) loadedFromCache: true ~75ms (13x sneller)
Na 30 minuten inactiviteit Cache verloopt Volgende oproep laadt opnieuw

Cache-eigenschappen

  • Duur: 30 minuten na laatste toegang
  • Automatische vernieuwing: Elke API-call naar het project reset de 30 minuten timer
  • Gedeeld: Zelfde cache wordt door UI en API gebruikt
  • Geheugenbeheer: Automatische schoonmaak bij 90% geheugendruk

Project uit cache verwijderen

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

Verwijdert een project uit de cache, waardoor geheugen vrijkomt.

Padparameters

Parameter Type Verplicht Beschrijving
tenantId GUID Ja Identificator van de tenant
projectId GUID Ja Identificator van het project

Respons (200 OK)

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

Workflow voorbeelden

Workflow A: CRUD-operaties (Auto-Laden)

Voor het aanmaken, bijwerken of verwijderen van onderzoeken, notitieboeken of blokken:

import requests

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

# Gewoon direct de operatie aanroepen - geen laden nodig!
response = requests.post(
    f"{BASE_URL}/api/{TENANT_ID}/{PROJECT_ID}/investigation",
    json={"name": "New Investigation", "description": "Created via API"},
    headers=headers
)
# Project wordt automatisch geladen indien nodig

Workflow B: Notitieboek uitvoeren (Vereist laden)

Voor het uitvoeren van notitieboeken en ophalen van resultaten:

import requests
import time

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

# Stap 1: Project laden (VEREIST voor uitvoering)
response = requests.get(
    f"{BASE_URL}/api/{TENANT_ID}/project/{PROJECT_ID}/load",
    headers=headers
)
print(f"Project geladen: {response.json()['projectName']}")

# Stap 2: Notitieboek uitvoeren
response = requests.post(
    f"{BASE_URL}/api/{TENANT_ID}/{PROJECT_ID}/execution/notebook/{NOTEBOOK_ID}",
    headers=headers
)
print(f"Uitvoering in wachtrij: {response.json()['status']}")

# Stap 3: Poll voor voltooiing
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)

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

# Stap 5: Project ontladen (optionele opruiming)
requests.delete(
    f"{BASE_URL}/api/{TENANT_ID}/project/{PROJECT_ID}/unload",
    headers=headers
)

Implementatievoorbeelden

cURL

# Project in 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"

# Project uit cache verwijderen
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):
        """Laad project in cache (vereist voor uitvoeringsoperaties)."""
        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 = "uit cache" if result['loadedFromCache'] else "uit database"
        print(f"Project '{result['projectName']}' geladen {status}")

        return result

    def unload_project(self, project_id):
        """Verwijder project uit 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)

# Gebruik met contextmanager
with ProjectCacheManager('your-api-key') as cache:
    result = cache.load_project('87654321-4321-4321-4321-210987654321')
    # Voer notitieboeken hier uit...
# Projecten worden automatisch ontladen bij afsluiten

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(`Mislukt: ${response.status}`);

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

    console.log(`Geladen: ${result.projectName} (uit 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))
    );
  }
}

// Gebruik
const cache = new ProjectCacheManager('your-api-key');
try {
  await cache.loadProject('87654321-4321-4321-4321-210987654321');
  // Voer notitieboeken hier uit...
} finally {
  await cache.unloadAll();
}

Best practices

  1. CRUD-operaties: Laad niet expliciet - laat auto-load het regelen
  2. Uitvoeringsoperaties: Laad altijd eerst het project
  3. Langdurige clients: Verwijder projecten als ze klaar zijn om geheugen vrij te maken
  4. Contextmanagers: Gebruik with statements (Python) of try/finally voor opruiming
  5. Geheugenbewustzijn: De cache ruimt automatisch op bij 90% geheugendruk, maar expliciet ontladen is beter
  6. Gedeelde cache: Bedenk dat UI-gebruikers dezelfde projectstatus zien als jouw API-operaties