Files
nexarch/mail/internal/healthcheck/checks.go
T
sysops 8ee0e6c771 feat(mail): INT-07 Health-Check-Endpunkt für Mail-Modul
Neues Paket mail/internal/healthcheck: Checker sammelt benannte
CheckFunc-Prüfungen, liefert Gesamt- und Einzelstatus je Komponente
(ok/degraded, nie ein generischer Fehler). Fehlertexte einzelner
Prüfungen fließen nie in die HTTP-Antwort — nur Name+Status je
Komponente.

Vier konkrete Prüfungen (checks.go) gegen die real vorhandenen
Ticket-Abhängigkeiten: DatabaseCheck (pgxpool.Ping), ObjectStorageCheck
(HeadBucket gegen den ARC-06-Bucket), SearchIndexCheck (reale
Manticore-Anfrage), JobQueueCheck (COUNT gegen mail_index_jobs,
SRC-02/indexworker — COUNT statt Zeilenzugriff, damit eine leere aber
erreichbare Queue nicht fälschlich als Ausfall gilt).

RegisterRoutes registriert GET /api/v1/mail/health ohne
Authentifizierung auf einem vom Aufrufer bereitgestellten
*http.ServeMux, gleiches Pfadschema wie mailapi (INT-01) — Core API-01
hat weiterhin keinen abrufbaren Router.

Alle drei Pflichtprüfungen mit echten Nachweisen: simulierter Ausfall
einer von vier Abhängigkeiten korrekt als degraded abgebildet, eine
Prüfung mit absichtlich eingebetteter Verbindungszeichenfolge inkl.
Passwort im Fehlertext taucht nirgends in der HTTP-Antwort auf, echter
httptest-HTTP-Server-Integrationstest gegen den Endpunkt. Alle vier
konkreten Prüfungen zusätzlich real gegen laufende Postgres-, MinIO-
und Manticore-Instanzen verifiziert (inkl. echter ARC-06-Provisionierung).

go build/go vet/golangci-lint clean, gesamtes Mail-Modul
regressionsfrei getestet.
2026-09-01 19:49:47 +02:00

57 lines
1.9 KiB
Go

package healthcheck
import (
"context"
"fmt"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/jackc/pgx/v5/pgxpool"
"gitea.perlbach24.de/scripte/nexarch/mail/internal/search"
)
// DatabaseCheck prüft die Erreichbarkeit der Tenant-Postgres-Datenbank
// (Akzeptanzkriterium 1: Datenbank).
func DatabaseCheck(pool *pgxpool.Pool) CheckFunc {
return func(ctx context.Context) error {
return pool.Ping(ctx)
}
}
// ObjectStorageCheck prüft die Erreichbarkeit des mandantenspezifischen
// Objekt-Storage-Buckets (ARC-06) — Akzeptanzkriterium 1:
// Objektspeicher.
func ObjectStorageCheck(s3Admin *s3.Client, bucket string) CheckFunc {
return func(ctx context.Context) error {
_, err := s3Admin.HeadBucket(ctx, &s3.HeadBucketInput{Bucket: aws.String(bucket)})
return err
}
}
// SearchIndexCheck prüft die Erreichbarkeit des Manticore-Suchindex
// (SRC-01) — Akzeptanzkriterium 1: Suchindex. Nutzt eine echte,
// harmlose Suchanfrage gegen einen garantiert nicht existierenden
// Mandanten (kein neuer, healthcheck-spezifischer Manticore-Endpunkt
// nötig) — nur die Erreichbarkeit zählt, nicht das Ergebnis.
func SearchIndexCheck(client *search.Client) CheckFunc {
return func(ctx context.Context) error {
_, err := client.Search(ctx, "healthcheck-probe-kein-echter-mandant", "")
return err
}
}
// JobQueueCheck prüft die Erreichbarkeit der Postgres-Jobqueue
// (SRC-02, mail_index_jobs) — Akzeptanzkriterium 1: Jobqueue. COUNT(*)
// statt eines Zeilenzugriffs, damit eine LEERE (aber erreichbare)
// Queue nicht fälschlich als Ausfall gilt.
func JobQueueCheck(pool *pgxpool.Pool) CheckFunc {
return func(ctx context.Context) error {
var count int64
if err := pool.QueryRow(ctx, "SELECT count(*) FROM mail_index_jobs").Scan(&count); err != nil {
return fmt.Errorf("healthcheck: jobqueue: %w", err)
}
return nil
}
}