Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

create_connection, send and recv instead of simply open / avoid do statements #185

Open
femtotrader opened this issue Jan 4, 2023 · 3 comments

Comments

@femtotrader
Copy link

Hello,

Sorry I'm new to websockets.
I want to convert the following Python code to Julia

from websocket import create_connection
import orjson

ws = create_connection("wss://ws.kraken.com/")
message = {"event":"subscribe", "subscription":{"name":"trade"}, "pair":["XBT/USDT","XBT/USD"]}

ws.send(orjson.dumps(message))

while True:
    message = ws.recv()
    message = orjson.loads(message)
    print(message)
    if isinstance(message, list):
        print(message[2], message[3])

I did using doc

using WebSockets
import JSON


const url = "wss://ws.kraken.com/"

WebSockets.open(url) do ws_client  
    # msg = "{\"event\":\"subscribe\", \"subscription\":{\"name\":\"trade\"}, \"pair\":[\"XBT/USD\",\"XRP/USD\"]}"

    msg = Dict(
        "event" => "subscribe", 
        "subscription" => Dict("name" => "trade"),
        "pair" => ["XBT/USDT", "XBT/USD"]
    )
    msg = JSON.json(msg)

    writeguarded(ws_client, msg)

    while (true)
        data, success = readguarded(ws_client)
        if success
            println(stderr, ws_client, " received:", String(data))
        end
            
    end
end;

but I don't like Julia do statements.

Moreover I would prefer to have separate create_connection, send and recv call like in the Python example but in the Julia example open takes handle function as parameter which is a mix of all this.

How can I achieve that? (ie having a Julia code nearer than the Python code)

Kind regards

@hustf
Copy link
Collaborator

hustf commented Jan 5, 2023

Hello, femtotrader. I think I understand your dislike of do-functions. You find remnants of my own reluctance in this repository. They may mature on you, as they did for me, but in the meantime, I suggest you rewrite:

function handle_open_connection(ws_client)  
    msg = Dict(
        "event" => "subscribe", 
        "subscription" => Dict("name" => "trade"),
        "pair" => ["XBT/USDT", "XBT/USD"]
    )
    msg = JSON.json(msg)
    writeguarded(ws_client, msg)
    while (true)
        data, success = readguarded(ws_client)
        if success
            println(stderr, ws_client, " received:", String(data))
        end
    end
end

const url = "wss://ws.kraken.com/"

WebSockets.open(handle_open_connection, url)

What you ask for is possible, although it breaks with a couple of practices that are common in Julia although they also increase your chance to 'monitor as things happen'. You are going to make ws a global, and you'll have to remember to close(ws) yourself. I don't think either is a sin. I recognize your user name - you would know the pitfalls and workarounds.

You can basically dissect the function WebSockets.open and do everything in the REPL line by line, more closely resembling Python. I suggest the REPL because we added some colouring that makes monitoring the state of the connection a bit friendlier.

Your thread of execution can of course easily get stuck in waiting forever for the other side (while the other side may be waiting for you). If you don't want that to happen, execute functions with tsk = @asynchandle_open_connection(ws).

I believe using this package as you do is ok for easing the transition. If you plan on doing something larger or permanent, though, I actually recommend you have a look at HTTP.jl. That one is the long-term solution for websockets in Julia, although we maintain this in order to keep other useful, old packages alive. I'm pinging @fonsp here, as this issue relates to a discussion we had recently.

@femtotrader
Copy link
Author

Thanks @hustf for your very detailed answer.

I was expecting something like this would be possible:

const url = "wss://ws.kraken.com/"

ws_client = WebSockets.open(url)
msg = Dict(
    "event" => "subscribe", 
    "subscription" => Dict("name" => "trade"),
    "pair" => ["XBT/USDT", "XBT/USD"]
)
msg = JSON.json(msg)
writeguarded(ws_client, msg)
while (true)
    data, success = readguarded(ws_client)
    if success
        println(stderr, ws_client, " received:", String(data))
    end
end

close(ws_client)

because with such a rewrite it would be easier to reuse WebSockets.jl in a quite complex project.

I will try using REPL and WebSockets.open code

function open(f::Function, url; verbose=false, subprotocol = "", kw...)

@hustf
Copy link
Collaborator

hustf commented Jan 5, 2023

Good luck!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants