33 lines
1.3 KiB
Go
33 lines
1.3 KiB
Go
package delivery
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
)
|
|
|
|
// Sink — one channel's transport. the impure seam: voice (local audio via the
|
|
// tts module), ntfy (push), telegram (push through your relay). each is a
|
|
// separate module with its own unit; the dispatcher holds one per channel.
|
|
//
|
|
// A nil Sink = that channel is not wired (the daemon doesn't have to wire all
|
|
// three at scaffold time). sends to an unwired channel are skipped — the
|
|
// daemon should wire what the routing table can produce for its configured
|
|
// severities, but a missing sink is a config gap, not a panic.
|
|
type Sink interface {
|
|
Send(ctx context.Context, s Sendable) error
|
|
}
|
|
|
|
// AckTracker — for sev4 telegram repeat-til-ack. maps a send key (rule name)
|
|
// → acked + last-sent. the daemon's tick loop calls ShouldRepeat each cycle;
|
|
// when the user acknowledges (a tap on the telegram message, a voice "got it"),
|
|
// MarkAcked stops the repeat for that key.
|
|
//
|
|
// Pure decision lives in ShouldRepeat (ack.go); this is the stateful seam.
|
|
// the production impl is a store-backed table; the scaffold's fake is in-memory.
|
|
type AckTracker interface {
|
|
WasAcked(ctx context.Context, key string) (bool, error)
|
|
MarkSent(ctx context.Context, key string, ts time.Time) error
|
|
LastSent(ctx context.Context, key string) (time.Time, error)
|
|
MarkAcked(ctx context.Context, key string) error
|
|
}
|