upwatch: hold a seeding torrent app for one line test, then put its limit back exactly (R-1250)
gates / gates (push) Successful in 1m22s

When the agent waits for quiet and qBittorrent or Transmission runs: record the limit first,
hold at 1 KiB/s, ask the agent for a test on request, put the old limit back (deferred; a
household change during the test stays). Start-up puts back a limit a killed controller left;
the 50 % rule skips while a hold record exists. Commit only.
This commit is contained in:
2026-10-24 13:19:07 +02:00
parent bddc477e22
commit 046b808792
10 changed files with 789 additions and 33 deletions
+16 -1
View File
@@ -14,6 +14,8 @@ import (
type State struct {
Line []LineRecord `json:"line,omitempty"`
QBLimit *QBLimitState `json:"qb_limit,omitempty"`
// Hold is a torrent app held low for a line test on request (R-1250, linehold.go); nil when none.
Hold *LineHold `json:"line_test_hold,omitempty"`
}
// Store is the settings half the service needs (settings.Settings satisfies it).
@@ -44,7 +46,14 @@ type Service struct {
// to ep0 inside the tunnel. nil or ok=false = not measured. Read every 15 minutes (RefreshMeasured), never per
// minute.
Measured func(ctx context.Context) (mbps float64, at time.Time, ok bool)
Log *log.Logger
// The line test for a box that seeds all day (R-1250, linehold.go). Torrents are the apps that can be held, in
// order of preference; TorrentRunning says whether one runs now; LineWaiting is the agent's waiting_for_quiet;
// LineRun is its test on request. Any nil = no hold.
Torrents []Holdable
TorrentRunning func(stack string) bool
LineWaiting func(ctx context.Context) bool
LineRun func(ctx context.Context) (LineRunResult, error)
Log *log.Logger
mu sync.Mutex
measured float64
@@ -137,6 +146,12 @@ func (s *Service) QBLimitNow(ctx context.Context) {
s.RefreshMeasured(ctx)
line, known := s.MeasuredLine()
cur := decode(s.Store.GetUpwatch())
if cur.Hold != nil {
// A line-test hold is in place or was left behind: qBittorrent holds the test value, which the rule would
// read as the household's change and then never touch the limit again (linehold.go).
logx.Debugf(s.Log, "[upwatch] qBittorrent limit: a line-test hold record exists — rule skipped until it is cleared")
return
}
var st QBLimitState
if cur.QBLimit != nil {
st = *cur.QBLimit