gofmt notification files
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 49s
CI / test-go-edu-search (push) Successful in 45s
CI / test-python-klausur (push) Failing after 3m41s
CI / test-python-agent-core (push) Successful in 38s
CI / test-nodejs-website (push) Successful in 49s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 49s
CI / test-go-edu-search (push) Successful in 45s
CI / test-python-klausur (push) Failing after 3m41s
CI / test-python-agent-core (push) Successful in 38s
CI / test-nodejs-website (push) Successful in 49s
This commit is contained in:
@@ -2,10 +2,10 @@ package database
|
|||||||
|
|
||||||
// NotificationMigrations creates the one table Phase 9d needs:
|
// NotificationMigrations creates the one table Phase 9d needs:
|
||||||
//
|
//
|
||||||
// notification_log — one row per (event, lead_days, audience, channel)
|
// notification_log — one row per (event, lead_days, audience, channel)
|
||||||
// that the cron scanner has already attempted. The UNIQUE constraint
|
// that the cron scanner has already attempted. The UNIQUE constraint
|
||||||
// makes the cron idempotent — running it twice on the same day does
|
// makes the cron idempotent — running it twice on the same day does
|
||||||
// not re-send.
|
// not re-send.
|
||||||
//
|
//
|
||||||
// channel ∈ {'matrix', 'email'} — set by the dispatcher.
|
// channel ∈ {'matrix', 'email'} — set by the dispatcher.
|
||||||
// audience ∈ {'parents', 'students'}.
|
// audience ∈ {'parents', 'students'}.
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ import (
|
|||||||
// lead_days, audience) pairs are due today, dispatches via the configured
|
// lead_days, audience) pairs are due today, dispatches via the configured
|
||||||
// upstream URLs, and writes a notification_log row for idempotency.
|
// upstream URLs, and writes a notification_log row for idempotency.
|
||||||
type Service struct {
|
type Service struct {
|
||||||
db *pgxpool.Pool
|
db *pgxpool.Pool
|
||||||
matrixURL string // empty → status=skipped
|
matrixURL string // empty → status=skipped
|
||||||
emailURL string // empty → status=skipped
|
emailURL string // empty → status=skipped
|
||||||
httpTimeout time.Duration
|
httpTimeout time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dispatch is the contract our upstream services (Matrix bridge + Email
|
// Dispatch is the contract our upstream services (Matrix bridge + Email
|
||||||
@@ -85,11 +85,11 @@ func (s *Service) ListLog(ctx context.Context, eventID, ownerUserID string) ([]L
|
|||||||
// renders + dispatches + logs. Idempotent via the UNIQUE constraint on
|
// renders + dispatches + logs. Idempotent via the UNIQUE constraint on
|
||||||
// notification_log.
|
// notification_log.
|
||||||
type RunResult struct {
|
type RunResult struct {
|
||||||
Date string `json:"date"`
|
Date string `json:"date"`
|
||||||
Sent int `json:"sent"`
|
Sent int `json:"sent"`
|
||||||
Failed int `json:"failed"`
|
Failed int `json:"failed"`
|
||||||
Skipped int `json:"skipped"`
|
Skipped int `json:"skipped"`
|
||||||
AlreadyLogged int `json:"already_logged"`
|
AlreadyLogged int `json:"already_logged"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) RunForDate(ctx context.Context, runDate time.Time) (*RunResult, error) {
|
func (s *Service) RunForDate(ctx context.Context, runDate time.Time) (*RunResult, error) {
|
||||||
@@ -141,15 +141,15 @@ func (s *Service) RunForDate(ctx context.Context, runDate time.Time) (*RunResult
|
|||||||
// dueEvent holds the small slice of cal_school_event row we need plus the
|
// dueEvent holds the small slice of cal_school_event row we need plus the
|
||||||
// matched lead_day for this run.
|
// matched lead_day for this run.
|
||||||
type dueEvent struct {
|
type dueEvent struct {
|
||||||
ID string
|
ID string
|
||||||
Title string
|
Title string
|
||||||
EventType string
|
EventType string
|
||||||
StartDate time.Time
|
StartDate time.Time
|
||||||
ClassName string // optional, may be empty for "alle Klassen"
|
ClassName string // optional, may be empty for "alle Klassen"
|
||||||
OwnerUserID string
|
OwnerUserID string
|
||||||
NotifyParents bool
|
NotifyParents bool
|
||||||
NotifyStudents bool
|
NotifyStudents bool
|
||||||
LeadDays int
|
LeadDays int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) dueEvents(ctx context.Context, runDate time.Time) ([]dueEvent, error) {
|
func (s *Service) dueEvents(ctx context.Context, runDate time.Time) ([]dueEvent, error) {
|
||||||
@@ -177,9 +177,9 @@ func (s *Service) dueEvents(ctx context.Context, runDate time.Time) ([]dueEvent,
|
|||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var (
|
var (
|
||||||
id, title, eventType, ownerUserID, classNames string
|
id, title, eventType, ownerUserID, classNames string
|
||||||
notifyParents, notifyStudents bool
|
notifyParents, notifyStudents bool
|
||||||
startDate time.Time
|
startDate time.Time
|
||||||
leadDays []int32
|
leadDays []int32
|
||||||
)
|
)
|
||||||
if err := rows.Scan(&id, &title, &eventType, &startDate, &ownerUserID,
|
if err := rows.Scan(&id, &title, &eventType, &startDate, &ownerUserID,
|
||||||
¬ifyParents, ¬ifyStudents, &leadDays, &classNames); err != nil {
|
¬ifyParents, ¬ifyStudents, &leadDays, &classNames); err != nil {
|
||||||
|
|||||||
@@ -19,9 +19,10 @@ type Vars struct {
|
|||||||
// bucket and language, then substitutes the {{var}} placeholders.
|
// bucket and language, then substitutes the {{var}} placeholders.
|
||||||
//
|
//
|
||||||
// lead is grouped into three buckets:
|
// lead is grouped into three buckets:
|
||||||
// 0 → "today"
|
//
|
||||||
// 1 → "tomorrow"
|
// 0 → "today"
|
||||||
// >=2 → "in X days" with X = lead value
|
// 1 → "tomorrow"
|
||||||
|
// >=2 → "in X days" with X = lead value
|
||||||
//
|
//
|
||||||
// Falls back through (lang → de) and (event_type → "andere") so we never
|
// Falls back through (lang → de) and (event_type → "andere") so we never
|
||||||
// fail to render even with custom rule combos.
|
// fail to render even with custom rule combos.
|
||||||
|
|||||||
Reference in New Issue
Block a user