Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: gotd/td
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: f059afbfe5fd1d1cffb51b8fb028fdfdaaec8648
Choose a base ref
..
head repository: gotd/td
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: a04b4e41b6153a538cb6558abafa6369a0e2c620
Choose a head ref
1 change: 1 addition & 0 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
@@ -44,3 +44,4 @@ jobs:
env:
GOTD_TEST_EXTERNAL: 1
GOTD_MTPROXY_ADDR: "127.0.0.1:3128"
GOTD_E2E_DIALOGS_BROKEN: 1 # TODO(ernado): enable when fixed
4 changes: 2 additions & 2 deletions examples/go.mod
Original file line number Diff line number Diff line change
@@ -33,7 +33,7 @@ require (
github.com/golang/snappy v0.0.4 // indirect
github.com/gotd/ige v0.2.2 // indirect
github.com/gotd/neo v0.1.5 // indirect
github.com/klauspost/compress v1.17.10 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
@@ -50,7 +50,7 @@ require (
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect
golang.org/x/net v0.29.0 // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/text v0.18.0 // indirect
golang.org/x/text v0.19.0 // indirect
google.golang.org/protobuf v1.33.0 // indirect
nhooyr.io/websocket v1.8.11 // indirect
rsc.io/qr v0.2.0 // indirect
44 changes: 13 additions & 31 deletions examples/go.sum
Original file line number Diff line number Diff line change
@@ -48,10 +48,8 @@ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU=
github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/compress v1.17.10/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@@ -76,21 +74,15 @@ github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI=
go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE=
go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs=
go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4=
go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ=
go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4=
go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw=
go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8=
go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA=
go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0=
go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4=
go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI=
go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4=
go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
@@ -103,9 +95,7 @@ go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME=
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
@@ -115,33 +105,25 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA=
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM=
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
27 changes: 16 additions & 11 deletions telegram/client.go
Original file line number Diff line number Diff line change
@@ -59,12 +59,12 @@ type Client struct {
// Ref: https://pkg.go.dev/sync/atomic#pkg-note-BUG

// Connection factory fields.
connsCounter atomic.Int64
create connConstructor // immutable
resolver dcs.Resolver // immutable
onDead func() // immutable
connBackoff func() backoff.BackOff // immutable
defaultMode manager.ConnMode // immutable
connsCounter atomic.Int64
create connConstructor // immutable
resolver dcs.Resolver // immutable
onDead func() // immutable
newConnBackoff func() backoff.BackOff // immutable
defaultMode manager.ConnMode // immutable

// Migration state.
migrationTimeout time.Duration // immutable
@@ -90,10 +90,11 @@ type Client struct {
testDC bool // immutable

// Connection state. Guarded by connMux.
session *pool.SyncSession
cfg *manager.AtomicConfig
conn clientConn
connMux sync.Mutex
session *pool.SyncSession
cfg *manager.AtomicConfig
conn clientConn
connBackoff atomic.Pointer[backoff.BackOff]
connMux sync.Mutex

// Restart signal channel.
restart chan struct{} // immutable
@@ -133,6 +134,9 @@ type Client struct {

// onTransfer is called in transfer.
onTransfer AuthTransferHandler

// onSelfError is called on error calling Self().
onSelfError func(ctx context.Context, err error) error
}

// NewClient creates new unstarted client.
@@ -160,14 +164,15 @@ func NewClient(appID int, appHash string, opt Options) *Client {
create: defaultConstructor(),
resolver: opt.Resolver,
defaultMode: mode,
connBackoff: opt.ReconnectionBackoff,
newConnBackoff: opt.ReconnectionBackoff,
onDead: opt.OnDead,
clock: opt.Clock,
device: opt.Device,
migrationTimeout: opt.MigrationTimeout,
noUpdatesMode: opt.NoUpdates,
mw: opt.Middlewares,
onTransfer: opt.OnTransfer,
onSelfError: opt.OnSelfError,
}
if opt.TracerProvider != nil {
client.tracer = opt.TracerProvider.Tracer(oteltg.Name)
6 changes: 6 additions & 0 deletions telegram/client_external_test.go
Original file line number Diff line number Diff line change
@@ -2,6 +2,8 @@ package telegram_test

import (
"context"
"os"
"strconv"
"strings"
"testing"
"time"
@@ -79,6 +81,10 @@ const dialog = `— Да?

func TestExternalE2EUsersDialog(t *testing.T) {
testutil.SkipExternal(t)
if v, _ := strconv.ParseBool(os.Getenv("GOTD_E2E_DIALOGS_BROKEN")); v {
// TODO(ernado): enable when fixed
t.Skip("Dialogs are broken.")
}

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
defer cancel()
27 changes: 25 additions & 2 deletions telegram/connect.go
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@ import (
"github.com/gotd/td/exchange"
"github.com/gotd/td/tdsync"
"github.com/gotd/td/telegram/auth"
"github.com/gotd/td/tgerr"
)

func (c *Client) runUntilRestart(ctx context.Context) error {
@@ -29,6 +30,12 @@ func (c *Client) runUntilRestart(ctx context.Context) error {
if !auth.IsUnauthorized(err) {
c.log.Warn("Got error on self", zap.Error(err))
}
if h := c.onSelfError; h != nil {
// Help with https://github.com/gotd/td/issues/1458.
if err := h(ctx, err); err != nil {
return errors.Wrap(err, "onSelfError")
}
}
return nil
}

@@ -54,13 +61,24 @@ func (c *Client) runUntilRestart(ctx context.Context) error {
}

func (c *Client) isPermanentError(err error) bool {
return errors.Is(err, exchange.ErrKeyFingerprintNotFound)
// See https://github.com/gotd/td/issues/1458.
if errors.Is(err, exchange.ErrKeyFingerprintNotFound) {
return true
}
if tgerr.Is(err, "AUTH_KEY_UNREGISTERED", "SESSION_EXPIRED") {
return true
}
if auth.IsUnauthorized(err) {
return true
}
return false
}

func (c *Client) reconnectUntilClosed(ctx context.Context) error {
// Note that we currently have no timeout on connection, so this is
// potentially eternal.
b := tdsync.SyncBackoff(backoff.WithContext(c.connBackoff(), ctx))
b := tdsync.SyncBackoff(backoff.WithContext(c.newConnBackoff(), ctx))
c.connBackoff.Store(&b)

return backoff.RetryNotify(func() error {
if err := c.runUntilRestart(ctx); err != nil {
@@ -83,6 +101,11 @@ func (c *Client) reconnectUntilClosed(ctx context.Context) error {
func (c *Client) onReady() {
c.log.Debug("Ready")
c.ready.Signal()

if b := c.connBackoff.Load(); b != nil {
// Reconnect faster next time.
(*b).Reset()
}
}

func (c *Client) resetReady() {
2 changes: 1 addition & 1 deletion telegram/connect_test.go
Original file line number Diff line number Diff line change
@@ -33,7 +33,7 @@ func (m fingerprintNotFoundConn) Ready() <-chan struct{} {

func TestClient_reconnectUntilClosed(t *testing.T) {
client := Client{
connBackoff: func() backoff.BackOff {
newConnBackoff: func() backoff.BackOff {
return backoff.NewConstantBackOff(time.Nanosecond)
},
log: zap.NewNop(),
2 changes: 1 addition & 1 deletion telegram/message/entity/format_test.go
Original file line number Diff line number Diff line change
@@ -54,7 +54,7 @@ func TestBuilder_GrowText(t *testing.T) {
)

b.GrowText(100)
a.Equal(100, b.message.Cap())
a.LessOrEqual(100, b.message.Cap())
}

func TestBuilder_GrowEntities(t *testing.T) {
2 changes: 1 addition & 1 deletion telegram/migrate_to_dc_test.go
Original file line number Diff line number Diff line change
@@ -110,7 +110,7 @@ func newMigrationClient(t *testing.T, h migrationTestHandler) *Client {
session: pool.NewSyncSession(pool.Session{
DC: 2,
}),
connBackoff: defaultBackoff(clock.System),
newConnBackoff: defaultBackoff(clock.System),
ctx: context.Background(),
cancel: func() {},
migrationTimeout: 10 * time.Second,
10 changes: 10 additions & 0 deletions telegram/options.go
Original file line number Diff line number Diff line change
@@ -100,6 +100,14 @@ type Options struct {
// OnTransfer is called during authorization transfer.
// See [AuthTransferHandler] for details.
OnTransfer AuthTransferHandler

// OnSelfError is called when client receives error calling Self() on connect.
// Return error to stop reconnection.
//
// NB: this method is called immediately after connection, so it's not expected to be
// non-nil error on first connection before auth, so it's safe to return nil until
// first successful auth.
OnSelfError func(ctx context.Context, err error) error
}

func (opt *Options) setDefaults() {
@@ -156,6 +164,8 @@ func defaultBackoff(c clock.Clock) func() backoff.BackOff {
b := backoff.NewExponentialBackOff()
b.Clock = c
b.MaxElapsedTime = 0
b.MaxInterval = time.Second * 5
b.InitialInterval = time.Millisecond * 100
return b
}
}
2 changes: 2 additions & 0 deletions telegram/updates/internal/e2e/manager_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build linux

package e2e

import (
24 changes: 24 additions & 0 deletions telegram/updates/state.go
Original file line number Diff line number Diff line change
@@ -10,8 +10,11 @@ import (
"go.uber.org/zap"
"golang.org/x/sync/errgroup"

"github.com/gotd/td/exchange"
"github.com/gotd/td/telegram"
"github.com/gotd/td/telegram/auth"
"github.com/gotd/td/tg"
"github.com/gotd/td/tgerr"
)

const (
@@ -137,6 +140,21 @@ func (s *internalState) Push(ctx context.Context, u tg.UpdatesClass) error {
}
}

// isFatalError returns true if error is fatal so we should stop updates handler.
func isFatalError(err error) bool {
// See https://github.com/gotd/td/issues/1458.
if errors.Is(err, exchange.ErrKeyFingerprintNotFound) {
return true
}
if tgerr.Is(err, "AUTH_KEY_UNREGISTERED", "SESSION_EXPIRED") {
return true
}
if auth.IsUnauthorized(err) {
return true
}
return false
}

func (s *internalState) Run(ctx context.Context) error {
if s == nil {
return errors.New("invalid: nil internalState")
@@ -159,11 +177,17 @@ func (s *internalState) Run(ctx context.Context) error {
ctx := trace.ContextWithSpanContext(ctx, u.span)
if err := s.handleUpdates(ctx, u.update); err != nil {
s.log.Error("Handle updates error", zap.Error(err))
if isFatalError(err) {
return errors.Wrap(err, "fatal error")
}
}
case u := <-s.internalQueue:
ctx := trace.ContextWithSpanContext(ctx, u.span)
if err := s.handleUpdates(ctx, u.update); err != nil {
s.log.Error("Handle updates error", zap.Error(err))
if isFatalError(err) {
return errors.Wrap(err, "fatal error")
}
}
case <-s.pts.gapTimeout.C:
s.log.Debug("Pts gap timeout")