hirokisan / bybit

Bybit client library for Go
https://pkg.go.dev/github.com/hirokisan/bybit/v2
MIT License
90 stars 58 forks source link

panic: repeated read on failed websocket connection #144

Closed mmavka closed 8 months ago

mmavka commented 8 months ago

Hi. Thanks for the library

Code

package main

import (
    "context"
    "fmt"
    "github.com/hirokisan/bybit/v2"
    "time"
)

func main() {
    client := bybit.NewClient()
    res, err := client.Future().USDTPerpetual().Symbols()

    wsClient := bybit.NewWebsocketClient()
    svcRoot := wsClient.V5()

    go func() {
        for _, result := range res.Result {
            svc, err := svcRoot.Public(bybit.CategoryV5Linear)
            if err != nil {
                fmt.Println(err)
            }
            _, err = svc.SubscribeKline(bybit.V5WebsocketPublicKlineParamKey{
                Interval: bybit.Interval1,
                Symbol:   bybit.SymbolV5(result.Name),
            }, func(response bybit.V5WebsocketPublicKlineResponse) error {
                fmt.Println(response)
                return nil
            })
            go WS(svc)
        }

    }()

    for {
        time.Sleep(time.Second)
    }
}

func WS(svc bybit.V5WebsocketPublicServiceI) {
    svc.Start(context.Background(), func(isWebsocketClosed bool, err error) {
        fmt.Println(svc, isWebsocketClosed, err)
        WS(svc)
    })
}

I have error:

false read tcp 192.168.1.2:32343->52.84.106.124:443: wsarecv: An existing connection was forcibly closed by the remote host.
false read tcp 192.168.1.2:32343->52.84.106.124:443: wsarecv: An existing connection was forcibly closed by the remote host.
panic: repeated read on failed websocket connection

goroutine 4031 [running]:
github.com/gorilla/websocket.(*Conn).NextReader(0xc001cfa2c0)
        C:/Users/mmavka/go/pkg/mod/github.com/gorilla/websocket@v1.5.0/conn.go:1030 +0x2a8
github.com/gorilla/websocket.(*Conn).ReadMessage(0x0?)
        C:/Users/mmavka/go/pkg/mod/github.com/gorilla/websocket@v1.5.0/conn.go:1093 +0x19
github.com/hirokisan/bybit/v2.(*V5WebsocketPublicService).Run(0xc001cc8900)
        C:/Users/mmavka/go/pkg/mod/github.com/hirokisan/bybit/v2@v2.24.0/v5_ws_public.go:193 +0x3a
github.com/hirokisan/bybit/v2.(*V5WebsocketPublicService).Start.func1()
        C:/Users/mmavka/go/pkg/mod/github.com/hirokisan/bybit/v2@v2.24.0/v5_ws_public.go:152 +0x15d
created by github.com/hirokisan/bybit/v2.(*V5WebsocketPublicService).Start
        C:/Users/mmavka/go/pkg/mod/github.com/hirokisan/bybit/v2@v2.24.0/v5_ws_public.go:141 +0xec

Process finished with the exit code 2
mmavka commented 8 months ago

How i can reconnect without panic?

hirokisan commented 8 months ago

panic: repeated read on failed websocket connection

https://github.com/gorilla/websocket/blob/9111bb834a68b893cebbbaed5060bdbc1d9ab7d2/conn.go#L1025-L1031

hirokisan commented 8 months ago

@mmavka

I don't know if I am understanding the details,I think it is an implementation issue.

How about trying this?

I have made some changes to your code.

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/hirokisan/bybit/v2"
    "golang.org/x/sync/errgroup"
)

func main() {
    if err := run(); err != nil {
        log.Fatal(err)
    }
}

func run() error {
    client := bybit.NewClient()
    res, err := client.Future().USDTPerpetual().Symbols()
    if err != nil {
        return err
    }

    wsClient := bybit.NewWebsocketClient()
    svcRoot := wsClient.V5()

    var eg errgroup.Group

    for _, result := range res.Result {
        name := result.Name
        eg.Go(func() error {
            svc, err := svcRoot.Public(bybit.CategoryV5Linear)
            if err != nil {
                fmt.Println(err)
            }
            _, err = svc.SubscribeKline(bybit.V5WebsocketPublicKlineParamKey{
                Interval: bybit.Interval1,
                Symbol:   bybit.SymbolV5(name),
            }, func(response bybit.V5WebsocketPublicKlineResponse) error {
                fmt.Println(response)
                return nil
            })
            WS(svc)

            return nil
        })
    }

    if err := eg.Wait(); err != nil {
        return err
    }
    return nil
}

func WS(svc bybit.V5WebsocketPublicServiceI) {
    svc.Start(context.Background(), func(isWebsocketClosed bool, err error) {
        fmt.Println(svc, isWebsocketClosed, err)
        WS(svc)
    })
}
mmavka commented 8 months ago

Thanks for the answer! I solved my issue. I had an implementation problem

Code

func main() {
    client := bybit.NewClient()
    res, err := client.Future().USDTPerpetual().Symbols()
    if err != nil {
        log.Fatal(err)
    }

    wsClient := bybit.NewWebsocketClient()
    svcRoot := wsClient.V5()
    svc, err := svcRoot.Public(bybit.CategoryV5Linear)
    if err != nil {
        fmt.Println(err)
    }

    for _, result := range res.Result {
        name := result.Name
        _, err = svc.SubscribeKline(bybit.V5WebsocketPublicKlineParamKey{
            Interval: bybit.Interval1,
            Symbol:   bybit.SymbolV5(name),
        }, func(response bybit.V5WebsocketPublicKlineResponse) error {
            fmt.Println(response)
            return nil
        })

    }
    go WS(svc)
}

func WS(svc bybit.V5WebsocketPublicServiceI) {
    for {
        svc.Start(context.Background(), func(isWebsocketClosed bool, err error) {
            fmt.Println(countErr, svc, isWebsocketClosed, err)
        })
    }
}

Testing now... ))

hirokisan commented 8 months ago

I'll close 👍