AnnounceEntry
Per-URL announce bookkeeping. This is the KiteTorrent port of the live state libtorrent carries in aux::announce_entry and aux::announce_infohash (include/libtorrent/aux_/announce_entry.hpp). The session module owns the announce loop and tier logic; this struct is the mutable state it threads per tracker URL so the loop can decide when to (re-)announce and what to send.
It is a plain mutable holder rather than a data class because the loop mutates it in place across announces, exactly as libtorrent mutates the fields of an announce_entry between calls.
Properties
whether we have already sent a completed event to this tracker (libtorrent announce_infohash::complete_sent); prevents re-sending it.
whether the most recent announce succeeded. libtorrent derives is_working() as fails == 0, which we mirror via markWorking and markFailed.
the last TrackerEvent we sent this tracker, so the loop can send started exactly once and decide whether completed is still owed.
the earliest epoch-second the loop may re-announce even for an early/forced refresh (libtorrent announce_infohash::min_announce), derived from a response's AnnounceResponse.minInterval.
the wall-clock epoch-second instant the loop may next announce to this tracker (libtorrent announce_infohash::next_announce), 0 meaning "as soon as possible".
Functions
Record a failed announce at nowEpochSecs, porting announce_infohash::failed: bump fails (saturating at 127), mark not-working, and push nextAnnounceEpochSecs out by the exponential back-off in TrackerBackoff.nextDelaySecs. retryIntervalSecs is libtorrent's retry_interval floor (e.g. a tracker-supplied retry hint).
Record a successful announce against this tracker at nowEpochSecs: clear the failure counter, mark working, and schedule the next announce interval seconds out with the floor at minInterval (libtorrent sets both next_announce and min_announce on a good response). Captures any trackerId echoed.