fix(filter): suppress subscription renewal in background mode#1304
fix(filter): suppress subscription renewal in background mode#1304xAlisher wants to merge 2 commits into
Conversation
Adds backgroundMode to Sub and SetBackgroundMode(bool) to both Sub and FilterManager. When background=true, subscriptionLoop skips the 5-second health-check ticker and drops expired subscription IDs from the closing channel without resubscribing. When background=false (foreground return), a resubscription is immediately triggered for any expired filters. Background context (status-im/status-app#21045): On Android, each Waku filter subscription has a relay-side TTL (~13.5 min observed). When it expires, the closing channel fires, checkAndResubscribe runs, and a new wf.Subscribe() RPC wakes the LTE modem. With a loaded account this happens every ~13.5 min overnight, producing a 55% radio duty cycle (~144 mAh/hr) while the screen is locked. With background mode active, no network I/O occurs during subscription expiry. On foreground return, all expired filters are resubscribed in one burst — the user sees a brief reconnect, then full message delivery. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
R1 of battery-drain fix (#21045).
When the Android app is backgrounded, expiring light-client filter
subscriptions triggered wf.Subscribe() RPCs that woke the LTE radio.
This adds a background-mode gate at every layer of the call chain:
Messenger.SetAppBackground
→ messaging.API.SetFilterBackgroundMode
→ transport.Transport.SetFilterBackgroundMode
→ Waku interface / gowaku.Waku
→ filterapi.FilterManager.SetBackgroundMode (go-waku)
→ filterapi.Sub.SetBackgroundMode (go-waku)
While backgrounded the subscriptionLoop's ticker and closing-channel
cases are suppressed; on foreground return a single resubscribe is
queued to catch any subscriptions that expired while idle.
go-waku changes: logos-messaging/logos-delivery-go#1304
go.mod replace directive: xAlisher/go-waku@ab4609ef
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Includes fix(filter): suppress Waku filter-subscription renewal in background (R1 of #21045 battery-drain fix, logos-messaging/logos-delivery-go#1304) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
FilterHealthCheckLoop fires every 1 min and sends a Waku protocol ping to each subscribed filter peer. On Android, these pings queue up during Doze and flush in maintenance windows (~15 min), keeping the LTE modem at ~55-58% duty cycle even when the app is backgrounded. This was the dominant radio wakeup source missed by the previous commit (which only gated subscription renewal in subscriptionLoop). mag's measurement on #21111 confirmed modem still 58% active post-R1. Add backgroundMode atomic.Bool to WakuFilterLightNode with a SetBackgroundMode(bool) method. FilterHealthCheckLoop skips PingPeers() when backgrounded. FilterManager.SetBackgroundMode now cascades to both layers: subscription renewal (api/filter) and health-check pings (protocol/filter). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…sion) Adds FilterHealthCheckLoop background guard — the dominant LTE radio wakeup source (1-min pings to filter peers, batched by Doze into ~15-min windows at ~55% duty cycle). go-waku change: logos-messaging/logos-delivery-go#1304 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
igor-sirotin
left a comment
There was a problem hiding this comment.
TLDR; This change would silently make Status deaf after 5 minutes of being in backgroundMode.
Explaining the consequences
-
There is indeed a TTL for subscriptions: it's 5 minutes here.
- TTL is extended with either a SUBSCRIBE request, or PING, but both are blocked in this PR. If neither of these 2 is received within 5 minutes, the subscription is closed.
- (not sure where ~13.5 minutes is coming from)
-
If a subscription died for any other reasons (e.g. remote peer is down), we should resubscribe to other nodes.
- Each subscription's health is currently checked once in 5 seconds. But this PR drops this logic in
backgroundMode=true.
- Each subscription's health is currently checked once in 5 seconds. But this PR drops this logic in
So after 5 minutes of backgroundMode=true, all connected nodes will expire the subscription, and we will silently ignore this. Effect: no incoming messages.
My suggestion is:
- Increase TTL in the fleet up to 30 minutes
- Keep PING working, but increase the period to 10 minutes.
- Keep the re-subscription logic.
Warning
Increasing a TTL should be consulted with AnonComms team, I'm not sure if it's a safe move.
"background mode"
I understand the intention, but I'm not sure I agree with the idea of "Background mode" in general.
Why is background mode more important than foreground? Why allow draining the battery when the app is opened?
We should look for a solution that can be always applicable.
I guess in background we could allow Status to have some delays in message delivery, but this would be implemented in a vey different way, and as a user I would expect messages to arrive instantly. And in any way, reliability should not be neglected.
Other comments
Please remove any mentions of UI/LTE and other app-level logic.
If we keep backgroundMode, then it could be mentioned once, as a use-case example. But in general, e.g. UI is not a concern of logos-delivery-go.
jrainville
left a comment
There was a problem hiding this comment.
I agree with Igor. This change would realistically make the message receiver not work.
I think we could skip this change for now and keep only the status-go change of not doing store node calls.
The changes here have a too big chance of introducing a regression where push notifications would just not work, which defeats the whole purpose of the background service.
R1 of battery-drain fix (#21045).
When the Android app is backgrounded, expiring light-client filter
subscriptions triggered wf.Subscribe() RPCs that woke the LTE radio.
This adds a background-mode gate at every layer of the call chain:
Messenger.SetAppBackground
→ messaging.API.SetFilterBackgroundMode
→ transport.Transport.SetFilterBackgroundMode
→ Waku interface / gowaku.Waku
→ filterapi.FilterManager.SetBackgroundMode (go-waku)
→ filterapi.Sub.SetBackgroundMode (go-waku)
While backgrounded the subscriptionLoop's ticker and closing-channel
cases are suppressed; on foreground return a single resubscribe is
queued to catch any subscriptions that expired while idle.
go-waku changes: logos-messaging/logos-delivery-go#1304
go.mod replace directive: xAlisher/go-waku@ab4609ef
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…sion) Adds FilterHealthCheckLoop background guard — the dominant LTE radio wakeup source (1-min pings to filter peers, batched by Doze into ~15-min windows at ~55% duty cycle). go-waku change: logos-messaging/logos-delivery-go#1304 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Problem
On mobile (Android/iOS), Waku filter subscriptions have a relay-side TTL of ~13.5 minutes (observed). When a subscription expires, the
closingchannel fires insubscriptionLoop,checkAndResubscriberuns, and a newwf.Subscribe()RPC is issued — waking the LTE modem from RRC Idle.With a loaded account (50 contacts, 3 communities) this produces ~4.4 radio wakeups/hr overnight: ~144 mAh/hr of battery drain with the screen locked. Measured via
dumpsys batterystats --chargedon Android 13 (status-im/status-app#21045, T5b soak).Fix
Adds
backgroundMode atomic.BooltoSub+SetBackgroundMode(bool)onSubandFilterManager.background=true (screen locked):
background=false (foreground return):
closingto trigger resubscriptionImpact
Messages sent while backgrounded are delivered via mailserver on foreground — not lost.
Usage
Companion status-go PR: status-im/status-go#7508