From 4de6d72cfed866924edc62a860976a0e3badecf5 Mon Sep 17 00:00:00 2001 From: MarekWo Date: Sat, 28 Mar 2026 15:05:35 +0100 Subject: [PATCH] fix(dm): update delivery path from PATH event after ACK race When both ACK and PATH_UPDATE fire for FLOOD delivery, _on_ack may store empty path before PATH_UPDATE can provide the discovered route. Now _on_path_update also checks for recently-delivered DMs with empty delivery_path and backfills with the discovered path from the event. Co-Authored-By: Claude Opus 4.6 --- app/database.py | 15 +++++++++++++++ app/device_manager.py | 19 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/app/database.py b/app/database.py index 33babd9..4576f75 100644 --- a/app/database.py +++ b/app/database.py @@ -688,6 +688,21 @@ class Database: "UPDATE direct_messages SET delivery_status=? WHERE id=?", (status, dm_id)) + def get_recent_delivered_dm_with_empty_path(self, contact_pubkey: str) -> Optional[Dict]: + """Find most recent delivered outgoing DM with empty delivery_path.""" + with self._connect() as conn: + row = conn.execute( + """SELECT id, delivery_attempt, delivery_max_attempts + FROM direct_messages + WHERE contact_pubkey=? AND direction='out' + AND (delivery_path IS NULL OR delivery_path='') + AND delivery_status IS NULL + AND delivery_attempt IS NOT NULL + ORDER BY id DESC LIMIT 1""", + (contact_pubkey,) + ).fetchone() + return dict(row) if row else None + def relink_orphaned_dms(self, public_key: str, name: str = '') -> int: """Re-link DMs with NULL contact_pubkey back to this contact. diff --git a/app/device_manager.py b/app/device_manager.py index 180abe1..f3fff13 100644 --- a/app/device_manager.py +++ b/app/device_manager.py @@ -809,6 +809,25 @@ class DeviceManager: self._retry_tasks.pop(dm_id, None) break # Only confirm the most recent pending DM to this contact + # Update delivery_path for recently-delivered DMs where _on_ack + # stored empty path (FLOOD mode) before PATH_UPDATE could provide it + discovered_path = data.get('path', '') + if discovered_path and pubkey: + recent = self.db.get_recent_delivered_dm_with_empty_path(pubkey) + if recent: + self.db.update_dm_delivery_info( + recent['id'], recent['delivery_attempt'], + recent['delivery_max_attempts'], discovered_path) + if self.socketio: + self.socketio.emit('dm_delivered_info', { + 'dm_id': recent['id'], + 'attempt': recent['delivery_attempt'], + 'max_attempts': recent['delivery_max_attempts'], + 'path': discovered_path, + }, namespace='/chat') + logger.debug(f"Updated delivery path for dm_id={recent['id']} " + f"with discovered path {discovered_path[:16]}") + except Exception as e: logger.error(f"Error handling path update: {e}")