Gateway presence not re-sent after reconnecting to the server #3

Closed
opened 2026-10-07 18:49:26 +00:00 by asxpi · 1 comment

Gateway presence not re-sent after reconnecting to the server

What happens

After ejabberd restarts, linked users can be left without the gateway's
presence: their client shows the gateway offline / "Not linked" until the
client itself reconnects.

On xmpp.asxp.io (stack recreated at 18:04): the engine reported the account
ready at 18:04:47 (updates running), the component reached ejabberd at
18:04:50 after two refused attempts. sendGatewayPresence ran on the state
change, while the component stream was down, so that presence was lost; the
user's client probed while the component was still disconnected. A manual
probe at 18:25 got the expected available presence.

Why

component/gateway.tcl: sendGatewayPresence runs only on an account state
change (onEngineEvent state) and on a probe/available from the user
(onPresence). Nothing runs it when the component's stream (re)connects
(ready as telegram.<domain> (fresh bind)).

Fix

On every component ready (fresh bind or reconnect), send
sendGatewayPresence to each account in acct, and once M1 lands, the peers'
last known presence too. Optionally probe each linked user so their current
presence is known after a restart.

Peer presence is not forwarded at all yet: onEngineEvent drops
user_status (gateway.tcl:129), and a subscription to <id>@telegram.<domain>
is answered subscribed with no presence afterwards (M1 per DESIGN.md).

Environment

feat/telegram-connect at cb68dd9, anotherim-server compose deployment
(ejabberd 26.09).

## Gateway presence not re-sent after reconnecting to the server ### What happens After ejabberd restarts, linked users can be left without the gateway's presence: their client shows the gateway offline / "Not linked" until the client itself reconnects. On xmpp.asxp.io (stack recreated at 18:04): the engine reported the account `ready` at 18:04:47 (`updates running`), the component reached ejabberd at 18:04:50 after two refused attempts. `sendGatewayPresence` ran on the state change, while the component stream was down, so that presence was lost; the user's client probed while the component was still disconnected. A manual probe at 18:25 got the expected available presence. ### Why `component/gateway.tcl`: `sendGatewayPresence` runs only on an account state change (`onEngineEvent` `state`) and on a probe/available from the user (`onPresence`). Nothing runs it when the component's stream (re)connects (`ready as telegram.<domain> (fresh bind)`). ### Fix On every component ready (fresh bind or reconnect), send `sendGatewayPresence` to each account in `acct`, and once M1 lands, the peers' last known presence too. Optionally probe each linked user so their current presence is known after a restart. ### Related Peer presence is not forwarded at all yet: `onEngineEvent` drops `user_status` (`gateway.tcl:129`), and a subscription to `<id>@telegram.<domain>` is answered `subscribed` with no presence afterwards (M1 per DESIGN.md). ### Environment `feat/telegram-connect` at `cb68dd9`, anotherim-server compose deployment (ejabberd 26.09).
ann referenced this issue from a commit 2026-10-12 23:13:07 +00:00
The three open issues: a message to a non-numeric address is bounced instead of dropped (#1), a linked account's contacts reach the roster (#2), and the gateway's presence survives a reconnect (#3). gateway.tcl bounces a chat message to a JID on our domain that names no peer with item-not-found, saying how to address a Telegram user; when the localpart is a Telegram username the linked account resolves it and the error names the JID to write to, or says no such user; a presence subscription to such a JID is answered unsubscribed. The engine gains `contacts` (account.Contacts over contacts.getContacts, the users' access hashes kept through peers.Apply, deleted accounts left out; the fake answers Alice and Bob; docs/frames.md), and the new component/roster.tcl puts them in the user's roster when the account turns ready and every time the component's stream comes up: with the roster privilege the server states in its XEP-0356 <privilege> message, a roster get and the pushes that make it match (adds, renames, contacts gone from Telegram removed, one item per iq); without one, an XEP-0144 roster item exchange. The grant may arrive before or after the stream's ready event, so it is kept until the stream drops and the sync waits two seconds for it. On every ready main.tcl sends each linked user the gateway's presence again and a probe, and the engine's account list sends it too when the stream was up first. DESIGN.md's registration step 5 and the milestones now say what M0 does. The libtacky submodule moves to the rig that grants the privilege under XMPP_COMPONENT_PRIVILEGE=1; make e2e runs the end-to-end test in both modes, with the gateway restarted in the middle to see its presence come back and the roster left alone. make test passes (coverage 92.5 %); e2e 44 of 44 with the privilege and 44 of 44 without.
Owner

Addressed in 58b32c7 (main). At cb68dd9 main.tcl's ready handler did resend the presence, so I could not reproduce the loss as described, but the path is now belt and braces: on every component ready each linked user gets the gateway's presence again plus a probe, and the engine's account list sends it too when the stream came up before the accounts were known. The end-to-end test now restarts the gateway mid-run and checks the presence comes back without a probe from the client. If it still happens on a real restart, the component's log around connected as at -log debug would help.

Addressed in 58b32c7 (main). At cb68dd9 main.tcl's ready handler did resend the presence, so I could not reproduce the loss as described, but the path is now belt and braces: on every component ready each linked user gets the gateway's presence again plus a probe, and the engine's account list sends it too when the stream came up before the accounts were known. The end-to-end test now restarts the gateway mid-run and checks the presence comes back without a probe from the client. If it still happens on a real restart, the component's log around `connected as` at `-log debug` would help.
ann closed this issue 2026-10-12 23:17:57 +00:00
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
another-im/tackygram#3
No description provided.