Zum Inhalt

Polycrate API 0.14.13

Release-Datum: 16. März 2026
Typ: Feature-Patch

Highlights

  • PostgreSQL Full-Text-Search – Globale Suche direkt in PostgreSQL, kein externer Dienst nötig: SearchIndex, API-Endpoint, Alpine.js-Komponente in der Topbar
  • API Query Optimierungen – N+1-Fixes für Organizations, CatalogueApps und Workspaces via Django Silk identifiziert und behoben
  • CatalogueApp List Pricing-Felder – Eliminiert ~97 unnötige Detail-API-Calls im externen Pricing-Calculator
  • Production Performance – Gunicorn preload, Seed Job als eigene Action, Dockerfile Build-Time Assets
  • Workspace Reconciliation Fix – „Commit info is missing" bei CLI-erstellten Workspaces behoben

Artefakte

Docker Image

docker pull cargo.ayedo.cloud/polycrate/polycrate-api:0.14.13

Block

polycrate pull cargo.ayedo.cloud/ayedo/k8s/polycrate-api:0.9.10
polycrate run polycrate-api install

Neue Features

Globale Suche über alle relevanten Objekte (Workspaces, Hosts, K8sClusters, S3Buckets etc.) direkt in PostgreSQL – ohne externen Suchdienst.

Bestandteile:

  • SearchIndex Model (migrations/0067_searchindex.py) – speichert vorberechnete tsvector-Felder pro Objekt; wird via Celery-Task und search_reindex Management Command befüllt
  • PostgresSearchService (polycrate_api/search.py) – kapselt Suche via SearchVector/SearchQuery; search_type="plain" (korrekt für Infrastruktur-Bezeichner mit Bindestrichen)
  • GlobalSearchAPIView – DRF-Endpoint mit Rate-Limiting (GlobalSearchThrottle, throttles.py)
  • globalSearch Alpine.js-Komponente – Eingabefeld in der Topbar mit Debounce, Ergebnisliste mit Objekt-Typ und Link

Datenbankvoraussetzung: pg_trgm + unaccent Extensions (siehe nächster Punkt).

CNPG: pg_trgm + unaccent Extension

Die pg_trgm und unaccent Extensions sind in den offiziellen CNPG-Images bereits enthalten (PostgreSQL contrib-Paket). Aktivierung auf zwei Ebenen:

  1. CNPG postInitTemplateSQL – Extension beim Cluster-Init in template1 (vererbt sich an neue Datenbanken)
  2. Django Migration RunSQL (0066_enable_pg_trgm.py) – CREATE EXTENSION IF NOT EXISTS als idempotente Absicherung für bestehende Datenbanken

CatalogueApp List: Pricing-Felder im List-Serializer

Der externe Pricing-Calculator des Customer Portals verursachte bisher ~104 API-Calls pro Lauf, da für jede App ein separater Detail-Call nötig war.

Fix: product_regular und product_ha werden als vollständige Nested-Objekte (via ProductSimpleSerializer) im CatalogueAppListSerializer geliefert. Die ~97 Detail-Calls entfallen.

ManagedObject-Formulare: Submit-Indicator

Die generischen Create/Edit-Formulare (object_form_page.html) zeigen jetzt einen klaren Submitting/Creating/Saving-Indicator während des Absendvorgangs:

  • Alpine.js-basiert: x-data="{ submitting: false }" auf dem <form>-Element
  • Submit-Button wechselt zu „Saving…" + deaktiviert (verhindert Doppelklick)

Seed Job als eigene Action

Neues polycrate run polycrate-api seed – ein idempotenter Kubernetes Job, der statische Lookup-Daten (Provider, PoPs, Datasources) befüllt. Sicher gegen laufende API ausführbar.

  • install.yml + migrate.yml: seed Job wird automatisch nach migrate ausgeführt
  • start.sh: migrate + seed aus Prod-Startskript entfernt (nur noch Dev-Branch)

Fixes

S3Bucket: PROVIDER_API_SERVER_UNREACHABLE Fehlerdetail propagiert

S3Buckets zeigten die Condition PROVIDER_API_SERVER_UNREACHABLE ohne nachvollziehbare Ursache im Bucket-Log. Die tatsächliche Fehlerursache (SSL-Fehler, DNS, Timeout) stand nur im S3Cluster-Log.

Fix: S3Bucket.run_reconciliation() liest die reason aus der S3Cluster-Condition aus und propagiert sie in die eigene Condition sowie den Log.

Workspace Reconciliation: „Commit info is missing"

Bei CLI-erstellten Workspaces schlug die Reconciliation mit "Commit info is missing" fehl, wenn das verknüpfte GitLab-Projekt noch keine Commits enthielt.

Fixes:

  • git_commit_sha wird jetzt aus den Submission-Metadaten gesetzt, wenn der Workspace via CLI Action Run Submission erstellt wird
  • pull_or_clone() enthält einen Guard, der leere Repositories erkennt und überspringt statt abzubrechen

Beim Seitenreload erschien die Navigationssidebar kurz im aufgeklappten Zustand, bevor Alpine.js den Collapsed-Status aus localStorage anwenden konnte.

Fix:

  • Inline-Script (ohne defer) in base.html liest sidebarCollapsed aus localStorage und schreibt die Grid-Spaltenbreite direkt als style-Attribut – vor Alpine-Init
  • Alpine's :class-Binding durch :style-Binding ersetzt

Performance & Developer Experience

API Query Optimierungen

Via Django Silk identifizierte N+1-Probleme behoben:

  • /api/v1/organizations/has_active_downtime via prefetch_related (statt 1 EXISTS-Query pro Organization)
  • /api/v1/catalogue-apps/ – Pricing-Felder direkt im List-Serializer (eliminiert ~97 Detail-Calls)
  • /api/v1/workspaces/ – Wide-SELECT-Reduktion, Prefetch für Status-/Condition-Felder

Production Startup Optimierungen

  • Gunicorn (start.sh): --preload, --max-requests, --max-requests-jitter, --timeout, --graceful-timeout, --keep-alive
  • Dockerfile: collectstatic + spectacular in Build-Zeit verschoben (CompressedManifestStaticFilesStorage) – spart Startzeit
  • Celery Beat (start-beat.sh): Log-Level debugwarning
  • Flower: Aus Prod-Block entfernt

Django Silk API Profiling (Development)

Django Silk ist in der Development-Umgebung aktiv und erfasst alle HTTP-Requests inklusive DRF API Calls.

Silk-Dashboard: /silk/

Migration

Zwei neue Datenbank-Migrationen sind enthalten:

  • 0066_enable_pg_trgm – Aktiviert pg_trgm und unaccent Extensions
  • 0067_searchindex – Erstellt das SearchIndex-Model

Nach dem Update search_reindex ausführen, um den initialen Suchindex zu befüllen:

python manage.py search_reindex

Oder via Celery Task (wird automatisch getriggert).

Direktes Update von 0.14.12 möglich. polycrate run polycrate-api migrate ausführen.