0.1.52 Gateway
This commit is contained in:
@@ -743,6 +743,53 @@ each page read as a pile of unrelated controls. Things to preserve:
|
||||
the page that can do something about it. A screen that both summarises and changes state
|
||||
is where an accidental click lives.
|
||||
|
||||
**The gateway's own settings are `/admin/settings`**, reached from the account menu in the
|
||||
top bar rather than from the rail — every other page decides what the *televisions* do, and
|
||||
this one is about the server process. It is `store.GatewaySettings` (one `app_settings` row)
|
||||
over `internal/api/gateway_settings.go`, and it holds the household timezone, the log level,
|
||||
the idle sign-out, the two alert windows and the Emby health probe. Things to preserve:
|
||||
|
||||
- **Every field is an override, and `.env` is still the configuration.** Blank means
|
||||
"whatever this container was started with", which the page prints beside each field, so
|
||||
clearing a setting is a real undo rather than a value the operator has to remember. A
|
||||
setting that can legitimately be *off* therefore needs a third value: **-1 is off, 0 is
|
||||
deployed** (`store.GatewaySettingsOff`), because a plain zero would make "turn this off"
|
||||
indistinguishable from "leave it alone".
|
||||
- **Nothing reads the document directly.** The effective-value helpers in
|
||||
`gateway_settings.go` — `householdLocation`, `sessionIdleExpiry`, `sonarrAlertWindow`,
|
||||
`radarrAlertWindow`, `embyHealthInterval` — are the only readers, so adding a setting is
|
||||
one helper beside its config field rather than teaching every call site that an override
|
||||
exists. `s.cfg.SonarrLocation` in particular should not be read directly any more:
|
||||
`householdLocation()` is what makes a timezone change reach the schedule rows, the hero
|
||||
rotation and the sign-in history.
|
||||
- **A setting that is read once at start-up is not a setting.** `WatchEmbyReachability`
|
||||
re-reads its cadence every tick and keeps ticking (slowly) while the probe is off, so
|
||||
switching it back on does not need a restart; the idle sweep reads the expiry inside
|
||||
`Run` rather than closing over it; and the log level is a `*slog.LevelVar` threaded from
|
||||
`main` through `Deps.LogLevel`, applied on save rather than waited for — an operator who
|
||||
has just turned debug on and gone to look at the log must not spend thirty seconds
|
||||
believing it did not work. `deployedLogLevel` is remembered because clearing the
|
||||
override has to restore *something*, and the variable itself has by then been moved.
|
||||
|
||||
**Two things a television does are notifications now**, both in `internal/api/device_activity.go`.
|
||||
`TypeDeviceFirstUse` announces the first time a set opened Memby on a household-local day
|
||||
and `TypeDeviceUpdated` announces one that finished updating itself. Things to preserve:
|
||||
|
||||
- **First use is anchored on `/v1/home`**, not on the auth middleware every call passes
|
||||
through: a set left on overnight polls `/v1/status` every ten seconds, so any-request
|
||||
would announce it at midnight — an event nobody did, at the hour nobody is reading. It is
|
||||
marked *before* the cached response is served, because a household whose rows are still
|
||||
warm from another set has still just been opened by this one.
|
||||
- **The answer comes from the insert.** `store.MarkDeviceDay` is `ON CONFLICT DO NOTHING`
|
||||
on `device_activity_days`, so two televisions racing on the same row cannot both be told
|
||||
they were first. The marks are retired with the device and pruned by their own
|
||||
housekeeping task.
|
||||
- **An update needs a previous version to be an update.** `announceDeviceUpdate` fires from
|
||||
`captureClientIdentity` — the only place a set that updated in place is ever seen, since
|
||||
it never signs in again — and an empty previous version is a build this gateway had never
|
||||
been told the version of, not a version that moved. A *downgrade* is still announced: a
|
||||
sideloaded step backwards is news too.
|
||||
|
||||
**Explaining a recommendation** is `recommend/explain.go`: `Why(profile, item, limit)` is a
|
||||
pure function turning the learned weights into the phrases a detail page shows. It is kept
|
||||
apart from `Score` on purpose — the scorer decides *order* and may be opaque, this decides
|
||||
|
||||
Reference in New Issue
Block a user