client: improve disconnection detection

Signed-off-by: Sumner Evans <sumner.evans@automattic.com>
This commit is contained in:
Sumner Evans
2024-12-05 13:33:20 -07:00
parent 71ebb72ede
commit 2a7146d987
2 changed files with 38 additions and 14 deletions
+37 -13
View File
@@ -47,6 +47,7 @@ type TelegramClient struct {
userLogin *bridgev2.UserLogin userLogin *bridgev2.UserLogin
client *telegram.Client client *telegram.Client
updatesManager *updates.Manager updatesManager *updates.Manager
clientCtx context.Context
clientCancel context.CancelFunc clientCancel context.CancelFunc
appConfigLock sync.Mutex appConfigLock sync.Mutex
@@ -225,7 +226,7 @@ func NewTelegramClient(ctx context.Context, tc *TelegramConnector, login *bridge
OnDead: client.onDead, OnDead: client.onDead,
OnSession: client.onConnectionStateChange("session"), OnSession: client.onConnectionStateChange("session"),
OnConnected: client.onConnectionStateChange("connected"), OnConnected: client.onConnectionStateChange("connected"),
PingCallback: client.onConnectionStateChange("ping"), PingCallback: client.onPing,
OnAuthError: func(err error) { client.onAuthError(context.Background(), err) }, OnAuthError: func(err error) { client.onAuthError(context.Background(), err) },
PingTimeout: time.Duration(tc.Config.Ping.TimeoutSeconds) * time.Second, PingTimeout: time.Duration(tc.Config.Ping.TimeoutSeconds) * time.Second,
PingInterval: time.Duration(tc.Config.Ping.IntervalSeconds) * time.Second, PingInterval: time.Duration(tc.Config.Ping.IntervalSeconds) * time.Second,
@@ -412,6 +413,14 @@ func (t *TelegramClient) sendBadCredentialsOrUnknownError(err error) {
} }
} }
func (t *TelegramClient) onPing() {
if t.userLogin.BridgeState.GetPrev().StateEvent == status.StateConnected {
t.main.Bridge.Log.Info().Msg("Got ping, not checking connectivity because we are already connected")
} else {
t.onConnectionStateChange("ping while not connected")
}
}
func (t *TelegramClient) onConnectionStateChange(reason string) func() { func (t *TelegramClient) onConnectionStateChange(reason string) func() {
return func() { return func() {
log := t.main.Bridge.Log.With(). log := t.main.Bridge.Log.With().
@@ -423,15 +432,21 @@ func (t *TelegramClient) onConnectionStateChange(reason string) func() {
ctx := log.WithContext(context.Background()) ctx := log.WithContext(context.Background())
if t.client == nil { if t.client == nil {
log.Warn().Msg("client is nil")
return return
} }
authStatus, err := t.client.Auth().Status(ctx) authStatus, err := t.client.Auth().Status(ctx)
if err != nil { if err != nil {
if errors.Is(err, syscall.EPIPE) { if errors.Is(err, syscall.EPIPE) {
// This is a pipe error, try reconnecting // This is a pipe error, try disconnecting which will force the
// updatesManager to fail and cause the client to reconnect.
t.userLogin.BridgeState.Send(status.BridgeState{
StateEvent: status.StateTransientDisconnect,
Error: "pipe-error",
Message: humanise.Error(err),
})
t.Disconnect() t.Disconnect()
t.Connect(t.main.Bridge.Log.WithContext(context.Background()))
} else { } else {
t.sendBadCredentialsOrUnknownError(err) t.sendBadCredentialsOrUnknownError(err)
} }
@@ -460,15 +475,15 @@ func (t *TelegramClient) Connect(ctx context.Context) {
} }
var err error var err error
ctx, t.clientCancel, err = connectTelegramClient(ctx, t.client) t.clientCtx, t.clientCancel, err = connectTelegramClient(ctx, t.client)
if err != nil { if err != nil {
t.sendBadCredentialsOrUnknownError(err) t.sendBadCredentialsOrUnknownError(err)
return return
} }
go func() { go func() {
err = t.updatesManager.Run(ctx, t.client.API(), t.telegramUserID, updates.AuthOptions{}) err = t.updatesManager.Run(t.clientCtx, t.client.API(), t.telegramUserID, updates.AuthOptions{})
if err != nil { if err != nil {
zerolog.Ctx(ctx).Err(err).Msg("failed to run updates manager") zerolog.Ctx(t.clientCtx).Err(err).Msg("failed to run updates manager")
t.Disconnect() t.Disconnect()
t.Connect(t.main.Bridge.Log.WithContext(context.Background())) t.Connect(t.main.Bridge.Log.WithContext(context.Background()))
} }
@@ -476,9 +491,9 @@ func (t *TelegramClient) Connect(ctx context.Context) {
// Update the logged-in user's ghost info (this also updates the user // Update the logged-in user's ghost info (this also updates the user
// login's remote name and profile). // login's remote name and profile).
if me, err := t.client.Self(ctx); err != nil { if me, err := t.client.Self(t.clientCtx); err != nil {
t.sendBadCredentialsOrUnknownError(err) t.sendBadCredentialsOrUnknownError(err)
} else if _, err := t.updateGhost(ctx, t.telegramUserID, me); err != nil { } else if _, err := t.updateGhost(t.clientCtx, t.telegramUserID, me); err != nil {
t.sendBadCredentialsOrUnknownError(err) t.sendBadCredentialsOrUnknownError(err)
} else { } else {
t.userLogin.BridgeState.Send(status.BridgeState{StateEvent: status.StateConnected}) t.userLogin.BridgeState.Send(status.BridgeState{StateEvent: status.StateConnected})
@@ -496,6 +511,7 @@ func (t *TelegramClient) Connect(ctx context.Context) {
} }
func (t *TelegramClient) Disconnect() { func (t *TelegramClient) Disconnect() {
t.userLogin.Log.Info().Msg("disconnecting client")
if t.clientCancel != nil { if t.clientCancel != nil {
t.clientCancel() t.clientCancel()
} }
@@ -642,11 +658,19 @@ func (t *TelegramClient) IsLoggedIn() bool {
if t == nil { if t == nil {
return false return false
} }
t.main.Bridge.Log.Debug(). select {
Bool("has_client", t.client != nil). case <-t.clientCtx.Done():
Bool("has_auth_key", t.userLogin.Metadata.(*UserLoginMetadata).Session.HasAuthKey()). t.main.Bridge.Log.Debug().
Msg("Checking if user is logged in") Bool("client_context_done", true).
return t.client != nil && t.userLogin.Metadata.(*UserLoginMetadata).Session.HasAuthKey() Msg("Checking if user is logged in")
return false
default:
t.main.Bridge.Log.Debug().
Bool("has_client", t.client != nil).
Bool("has_auth_key", t.userLogin.Metadata.(*UserLoginMetadata).Session.HasAuthKey()).
Msg("Checking if user is logged in")
return t.client != nil && t.userLogin.Metadata.(*UserLoginMetadata).Session.HasAuthKey()
}
} }
func (t *TelegramClient) LogoutRemote(ctx context.Context) { func (t *TelegramClient) LogoutRemote(ctx context.Context) {
+1 -1
View File
@@ -68,7 +68,7 @@ func (p *PhoneLogin) SubmitUserInput(ctx context.Context, input map[string]strin
}) })
var err error var err error
authClientContext, _ := context.WithTimeoutCause(log.WithContext(context.Background()), time.Hour, errors.New("phone login took over one hour")) authClientContext, _ := context.WithTimeoutCause(log.WithContext(context.Background()), time.Hour, errors.New("phone login took over one hour"))
_, p.authClientCancel, err = connectTelegramClient(authClientContext, p.authClient) ctx, p.authClientCancel, err = connectTelegramClient(authClientContext, p.authClient)
if err != nil { if err != nil {
return nil, err return nil, err
} }