extract the D-Bus service client from the gui #84
Loading…
Reference in a new issue
No description provided.
Delete branch "change/service-client"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
First seam of #83.
Problem
AqomuiGuiowns its D-Bus transport inline: proxy creation, signal subscriptions,dbus_call's restart-recovery machinery, and agetattr(self, reply)()status dispatch that aborts the GUI from inside a Qt slot if the service ever emits a status without a handler (the"fail"status did exactly that once).Fix
aqomui/service_client.py:ServiceClientowns the bus proxy (follow_name_owner_changes), idempotent signal subscription from a{signal: handler}mapping,call()with the one-silent-recovery-then-ask flow, and the owner-wait poll. UI policy stays in the GUI and arrives as callbacks:notify,on_recovered(re-register bypass net info, re-sync tunnel state),on_unavailable(the Quit/Restart dialog).dbus_call/wait_for_service_owner/create_dbus_objectare gone,initialize_serviceno longer rebuilds a proxy (the unit isType=dbus, so systemctl returns with the name owned, and the proxy follows the name anyway), and all 26 call sites go throughself.service.call.openvpn_log_monitorbecomesdispatch_statuswith an explicitSTATUSESwhitelist (the 4 statuses × 3 role suffixes the service emits); an unknown status is logged instead of dispatched blind.aqomui_cli.pystill builds its own proxy — it can adoptServiceClientwhen it gets attention (its-cis broken independently).Verification
tests/test_service_client.pyagainst the real client (with a fake clock, so the owner-wait poll and give-up paths are now tested for real instead of stubbed); new GUI tests cover known/unknown status dispatch and assert every whitelisted status has a handler.ruff check --select E9,F63,F7,F82andcompileall -W error::SyntaxWarningclean.systemctl restart aqomuiunder a running GUI recovers silently — since that flow now runs through the extracted client.Regression fix (second commit): bypass died after a service restart
Live testing #73's merge found a gap in it: with the proxy following the name, calls against a restarted service just succeed — so the recovery hook that re-registers the bypass network info never fires (before #80, the dialog's Restart path did this). The fresh service then has no
net, the next bypass-tunnel teardown logs "no network info registered - skipping bypass rebuild", and table 11 is left without a default route: bypass works at app start and while a bypass tunnel is up, and dies the moment it disconnects.Fix: the client watches
NameOwnerChanged(issue #73's original suggestion) — a new unique owner behind the well-known name means a service with a clean slate, soon_recoveredruns proactively even though no call failed. The in-call recovery path records the new owner first so the queued watch notification doesn't resync twice.Live verification for this now includes: restart the service under the running GUI, then connect and disconnect a bypass server — bypassed apps must still reach the internet through the physical link afterwards (
ip route show table 11keeps a default route).🤖 Generated with Claude Code