Follow-up from PR #8 review. Consolidates original follow-up items 2 and 3 into one piece of work, per the review discussion.
Background. PR #8 landed inter-request pacing to avoid RT-OCF request drops, plus the residual-pace() optimization. Two open questions remained:
- (orig. item 2) Drop within-transfer Block2 pacing entirely?
- (orig. item 3) Replace the
_DEFAULT_RATE_LIMIT_RPS = 5.0 floor with each descriptor's measured ceiling.
The measurement evidence on dropping within-transfer pacing was inconclusive: on a marginal device (dishwasher, 10.0.0.129) an interleaved 40-sweep test showed 2/60 hrefs failing paced vs 5/60 unpaced, but non-significant (Fisher's exact p≈0.44), and the failures were 3 clustered /device/0 congestion events — not 60 independent trials — where the paced sweep also failed in two of the three. So within-transfer pacing could not be shown to help or be shown safe to remove on that device class. Rather than drop it globally on a "should be safe" basis, we fold the decision into the per-descriptor ceiling work.
Plan.
- Plumb per-device rate first — this isn't a constant swap.
bridge.py:237 constructs DtlsCoapSession(...) without passing rate_limit_rps, so every device currently runs at the _DEFAULT_RATE_LIMIT_RPS = 5.0 default; the measured ceilings live only as comments above the PollTier lists (samples/dryer.py, samples/oven.py), not as a descriptor field. Add a rate field to the descriptor and have the bridge pass it into DtlsCoapSession(rate_limit_rps=...), keeping _DEFAULT_RATE_LIMIT_RPS as the fallback when a descriptor omits it. (Values come from the descriptors — the 3 frozen samples here plus those localthings maintains; the library keeps the 5.0 floor.)
- Set each descriptor's ceiling (oven ~8 rps → 125 ms, dryer ~14 rps → 71 ms) so inter-poll spacing in
PollScheduler._do_tier is not over-conservative.
- Make within-transfer Block2 pacing (
if num > 0: self.pace() in DtlsCoapSession.get()) conditional on the measured per-device ceiling rather than unconditional — keep it for devices whose ceiling warrants it, skip it where measured headroom shows continuation GETs are not throttled.
- Re-verify multi-block
/device/0 on characterized hardware (oven/dryer, fridge/dishwasher) after the change.
Acceptance. Per-descriptor ceilings drive both inter-poll and within-transfer pacing; no regression in Block2 completion on the four characterized appliances; marginal devices (dishwasher) retain their within-transfer insurance.
Follow-up from PR #8 review. Consolidates original follow-up items 2 and 3 into one piece of work, per the review discussion.
Background. PR #8 landed inter-request pacing to avoid RT-OCF request drops, plus the residual-
pace()optimization. Two open questions remained:_DEFAULT_RATE_LIMIT_RPS = 5.0floor with each descriptor's measured ceiling.The measurement evidence on dropping within-transfer pacing was inconclusive: on a marginal device (dishwasher, 10.0.0.129) an interleaved 40-sweep test showed 2/60 hrefs failing paced vs 5/60 unpaced, but non-significant (Fisher's exact p≈0.44), and the failures were 3 clustered
/device/0congestion events — not 60 independent trials — where the paced sweep also failed in two of the three. So within-transfer pacing could not be shown to help or be shown safe to remove on that device class. Rather than drop it globally on a "should be safe" basis, we fold the decision into the per-descriptor ceiling work.Plan.
bridge.py:237constructsDtlsCoapSession(...)without passingrate_limit_rps, so every device currently runs at the_DEFAULT_RATE_LIMIT_RPS = 5.0default; the measured ceilings live only as comments above thePollTierlists (samples/dryer.py,samples/oven.py), not as a descriptor field. Add a rate field to the descriptor and have the bridge pass it intoDtlsCoapSession(rate_limit_rps=...), keeping_DEFAULT_RATE_LIMIT_RPSas the fallback when a descriptor omits it. (Values come from the descriptors — the 3 frozen samples here plus those localthings maintains; the library keeps the 5.0 floor.)PollScheduler._do_tieris not over-conservative.if num > 0: self.pace()inDtlsCoapSession.get()) conditional on the measured per-device ceiling rather than unconditional — keep it for devices whose ceiling warrants it, skip it where measured headroom shows continuation GETs are not throttled./device/0on characterized hardware (oven/dryer, fridge/dishwasher) after the change.Acceptance. Per-descriptor ceilings drive both inter-poll and within-transfer pacing; no regression in Block2 completion on the four characterized appliances; marginal devices (dishwasher) retain their within-transfer insurance.