package telegramimport ()// API returns *tg.Client for calling raw MTProto methods.func ( *Client) () *tg.Client {return .tg}// Invoke invokes raw MTProto RPC method. It sends input and decodes result// into output.func ( *Client) ( context.Context, bin.Encoder, bin.Decoder) error {if .tracer != nil { := "Invoke"var []attribute.KeyValueif , := .(interface{ () uint32 }); { := .() = append(,attribute.Int64("tg.method.id_int", int64()),attribute.String("tg.method.id", fmt.Sprintf("%x", )), ) := .opts.Types.Get()if == "" { = fmt.Sprintf("0x%x", ) } else { = append(, attribute.String("tg.method.name", )) } = fmt.Sprintf("Invoke: %s", ) } , := .tracer.Start(, ,trace.WithAttributes(...),trace.WithSpanKind(trace.SpanKindClient), ) = defer .End() }return .invoker.Invoke(, , )}// invokeDirect directly invokes RPC method, automatically handling datacenter redirects.func ( *Client) ( context.Context, bin.Encoder, bin.Decoder) error {if := .invokeConn(, , ); != nil {// Handling datacenter migration request.if , := tgerr.As(); && strings.HasSuffix(.Type, "_MIGRATE") { := .Argument := .log.With(log.String("error_type", .Type),log.Int("target_dc", ), )// If migration error is FILE_MIGRATE or STATS_MIGRATE, then the method // called by authorized client, so we should try to transfer auth to new DC // and create new connection.if .IsOneOf("FILE_MIGRATE", "STATS_MIGRATE") { .Debug(, "Invoking on target DC")return .invokeSub(, , , ) }// Otherwise we should change primary DC. .Info(, "Migrating to target DC")return .invokeMigrate(, , , ) }return }returnnil}// invokeConn directly invokes RPC call on primary connection without any// additional handling.//// If the connection dies before the request is processed by the server,// invokeConn waits until the reconnection loop replaces the connection and// retries the request on it, see https://github.com/gotd/td/issues/1030.func ( *Client) ( context.Context, bin.Encoder, bin.Decoder) error {for { .connMux.Lock() := .conn := .connChanged .connMux.Unlock() := .Invoke(, , )if == nil || !errRetryableOnNewConn() {return }var <-chanstruct{}if .ctx != nil { = .ctx.Done() } .log.Debug(, "Primary connection is dead, waiting for new connection to retry",log.Error(), )select {case<-.Done():returnerrors.Wrap(.Err(), "wait for reconnect")case<-:// Client is closed, no reconnection will happen.returnerrors.Wrap(.ctx.Err(), "client closed")case<-: } }}// errRetryableOnNewConn reports whether request failed because connection// died before the request was processed by the server (request was not sent,// or sent but not acknowledged), so it is safe to retry the request on a new// connection.func ( error) bool {returnerrors.Is(, pool.ErrConnDead) || errors.Is(, rpc.ErrEngineClosed)}
The pages are generated with Goldsv0.8.4. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.