Neues Paket mail/internal/notifyclient: Mail-seitige Kopplung an Core CFG-02/CFG-05 (POST /notify, service-token-authentifiziert). Core CFG-02/CFG-05 stehen auf core-kanban zwar auf "Fertig", haben im aktuellen Repository-Stand aber keinen abrufbaren Endpunkt — dieselbe Situation wie ARC-06/Core TEN-01 und INT-01/Core API-01, im Prüfprotokoll begründet. Client richtet sich nach dem in CFG-05s eigener Beschreibung dokumentierten Vertrag. 204 wird bewusst nicht als Fehler behandelt (CFG-05 wrappt laut Beschreibung bereits notifyprefs.EnqueueIfAllowed — die Zustellentscheidung nach Benutzerpräferenz liegt vollständig bei Core, Mail dupliziert diese Logik nicht). Neues Paket mail/internal/importnotify: NotifyBatch löst am Ende EINES imapimport.RunOnce-Laufs höchstens EINEN Notify-Aufruf aus — es gibt strukturell keinen Codepfad für mehr als einen Aufruf je Lauf (Bündelung statt Flut bei Massenimport). Alle drei Pflichtprüfungen mit echten Nachweisen: eine neue Nachricht löst genau eine Benachrichtigung aus, 50 neue Nachrichten weiterhin genau eine gebündelte Benachrichtigung (Count: 50), ein echter HTTP-Server bildet den CFG-05-204-Unterdrückungsvertrag nach und bestätigt keine Zustellung ohne Fehler. Ergänzt um echte Fehlerpfade (5xx, nicht erreichbarer Endpunkt mit Timeout statt unbegrenztem Warten). go build/go vet/golangci-lint clean, gesamtes Mail-Modul regressionsfrei getestet.
53 lines
2.1 KiB
Go
53 lines
2.1 KiB
Go
// Package importnotify verbindet mail/internal/imapimport (ING-01/IMP-01)
|
|
// mit mail/internal/notifyclient (INT-05, Core CFG-02/CFG-05):
|
|
// genau EINE Benachrichtigung je abgeschlossenem Abgleichslauf
|
|
// (imapimport.SyncResult), nicht eine je neuer Nachricht
|
|
// (Akzeptanzkriterium 3: gebündelt statt Flut bei Massenimport).
|
|
package importnotify
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"gitea.perlbach24.de/scripte/nexarch/mail/internal/imapimport"
|
|
"gitea.perlbach24.de/scripte/nexarch/mail/internal/notifyclient"
|
|
)
|
|
|
|
// eventTypeMailNew ist der bei Core registrierte Ereignistyp für neu
|
|
// importierte Mails.
|
|
const eventTypeMailNew = "mail.new"
|
|
|
|
// Notifier ist die für NotifyBatch benötigte Teilmenge von
|
|
// *notifyclient.Client — als Schnittstelle für Tests ohne echten HTTP-
|
|
// Server.
|
|
type Notifier interface {
|
|
Notify(ctx context.Context, ev notifyclient.Event) error
|
|
}
|
|
|
|
// NotifyBatch löst — falls result.NewMessages > 0 — GENAU EINE
|
|
// Benachrichtigung für den gesamten Abgleichslauf aus
|
|
// (Akzeptanzkriterium 1: neue Mail löst zeitnah ein Ereignis aus;
|
|
// Akzeptanzkriterium 3: Massenimport erzeugt eine gebündelte
|
|
// Zusammenfassung statt Dutzende Einzelbenachrichtigungen — es gibt in
|
|
// diesem Paket schlicht KEINEN Codepfad, der mehr als einen Notify-
|
|
// Aufruf je Abgleichslauf absetzt). Bei result.NewMessages == 0 wird
|
|
// nichts gesendet.
|
|
//
|
|
// Ein Fehler beim Senden wird zurückgeliefert, blockiert aber
|
|
// strukturell NIE die bereits abgeschlossene Nachrichtenübernahme —
|
|
// NotifyBatch wird vom Aufrufer NACH dem erfolgreichen
|
|
// imapimport.RunOnce aufgerufen, nie währenddessen, und ein Fehler
|
|
// hier nimmt keine bereits persistierte Nachricht zurück.
|
|
func NotifyBatch(ctx context.Context, notifier Notifier, tenantSlug, mailboxName string, result imapimport.SyncResult) error {
|
|
if result.NewMessages == 0 {
|
|
return nil
|
|
}
|
|
summary := fmt.Sprintf("%d neue Mail(s) in %s", result.NewMessages, mailboxName)
|
|
return notifier.Notify(ctx, notifyclient.Event{
|
|
TenantSlug: tenantSlug,
|
|
EventType: eventTypeMailNew,
|
|
Summary: summary,
|
|
Count: result.NewMessages,
|
|
})
|
|
}
|