proxy_client: resubscribe when a push is rejected as stale

pushNotificationReceived() drops a notification whose session id does not
match, and does nothing else. Nothing tells the server it is notifying
with a session the client no longer knows, so it keeps waking the device
for notifications that can only be discarded, and the values they
announce are never fetched.

Observed on Android: a call arrives while the account is deactivated in
doze. The push carrying the connection request is rejected as stale, so
the daemon never learns which value to fetch. The call is only saved by
the wake-up side effect: the account reconnects and rediscovers the value
through the DHT, which took between 1.7 and 31 seconds across the runs
measured. Delivery is left to a race the caller sometimes loses.

Treat a session mismatch as evidence that the server holds stale
listeners and ask for the subscriptions to be sent again. Reuse
listenerRestartTimer_ and the pushSubscriptionPending_ flag, so the
recovery path is the same one used when a subscription could not be sent
at token time. Stale listeners notify in bursts and rearming the timer
cancels the pending wait, so a burst coalesces into a single pass.

This complements, and does not replace, sending the subscriptions once
the connection is up: that change prevents the mismatch, this one
recovers from it if it happens anyway.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Cyrille BéraudandCopilot committed 2026-09-26 14:27:30 -04:00
1 parent 79ba60f647
commit dc912fa8cf
1 file changed
+16
+16
View File
@@ -1285,6 +1285,22 @@ DhtProxyClient::pushNotificationReceived([[maybe_unused]] const std::map<std::st
if (sessionId != notification.end() and sessionId->second != pushSessionId_) {
if (logger_)
logger_->debug("[proxy:client] [push] ignoring push for other session");
// A mismatch proves the server still has a listener registered under a previous
// session: it keeps waking this device for notifications that can only be
// discarded, and the values they announce are never fetched. Ask for the
// subscriptions to be sent again so the server learns the current session,
// instead of waiting for an unrelated event to trigger one.
//
// restartListeners() is rate limited by its own timer: stale listeners notify in
// bursts, and rearming the timer on each one simply coalesces them into a single
// pass.
{
std::lock_guard l(lockCurrentProxyInfos_);
pushSubscriptionPending_ = true;
}
listenerRestartTimer_->expires_at(std::chrono::steady_clock::now());
listenerRestartTimer_->async_wait(
std::bind(&DhtProxyClient::restartListeners, this, std::placeholders::_1));
return PushNotificationResult::IgnoredWrongSession;
}
std::lock_guard lock(searchLock_);