1
bot/get_updates.go

95 lines
1.9 KiB
Go
Raw Permalink Normal View History

2022-04-26 00:02:51 +08:00
package bot
import (
"context"
"errors"
"sync"
2022-04-26 00:02:51 +08:00
"sync/atomic"
"time"
"github.com/go-telegram/bot/models"
)
const (
maxTimeoutAfterError = time.Second * 5
)
type getUpdatesParams struct {
Offset int64 `json:"offset,omitempty"`
Limit int `json:"limit,omitempty"`
Timeout int `json:"timeout,omitempty"`
AllowedUpdates AllowedUpdates `json:"allowed_updates,omitempty"`
2022-04-26 00:02:51 +08:00
}
type AllowedUpdates []string
// GetUpdates https://core.telegram.org/bots/api#getupdates
func (b *Bot) getUpdates(ctx context.Context, wg *sync.WaitGroup) {
defer wg.Done()
2022-04-26 00:02:51 +08:00
var timeoutAfterError time.Duration
for {
select {
case <-ctx.Done():
return
default:
}
if timeoutAfterError > 0 {
2023-04-13 16:39:58 +08:00
if b.isDebug {
b.debugHandler("wait after error, %v", timeoutAfterError)
}
2022-04-26 00:02:51 +08:00
select {
case <-ctx.Done():
return
case <-time.After(timeoutAfterError):
}
}
params := &getUpdatesParams{
Timeout: int((b.pollTimeout - time.Second).Seconds()),
Offset: atomic.LoadInt64(&b.lastUpdateID) + 1,
}
if b.allowedUpdates != nil {
params.AllowedUpdates = b.allowedUpdates
}
2022-04-26 00:02:51 +08:00
var updates []*models.Update
errRequest := b.rawRequest(ctx, "getUpdates", params, &updates)
2022-04-26 00:02:51 +08:00
if errRequest != nil {
if errors.Is(errRequest, context.Canceled) {
return
}
b.error("error get updates, %w", errRequest)
2022-04-26 00:02:51 +08:00
timeoutAfterError = incErrTimeout(timeoutAfterError)
continue
}
timeoutAfterError = 0
for _, upd := range updates {
atomic.StoreInt64(&b.lastUpdateID, upd.ID)
select {
case <-ctx.Done():
b.error("some updates lost, ctx done")
return
case b.updates <- upd:
2022-04-26 00:02:51 +08:00
}
}
}
}
func incErrTimeout(timeout time.Duration) time.Duration {
if timeout == 0 {
return time.Millisecond * 100 // first timeout
}
timeout *= 2
if timeout > maxTimeoutAfterError {
return maxTimeoutAfterError
}
return timeout
}