adshao / go-binance

A Go SDK for Binance API
MIT License
1.49k stars 661 forks source link

How to re-run websocket if it down #384

Closed Icarus9913 closed 4 weeks ago

Icarus9913 commented 2 years ago

I found you use for loop to traverse. But once it meet err the whole websokcetTick will down. In this situation, how can we run it gain?

https://github.com/adshao/go-binance/blob/774259245842dd69ed7731d8ef09a772d9c837b0/v2/futures/websocket.go#L54-L63

Icarus9913 commented 2 years ago

cc @adshao

Icarus9913 commented 2 years ago

Can we use continue instead of return in line 60?

Icarus9913 commented 2 years ago

This is my err log:

websokcet get price err(this is custom): websocket: close 1006 (abnormal closure): unexpected EOF

Icarus9913 commented 2 years ago

In another way, we could add one boolean arg to check whether it should continue when it occurs an error.

adshao commented 2 years ago

Can we use continue instead of return in line 60?

It's impossible to break the loop if we use continue. Maybe you can just reconnect websocket from the first place to retry.

gurkanguray commented 2 years ago

@Icarus9913 your errHandler function should "handle" the error. If you want to reconnect immediately, just reconnect it while handling error. Here is an example function:

func errorHandler(symbol string, klineInterval string) func(err error) {
    return func(err error) { // handler function that handles error
        fmt.Println("Error: ", err.Error())
        _, _, err = binance.WsKlineServe(symbol, klineInterval, klineHandler(klineInterval), errorHandler(symbol, klineInterval)) // start the kline websocket connection again with the same interval
        if err != nil {                                                                                                            // if there is an error on reconnecting (I suggest you to check your internet connection first and binance api/server status here)
            fmt.Println(err.Error())
            return
        }
    }
}
rodrigo-brito commented 1 year ago

I used it with a channel wrapper, when it disconnects I use a backoff retry: https://github.com/rodrigo-brito/ninjabot/blob/main/exchange/binance.go#L470-L514

func (b *Binance) CandlesSubscription(ctx context.Context, pair, period string) (chan model.Candle, chan error) {
    ccandle := make(chan model.Candle)
    cerr := make(chan error)

    go func() {
        ba := &backoff.Backoff{
            Min: 100 * time.Millisecond,
            Max: 1 * time.Second,
        }

        for {
            done, _, err := binance.WsKlineServe(pair, period, func(event *binance.WsKlineEvent) {
                ba.Reset()
                candle := CandleFromWsKline(pair, event.Kline)
                ccandle <- candle

            }, func(err error) {
                cerr <- err
            })
            if err != nil {
                cerr <- err
                close(cerr)
                close(ccandle)
                return
            }

            select {
            case <-ctx.Done():
                close(cerr)
                close(ccandle)
                return
            case <-done:
                time.Sleep(ba.Duration())
            }
        }
    }()

    return ccandle, cerr
}

The final usage will looks like:

candles, _ := binance.CandlesSubscription(ctx, "BTCUSDT", "1h")
for candle := range candles {
// your logic here
}
xyq-c-cpp commented 4 weeks ago

No response for a long time, close this issue