0.3.05
This commit is contained in:
@@ -17,13 +17,14 @@ const GatewaySettingsKey = "gateway_settings"
|
||||
// GatewaySettings is the handful of server-level decisions an operator can change
|
||||
// without a redeployment.
|
||||
//
|
||||
// Every field is an *override* of the value the container was started with, and the zero
|
||||
// value means "whatever was deployed". That is the whole design: `.env` remains the
|
||||
// Most fields are an *override* of the value the container was started with, and their
|
||||
// zero value means "whatever was deployed". That is the whole design: `.env` remains the
|
||||
// configuration — it is what a fresh container comes up with, what deploy-server.ps1
|
||||
// writes and what an operator locked out of the console still has — and this row is a
|
||||
// runtime amendment to it, so the console can always show the deployed value beside the
|
||||
// one in force and an operator can put a setting back by clearing it rather than by
|
||||
// remembering what it used to be.
|
||||
// remembering what it used to be. NotificationDisplay is the exception: it is a native
|
||||
// server policy with a Home-only default rather than an environment-backed value.
|
||||
//
|
||||
// A window that can legitimately be *off* therefore needs a value distinct from "not
|
||||
// overridden", which is why the two alert windows and the health interval take -1 for off
|
||||
@@ -44,6 +45,10 @@ type GatewaySettings struct {
|
||||
// added" banner stays on offer to a television that was switched off at the time.
|
||||
SonarrAlertMinutes int `json:"sonarrAlertMinutes"`
|
||||
RadarrAlertMinutes int `json:"radarrAlertMinutes"`
|
||||
// NotificationDisplay is where informational banners may be drawn across every
|
||||
// viewer and television. It is server-owned rather than a per-viewer preference:
|
||||
// one household should not have different interruption rules on different sets.
|
||||
NotificationDisplay string `json:"notificationDisplay"`
|
||||
// EmbyHealthSeconds is how often the reachability probe asks Emby whether it is there.
|
||||
EmbyHealthSeconds int `json:"embyHealthSeconds"`
|
||||
// SlowRequestMillis is how long a request must take before its log line carries a
|
||||
@@ -74,6 +79,20 @@ const GatewaySettingsOff = -1
|
||||
// and refusing is worth nothing if the list it refuses against lives somewhere else.
|
||||
var GatewayLogLevels = []string{"trace", "debug", "info", "warn", "error"}
|
||||
|
||||
const (
|
||||
NotificationDisplayEverywhere = "everywhere"
|
||||
NotificationDisplayHomeOnly = "home_only"
|
||||
NotificationDisplayOff = "off"
|
||||
)
|
||||
|
||||
// GatewayNotificationDisplays is the complete wire vocabulary, served to the console so
|
||||
// it cannot offer a value the gateway would refuse.
|
||||
var GatewayNotificationDisplays = []string{
|
||||
NotificationDisplayEverywhere,
|
||||
NotificationDisplayHomeOnly,
|
||||
NotificationDisplayOff,
|
||||
}
|
||||
|
||||
func normalizeGatewaySettings(settings GatewaySettings) GatewaySettings {
|
||||
settings.Timezone = strings.TrimSpace(settings.Timezone)
|
||||
if settings.Timezone != "" {
|
||||
@@ -91,6 +110,13 @@ func normalizeGatewaySettings(settings GatewaySettings) GatewaySettings {
|
||||
settings.SessionIdleDays = clampOverride(settings.SessionIdleDays, 1, 3650, false)
|
||||
settings.SonarrAlertMinutes = clampOverride(settings.SonarrAlertMinutes, 1, 24*60, true)
|
||||
settings.RadarrAlertMinutes = clampOverride(settings.RadarrAlertMinutes, 1, 7*24*60, true)
|
||||
settings.NotificationDisplay = strings.ToLower(strings.TrimSpace(settings.NotificationDisplay))
|
||||
if !containsString(GatewayNotificationDisplays, settings.NotificationDisplay) {
|
||||
// Missing covers both a new installation and a row written by an older gateway.
|
||||
// Unknown is equally conservative: silence from the setting must never authorise
|
||||
// an interruption over active playback.
|
||||
settings.NotificationDisplay = NotificationDisplayHomeOnly
|
||||
}
|
||||
settings.EmbyHealthSeconds = clampOverride(settings.EmbyHealthSeconds, 10, 3600, true)
|
||||
// The floor is 1ms rather than 0 because "breakdown on everything" is a real thing to
|
||||
// want for a few minutes, and off is a real thing to want too — this is the one
|
||||
@@ -133,7 +159,7 @@ func (s *Store) GatewaySettings(ctx context.Context) (GatewaySettings, error) {
|
||||
err := s.pool.QueryRow(ctx,
|
||||
`SELECT value FROM app_settings WHERE key = $1`, GatewaySettingsKey).Scan(&raw)
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return GatewaySettings{}, nil
|
||||
return normalizeGatewaySettings(GatewaySettings{}), nil
|
||||
}
|
||||
if err != nil {
|
||||
return GatewaySettings{}, fmt.Errorf("store: read gateway settings: %w", err)
|
||||
|
||||
@@ -21,6 +21,25 @@ func TestNormalizeGatewaySettingsRefusesWhatItCannotUse(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeGatewaySettingsDefaultsNotificationDisplayToHomeOnly(t *testing.T) {
|
||||
for _, value := range []string{"", "unknown"} {
|
||||
settings := normalizeGatewaySettings(GatewaySettings{NotificationDisplay: value})
|
||||
if settings.NotificationDisplay != NotificationDisplayHomeOnly {
|
||||
t.Fatalf("notification display %q became %q, want %q",
|
||||
value, settings.NotificationDisplay, NotificationDisplayHomeOnly)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeGatewaySettingsKeepsNotificationDisplayVocabulary(t *testing.T) {
|
||||
for _, value := range GatewayNotificationDisplays {
|
||||
settings := normalizeGatewaySettings(GatewaySettings{NotificationDisplay: " " + value + " "})
|
||||
if settings.NotificationDisplay != value {
|
||||
t.Fatalf("notification display %q became %q", value, settings.NotificationDisplay)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeGatewaySettingsKeepsTheThreeMeanings(t *testing.T) {
|
||||
settings := normalizeGatewaySettings(GatewaySettings{
|
||||
Timezone: "Pacific/Auckland", LogLevel: " Debug ",
|
||||
|
||||
Reference in New Issue
Block a user